diff --git a/core/src/main/java/hudson/model/ItemGroupMixIn.java b/core/src/main/java/hudson/model/ItemGroupMixIn.java index ff88a9b322869a2c7bbd62db53789c0751d29bff..15c1283743be14a7edb01d469255a8016ae57c25 100644 --- a/core/src/main/java/hudson/model/ItemGroupMixIn.java +++ b/core/src/main/java/hudson/model/ItemGroupMixIn.java @@ -146,10 +146,14 @@ public abstract class ItemGroupMixIn { TopLevelItem result; String requestContentType = req.getContentType(); - if(requestContentType==null) + String mode = req.getParameter("mode"); + if (requestContentType == null + && !(mode != null && mode.equals("copy"))) throw new Failure("No Content-Type header set"); - boolean isXmlSubmission = requestContentType.startsWith("application/xml") || requestContentType.startsWith("text/xml"); + boolean isXmlSubmission = requestContentType != null + && (requestContentType.startsWith("application/xml") + || requestContentType.startsWith("text/xml")); String name = req.getParameter("name"); if(name==null) @@ -162,7 +166,6 @@ public abstract class ItemGroupMixIn { throw new Failure(Messages.Hudson_JobAlreadyExists(name)); } - String mode = req.getParameter("mode"); if(mode!=null && mode.equals("copy")) { String from = req.getParameter("from"); diff --git a/core/src/main/java/hudson/model/View.java b/core/src/main/java/hudson/model/View.java index ce7910cb5520a25bf1f70f7fb55b818b64d6de11..561d178d734a03d6f286f5ff24e725d07de8ebf5 100644 --- a/core/src/main/java/hudson/model/View.java +++ b/core/src/main/java/hudson/model/View.java @@ -1157,18 +1157,22 @@ public abstract class View extends AbstractModelObject implements AccessControll public static View create(StaplerRequest req, StaplerResponse rsp, ViewGroup owner) throws FormException, IOException, ServletException { + String mode = req.getParameter("mode"); + String requestContentType = req.getContentType(); - if(requestContentType==null) + if (requestContentType == null + && !(mode != null && mode.equals("copy"))) throw new Failure("No Content-Type header set"); - boolean isXmlSubmission = requestContentType.startsWith("application/xml") || requestContentType.startsWith("text/xml"); + boolean isXmlSubmission = requestContentType != null + && (requestContentType.startsWith("application/xml") + || requestContentType.startsWith("text/xml")); String name = req.getParameter("name"); checkGoodName(name); if(owner.getView(name)!=null) throw new Failure(Messages.Hudson_ViewAlreadyExists(name)); - String mode = req.getParameter("mode"); if (mode==null || mode.length()==0) { if(isXmlSubmission) { View v = createViewFromXML(name, req.getInputStream()); diff --git a/test/src/test/java/hudson/jobs/CreateItemTest.java b/test/src/test/java/hudson/jobs/CreateItemTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ec0eef98d4703f67831a398851ba1c25b56f446e --- /dev/null +++ b/test/src/test/java/hudson/jobs/CreateItemTest.java @@ -0,0 +1,85 @@ +/* + * The MIT License + * + * Copyright 2015 Christopher Simons + * + * 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 hudson.jobs; + +import static org.junit.Assert.assertEquals; + +import java.net.URL; +import java.text.MessageFormat; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.jvnet.hudson.test.Issue; +import org.jvnet.hudson.test.JenkinsRule; + +import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; +import com.gargoylesoftware.htmlunit.HttpMethod; +import com.gargoylesoftware.htmlunit.WebRequest; + +/** + * Tests the /createItem REST API. + * + * @author Christopher Simons + */ +public class CreateItemTest { + private static final int ERROR_PRESET = (-1); + @Rule + public JenkinsRule rule = new JenkinsRule(); + + @Before + public void setup() { + rule.jenkins.setSecurityRealm(rule.createDummySecurityRealm()); + } + + @Issue("JENKINS-31235") + @Test + public void testCreateItemFromCopy() throws Exception { + rule.jenkins.setCrumbIssuer(null); + + String sourceJobName = "sourceJob"; + rule.createFreeStyleProject(sourceJobName); + + String newJobName = "newJob"; + URL apiURL = new URL(MessageFormat.format( + "{0}createItem?mode=copy&from={1}&name={2}", + rule.getURL().toString(), sourceJobName, newJobName)); + + WebRequest request = new WebRequest(apiURL, HttpMethod.POST); + deleteContentTypeHeader(request); + int result = ERROR_PRESET; + try { + result = rule.createWebClient() + .getPage(request).getWebResponse().getStatusCode(); + } catch (FailingHttpStatusCodeException e) { + result = e.getResponse().getStatusCode(); + } + + assertEquals("Creating job from copy should succeed.", 200, result); + } + + private void deleteContentTypeHeader(WebRequest request) { + request.setEncodingType(null); + } +}