Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
jenkins
提交
f6a6f0c3
J
jenkins
项目概览
xxadev
/
jenkins
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jenkins
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
f6a6f0c3
编写于
3月 29, 2018
作者:
D
Daniel Beck
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'security-stable-2.73' into security-stable-2.89
上级
4f68a6d3
7abc7133
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
807 addition
and
48 deletion
+807
-48
core/src/main/java/hudson/cli/CLICommand.java
core/src/main/java/hudson/cli/CLICommand.java
+2
-0
core/src/main/java/hudson/cli/handlers/ViewOptionHandler.java
.../src/main/java/hudson/cli/handlers/ViewOptionHandler.java
+3
-2
core/src/main/resources/lib/form/expandableTextbox.jelly
core/src/main/resources/lib/form/expandableTextbox.jelly
+1
-1
core/src/main/resources/lib/form/validateButton.jelly
core/src/main/resources/lib/form/validateButton.jelly
+1
-1
core/src/main/resources/lib/layout/confirmationLink.jelly
core/src/main/resources/lib/layout/confirmationLink.jelly
+2
-2
core/src/main/resources/lib/layout/stopButton.jelly
core/src/main/resources/lib/layout/stopButton.jelly
+4
-4
core/src/test/java/hudson/cli/handlers/ViewOptionHandlerTest.java
.../test/java/hudson/cli/handlers/ViewOptionHandlerTest.java
+9
-1
test/src/test/java/hudson/cli/CLIActionTest.java
test/src/test/java/hudson/cli/CLIActionTest.java
+32
-6
test/src/test/java/lib/form/ExpandableTextboxTest.java
test/src/test/java/lib/form/ExpandableTextboxTest.java
+96
-5
test/src/test/java/lib/form/ValidateButtonTest.java
test/src/test/java/lib/form/ValidateButtonTest.java
+157
-25
test/src/test/java/lib/layout/ConfirmationLinkTest.java
test/src/test/java/lib/layout/ConfirmationLinkTest.java
+205
-0
test/src/test/java/lib/layout/StopButtonTest.java
test/src/test/java/lib/layout/StopButtonTest.java
+150
-0
test/src/test/resources/lib/form/ExpandableTextboxTest/TestRootAction/index.jelly
...lib/form/ExpandableTextboxTest/TestRootAction/index.jelly
+33
-0
test/src/test/resources/lib/form/ValidateButtonTest/NoInjectionArePossible/index.jelly
...orm/ValidateButtonTest/NoInjectionArePossible/index.jelly
+43
-0
test/src/test/resources/lib/form/ValidateButtonTest/TestValidateIsCalled/index.jelly
.../form/ValidateButtonTest/TestValidateIsCalled/index.jelly
+1
-1
test/src/test/resources/lib/layout/ConfirmationLinkTest/TestRootAction/index.jelly
...ib/layout/ConfirmationLinkTest/TestRootAction/index.jelly
+35
-0
test/src/test/resources/lib/layout/StopButtonTest/TestRootAction/index.jelly
...rces/lib/layout/StopButtonTest/TestRootAction/index.jelly
+33
-0
未找到文件。
core/src/main/java/hudson/cli/CLICommand.java
浏览文件 @
f6a6f0c3
...
...
@@ -264,6 +264,8 @@ public abstract class CLICommand implements ExtensionPoint, Cloneable {
sc
.
setAuthentication
(
getTransportAuthentication
());
new
ClassParser
().
parse
(
authenticator
,
p
);
if
(!(
this
instanceof
LoginCommand
||
this
instanceof
LogoutCommand
||
this
instanceof
HelpCommand
))
Jenkins
.
getActiveInstance
().
checkPermission
(
Jenkins
.
READ
);
p
.
parseArgument
(
args
.
toArray
(
new
String
[
args
.
size
()]));
Authentication
auth
=
authenticator
.
authenticate
();
if
(
auth
==
Jenkins
.
ANONYMOUS
)
...
...
core/src/main/java/hudson/cli/handlers/ViewOptionHandler.java
浏览文件 @
f6a6f0c3
...
...
@@ -103,12 +103,13 @@ public class ViewOptionHandler extends OptionHandler<View> {
String
viewName
=
tok
.
nextToken
();
view
=
group
.
getView
(
viewName
);
if
(
view
==
null
)
if
(
view
==
null
)
{
group
.
checkPermission
(
View
.
READ
);
throw
new
IllegalArgumentException
(
String
.
format
(
"No view named %s inside view %s"
,
viewName
,
group
.
getDisplayName
()
));
}
view
.
checkPermission
(
View
.
READ
);
if
(
view
instanceof
ViewGroup
)
{
group
=
(
ViewGroup
)
view
;
...
...
core/src/main/resources/lib/form/expandableTextbox.jelly
浏览文件 @
f6a6f0c3
...
...
@@ -75,7 +75,7 @@ THE SOFTWARE.
<j:mute>${customizedFields.add(name)}</j:mute>
</j:if>
</td><td width="1">
<input type="button" value="▼" onclick="expandTextArea(this,'textarea.${
name
}')"
<input type="button" value="▼" onclick="expandTextArea(this,'textarea.${
h.jsStringEscape(name)
}')"
tooltip="${%tooltip}"/>
</td>
</tr>
...
...
core/src/main/resources/lib/form/validateButton.jelly
浏览文件 @
f6a6f0c3
...
...
@@ -48,7 +48,7 @@ THE SOFTWARE.
</st:documentation>
<f:entry>
<div style="float:right">
<input type="button" value="${title}" class="yui-button validate-button" onclick="validateButton('${descriptor.descriptorFullUrl}/${
method}','${with
}',this)" />
<input type="button" value="${title}" class="yui-button validate-button" onclick="validateButton('${descriptor.descriptorFullUrl}/${
h.jsStringEscape(method)}','${h.jsStringEscape(with)
}',this)" />
</div>
<div style="display:none;">
<img src="${imagesURL}/spinner.gif" /> ${attrs.progress}
...
...
core/src/main/resources/lib/layout/confirmationLink.jelly
浏览文件 @
f6a6f0c3
...
...
@@ -31,7 +31,7 @@ THE SOFTWARE.
<st:attribute
name=
"href"
use=
"required"
>
The URL to go to.
</st:attribute>
<st:attribute
name=
"post"
>
<st:attribute
name=
"post"
type=
"boolean"
>
Use POST rather than GET (recommended).
</st:attribute>
<st:attribute
name=
"message"
use=
"required"
>
...
...
@@ -42,7 +42,7 @@ THE SOFTWARE.
</st:attribute>
</st:documentation>
<j:set
var=
"id"
value=
"${h.generateId()}"
/>
<a
href=
"#"
class=
"${class}"
onclick=
"confirmPOST_${id}(${post ?
: 'false'}, '${attrs.href
}', '${h.jsStringEscape(message)}')"
><d:invokeBody/></a>
<a
href=
"#"
class=
"${class}"
onclick=
"confirmPOST_${id}(${post ?
'true' : 'false'}, '${h.jsStringEscape(attrs.href)
}', '${h.jsStringEscape(message)}')"
><d:invokeBody/></a>
<script>
function confirmPOST_${id}(post, href, message) {
if (confirm(message)) {
...
...
core/src/main/resources/lib/layout/stopButton.jelly
浏览文件 @
f6a6f0c3
...
...
@@ -39,13 +39,13 @@ THE SOFTWARE.
</st:documentation>
<j:choose>
<j:when
test=
"${confirm == null}"
>
<a
class=
"stop-button-link"
href=
"${href}"
onclick=
'new Ajax.Request("${h
ref
}"); return false;'
>
<l:icon
class=
"icon-stop icon-sm"
/>
<a
class=
"stop-button-link"
href=
"${href}"
onclick=
'new Ajax.Request("${h
.jsStringEscape(href)
}"); return false;'
>
<l:icon
class=
"icon-stop icon-sm"
alt=
"${alt}"
/>
</a>
</j:when>
<j:otherwise>
<a
class=
"stop-button-link"
href=
"${href}"
onclick=
'if(confirm("${
confirm}"))new Ajax.Request("${href
}"); return false;'
>
<l:icon
class=
"icon-stop icon-sm"
/>
<a
class=
"stop-button-link"
href=
"${href}"
onclick=
'if(confirm("${
h.jsStringEscape(confirm)}"))new Ajax.Request("${h.jsStringEscape(href)
}"); return false;'
>
<l:icon
class=
"icon-stop icon-sm"
alt=
"${alt}"
/>
</a>
</j:otherwise>
</j:choose>
...
...
core/src/test/java/hudson/cli/handlers/ViewOptionHandlerTest.java
浏览文件 @
f6a6f0c3
...
...
@@ -31,10 +31,12 @@ import static org.mockito.Mockito.verifyZeroInteractions;
import
static
org
.
mockito
.
Mockito
.
when
;
import
hudson.model.ViewGroup
;
import
hudson.model.View
;
import
hudson.security.ACL
;
import
hudson.security.Permission
;
import
jenkins.model.Jenkins
;
import
org.acegisecurity.AccessDeniedException
;
import
org.acegisecurity.Authentication
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
...
...
@@ -83,6 +85,12 @@ public class ViewOptionHandlerTest {
PowerMockito
.
when
(
Jenkins
.
getActiveInstance
()).
thenReturn
(
jenkins
);
when
(
jenkins
.
getView
(
"outer"
)).
thenReturn
(
outer
);
when
(
jenkins
.
getDisplayName
()).
thenReturn
(
"Jenkins"
);
when
(
jenkins
.
getACL
()).
thenReturn
(
new
ACL
()
{
@Override
public
boolean
hasPermission
(
Authentication
a
,
Permission
p
)
{
return
true
;
}
});
}
@Test
public
void
resolveTopLevelView
()
throws
Exception
{
...
...
test/src/test/java/hudson/cli/CLIActionTest.java
浏览文件 @
f6a6f0c3
...
...
@@ -4,6 +4,7 @@ import com.google.common.collect.Lists;
import
hudson.Functions
;
import
hudson.Launcher
;
import
hudson.Proc
;
import
hudson.model.AllView
;
import
hudson.model.Item
;
import
hudson.model.User
;
import
hudson.remoting.Channel
;
...
...
@@ -134,17 +135,17 @@ public class CLIActionTest {
j
.
jenkins
.
setAuthorizationStrategy
(
new
MockAuthorizationStrategy
().
grant
(
Jenkins
.
ADMINISTER
).
everywhere
().
to
(
ADMIN
));
j
.
createFreeStyleProject
(
"p"
);
// CLICommand with @Argument:
assertExitCode
(
3
,
false
,
jar
,
"-remoting"
,
"get-job"
,
"p"
);
// IllegalArgumentException from GenericItemOptionHandler
assertExitCode
(
3
,
false
,
jar
,
"get-job"
,
"p"
);
// ditto under new protocol
assertExitCode
(
3
,
false
,
jar
,
"-remoting"
,
"get-job"
,
"--username"
,
ADMIN
,
"--password"
,
ADMIN
,
"p"
);
//
JENKINS-12543: too late
assertExitCode
(
3
,
false
,
jar
,
"get-job"
,
"--username"
,
ADMIN
,
"--password"
,
ADMIN
,
"p"
);
// same
assertExitCode
(
6
,
false
,
jar
,
"-remoting"
,
"get-job"
,
"p"
);
// SECURITY-754 requires Overall/Read for nearly all CLICommands.
assertExitCode
(
6
,
false
,
jar
,
"get-job"
,
"p"
);
// ditto under new protocol
assertExitCode
(
6
,
false
,
jar
,
"-remoting"
,
"get-job"
,
"--username"
,
ADMIN
,
"--password"
,
ADMIN
,
"p"
);
// SECURITY-754 and
JENKINS-12543: too late
assertExitCode
(
6
,
false
,
jar
,
"get-job"
,
"--username"
,
ADMIN
,
"--password"
,
ADMIN
,
"p"
);
// same
assertExitCode
(
0
,
false
,
jar
,
"-remoting"
,
"login"
,
"--username"
,
ADMIN
,
"--password"
,
ADMIN
);
try
{
assertExitCode
(
3
,
false
,
jar
,
"-remoting"
,
"get-job"
,
"p"
);
//
ClientAuthenticationCache also used too late
assertExitCode
(
6
,
false
,
jar
,
"-remoting"
,
"get-job"
,
"p"
);
// SECURITY-754:
ClientAuthenticationCache also used too late
}
finally
{
assertExitCode
(
0
,
false
,
jar
,
"-remoting"
,
"logout"
);
}
assertExitCode
(
3
,
true
,
jar
,
"-remoting"
,
"get-job"
,
"p"
);
//
does not work with API tokens
assertExitCode
(
6
,
true
,
jar
,
"-remoting"
,
"get-job"
,
"p"
);
// SECURITY-754:
does not work with API tokens
assertExitCode
(
0
,
true
,
jar
,
"get-job"
,
"p"
);
// but does under new protocol
// @CLIMethod:
assertExitCode
(
6
,
false
,
jar
,
"-remoting"
,
"disable-job"
,
"p"
);
// AccessDeniedException from CLIRegisterer?
...
...
@@ -269,6 +270,31 @@ public class CLIActionTest {
assertEquals
(
0
,
proc
.
join
());
}
@Issue
(
"SECURITY-754"
)
@Test
public
void
noPreAuthOptionHandlerInfoLeak
()
throws
Exception
{
File
jar
=
tmp
.
newFile
(
"jenkins-cli.jar"
);
FileUtils
.
copyURLToFile
(
j
.
jenkins
.
getJnlpJars
(
"jenkins-cli.jar"
).
getURL
(),
jar
);
j
.
jenkins
.
setSecurityRealm
(
j
.
createDummySecurityRealm
());
j
.
jenkins
.
addView
(
new
AllView
(
"v1"
));
j
.
jenkins
.
addNode
(
j
.
createSlave
(
"n1"
,
null
,
null
));
j
.
jenkins
.
setAuthorizationStrategy
(
new
MockAuthorizationStrategy
().
grant
(
Jenkins
.
ADMINISTER
).
everywhere
().
to
(
ADMIN
));
// No anonymous read access
assertExitCode
(
6
,
false
,
jar
,
"get-view"
,
"v1"
);
assertExitCode
(
6
,
false
,
jar
,
"get-view"
,
"v2"
);
// Error code 3 before SECURITY-754
assertExitCode
(
6
,
false
,
jar
,
"get-node"
,
"n1"
);
assertExitCode
(
6
,
false
,
jar
,
"get-node"
,
"n2"
);
// Error code 3 before SECURITY-754
// Authenticated with no read access
assertExitCode
(
6
,
false
,
jar
,
"-auth"
,
"user:user"
,
"get-view"
,
"v1"
);
assertExitCode
(
6
,
false
,
jar
,
"-auth"
,
"user:user"
,
"get-view"
,
"v2"
);
// Error code 3 before SECURITY-754
assertExitCode
(
6
,
false
,
jar
,
"-auth"
,
"user:user"
,
"get-node"
,
"n1"
);
assertExitCode
(
6
,
false
,
jar
,
"-auth"
,
"user:user"
,
"get-node"
,
"n2"
);
// Error code 3 before SECURITY-754
// Anonymous read access
j
.
jenkins
.
setAuthorizationStrategy
(
new
MockAuthorizationStrategy
().
grant
(
Jenkins
.
ADMINISTER
).
everywhere
().
to
(
ADMIN
).
grant
(
Jenkins
.
READ
,
Item
.
READ
).
everywhere
().
toEveryone
());
assertExitCode
(
6
,
false
,
jar
,
"get-view"
,
"v1"
);
assertExitCode
(
6
,
false
,
jar
,
"get-view"
,
"v2"
);
// Error code 3 before SECURITY-754
}
@TestExtension
(
"encodingAndLocale"
)
public
static
class
TestDiagnosticCommand
extends
CLICommand
{
...
...
test/src/test/java/lib/form/ExpandableTextboxTest.java
浏览文件 @
f6a6f0c3
...
...
@@ -24,39 +24,130 @@
package
lib.form
;
import
static
com
.
gargoylesoftware
.
htmlunit
.
HttpMethod
.
POST
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertNotEquals
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
com.gargoylesoftware.htmlunit.Page
;
import
com.gargoylesoftware.htmlunit.WebRequest
;
import
com.gargoylesoftware.htmlunit.html.DomNodeList
;
import
com.gargoylesoftware.htmlunit.html.HtmlAnchor
;
import
com.gargoylesoftware.htmlunit.html.HtmlButton
;
import
com.gargoylesoftware.htmlunit.html.HtmlButtonInput
;
import
com.gargoylesoftware.htmlunit.html.HtmlElement
;
import
com.gargoylesoftware.htmlunit.html.HtmlElementUtil
;
import
com.gargoylesoftware.htmlunit.html.HtmlPage
;
import
hudson.model.UnprotectedRootAction
;
import
hudson.util.HttpResponses
;
import
lib.layout.ConfirmationLinkTest
;
import
org.junit.Assert
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.jvnet.hudson.test.Issue
;
import
org.jvnet.hudson.test.HudsonTestCase
;
import
org.jvnet.hudson.test.JenkinsRule
;
import
org.jvnet.hudson.test.TestExtension
;
import
org.kohsuke.stapler.HttpResponse
;
import
org.kohsuke.stapler.StaplerRequest
;
import
org.kohsuke.stapler.WebMethod
;
import
org.w3c.dom.NodeList
;
import
javax.annotation.CheckForNull
;
/**
* @author Kohsuke Kawaguchi
*/
public
class
ExpandableTextboxTest
extends
HudsonTestCase
{
public
class
ExpandableTextboxTest
{
@Rule
public
JenkinsRule
j
=
new
JenkinsRule
();
@Issue
(
"JENKINS-2816"
)
@Test
public
void
testMultiline
()
throws
Exception
{
// because attribute values are normalized, it's not very easy to encode multi-line string as @value. So let's use the system message here.
jenkins
.
setSystemMessage
(
"foo\nbar\nzot"
);
j
.
j
enkins
.
setSystemMessage
(
"foo\nbar\nzot"
);
HtmlPage
page
=
evaluateAsHtml
(
"<l:layout><l:main-panel><table><j:set var='instance' value='${it}'/><f:expandableTextbox field='systemMessage' /></table></l:main-panel></l:layout>"
);
// System.out.println(page.getWebResponse().getContentAsString());
NodeList
textareas
=
page
.
getElementsByTagName
(
"textarea"
);
assertEquals
(
1
,
textareas
.
getLength
());
assertEquals
(
jenkins
.
getSystemMessage
(),
textareas
.
item
(
0
).
getTextContent
());
assertEquals
(
j
.
j
enkins
.
getSystemMessage
(),
textareas
.
item
(
0
).
getTextContent
());
}
/**
* Evaluates the literal Jelly script passed as a parameter as HTML and returns the page.
*/
protected
HtmlPage
evaluateAsHtml
(
String
jellyScript
)
throws
Exception
{
HudsonTestCase
.
WebClient
wc
=
new
WebClient
();
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
WebRequest
req
=
new
WebRequest
(
wc
.
createCrumbedUrl
(
"eval"
),
POST
);
req
.
setEncodingType
(
null
);
req
.
setRequestBody
(
"<j:jelly xmlns:j='jelly:core' xmlns:st='jelly:stapler' xmlns:l='/lib/layout' xmlns:f='/lib/form'>"
+
jellyScript
+
"</j:jelly>"
);
Page
page
=
wc
.
getPage
(
req
);
return
(
HtmlPage
)
page
;
}
@Test
public
void
noInjectionArePossible
()
throws
Exception
{
TestRootAction
testParams
=
j
.
jenkins
.
getExtensionList
(
UnprotectedRootAction
.
class
).
get
(
TestRootAction
.
class
);
assertNotNull
(
testParams
);
checkRegularCase
(
testParams
);
checkInjectionInName
(
testParams
);
}
private
void
checkRegularCase
(
TestRootAction
testParams
)
throws
Exception
{
testParams
.
paramName
=
"testName"
;
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
wc
.
getOptions
().
setThrowExceptionOnFailingStatusCode
(
false
);
HtmlPage
p
=
wc
.
goTo
(
"test"
);
HtmlElementUtil
.
click
(
getExpandButton
(
p
));
assertNotEquals
(
"hacked"
,
p
.
getTitleText
());
}
private
void
checkInjectionInName
(
TestRootAction
testParams
)
throws
Exception
{
testParams
.
paramName
=
"testName',document.title='hacked'+'"
;
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
wc
.
getOptions
().
setThrowExceptionOnFailingStatusCode
(
false
);
HtmlPage
p
=
wc
.
goTo
(
"test"
);
HtmlElementUtil
.
click
(
getExpandButton
(
p
));
assertNotEquals
(
"hacked"
,
p
.
getTitleText
());
}
private
HtmlButtonInput
getExpandButton
(
HtmlPage
page
){
DomNodeList
<
HtmlElement
>
buttons
=
page
.
getElementById
(
"test-panel"
).
getElementsByTagName
(
"input"
);
// the first one is the text input
assertEquals
(
2
,
buttons
.
size
());
return
(
HtmlButtonInput
)
buttons
.
get
(
1
);
}
@TestExtension
(
"noInjectionArePossible"
)
public
static
final
class
TestRootAction
implements
UnprotectedRootAction
{
public
String
paramName
;
@Override
public
@CheckForNull
String
getIconFileName
()
{
return
null
;
}
@Override
public
@CheckForNull
String
getDisplayName
()
{
return
null
;
}
@Override
public
String
getUrlName
()
{
return
"test"
;
}
@WebMethod
(
name
=
"submit"
)
public
HttpResponse
doSubmit
(
StaplerRequest
request
)
{
return
HttpResponses
.
plainText
(
"method:"
+
request
.
getMethod
());
}
}
}
test/src/test/java/lib/form/ValidateButtonTest.java
浏览文件 @
f6a6f0c3
...
...
@@ -23,53 +23,185 @@
*/
package
lib.form
;
import
com.gargoylesoftware.htmlunit.html.DomNodeList
;
import
com.gargoylesoftware.htmlunit.html.HtmlButton
;
import
com.gargoylesoftware.htmlunit.html.HtmlElement
;
import
com.gargoylesoftware.htmlunit.html.HtmlElementUtil
;
import
com.gargoylesoftware.htmlunit.html.HtmlFormUtil
;
import
org.jvnet.hudson.test.HudsonTestCase
;
import
hudson.model.UnprotectedRootAction
;
import
jenkins.model.Jenkins
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.jvnet.hudson.test.JenkinsRule
;
import
org.jvnet.hudson.test.TestExtension
;
import
org.kohsuke.stapler.QueryParameter
;
import
hudson.model.Describable
;
import
hudson.model.Descriptor
;
import
hudson.Extension
;
import
com.gargoylesoftware.htmlunit.html.HtmlPage
;
import
org.kohsuke.stapler.StaplerRequest
;
import
javax.annotation.CheckForNull
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertNotEquals
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
junit
.
Assert
.
assertFalse
;
/**
*
*
* @author Kohsuke Kawaguchi
*/
public
class
ValidateButtonTest
extends
HudsonTestCase
implements
Describable
<
ValidateButtonTest
>
{
public
class
ValidateButtonTest
{
@Rule
public
JenkinsRule
j
=
new
JenkinsRule
();
public
void
test1
()
throws
Exception
{
DescriptorImpl
d
=
getDescriptor
();
@Test
public
void
testValidateIsCalled
()
throws
Exception
{
TestValidateIsCalled
.
DescriptorImpl
d
=
j
.
jenkins
.
getDescriptorByType
(
TestValidateIsCalled
.
DescriptorImpl
.
class
);
assertNotNull
(
d
);
d
.
test1Outcome
=
new
Exception
();
// if doValidateTest1() doesn't get invoked, we want to know.
HtmlPage
p
=
createWebClient
().
goTo
(
"self/test1
"
);
HtmlPage
p
=
j
.
createWebClient
().
goTo
(
"test
"
);
HtmlButton
button
=
HtmlFormUtil
.
getButtonByCaption
(
p
.
getFormByName
(
"config"
),
"test"
);
HtmlElementUtil
.
click
(
button
);
if
(
d
.
test1Outcome
!=
null
)
throw
d
.
test1Outcome
;
}
public
DescriptorImpl
getDescriptor
()
{
return
jenkins
.
getDescriptorByType
(
DescriptorImpl
.
class
);
@TestExtension
(
"testValidateIsCalled"
)
public
static
final
class
TestValidateIsCalled
implements
Describable
<
TestValidateIsCalled
>,
UnprotectedRootAction
{
@Override
public
@CheckForNull
String
getIconFileName
()
{
return
null
;
}
@Override
public
@CheckForNull
String
getDisplayName
()
{
return
null
;
}
@Override
public
String
getUrlName
()
{
return
"test"
;
}
public
DescriptorImpl
getDescriptor
()
{
return
Jenkins
.
getInstance
().
getDescriptorByType
(
DescriptorImpl
.
class
);
}
@Extension
public
static
final
class
DescriptorImpl
extends
Descriptor
<
TestValidateIsCalled
>
{
private
Exception
test1Outcome
;
public
void
doValidateTest1
(
@QueryParameter
(
"a"
)
String
a
,
@QueryParameter
(
"b"
)
boolean
b
,
@QueryParameter
(
"c"
)
boolean
c
,
@QueryParameter
(
"d"
)
String
d
,
@QueryParameter
(
"e"
)
String
e
)
{
try
{
assertEquals
(
"avalue"
,
a
);
assertTrue
(
b
);
assertFalse
(
c
);
assertEquals
(
"dvalue"
,
d
);
assertEquals
(
"e2"
,
e
);
test1Outcome
=
null
;
}
catch
(
Exception
t
)
{
test1Outcome
=
t
;
}
}
}
}
@Extension
public
static
final
class
DescriptorImpl
extends
Descriptor
<
ValidateButtonTest
>
{
private
Exception
test1Outcome
;
public
void
doValidateTest1
(
@QueryParameter
(
"a"
)
String
a
,
@QueryParameter
(
"b"
)
boolean
b
,
@QueryParameter
(
"c"
)
boolean
c
,
@QueryParameter
(
"d"
)
String
d
,
@QueryParameter
(
"e"
)
String
e
)
{
try
{
assertEquals
(
"avalue"
,
a
);
assertTrue
(
b
);
assertFalse
(
c
);
assertEquals
(
"dvalue"
,
d
);
assertEquals
(
"e2"
,
e
);
test1Outcome
=
null
;
}
catch
(
Exception
t
)
{
test1Outcome
=
t
;
@Test
public
void
noInjectionArePossible
()
throws
Exception
{
NoInjectionArePossible
.
DescriptorImpl
d
=
j
.
jenkins
.
getDescriptorByType
(
NoInjectionArePossible
.
DescriptorImpl
.
class
);
assertNotNull
(
d
);
checkRegularCase
(
d
);
checkInjectionInMethod
(
d
);
checkInjectionInWith
(
d
);
}
private
void
checkRegularCase
(
NoInjectionArePossible
.
DescriptorImpl
descriptor
)
throws
Exception
{
descriptor
.
paramMethod
=
"validateInjection"
;
descriptor
.
paramWith
=
"a,b"
;
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
wc
.
getOptions
().
setThrowExceptionOnFailingStatusCode
(
false
);
HtmlPage
p
=
wc
.
goTo
(
"test"
);
descriptor
.
wasCalled
=
false
;
HtmlElementUtil
.
click
(
getValidateButton
(
p
));
assertNotEquals
(
"hacked"
,
p
.
getTitleText
());
assertTrue
(
descriptor
.
wasCalled
);
}
private
void
checkInjectionInMethod
(
NoInjectionArePossible
.
DescriptorImpl
descriptor
)
throws
Exception
{
descriptor
.
paramMethod
=
"validateInjection',document.title='hacked'+'"
;
descriptor
.
paramWith
=
"a,b"
;
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
wc
.
getOptions
().
setThrowExceptionOnFailingStatusCode
(
false
);
HtmlPage
p
=
wc
.
goTo
(
"test"
);
// no check on wasCalled because the button that is expected by the method is not passed (arguments are shifted due to the injection)
HtmlElementUtil
.
click
(
getValidateButton
(
p
));
assertNotEquals
(
"hacked"
,
p
.
getTitleText
());
}
private
void
checkInjectionInWith
(
NoInjectionArePossible
.
DescriptorImpl
descriptor
)
throws
Exception
{
descriptor
.
paramMethod
=
"validateInjection"
;
descriptor
.
paramWith
=
"a,b',document.title='hacked'+'"
;
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
wc
.
getOptions
().
setThrowExceptionOnFailingStatusCode
(
false
);
HtmlPage
p
=
wc
.
goTo
(
"test"
);
descriptor
.
wasCalled
=
false
;
HtmlElementUtil
.
click
(
getValidateButton
(
p
));
assertNotEquals
(
"hacked"
,
p
.
getTitleText
());
assertTrue
(
descriptor
.
wasCalled
);
}
private
HtmlButton
getValidateButton
(
HtmlPage
page
){
DomNodeList
<
HtmlElement
>
buttons
=
page
.
getElementById
(
"test-panel"
).
getElementsByTagName
(
"button"
);
assertEquals
(
1
,
buttons
.
size
());
return
(
HtmlButton
)
buttons
.
get
(
0
);
}
@TestExtension
(
"noInjectionArePossible"
)
public
static
final
class
NoInjectionArePossible
implements
Describable
<
NoInjectionArePossible
>,
UnprotectedRootAction
{
@Override
public
@CheckForNull
String
getIconFileName
()
{
return
null
;
}
@Override
public
@CheckForNull
String
getDisplayName
()
{
return
null
;
}
@Override
public
String
getUrlName
()
{
return
"test"
;
}
public
DescriptorImpl
getDescriptor
()
{
return
Jenkins
.
getInstance
().
getDescriptorByType
(
DescriptorImpl
.
class
);
}
@Extension
public
static
final
class
DescriptorImpl
extends
Descriptor
<
NoInjectionArePossible
>
{
private
boolean
wasCalled
=
false
;
public
String
paramMethod
=
"validateInjection"
;
public
String
paramWith
=
null
;
public
void
doValidateInjection
(
StaplerRequest
request
)
{
wasCalled
=
true
;
}
}
}
...
...
test/src/test/java/lib/layout/ConfirmationLinkTest.java
0 → 100644
浏览文件 @
f6a6f0c3
/*
* The MIT License
*
* Copyright (c) 2018, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
lib.layout
;
import
com.gargoylesoftware.htmlunit.Page
;
import
com.gargoylesoftware.htmlunit.html.DomNodeList
;
import
com.gargoylesoftware.htmlunit.html.HtmlAnchor
;
import
com.gargoylesoftware.htmlunit.html.HtmlElement
;
import
com.gargoylesoftware.htmlunit.html.HtmlElementUtil
;
import
com.gargoylesoftware.htmlunit.html.HtmlPage
;
import
hudson.model.UnprotectedRootAction
;
import
hudson.util.HttpResponses
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.jvnet.hudson.test.JenkinsRule
;
import
org.jvnet.hudson.test.TestExtension
;
import
org.kohsuke.stapler.HttpResponse
;
import
org.kohsuke.stapler.StaplerRequest
;
import
org.kohsuke.stapler.WebMethod
;
import
javax.annotation.CheckForNull
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertNotEquals
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
public
class
ConfirmationLinkTest
{
@Rule
public
JenkinsRule
j
=
new
JenkinsRule
();
private
static
final
String
hrefPayload
=
"',document.title='hacked'+'"
;
private
static
final
String
messagePayload
=
"',document.title='hacked'+'"
;
private
static
final
String
postPayload
=
"document.title='hacked'"
;
@Test
public
void
noInjectionArePossible
()
throws
Exception
{
TestRootAction
testParams
=
j
.
jenkins
.
getExtensionList
(
UnprotectedRootAction
.
class
).
get
(
TestRootAction
.
class
);
assertNotNull
(
testParams
);
checkRegularCase
(
testParams
);
checkRegularCasePost
(
testParams
);
checkInjectionInHref
(
testParams
);
checkInjectionInMessage
(
testParams
);
checkInjectionInPost
(
testParams
);
}
private
void
checkRegularCase
(
TestRootAction
testParams
)
throws
Exception
{
testParams
.
paramHref
=
"#"
;
testParams
.
paramMessage
=
"Message to confirm the click"
;
testParams
.
paramClass
=
null
;
testParams
.
paramPost
=
null
;
HtmlPage
p
=
j
.
createWebClient
().
goTo
(
"test"
);
assertTrue
(
p
.
getWebResponse
().
getContentAsString
().
contains
(
"Message to confirm the click"
));
}
private
void
checkRegularCasePost
(
TestRootAction
testParams
)
throws
Exception
{
testParams
.
paramHref
=
"submit"
;
testParams
.
paramMessage
=
"Message to confirm the click"
;
testParams
.
paramClass
=
null
;
testParams
.
paramPost
=
true
;
assertMethodPostAfterClick
();
testParams
.
paramPost
=
"true"
;
assertMethodPostAfterClick
();
testParams
.
paramPost
=
"TruE"
;
assertMethodPostAfterClick
();
testParams
.
paramPost
=
false
;
assertMethodGetAfterClick
();
testParams
.
paramPost
=
"false"
;
assertMethodGetAfterClick
();
testParams
.
paramPost
=
"any other string"
;
assertMethodGetAfterClick
();
}
private
void
assertMethodGetAfterClick
()
throws
Exception
{
Page
pageAfterClick
=
getPageAfterClick
();
assertTrue
(
pageAfterClick
.
getWebResponse
().
getContentAsString
().
contains
(
"method:GET"
));
}
private
void
assertMethodPostAfterClick
()
throws
Exception
{
Page
pageAfterClick
=
getPageAfterClick
();
assertTrue
(
pageAfterClick
.
getWebResponse
().
getContentAsString
().
contains
(
"method:POST"
));
}
private
Page
getPageAfterClick
()
throws
Exception
{
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
wc
.
getOptions
().
setThrowExceptionOnFailingStatusCode
(
false
);
HtmlPage
p
=
wc
.
goTo
(
"test"
);
return
HtmlElementUtil
.
click
(
getClickableLink
(
p
));
}
private
void
checkInjectionInHref
(
TestRootAction
testParams
)
throws
Exception
{
testParams
.
paramHref
=
hrefPayload
;
testParams
.
paramMessage
=
"Message to confirm the click"
;
testParams
.
paramClass
=
null
;
testParams
.
paramPost
=
null
;
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
wc
.
getOptions
().
setThrowExceptionOnFailingStatusCode
(
false
);
HtmlPage
p
=
wc
.
goTo
(
"test"
);
Page
pageAfterClick
=
HtmlElementUtil
.
click
(
getClickableLink
(
p
));
assertNotEquals
(
"hacked"
,
p
.
getTitleText
());
assertTrue
(
p
.
getWebResponse
().
getContentAsString
().
contains
(
"Message to confirm the click"
));
// the url it clicks on is escaped and so does not exist
assertEquals
(
404
,
pageAfterClick
.
getWebResponse
().
getStatusCode
());
}
private
void
checkInjectionInMessage
(
TestRootAction
testParams
)
throws
Exception
{
testParams
.
paramHref
=
"#"
;
testParams
.
paramMessage
=
messagePayload
;
testParams
.
paramClass
=
null
;
testParams
.
paramPost
=
null
;
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
wc
.
getOptions
().
setThrowExceptionOnFailingStatusCode
(
false
);
HtmlPage
p
=
wc
.
goTo
(
"test"
);
Page
pageAfterClick
=
HtmlElementUtil
.
click
(
getClickableLink
(
p
));
assertNotEquals
(
"hacked"
,
p
.
getTitleText
());
// the url is normally the same page so it's ok
assertEquals
(
200
,
pageAfterClick
.
getWebResponse
().
getStatusCode
());
}
private
void
checkInjectionInPost
(
TestRootAction
testParams
)
throws
Exception
{
testParams
.
paramHref
=
"#"
;
testParams
.
paramMessage
=
"Message to confirm the click"
;
testParams
.
paramClass
=
null
;
testParams
.
paramPost
=
postPayload
;
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
wc
.
getOptions
().
setThrowExceptionOnFailingStatusCode
(
false
);
HtmlPage
p
=
wc
.
goTo
(
"test"
);
Page
pageAfterClick
=
HtmlElementUtil
.
click
(
getClickableLink
(
p
));
assertNotEquals
(
"hacked"
,
p
.
getTitleText
());
assertTrue
(
p
.
getWebResponse
().
getContentAsString
().
contains
(
"Message to confirm the click"
));
// the url is normally the same page so it's ok
assertEquals
(
200
,
pageAfterClick
.
getWebResponse
().
getStatusCode
());
}
private
HtmlAnchor
getClickableLink
(
HtmlPage
page
){
DomNodeList
<
HtmlElement
>
anchors
=
page
.
getElementById
(
"test-panel"
).
getElementsByTagName
(
"a"
);
assertEquals
(
1
,
anchors
.
size
());
return
(
HtmlAnchor
)
anchors
.
get
(
0
);
}
@TestExtension
(
"noInjectionArePossible"
)
public
static
final
class
TestRootAction
implements
UnprotectedRootAction
{
public
String
paramHref
=
""
;
public
String
paramMessage
=
""
;
public
String
paramClass
;
public
Object
paramPost
;
@Override
public
@CheckForNull
String
getIconFileName
()
{
return
null
;
}
@Override
public
@CheckForNull
String
getDisplayName
()
{
return
null
;
}
@Override
public
String
getUrlName
()
{
return
"test"
;
}
@WebMethod
(
name
=
"submit"
)
public
HttpResponse
doSubmit
(
StaplerRequest
request
)
{
return
HttpResponses
.
plainText
(
"method:"
+
request
.
getMethod
());
}
}
}
test/src/test/java/lib/layout/StopButtonTest.java
0 → 100644
浏览文件 @
f6a6f0c3
/*
* The MIT License
*
* Copyright (c) 2018, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
lib.layout
;
import
com.gargoylesoftware.htmlunit.html.DomNodeList
;
import
com.gargoylesoftware.htmlunit.html.HtmlAnchor
;
import
com.gargoylesoftware.htmlunit.html.HtmlElement
;
import
com.gargoylesoftware.htmlunit.html.HtmlElementUtil
;
import
com.gargoylesoftware.htmlunit.html.HtmlPage
;
import
hudson.model.UnprotectedRootAction
;
import
hudson.util.HttpResponses
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.jvnet.hudson.test.JenkinsRule
;
import
org.jvnet.hudson.test.TestExtension
;
import
org.kohsuke.stapler.HttpResponse
;
import
org.kohsuke.stapler.StaplerRequest
;
import
org.kohsuke.stapler.WebMethod
;
import
javax.annotation.CheckForNull
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertNotEquals
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
public
class
StopButtonTest
{
@Rule
public
JenkinsRule
j
=
new
JenkinsRule
();
private
static
final
String
hrefPayload
=
"\",document.title='hacked',\""
;
private
static
final
String
postPayload
=
"\",document.title='hacked',\""
;
@Test
public
void
noInjectionArePossible
()
throws
Exception
{
TestRootAction
testParams
=
j
.
jenkins
.
getExtensionList
(
UnprotectedRootAction
.
class
).
get
(
TestRootAction
.
class
);
assertNotNull
(
testParams
);
checkRegularCase
(
testParams
);
checkInjectionInHref
(
testParams
);
checkInjectionInHrefWithConfirm
(
testParams
);
checkInjectionInConfirm
(
testParams
);
}
private
void
checkRegularCase
(
TestRootAction
testParams
)
throws
Exception
{
testParams
.
paramHref
=
"#"
;
testParams
.
paramAlt
=
"Message to confirm the click"
;
testParams
.
paramConfirm
=
null
;
HtmlPage
p
=
j
.
createWebClient
().
goTo
(
"test"
);
assertTrue
(
p
.
getWebResponse
().
getContentAsString
().
contains
(
"Message to confirm the click"
));
}
private
void
checkInjectionInHref
(
TestRootAction
testParams
)
throws
Exception
{
testParams
.
paramHref
=
hrefPayload
;
testParams
.
paramAlt
=
"Alternative text for icon"
;
testParams
.
paramConfirm
=
null
;
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
wc
.
getOptions
().
setThrowExceptionOnFailingStatusCode
(
false
);
HtmlPage
p
=
wc
.
goTo
(
"test"
);
HtmlElementUtil
.
click
(
getStopLink
(
p
));
assertNotEquals
(
"hacked"
,
p
.
getTitleText
());
assertTrue
(
p
.
getWebResponse
().
getContentAsString
().
contains
(
"Alternative text for icon"
));
}
private
void
checkInjectionInHrefWithConfirm
(
TestRootAction
testParams
)
throws
Exception
{
testParams
.
paramHref
=
hrefPayload
;
testParams
.
paramAlt
=
"Alternative text for icon"
;
testParams
.
paramConfirm
=
"Confirm message"
;
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
wc
.
getOptions
().
setThrowExceptionOnFailingStatusCode
(
false
);
HtmlPage
p
=
wc
.
goTo
(
"test"
);
HtmlElementUtil
.
click
(
getStopLink
(
p
));
assertNotEquals
(
"hacked"
,
p
.
getTitleText
());
assertTrue
(
p
.
getWebResponse
().
getContentAsString
().
contains
(
"Alternative text for icon"
));
}
private
void
checkInjectionInConfirm
(
TestRootAction
testParams
)
throws
Exception
{
testParams
.
paramHref
=
"#"
;
testParams
.
paramAlt
=
"Alternative text for icon"
;
testParams
.
paramConfirm
=
postPayload
;
JenkinsRule
.
WebClient
wc
=
j
.
createWebClient
();
wc
.
getOptions
().
setThrowExceptionOnFailingStatusCode
(
false
);
HtmlPage
p
=
wc
.
goTo
(
"test"
);
HtmlElementUtil
.
click
(
getStopLink
(
p
));
assertNotEquals
(
"hacked"
,
p
.
getTitleText
());
assertTrue
(
p
.
getWebResponse
().
getContentAsString
().
contains
(
"Alternative text for icon"
));
}
private
HtmlAnchor
getStopLink
(
HtmlPage
page
){
DomNodeList
<
HtmlElement
>
anchors
=
page
.
getElementById
(
"test-panel"
).
getElementsByTagName
(
"a"
);
assertEquals
(
1
,
anchors
.
size
());
return
(
HtmlAnchor
)
anchors
.
get
(
0
);
}
@TestExtension
(
"noInjectionArePossible"
)
public
static
class
TestRootAction
implements
UnprotectedRootAction
{
public
String
paramHref
=
""
;
public
String
paramAlt
=
""
;
public
String
paramConfirm
;
@Override
public
@CheckForNull
String
getIconFileName
()
{
return
null
;
}
@Override
public
@CheckForNull
String
getDisplayName
()
{
return
null
;
}
@Override
public
@CheckForNull
String
getUrlName
()
{
return
"test"
;
}
@WebMethod
(
name
=
"submit"
)
public
HttpResponse
doSubmit
(
StaplerRequest
request
)
{
return
HttpResponses
.
plainText
(
"method:"
+
request
.
getMethod
());
}
}
}
test/src/test/resources/lib/form/ExpandableTextboxTest/TestRootAction/index.jelly
0 → 100644
浏览文件 @
f6a6f0c3
<!--
The MIT License
Copyright (c) 2018, CloudBees, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:l="/lib/layout">
<l:layout title="Try to inject javascript inside confirmationLink">
<l:main-panel>
<div id="test-panel">
<f:expandableTextbox name="${it.paramName}" />
</div>
</l:main-panel>
</l:layout>
</j:jelly>
\ No newline at end of file
test/src/test/resources/lib/form/ValidateButtonTest/NoInjectionArePossible/index.jelly
0 → 100644
浏览文件 @
f6a6f0c3
<!--
The MIT License
Copyright (c) 2018, CloudBees, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout" xmlns:f="/lib/form">
<l:layout title="Try to inject javascript inside validateButton">
<l:main-panel>
<div id="test-panel">
<f:form method="post" name="config" action="thisFormWillNotBeSubmitted">
<!--<j:set var="instance" value="${it}" />-->
<j:set var="descriptor" value="${it.descriptor}" />
<f:entry title="a title">
<f:textbox name="a" value="avalue" />
</f:entry>
<f:entry title="b title">
<f:textbox name="b" value="bvalue" />
</f:entry>
<f:validateButton title="test" method="${descriptor.paramMethod}" with="${descriptor.paramWith}" />
</f:form>
</div>
</l:main-panel>
</l:layout>
</j:jelly>
\ No newline at end of file
test/src/test/resources/lib/form/ValidateButtonTest/
test1
.jelly
→
test/src/test/resources/lib/form/ValidateButtonTest/
TestValidateIsCalled/index
.jelly
浏览文件 @
f6a6f0c3
...
...
@@ -26,7 +26,7 @@ THE SOFTWARE.
Config page
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:
st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson
" xmlns:f="/lib/form">
<j:jelly xmlns:j="jelly:core" xmlns:
l="/lib/layout
" xmlns:f="/lib/form">
<l:layout title="Testing the effect of validateButton">
<l:main-panel>
<f:form method="post" name="config" action="thisFormWillNotBeSubmitted">
...
...
test/src/test/resources/lib/layout/ConfirmationLinkTest/TestRootAction/index.jelly
0 → 100644
浏览文件 @
f6a6f0c3
<!--
The MIT License
Copyright (c) 2018, CloudBees, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout">
<l:layout title="Try to inject javascript inside confirmationLink">
<l:main-panel>
<div id="test-panel">
<l:confirmationLink href="${it.paramHref}" message="${it.paramMessage}" class="${it.paramClass}" post="${it.paramPost}">
link name
</l:confirmationLink>
</div>
</l:main-panel>
</l:layout>
</j:jelly>
\ No newline at end of file
test/src/test/resources/lib/layout/StopButtonTest/TestRootAction/index.jelly
0 → 100644
浏览文件 @
f6a6f0c3
<!--
The MIT License
Copyright (c) 2018, CloudBees, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:l="/lib/layout">
<l:layout title="Try to inject javascript inside stopButton">
<l:main-panel>
<div id="test-panel">
<l:stopButton href="${it.paramHref}" alt="${it.paramAlt}" confirm="${it.paramConfirm}" />
</div>
</l:main-panel>
</l:layout>
</j:jelly>
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录