未验证 提交 af09aaea 编写于 作者: J Jesse Glick

Merge branch 'master' into remotingCLI

......@@ -13,7 +13,7 @@
def runTests = true
def failFast = false
properties([buildDiscarder(logRotator(numToKeepStr: '50', artifactNumToKeepStr: '20')), durabilityHint('PERFORMANCE_OPTIMIZED')])
properties([buildDiscarder(logRotator(numToKeepStr: '50', artifactNumToKeepStr: '3')), durabilityHint('PERFORMANCE_OPTIMIZED')])
// see https://github.com/jenkins-infra/documentation/blob/master/ci.adoc for information on what node types are available
def buildTypes = ['Linux', 'Windows']
......
......@@ -63,7 +63,7 @@ THE SOFTWARE.
<dependency>
<groupId>org.jenkins-ci</groupId>
<artifactId>version-number</artifactId>
<version>1.5</version>
<version>1.6</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci</groupId>
......
......@@ -79,6 +79,7 @@ import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.FileSystemException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
......@@ -3266,7 +3267,7 @@ public final class FilePath implements Serializable {
parentRealPath = parentAbsolutePath.toRealPath();
}
catch(NoSuchFileException e) {
throw new IllegalArgumentException("The parent does not exist");
return false;
}
// example: "a/b/c" that will become "b/c" then just "c", and finally an empty string
......@@ -3307,6 +3308,9 @@ public final class FilePath implements Serializable {
Path child = currentFileAbsolutePath.normalize();
Path parent = parentAbsolutePath.normalize();
return child.startsWith(parent);
} catch(FileSystemException e) {
LOGGER.log(Level.WARNING, String.format("Problem during call to the method toRealPath on %s", currentFileAbsolutePath), e);
return false;
}
}
......
......@@ -33,6 +33,7 @@ import hudson.model.ModelObject;
import hudson.model.UpdateCenter;
import hudson.model.UpdateSite;
import hudson.util.VersionNumber;
import io.jenkins.lib.versionnumber.JavaSpecificationVersion;
import jenkins.YesNoMaybe;
import jenkins.model.Jenkins;
import jenkins.util.java.JavaUtils;
......@@ -763,8 +764,8 @@ public class PluginWrapper implements Comparable<PluginWrapper>, ModelObject {
String minimumJavaVersion = getMinimumJavaVersion();
if (minimumJavaVersion != null) {
VersionNumber actualVersion = JavaUtils.getCurrentJavaRuntimeVersionNumber();
if (actualVersion.isOlderThan(new VersionNumber(minimumJavaVersion))) {
JavaSpecificationVersion actualVersion = JavaUtils.getCurrentJavaRuntimeVersionNumber();
if (actualVersion.isOlderThan(new JavaSpecificationVersion(minimumJavaVersion))) {
versionDependencyError(Messages.PluginWrapper_obsoleteJava(actualVersion.toString(), minimumJavaVersion), actualVersion.toString(), minimumJavaVersion);
}
}
......
......@@ -39,8 +39,10 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.GregorianCalendar;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.StringTokenizer;
import java.util.logging.Level;
......@@ -59,7 +61,6 @@ import org.apache.tools.zip.ZipOutputStream;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.HttpResponses;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
......@@ -75,7 +76,7 @@ import org.kohsuke.stapler.StaplerResponse;
public final class DirectoryBrowserSupport implements HttpResponse {
// escape hatch for SECURITY-904 to keep legacy behavior
@SuppressFBWarnings(value = "MS_SHOULD_BE_FINAL", justification = "Accessible via System Groovy Scripts")
public static boolean ALLOW_SYMLINK_ESCAPE = Boolean.getBoolean(DirectoryBrowserSupport.class.getName() + ".allowSymlinkEscape");
public static boolean ALLOW_SYMLINK_ESCAPE = SystemProperties.getBoolean(DirectoryBrowserSupport.class.getName() + ".allowSymlinkEscape");
public final ModelObject owner;
......@@ -436,33 +437,79 @@ public final class DirectoryBrowserSupport implements HttpResponse {
try (ZipOutputStream zos = new ZipOutputStream(outputStream)) {
zos.setEncoding(System.getProperty("file.encoding")); // TODO JENKINS-20663 make this overridable via query parameter
// TODO consider using run(Callable) here
for (String n : dir.list(glob.isEmpty() ? "**" : glob, null, /* TODO what is the user expectation? */true)) {
String relativePath;
if (glob.length() == 0) {
// JENKINS-19947: traditional behavior is to prepend the directory name
relativePath = dir.getName() + '/' + n;
} else {
relativePath = n;
}
String targetFile = dir.toString().substring(root.toString().length()) + n;
if (!ALLOW_SYMLINK_ESCAPE && root.supportIsDescendant() && !root.isDescendant(targetFile)) {
LOGGER.log(Level.INFO, "Trying to access a file outside of the directory: " + root + ", illicit target: " + targetFile);
} else {
// In ZIP archives "All slashes MUST be forward slashes" (http://pkware.com/documents/casestudies/APPNOTE.TXT)
// TODO On Linux file names can contain backslashes which should not treated as file separators.
// Unfortunately, only the file separator char of the master is known (File.separatorChar)
// but not the file separator char of the (maybe remote) "dir".
ZipEntry e = new ZipEntry(relativePath.replace('\\', '/'));
VirtualFile f = dir.child(n);
e.setTime(f.lastModified());
zos.putNextEntry(e);
try (InputStream in = f.open()) {
IOUtils.copy(in, zos);
}
zos.closeEntry();
if (glob.isEmpty()) {
if (!root.supportsQuickRecursiveListing()) {
// avoid slow listing when the Glob can do a quicker job
glob = "**";
}
}
if (glob.isEmpty()) {
Map<String, VirtualFile> nameToVirtualFiles = collectRecursivelyAllLegalChildren(dir);
sendZipUsingMap(zos, dir, nameToVirtualFiles);
} else {
Collection<String> listOfFile = dir.list(glob, null, /* TODO what is the user expectation? */true);
sendZipUsingListOfNames(zos, dir, listOfFile);
}
}
}
private static void sendZipUsingMap(ZipOutputStream zos, VirtualFile dir, Map<String, VirtualFile> nameToVirtualFiles) throws IOException {
for (Map.Entry<String, VirtualFile> entry : nameToVirtualFiles.entrySet()) {
String n = entry.getKey();
// JENKINS-19947: traditional behavior is to prepend the directory name
String relativePath = dir.getName() + '/' + n;
VirtualFile f = entry.getValue();
sendOneZipEntry(zos, f, relativePath);
}
}
private static void sendZipUsingListOfNames(ZipOutputStream zos, VirtualFile dir, Collection<String> listOfFileNames) throws IOException {
for (String relativePath : listOfFileNames) {
VirtualFile f = dir.child(relativePath);
sendOneZipEntry(zos, f, relativePath);
}
}
private static void sendOneZipEntry(ZipOutputStream zos, VirtualFile vf, String relativePath) throws IOException {
// In ZIP archives "All slashes MUST be forward slashes" (http://pkware.com/documents/casestudies/APPNOTE.TXT)
// TODO On Linux file names can contain backslashes which should not treated as file separators.
// Unfortunately, only the file separator char of the master is known (File.separatorChar)
// but not the file separator char of the (maybe remote) "dir".
ZipEntry e = new ZipEntry(relativePath.replace('\\', '/'));
e.setTime(vf.lastModified());
zos.putNextEntry(e);
try (InputStream in = vf.open()) {
IOUtils.copy(in, zos);
}
finally {
zos.closeEntry();
}
}
private static Map<String, VirtualFile> collectRecursivelyAllLegalChildren(VirtualFile dir) throws IOException {
Map<String, VirtualFile> nameToFiles = new LinkedHashMap<>();
collectRecursivelyAllLegalChildren(dir, "", nameToFiles);
return nameToFiles;
}
private static void collectRecursivelyAllLegalChildren(VirtualFile currentDir, String currentPrefix, Map<String, VirtualFile> nameToFiles) throws IOException {
if (currentDir.isFile()) {
if (currentDir.isDescendant("")) {
nameToFiles.put(currentPrefix, currentDir);
}
} else {
if (!currentPrefix.isEmpty()) {
currentPrefix += "/";
}
List<VirtualFile> children = currentDir.listOnlyDescendants();
for (VirtualFile child : children) {
collectRecursivelyAllLegalChildren(child, currentPrefix + child.getName(), nameToFiles);
}
}
}
......
......@@ -216,15 +216,8 @@ public class UpdateCenter extends AbstractModelObject implements Saveable, OnMas
if (ucOverride != null) {
logger.log(Level.INFO, "Using a custom update center defined by the system property: {0}", ucOverride);
UPDATE_CENTER_URL = ucOverride;
} else if (JavaUtils.isRunningWithJava8OrBelow()) {
UPDATE_CENTER_URL = "https://updates.jenkins.io/";
} else {
//TODO: Rollback the default for Java 11 when it goes to GA
String experimentalJava11UC = "https://updates.jenkins.io/temporary-experimental-java11/";
logger.log(Level.WARNING, "Running Jenkins with Java {0} which is available in the preview mode only. " +
"A custom experimental update center will be used: {1}",
new Object[] {System.getProperty("java.specification.version"), experimentalJava11UC});
UPDATE_CENTER_URL = experimentalJava11UC;
UPDATE_CENTER_URL = "https://updates.jenkins.io/";
}
}
......
......@@ -64,6 +64,7 @@ import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import io.jenkins.lib.versionnumber.JavaSpecificationVersion;
import jenkins.model.Jenkins;
import jenkins.model.DownloadSettings;
import jenkins.plugins.DetachedPluginsUtil;
......@@ -1133,8 +1134,8 @@ public class UpdateSite {
*/
public boolean isForNewerJava() {
try {
final VersionNumber currentRuntimeJavaVersion = JavaUtils.getCurrentJavaRuntimeVersionNumber();
return minimumJavaVersion != null && new VersionNumber(minimumJavaVersion).isNewerThan(
final JavaSpecificationVersion currentRuntimeJavaVersion = JavaUtils.getCurrentJavaRuntimeVersionNumber();
return minimumJavaVersion != null && new JavaSpecificationVersion(minimumJavaVersion).isNewerThan(
currentRuntimeJavaVersion);
} catch (NumberFormatException nfe) {
logBadMinJavaVersion();
......
......@@ -47,7 +47,7 @@ public abstract class AbstractDiskSpaceMonitor extends NodeMonitor {
if(size!=null && size.size > getThresholdBytes() && c.isOffline() && c.getOfflineCause() instanceof DiskSpace)
if(this.getClass().equals(((DiskSpace)c.getOfflineCause()).getTrigger()))
if(getDescriptor().markOnline(c)) {
LOGGER.info(Messages.DiskSpaceMonitor_MarkedOnline(c.getName()));
LOGGER.info(Messages.DiskSpaceMonitor_MarkedOnline(c.getDisplayName()));
}
return size;
}
......@@ -64,7 +64,7 @@ public abstract class AbstractDiskSpaceMonitor extends NodeMonitor {
if(size!=null && size.size < getThresholdBytes()) {
size.setTriggered(this.getClass(), true);
if(getDescriptor().markOffline(c,size)) {
LOGGER.warning(Messages.DiskSpaceMonitor_MarkedOffline(c.getName()));
LOGGER.warning(Messages.DiskSpaceMonitor_MarkedOffline(c.getDisplayName()));
}
}
return size;
......
package hudson.util;
import hudson.FilePath;
import hudson.Util;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.selectors.FileSelector;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import static hudson.Util.fixEmpty;
......@@ -119,8 +124,12 @@ public abstract class DirScanner implements Serializable {
FileSet fs = Util.createFileSet(dir,includes,excludes);
fs.setDefaultexcludes(useDefaultExcludes);
fs.appendSelector(new DescendantFileSelector(fs.getDir()));
if(dir.exists()) {
DirectoryScanner ds = fs.getDirectoryScanner(new org.apache.tools.ant.Project());
// due to the DescendantFileSelector usage,
// the includedFiles are only the ones that are descendant
for( String f : ds.getIncludedFiles()) {
File file = new File(dir, f);
scanSingle(file, f, visitor);
......@@ -130,6 +139,53 @@ public abstract class DirScanner implements Serializable {
private static final long serialVersionUID = 1L;
}
private static class DescendantFileSelector implements FileSelector{
private final Set<String> alreadyDeselected;
private final FilePath baseDirFP;
private final int baseDirPathLength;
private DescendantFileSelector(File basedir){
this.baseDirFP = new FilePath(basedir);
this.baseDirPathLength = basedir.getPath().length();
this.alreadyDeselected = new HashSet<>();
}
@Override
public boolean isSelected(File basedir, String filename, File file) throws BuildException {
String parentName = file.getParent();
if (parentName.length() > baseDirPathLength) {
// remove the trailing slash
String parentRelativeName = parentName.substring(baseDirPathLength + 1);
// as the visit is done following depth-first approach, we just have to check the parent once
// and then simply using the set
// in case something went wrong with the order, the isDescendant is called with just a lost
// in terms of performance, no impact on the result
if (alreadyDeselected.contains(parentRelativeName)) {
alreadyDeselected.add(filename);
return false;
}
}
// else: we have the direct children of the basedir
if (file.isDirectory()) {
try {
if (baseDirFP.isDescendant(filename)) {
return true;
} else {
alreadyDeselected.add(filename);
return false;
}
}
catch (IOException | InterruptedException e) {
return true;
}
} else {
return true;
}
}
}
private static final long serialVersionUID = 1L;
}
......@@ -6,6 +6,7 @@ import com.google.common.collect.ImmutableSet;
import hudson.ClassicPluginStrategy;
import hudson.PluginWrapper;
import hudson.util.VersionNumber;
import io.jenkins.lib.versionnumber.JavaSpecificationVersion;
import jenkins.util.java.JavaUtils;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
......@@ -174,13 +175,13 @@ public class DetachedPluginsUtil {
*/
private final VersionNumber splitWhen;
private final String requiredVersion;
private final VersionNumber minJavaVersion;
private final JavaSpecificationVersion minJavaVersion;
private DetachedPlugin(String shortName, String splitWhen, String requiredVersion, String minJavaVersion) {
this.shortName = shortName;
this.splitWhen = new VersionNumber(splitWhen);
this.requiredVersion = requiredVersion;
this.minJavaVersion = new VersionNumber(minJavaVersion);
this.minJavaVersion = new JavaSpecificationVersion(minJavaVersion);
}
/**
......@@ -217,7 +218,7 @@ public class DetachedPluginsUtil {
}
@Nonnull
public VersionNumber getMinimumJavaVersion() {
public JavaSpecificationVersion getMinimumJavaVersion() {
return minJavaVersion;
}
}
......
......@@ -51,6 +51,7 @@ import java.util.Collections;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
......@@ -168,12 +169,38 @@ public abstract class VirtualFile implements Comparable<VirtualFile>, Serializab
public abstract boolean exists() throws IOException;
/**
* Lists children of this directory.
* Lists children of this directory. Only one level deep.
*
* @return a list of children (files and subdirectories); empty for a file or nonexistent directory
* @throws IOException if this directory exists but listing was not possible for some other reason
*/
public abstract @Nonnull VirtualFile[] list() throws IOException;
@Restricted(NoExternalUse.class)
public boolean supportsQuickRecursiveListing() {
return false;
}
/**
* Lists only the children that are descendant of the root directory (not necessarily the current VirtualFile).
* Only one level deep.
*
* @return a list of descendant children (files and subdirectories); empty for a file or nonexistent directory
* @throws IOException if this directory exists but listing was not possible for some other reason
*/
@Restricted(NoExternalUse.class)
public @Nonnull List<VirtualFile> listOnlyDescendants() throws IOException {
VirtualFile[] children = list();
List<VirtualFile> result = new ArrayList<>();
for (int i = 0; i < children.length; i++) {
VirtualFile child = children[i];
if (child.isDescendant("")) {
result.add(child);
}
}
return result;
}
/**
* @deprecated use {@link #list(String, String, boolean)} instead
*/
......@@ -379,6 +406,12 @@ public abstract class VirtualFile implements Comparable<VirtualFile>, Serializab
public boolean isDescendant(String childRelativePath) throws IOException {
return false;
}
String joinWithForwardSlashes(Collection<String> relativePath){
// instead of File.separator that is specific to the master, the / has the advantage to be supported
// by either Windows AND Linux for the Path.toRealPath() used in isDescendant
return String.join("/", relativePath) + "/";
}
/**
* Creates a virtual file wrapper for a local file.
......@@ -391,6 +424,7 @@ public abstract class VirtualFile implements Comparable<VirtualFile>, Serializab
private static final class FileVF extends VirtualFile {
private final File f;
private final File root;
private boolean cacheDescendant = false;
FileVF(File f, File root) {
this.f = f;
this.root = root;
......@@ -442,6 +476,29 @@ public abstract class VirtualFile implements Comparable<VirtualFile>, Serializab
}
return vfs;
}
@Override public boolean supportsQuickRecursiveListing() {
return true;
}
@Override public @Nonnull List<VirtualFile> listOnlyDescendants() throws IOException {
if (isIllegalSymlink()) {
return Collections.emptyList();
}
File[] children = f.listFiles();
if (children == null) {
return Collections.emptyList();
}
List<VirtualFile> legalChildren = new ArrayList<>(children.length);
for (File child : children) {
if (isDescendant(child.getName())) {
FileVF legalChild = new FileVF(child, root);
legalChild.cacheDescendant = true;
legalChildren.add(legalChild);
}
}
return legalChildren;
}
@Override
public Collection<String> list(String includes, String excludes, boolean useDefaultExcludes) throws IOException {
if (isIllegalSymlink()) {
......@@ -487,17 +544,14 @@ public abstract class VirtualFile implements Comparable<VirtualFile>, Serializab
}
}
private boolean isIllegalSymlink() { // TODO JENKINS-26838
private boolean isIllegalSymlink() {
try {
String myPath = f.toPath().toRealPath(new LinkOption[0]).toString();
String rootPath = root.toPath().toRealPath(new LinkOption[0]).toString();
if (!myPath.equals(rootPath) && !myPath.startsWith(rootPath + File.separatorChar)) {
return true;
}
return !this.isDescendant("");
} catch (IOException x) {
Logger.getLogger(VirtualFile.class.getName()).log(Level.FINE, "could not determine symlink status of " + f, x);
} catch (InvalidPathException x2) {
// if this cannot be converted to a path, it cannot be an illegal symlink, as it cannot exist
// it's the case when we are calling it with *zip*
Logger.getLogger(VirtualFile.class.getName()).log(Level.FINE, "Could not convert " + f + " to path", x2);
}
return false;
......@@ -518,15 +572,35 @@ public abstract class VirtualFile implements Comparable<VirtualFile>, Serializab
@Override
@Restricted(NoExternalUse.class)
public boolean isDescendant(String potentialChildRelativePath) throws IOException {
if (potentialChildRelativePath.isEmpty() && cacheDescendant) {
return true;
}
if (new File(potentialChildRelativePath).isAbsolute()) {
throw new IllegalArgumentException("Only a relative path is supported, the given path is absolute: " + potentialChildRelativePath);
}
// shortcut for direct child to avoid the complexity of the whole computation
// as we know that a file that is a direct descendant of its parent can only be descendant of the root
// if the parent is descendant AND the file itself is not symbolic
File directChild = new File(f, potentialChildRelativePath);
if (directChild.getParentFile().equals(f)) {
// potential shortcut for "simple" / direct child
if (!Util.isSymlink(directChild)) {
return true;
}
}
FilePath root = new FilePath(this.root);
String relativePath = computeRelativePathToRoot();
try {
return root.isDescendant(relativePath + potentialChildRelativePath);
boolean isDescendant = root.isDescendant(relativePath + potentialChildRelativePath);
if (isDescendant && potentialChildRelativePath.isEmpty()) {
// in DirectoryBrowserSupport#zip, multiple calls to isDescendant are done for the same VirtualFile
cacheDescendant = true;
}
return isDescendant;
}
catch (InterruptedException e) {
return false;
......@@ -547,8 +621,8 @@ public abstract class VirtualFile implements Comparable<VirtualFile>, Serializab
relativePath.addFirst(current.getName());
current = current.getParentFile();
}
return String.join(File.separator, relativePath) + File.separator;
return joinWithForwardSlashes(relativePath);
}
}
......@@ -563,6 +637,7 @@ public abstract class VirtualFile implements Comparable<VirtualFile>, Serializab
private static final class FilePathVF extends VirtualFile {
private final FilePath f;
private final FilePath root;
private boolean cacheDescendant = false;
FilePathVF(FilePath f, FilePath root) {
this.f = f;
this.root = root;
......@@ -617,13 +692,40 @@ public abstract class VirtualFile implements Comparable<VirtualFile>, Serializab
throw new IOException(x);
}
}
@Override public Collection<String> list(String includes, String excludes, boolean useDefaultExcludes) throws IOException {
@Override public boolean supportsQuickRecursiveListing() {
return this.f.getChannel() == FilePath.localChannel;
}
@Override public @Nonnull List<VirtualFile> listOnlyDescendants() throws IOException {
try {
return f.act(new Scanner(includes, excludes, useDefaultExcludes));
if (!isDescendant("")) {
return Collections.emptyList();
}
List<FilePath> children = f.list();
List<VirtualFile> legalChildren = new ArrayList<>(children.size());
for (FilePath child : children){
if (isDescendant(child.getName())) {
FilePathVF legalChild = new FilePathVF(child, this.root);
legalChild.cacheDescendant = true;
legalChildren.add(legalChild);
}
}
return legalChildren;
} catch (InterruptedException x) {
throw new IOException(x);
}
}
@Override public Collection<String> list(String includes, String excludes, boolean useDefaultExcludes) throws IOException {
try {
return f.act(new Scanner(includes, excludes, useDefaultExcludes));
} catch (InterruptedException x) {
throw new IOException(x);
}
}
@Override public VirtualFile child(String name) {
return new FilePathVF(f.child(name), this.root);
}
......@@ -685,9 +787,31 @@ public abstract class VirtualFile implements Comparable<VirtualFile>, Serializab
@Override
@Restricted(NoExternalUse.class)
public boolean isDescendant(String potentialChildRelativePath) throws IOException {
if (potentialChildRelativePath.equals("") && cacheDescendant) {
return true;
}
if (new File(potentialChildRelativePath).isAbsolute()) {
throw new IllegalArgumentException("Only a relative path is supported, the given path is absolute: " + potentialChildRelativePath);
}
// shortcut for direct child to avoid the complexity of the whole computation
// as we know that a file that is a direct descendant of its parent can only be descendant of the root
// if the parent is descendant
FilePath directChild = this.f.child(potentialChildRelativePath);
if (Objects.equals(directChild.getParent(), this.f)) {
try {
boolean isDirectDescendant = this.f.isDescendant(potentialChildRelativePath);
if (isDirectDescendant) {
return true;
}
// not a return false because you can be a non-descendant of your parent but still
// inside the root directory
}
catch (InterruptedException e) {
return false;
}
}
String relativePath = computeRelativePathToRoot();
......@@ -714,7 +838,7 @@ public abstract class VirtualFile implements Comparable<VirtualFile>, Serializab
current = current.getParent();
}
return String.join(File.separator, relativePath) + File.separator;
return joinWithForwardSlashes(relativePath);
}
}
private static final class Scanner extends MasterToSlaveFileCallable<List<String>> {
......
......@@ -24,6 +24,7 @@
package jenkins.util.java;
import hudson.util.VersionNumber;
import io.jenkins.lib.versionnumber.JavaSpecificationVersion;
import org.kohsuke.accmod.Restricted;
import org.kohsuke.accmod.restrictions.NoExternalUse;
......@@ -59,8 +60,8 @@ public class JavaUtils {
/**
* Returns the JVM's current version as a {@link VersionNumber} instance.
*/
public static VersionNumber getCurrentJavaRuntimeVersionNumber() {
return new VersionNumber(getCurrentRuntimeJavaVersion());
public static JavaSpecificationVersion getCurrentJavaRuntimeVersionNumber() {
return JavaSpecificationVersion.forCurrentJVM();
}
/**
......
BuildDiscarderProperty.displayName=Descargar build antiguos
BuildDiscarderProperty.displayName=Descartar build antiguos
......@@ -53,7 +53,7 @@ THE SOFTWARE.
The following commands are currently whitelisted for agents to execute on the master.
Type in any fully-qualified class names to whitelist them:
</p>
<textarea id="whitelist" name="whitelist" style="width:100%; height:5em">${it.whitelisted.read()}</textarea>
<textarea id="whitelist" name="whitelist" style="width:100%; height:5em">${it.whitelisted.exists() ? it.whitelisted.read() : ""}</textarea>
<j:set var="rejectedList" value="${it.rejected.describe()}"/>
......@@ -88,7 +88,7 @@ THE SOFTWARE.
<p>
The following rules control which part of <tt>$JENKINS_HOME</tt> can be accessed from agents:
</p>
<textarea id="filePathRules" name="filePathRules" style="width:100%; height:5em">${it.filePathRules.read()}</textarea>
<textarea id="filePathRules" name="filePathRules" style="width:100%; height:5em">${it.filePathRules.exists() ? it.filePathRules.read() : ""}</textarea>
<p>
Example:
</p>
......
......@@ -33,7 +33,9 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
......@@ -221,7 +223,6 @@ public class FilePathSEC904Test {
p.waitFor(2, TimeUnit.SECONDS);
}
@Test(expected = IllegalArgumentException.class)
@Issue("SECURITY-904")
public void isDescendant_throwIfParentDoesNotExist_symlink() throws Exception {
FilePath rootFolder = new FilePath(temp.newFolder("root"));
......@@ -230,15 +231,14 @@ public class FilePathSEC904Test {
FilePath linkToNonexistent = aFolder.child("linkToNonexistent");
linkToNonexistent.symlinkTo("__nonexistent__", null);
linkToNonexistent.isDescendant(".");
assertThat(linkToNonexistent.isDescendant("."), is(false));
}
@Test(expected = IllegalArgumentException.class)
@Issue("SECURITY-904")
public void isDescendant_throwIfParentDoesNotExist_directNonexistent() throws Exception {
FilePath rootFolder = new FilePath(temp.newFolder("root"));
FilePath nonexistent = rootFolder.child("nonexistent");
nonexistent.isDescendant(".");
assertThat(nonexistent.isDescendant("."), is(false));
}
@Test(expected = IllegalArgumentException.class)
......
......@@ -27,15 +27,20 @@ package jenkins.util;
import hudson.FilePath;
import hudson.model.TaskListener;
import org.apache.commons.io.FileUtils;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.jvnet.hudson.test.Issue;
import java.io.File;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
......@@ -56,6 +61,7 @@ public class VirtualFileSEC904Test {
// /_b => symlink to /root/b
// /b
// /_a => symlink to /root/a
// /_aatxt => symlink to /root/a/aa/aa.txt
// /ba
// ba.txt
private void prepareFileStructureForIsDescendant() throws Exception {
......@@ -82,6 +88,9 @@ public class VirtualFileSEC904Test {
File _a = new File(b, "_a");
new FilePath(_a).symlinkTo(a.getAbsolutePath(), TaskListener.NULL);
File _aatxt = new File(b, "_aatxt");
new FilePath(_aatxt).symlinkTo(aaTxt.getAbsolutePath(), TaskListener.NULL);
File _b = new File(a, "_b");
new FilePath(_b).symlinkTo(b.getAbsolutePath(), TaskListener.NULL);
File _b2 = new File(aaa, "_b2");
......@@ -177,4 +186,96 @@ public class VirtualFileSEC904Test {
assertTrue(virtualRoot.isDescendant("_b/_a/aa/../ab/ab.txt"));
assertTrue(virtualRoot.isDescendant("_b/_a/aa/aa.txt"));
}
@Test
@Issue("JENKINS-55050")
public void forFile_listOnlyDescendants_withoutIllegal() throws Exception {
this.prepareFileStructureForIsDescendant();
File root = tmp.getRoot();
File a = new File(root, "a");
File b = new File(root, "b");
VirtualFile virtualRoot = VirtualFile.forFile(root);
VirtualFile virtualFromA = VirtualFile.forFile(a);
VirtualFile virtualFromB = VirtualFile.forFile(b);
checkCommonAssertionForList(virtualRoot, virtualFromA, virtualFromB);
}
@Test
@Issue("SECURITY-904")
public void forFilePath_listOnlyDescendants_withoutIllegal() throws Exception {
this.prepareFileStructureForIsDescendant();
File root = tmp.getRoot();
File a = new File(root, "a");
File b = new File(root, "b");
VirtualFile virtualRoot = VirtualFile.forFilePath(new FilePath(root));
VirtualFile virtualFromA = VirtualFile.forFilePath(new FilePath(a));
VirtualFile virtualFromB = VirtualFile.forFilePath(new FilePath(b));
checkCommonAssertionForList(virtualRoot, virtualFromA, virtualFromB);
}
private void checkCommonAssertionForList(VirtualFile virtualRoot, VirtualFile virtualFromA, VirtualFile virtualFromB) throws Exception {
// outside link to folder is not returned
assertThat(virtualFromA.listOnlyDescendants(), containsInAnyOrder(
VFMatcher.hasName("aa"),
VFMatcher.hasName("ab")
));
// outside link to file is not returned
assertThat(virtualFromB.listOnlyDescendants(), contains(
VFMatcher.hasName("ba")
));
assertThat(virtualFromA.child("_b").listOnlyDescendants(), hasSize(0));
assertThat(virtualFromA.child("aa").listOnlyDescendants(), containsInAnyOrder(
VFMatcher.hasName("aaa"),
VFMatcher.hasName("aa.txt")
));
// only a outside link
assertThat(virtualFromA.child("aa").child("aaa").listOnlyDescendants(), hasSize(0));
// as we start from the root, the a/_b linking to root/b is legal
assertThat(virtualRoot.child("a").listOnlyDescendants(), containsInAnyOrder(
VFMatcher.hasName("aa"),
VFMatcher.hasName("ab"),
VFMatcher.hasName("_b")
));
assertThat(virtualRoot.child("a").child("_b").listOnlyDescendants(), containsInAnyOrder(
VFMatcher.hasName("_a"),
VFMatcher.hasName("_aatxt"),
VFMatcher.hasName("ba")
));
assertThat(virtualRoot.child("a").child("_b").child("_a").listOnlyDescendants(), containsInAnyOrder(
VFMatcher.hasName("aa"),
VFMatcher.hasName("ab"),
VFMatcher.hasName("_b")
));
}
private abstract static class VFMatcher extends TypeSafeMatcher<VirtualFile> {
private final String description;
private VFMatcher(String description) {
this.description = description;
}
public void describeTo(Description description) {
description.appendText(this.description);
}
public static VFMatcher hasName(String expectedName) {
return new VFMatcher("Has name: " + expectedName) {
protected boolean matchesSafely(VirtualFile vf) {
return expectedName.equals(vf.getName());
}
};
}
}
}
......@@ -76,7 +76,7 @@ THE SOFTWARE.
</issueManagement>
<properties>
<revision>2.164</revision>
<revision>2.165</revision>
<changelist>-SNAPSHOT</changelist>
<!-- *.html files are in UTF-8, and *.properties are in iso-8859-1, so this configuration is actually incorrect,
......@@ -107,7 +107,7 @@ THE SOFTWARE.
<maven-war-plugin.version>3.0.0</maven-war-plugin.version> <!-- JENKINS-47127 bump when 3.2.0 is out. Cf. MWAR-407 -->
<!-- Bundled Remoting version -->
<remoting.version>3.28</remoting.version>
<remoting.version>3.29</remoting.version>
<!-- Minimum Remoting version, which is tested for API compatibility -->
<remoting.minimum.supported.version>3.4</remoting.minimum.supported.version>
......@@ -146,7 +146,7 @@ THE SOFTWARE.
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
<version>2.6</version>
</dependency>
<dependency>
......
......@@ -54,7 +54,7 @@ THE SOFTWARE.
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jenkins-test-harness</artifactId>
<version>2.41.1</version>
<version>2.46</version>
<scope>test</scope>
<exclusions>
<exclusion>
......
......@@ -33,6 +33,8 @@ import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.MockAuthorizationStrategy;
import org.jvnet.hudson.test.SmokeTest;
import java.net.HttpURLConnection;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
......@@ -55,19 +57,19 @@ public class AboutJenkinsTest {
.grant(Jenkins.READ).everywhere().to(USER)
);
JenkinsRule.WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
{ // user cannot see it
wc.login(USER);
HtmlPage page = wc.goTo("about/");
assertEquals(403, page.getWebResponse().getStatusCode());
assertEquals(HttpURLConnection.HTTP_FORBIDDEN, page.getWebResponse().getStatusCode());
}
{ // admin can access it
wc.login(ADMIN);
HtmlPage page = wc.goTo("about/");
assertEquals(200, page.getWebResponse().getStatusCode());
assertEquals(HttpURLConnection.HTTP_OK, page.getWebResponse().getStatusCode());
assertThat(page.getWebResponse().getContentAsString(), containsString("Mavenized dependencies"));
}
}
......
package hudson;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.TextPage;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import hudson.remoting.Base64;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import javax.annotation.Nullable;
import java.net.HttpURLConnection;
import java.net.URL;
import jenkins.model.Jenkins;
import jenkins.model.identity.InstanceIdentityProvider;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.JenkinsRule.WebClient;
import org.jvnet.hudson.test.TestExtension;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
public class TcpSlaveAgentListenerTest {
......@@ -37,15 +23,15 @@ public class TcpSlaveAgentListenerTest {
@Test
public void headers() throws Exception {
WebClient wc = r.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
r.getInstance().setSlaveAgentPort(-1);
try {
r.createWebClient().goTo("tcpSlaveAgentListener");
fail("Should get 404");
} catch (FailingHttpStatusCodeException e) {
assertThat(e.getStatusCode(), is(404));
}
wc.assertFails("tcpSlaveAgentListener", HttpURLConnection.HTTP_NOT_FOUND);
r.getInstance().setSlaveAgentPort(0);
Page p = r.createWebClient().goTo("tcpSlaveAgentListener", "text/plain");
Page p = wc.goTo("tcpSlaveAgentListener", "text/plain");
assertEquals(HttpURLConnection.HTTP_OK, p.getWebResponse().getStatusCode());
assertThat(p.getWebResponse().getResponseHeaderValue("X-Instance-Identity"), notNullValue());
}
......@@ -54,15 +40,13 @@ public class TcpSlaveAgentListenerTest {
r.getInstance().setSlaveAgentPort(0);
int p = r.jenkins.getTcpSlaveAgentListener().getPort();
WebClient wc = r.createWebClient();
TextPage text = (TextPage) wc.getPage("http://localhost:"+p+"/");
TextPage text = wc.getPage(new URL("http://localhost:" + p + "/"));
String c = text.getContent();
assertThat(c,containsString(Jenkins.VERSION));
assertThat(c, containsString(Jenkins.VERSION));
try {
wc.getPage("http://localhost:"+p+"/xxx");
fail("Expected 404");
} catch (FailingHttpStatusCodeException e) {
assertThat(e.getStatusCode(),equalTo(404));
}
wc.setThrowExceptionOnFailingStatusCode(false);
Page page = wc.getPage(new URL("http://localhost:" + p + "/xxx"));
assertEquals(HttpURLConnection.HTTP_NOT_FOUND, page.getWebResponse().getStatusCode());
}
}
......@@ -37,6 +37,7 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.nio.file.Files;
import java.util.Arrays;
import java.util.List;
......@@ -233,11 +234,12 @@ public class CLITest {
sshd.start();
// Sanity check
JenkinsRule.WebClient wc = r.createWebClient();
wc.getOptions().setRedirectEnabled(false);
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = r.createWebClient()
.withRedirectEnabled(false)
.withThrowExceptionOnFailingStatusCode(false);
WebResponse rsp = wc.goTo("cli-proxy/").getWebResponse();
assertEquals(rsp.getContentAsString(), 302, rsp.getStatusCode());
assertEquals(rsp.getContentAsString(), HttpURLConnection.HTTP_MOVED_TEMP, rsp.getStatusCode());
assertEquals(rsp.getContentAsString(), null, rsp.getResponseHeaderValue("X-Jenkins"));
assertEquals(rsp.getContentAsString(), null, rsp.getResponseHeaderValue("X-Jenkins-CLI-Port"));
assertEquals(rsp.getContentAsString(), null, rsp.getResponseHeaderValue("X-SSH-Endpoint"));
......@@ -307,7 +309,7 @@ public class CLITest {
public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) throws IOException, ServletException {
rsp.setHeader("Location", url);
rsp.setContentType("text/html");
rsp.setStatus(302);
rsp.setStatus(HttpURLConnection.HTTP_MOVED_TEMP);
PrintWriter w = rsp.getWriter();
w.append("Redirect to ").append(url);
}
......
......@@ -5,14 +5,13 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import hudson.model.User;
import hudson.security.GlobalMatrixAuthorizationStrategy;
import jenkins.model.Jenkins;
import jenkins.security.apitoken.ApiTokenPropertyConfiguration;
import jenkins.security.apitoken.ApiTokenTestHelper;
import org.junit.Rule;
import org.junit.Test;
......@@ -24,6 +23,7 @@ import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.ElementNotFoundException;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
......@@ -63,7 +63,8 @@ public class HudsonHomeDiskUsageMonitorTest {
public void noAccessForNonAdmin() throws Exception {
ApiTokenTestHelper.enableLegacyBehavior();
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
// TODO: Use MockAuthorizationStrategy in later versions
JenkinsRule.DummySecurityRealm realm = j.createDummySecurityRealm();
......@@ -85,26 +86,19 @@ public class HudsonHomeDiskUsageMonitorTest {
HudsonHomeDiskUsageMonitor mon = HudsonHomeDiskUsageMonitor.get();
wc.withBasicApiToken(bob);
try {
wc.getPage(request);
fail();
} catch (FailingHttpStatusCodeException e) {
assertEquals(403, e.getStatusCode());
}
Page p = wc.getPage(request);
assertEquals(HttpURLConnection.HTTP_FORBIDDEN, p.getWebResponse().getStatusCode());
assertTrue(mon.isEnabled());
WebRequest requestReadOnly = new WebRequest(new URL(wc.getContextPath() + "administrativeMonitor/hudsonHomeIsFull"), HttpMethod.GET);
try {
wc.getPage(requestReadOnly);
fail();
} catch (FailingHttpStatusCodeException e) {
assertEquals(403, e.getStatusCode());
}
p = wc.getPage(requestReadOnly);
assertEquals(HttpURLConnection.HTTP_FORBIDDEN, p.getWebResponse().getStatusCode());
wc.withBasicApiToken(administrator);
wc.getPage(request);
p = wc.getPage(request);
assertEquals(HttpURLConnection.HTTP_OK, p.getWebResponse().getStatusCode());
assertFalse(mon.isEnabled());
}
/**
......
......@@ -26,22 +26,22 @@ package hudson.jobs;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.*;
import hudson.AbortException;
import com.gargoylesoftware.htmlunit.Page;
import hudson.model.Failure;
import hudson.model.Item;
import hudson.model.ItemGroup;
import hudson.model.listeners.ItemListener;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.MessageFormat;
import org.acegisecurity.AccessDeniedException;
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;
import hudson.model.FreeStyleProject;
......@@ -54,7 +54,6 @@ import org.jvnet.hudson.test.TestExtension;
* @author Christopher Simons
*/
public class CreateItemTest {
private static final int ERROR_PRESET = (-1);
@Rule
public JenkinsRule rule = new JenkinsRule();
......@@ -78,15 +77,13 @@ public class CreateItemTest {
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);
Page p = rule.createWebClient()
.withThrowExceptionOnFailingStatusCode(false)
.getPage(request);
assertEquals("Creating job from copy should succeed.",
HttpURLConnection.HTTP_OK,
p.getWebResponse().getStatusCode());
}
@Issue("JENKINS-34691")
......@@ -104,15 +101,14 @@ public class CreateItemTest {
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 fail.", 400, result);
Page p = rule.createWebClient()
.withThrowExceptionOnFailingStatusCode(false)
.getPage(request);
assertEquals("Creating job from copy should fail.",
HttpURLConnection.HTTP_BAD_REQUEST,
p.getWebResponse().getStatusCode());
assertThat(rule.jenkins.getItem("newJob"), nullValue());
}
......@@ -125,9 +121,13 @@ public class CreateItemTest {
rule.jenkins.setCrumbIssuer(null);
rule.createFolder("d1").createProject(FreeStyleProject.class, "p");
MockFolder d2 = rule.createFolder("d2");
rule.createWebClient().getPage(new WebRequest(new URL(d2.getAbsoluteUrl() + "createItem?mode=copy&name=p2&from=../d1/p"), HttpMethod.POST));
JenkinsRule.WebClient wc = rule.createWebClient();
wc.getPage(new WebRequest(new URL(d2.getAbsoluteUrl() + "createItem?mode=copy&name=p2&from=../d1/p"), HttpMethod.POST));
assertNotNull(d2.getItem("p2"));
rule.createWebClient().getPage(new WebRequest(new URL(d2.getAbsoluteUrl() + "createItem?mode=copy&name=p3&from=/d1/p"), HttpMethod.POST));
wc.getPage(new WebRequest(new URL(d2.getAbsoluteUrl() + "createItem?mode=copy&name=p3&from=/d1/p"), HttpMethod.POST));
assertNotNull(d2.getItem("p3"));
}
......
package hudson.model;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import hudson.security.ACL;
......@@ -9,6 +9,7 @@ import hudson.security.ACLContext;
import hudson.security.AccessDeniedException2;
import hudson.util.FormValidation;
import java.io.File;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import jenkins.model.Jenkins;
......@@ -117,18 +118,17 @@ public class AbstractItemTest {
WebRequest wr = new WebRequest(w.createCrumbedUrl(p.getUrl() + "confirmRename"), HttpMethod.POST);
wr.setRequestParameters(Arrays.asList(new NameValuePair("newName", "bar")));
w.login("alice", "alice");
assertThat(getPath(w.getPage(wr).getUrl()), equalTo(p.getUrl()));
Page page = w.getPage(wr);
assertThat(getPath(page.getUrl()), equalTo(p.getUrl()));
assertThat(p.getName(), equalTo("bar"));
wr = new WebRequest(w.createCrumbedUrl(p.getUrl() + "confirmRename"), HttpMethod.POST);
wr.setRequestParameters(Arrays.asList(new NameValuePair("newName", "baz")));
w.login("bob", "bob");
try {
assertThat(getPath(w.getPage(wr).getUrl()), equalTo(p.getUrl()));
fail("Expecting HTTP 403 Forbidden");
} catch (FailingHttpStatusCodeException e) {
assertThat(e.getStatusCode(), equalTo(403));
}
w.setThrowExceptionOnFailingStatusCode(false);
page = w.getPage(wr);
assertEquals(HttpURLConnection.HTTP_FORBIDDEN, page.getWebResponse().getStatusCode());
assertThat(p.getName(), equalTo("bar"));
}
......
......@@ -24,8 +24,8 @@
package hudson.model;
import com.gargoylesoftware.htmlunit.ElementNotFoundException;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
......@@ -120,16 +120,13 @@ public class AbstractProjectTest {
FreeStyleBuild b = project.scheduleBuild2(0).get();
assert b.getWorkspace().exists() : "Workspace should exist by now";
assertTrue("Workspace should exist by now", b.getWorkspace().exists());
// make sure that the action link is protected
JenkinsRule.WebClient wc = j.createWebClient();
try {
wc.getPage(new WebRequest(new URL(wc.getContextPath() + project.getUrl() + "doWipeOutWorkspace"), HttpMethod.POST));
fail("Expected HTTP status code 403");
} catch (FailingHttpStatusCodeException e) {
assertEquals(HttpURLConnection.HTTP_FORBIDDEN, e.getStatusCode());
}
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
Page page = wc.getPage(new WebRequest(new URL(wc.getContextPath() + project.getUrl() + "doWipeOutWorkspace"), HttpMethod.POST));
assertEquals(HttpURLConnection.HTTP_FORBIDDEN, page.getWebResponse().getStatusCode());
}
/**
......@@ -148,7 +145,7 @@ public class AbstractProjectTest {
JenkinsRule.WebClient webClient = j.createWebClient();
HtmlPage page = webClient.getPage(j.jenkins.getItem("test0"));
page = (HtmlPage) page.getAnchorByText("Workspace").click();
page = page.getAnchorByText("Workspace").click();
try {
String wipeOutLabel = ResourceBundle.getBundle("hudson/model/AbstractProject/sidepanel").getString("Wipe Out Workspace");
page.getAnchorByText(wipeOutLabel);
......@@ -405,24 +402,21 @@ public class AbstractProjectTest {
j.jenkins.setNumExecutors(0);
FreeStyleProject p = j.createFreeStyleProject();
JenkinsRule.WebClient wc = j.createWebClient();
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
WebResponse rsp = wc.getPage(j.getURL() + p.getUrl() + "build").getWebResponse();
assertEquals(201, rsp.getStatusCode());
WebResponse rsp = wc.goTo(p.getUrl() + "build", null).getWebResponse();
assertEquals(HttpURLConnection.HTTP_CREATED, rsp.getStatusCode());
assertNotNull(rsp.getResponseHeaderValue("Location"));
WebResponse rsp2 = wc.getPage(j.getURL() + p.getUrl() + "build").getWebResponse();
assertEquals(201, rsp2.getStatusCode());
WebResponse rsp2 = wc.goTo(p.getUrl() + "build", null).getWebResponse();
assertEquals(HttpURLConnection.HTTP_CREATED, rsp2.getStatusCode());
assertEquals(rsp.getResponseHeaderValue("Location"), rsp2.getResponseHeaderValue("Location"));
p.makeDisabled(true);
try {
wc.getPage(j.getURL() + p.getUrl() + "build");
fail();
} catch (FailingHttpStatusCodeException e) {
// request should fail
}
WebResponse rsp3 = wc.goTo(p.getUrl() + "build", null).getWebResponse();
assertEquals(HttpURLConnection.HTTP_CONFLICT, rsp3.getStatusCode());
}
/**
......
......@@ -35,9 +35,10 @@ import org.jvnet.hudson.test.JenkinsRule;
import java.io.File;
import java.net.HttpURLConnection;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* @author Kohsuke Kawaguchi
......@@ -83,17 +84,13 @@ public class ApiTest {
@Issue("SECURITY-165")
@Test public void xPathDocumentFunction() throws Exception {
File f = new File(j.jenkins.getRootDir(), "queue.xml");
JenkinsRule.WebClient client = j.createWebClient();
try {
client.goTo("api/xml?xpath=document(\"" + f.getAbsolutePath() + "\")", "application/xml");
fail("Should become 500 error");
} catch (com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException e) {
String contentAsString = e.getResponse().getContentAsString();
j.assertStringContains(
contentAsString,
"Illegal function: document");
}
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
// could expect application/xml but as an error occurred it's a text/html that is returned
Page page = wc.goTo("api/xml?xpath=document(\"" + f.getAbsolutePath() + "\")", null);
assertEquals(HttpURLConnection.HTTP_INTERNAL_ERROR, page.getWebResponse().getStatusCode());
assertThat(page.getWebResponse().getContentAsString(), containsString("Illegal function: document"));
}
@Test
......
......@@ -24,7 +24,6 @@
package hudson.model;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import static org.junit.Assert.*;
......@@ -41,16 +40,10 @@ public class AsynchPeopleTest {
@Issue("JENKINS-18641")
@Test public void display() throws Exception {
User.get("bob");
User.getById( "bob", true);
JenkinsRule.WebClient wc = j.createWebClient();
HtmlPage page;
try {
page = wc.goTo("asynchPeople");
} catch (FailingHttpStatusCodeException x) {
System.err.println(x.getResponse().getResponseHeaders());
System.err.println(x.getResponse().getContentAsString());
throw x;
}
HtmlPage page = wc.goTo("asynchPeople");
assertEquals(0, wc.waitForBackgroundJavaScript(120000));
boolean found = false;
for (DomElement table : page.getElementsByTagName("table")) {
......
......@@ -25,15 +25,16 @@ package hudson.model;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.*;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.xml.XmlPage;
import java.io.File;
import java.net.HttpURLConnection;
import java.nio.charset.StandardCharsets;
import jenkins.model.Jenkins;
import hudson.slaves.DumbSlave;
......@@ -79,18 +80,15 @@ public class ComputerTest {
Node nodeA = j.createSlave("nodeA", null, null);
Node nodeB = j.createSlave("nodeB", null, null);
WebClient wc = j.createWebClient();
WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
HtmlForm form = wc.getPage(nodeB, "configure").getFormByName("config");
form.getInputByName("_.name").setValueAttribute("nodeA");
try {
j.submit(form);
fail(NOTE);
} catch (FailingHttpStatusCodeException e) {
assertThat(NOTE, e.getStatusCode(), equalTo(400));
assertThat(NOTE, e.getResponse().getContentAsString(),
containsString("Agent called ‘nodeA’ already exists"));
}
Page page = j.submit(form);
assertEquals(NOTE, HttpURLConnection.HTTP_BAD_REQUEST, page.getWebResponse().getStatusCode());
assertThat(NOTE, page.getWebResponse().getContentAsString(),
containsString("Agent called ‘nodeA’ already exists"));
}
@Test
......@@ -109,7 +107,7 @@ public class ComputerTest {
private void verifyOfflineCause(Computer computer) throws Exception {
XmlPage page = j.createWebClient().goToXml("computer/" + computer.getName() + "/config.xml");
String content = page.getWebResponse().getContentAsString("UTF-8");
String content = page.getWebResponse().getContentAsString(StandardCharsets.UTF_8);
assertThat(content, containsString("temporaryOfflineCause"));
assertThat(content, containsString("<userId>username</userId>"));
assertThat(content, not(containsString("ApiTokenProperty")));
......
......@@ -184,8 +184,8 @@ public class DirectlyModifiableViewTest {
}
private Page doPost(View view, String path) throws Exception {
WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
WebRequest req = new WebRequest(
new URL(j.jenkins.getRootUrl() + view.getUrl() + path),
HttpMethod.POST
......
......@@ -23,7 +23,6 @@
*/
package hudson.model;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
......@@ -243,13 +242,8 @@ public class DirectoryBrowserSupportTest {
p.getPublishersList().add(new ArtifactArchiver("f"));
j.buildAndAssertSuccess(p);
HtmlPage page = j.createWebClient().goTo("job/" + p.getName() + "/lastSuccessfulBuild/artifact/");
try {
Page download = page.getAnchorByText("f").click();
assertEquals("Hello world!", download.getWebResponse().getContentAsString());
} catch (FailingHttpStatusCodeException x) {
IOUtils.copy(x.getResponse().getContentAsStream(), System.err);
throw x;
}
Page download = page.getAnchorByText("f").click();
assertEquals("Hello world!", download.getWebResponse().getContentAsString());
}
/** Simulation of a storage service with URLs unrelated to {@link Run#doArtifact}. */
@TestExtension("externalURLDownload")
......
......@@ -25,7 +25,6 @@ package hudson.model;
import static org.junit.Assert.*;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebRequest;
......@@ -169,20 +168,19 @@ public class HudsonTest {
public void deleteHudsonComputer() throws Exception {
WebClient wc = j.createWebClient();
HtmlPage page = wc.goTo("computer/(master)/");
for (HtmlAnchor a : page.getAnchors())
assertFalse(a.getHrefAttribute(),a.getHrefAttribute().endsWith("delete"));
for (HtmlAnchor a : page.getAnchors()) {
assertFalse(a.getHrefAttribute(), a.getHrefAttribute().endsWith("delete"));
}
wc.setThrowExceptionOnFailingStatusCode(false);
// try to delete it by hitting the final URL directly
WebRequest req = new WebRequest(new URL(wc.getContextPath()+"computer/(master)/doDelete"), HttpMethod.POST);
try {
wc.getPage(wc.addCrumb(req));
fail("Error code expected");
} catch (FailingHttpStatusCodeException e) {
assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, e.getStatusCode());
}
page = wc.getPage(wc.addCrumb(req));
assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, page.getWebResponse().getStatusCode());
// the master computer object should be still here
wc.goTo("computer/(master)/");
page = wc.goTo("computer/(master)/");
assertEquals(HttpURLConnection.HTTP_OK, page.getWebResponse().getStatusCode());
}
/**
......
......@@ -191,9 +191,10 @@ public class ItemsTest {
/** Use the REST command to create an empty project (normally used only from the UI in the New Item dialog). */
REST_EMPTY {
@Override void run(JenkinsRule r, String target) throws Exception {
JenkinsRule.WebClient wc = wc(r);
wc.getOptions().setRedirectEnabled(false);
wc.getOptions().setThrowExceptionOnFailingStatusCode(false); // redirect perversely counts as a failure
JenkinsRule.WebClient wc = wc(r)
// redirect perversely counts as a failure
.withRedirectEnabled(false)
.withThrowExceptionOnFailingStatusCode(false);
WebResponse webResponse = wc.getPage(new WebRequest(new URL(wc.getContextPath() + "createItem?name=" + target + "&mode=hudson.model.FreeStyleProject"), HttpMethod.POST)).getWebResponse();
if (webResponse.getStatusCode() != HttpStatus.SC_MOVED_TEMPORARILY) {
throw new FailingHttpStatusCodeException(webResponse);
......@@ -204,9 +205,9 @@ public class ItemsTest {
REST_COPY {
@Override void run(JenkinsRule r, String target) throws Exception {
r.createFreeStyleProject("dupe");
JenkinsRule.WebClient wc = wc(r);
wc.getOptions().setRedirectEnabled(false);
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = wc(r)
.withRedirectEnabled(false)
.withThrowExceptionOnFailingStatusCode(false);
WebResponse webResponse = wc.getPage(new WebRequest(new URL(wc.getContextPath() + "createItem?name=" + target + "&mode=copy&from=dupe"), HttpMethod.POST)).getWebResponse();
r.jenkins.getItem("dupe").delete();
if (webResponse.getStatusCode() != HttpStatus.SC_MOVED_TEMPORARILY) {
......@@ -228,9 +229,9 @@ public class ItemsTest {
REST_RENAME {
@Override void run(JenkinsRule r, String target) throws Exception {
r.createFreeStyleProject("dupe");
JenkinsRule.WebClient wc = wc(r);
wc.getOptions().setRedirectEnabled(false);
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = wc(r)
.withRedirectEnabled(false)
.withThrowExceptionOnFailingStatusCode(false);
WebResponse webResponse = wc.getPage(new WebRequest(new URL(wc.getContextPath() + "job/dupe/doRename?newName=" + target), HttpMethod.POST)).getWebResponse();
if (webResponse.getStatusCode() != HttpStatus.SC_MOVED_TEMPORARILY) {
r.jenkins.getItem("dupe").delete();
......
......@@ -24,7 +24,7 @@
*/
package hudson.model;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebAssert;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlFormUtil;
......@@ -52,7 +52,6 @@ import java.util.concurrent.CountDownLatch;
import jenkins.model.ProjectNamingStrategy;
import jenkins.security.apitoken.ApiTokenPropertyConfiguration;
import jenkins.security.apitoken.ApiTokenTestHelper;
import org.hamcrest.Matchers;
import org.junit.Rule;
......@@ -221,14 +220,19 @@ public class JobTest {
try {
wc.assertFails("job/testJob/config.xml", HttpURLConnection.HTTP_FORBIDDEN);
wc.withBasicApiToken(User.getById("alice", true)); // Has CONFIGURE and EXTENDED_READ permission
tryConfigDotXml(wc, 500, "Both perms; should get 500");
wc.setThrowExceptionOnFailingStatusCode(false);
// Has CONFIGURE and EXTENDED_READ permission
wc.withBasicApiToken(User.getById("alice", true));
tryConfigDotXml(wc, HttpURLConnection.HTTP_INTERNAL_ERROR, "Both perms; should get 500");
wc.withBasicApiToken(User.getById("bob", true)); // Has only CONFIGURE permission (this should imply EXTENDED_READ)
tryConfigDotXml(wc, 500, "Config perm should imply EXTENDED_READ");
// Has only CONFIGURE permission (this should imply EXTENDED_READ)
wc.withBasicApiToken(User.getById("bob", true));
tryConfigDotXml(wc, HttpURLConnection.HTTP_INTERNAL_ERROR, "Config perm should imply EXTENDED_READ");
wc.withBasicApiToken(User.getById("charlie", true)); // Has only EXTENDED_READ permission
tryConfigDotXml(wc, 403, "No permission, should get 403");
// Has only EXTENDED_READ permission
wc.withBasicApiToken(User.getById("charlie", true));
tryConfigDotXml(wc, HttpURLConnection.HTTP_FORBIDDEN, "No permission, should get 403");
} finally {
Item.EXTENDED_READ.setEnabled(saveEnabled);
}
......@@ -236,17 +240,17 @@ public class JobTest {
private static void tryConfigDotXml(JenkinsRule.WebClient wc, int status, String msg) throws Exception {
// Verify we can GET the config.xml:
wc.goTo("job/testJob/config.xml", "application/xml");
Page p = wc.goTo("job/testJob/config.xml", "application/xml");
assertEquals("Retrieving config.xml should be ok", HttpURLConnection.HTTP_OK, p.getWebResponse().getStatusCode());
// This page is a simple form to POST to /job/testJob/config.xml
// But it posts invalid data so we expect 500 if we have permission, 403 if not
HtmlPage page = wc.goTo("userContent/post.html");
try {
HtmlFormUtil.submit(page.getForms().get(0));
fail("Expected exception: " + msg);
} catch (FailingHttpStatusCodeException expected) {
assertEquals(msg, status, expected.getStatusCode());
}
wc.goTo("logout");
p = HtmlFormUtil.submit(page.getForms().get(0));
assertEquals(msg, status, p.getWebResponse().getStatusCode());
p = wc.goTo("logout");
assertEquals("To logout should be ok", HttpURLConnection.HTTP_OK, p.getWebResponse().getStatusCode());
}
@LocalData @Issue("JENKINS-6371")
......
......@@ -23,7 +23,6 @@
*/
package hudson.model;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebRequest;
......@@ -448,12 +447,10 @@ public class NodeTest {
WebRequest settings = new WebRequest(wc.createCrumbedUrl("computer/(master)/config.xml"));
settings.setHttpMethod(HttpMethod.POST);
settings.setRequestBody("<hudson/>");
try {
Page page = wc.getPage(settings);
fail(page.getWebResponse().getContentAsString());
} catch (FailingHttpStatusCodeException x) {
assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, x.getStatusCode());
}
wc.setThrowExceptionOnFailingStatusCode(false);
Page page = wc.getPage(settings);
assertEquals(HttpURLConnection.HTTP_BAD_REQUEST, page.getWebResponse().getStatusCode());
}
/**
......
......@@ -51,22 +51,22 @@ public class ParametersTest {
CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder();
project.getBuildersList().add(builder);
WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
HtmlPage page = wc.goTo("job/" + project.getName() + "/build?delay=0sec");
HtmlForm form = page.getFormByName("parameters");
HtmlElement element = (HtmlElement) DomNodeUtil.selectSingleNode(form, "//tr[td/div/input/@value='string']");
HtmlElement element = DomNodeUtil.selectSingleNode(form, "//tr[td/div/input/@value='string']");
assertNotNull(element);
assertEquals("string description", ((HtmlElement) DomNodeUtil.selectSingleNode(element.getNextSibling().getNextSibling(), "td[@class='setting-description']")).getTextContent());
HtmlTextInput stringParameterInput = (HtmlTextInput) DomNodeUtil.selectSingleNode(element, ".//input[@name='value']");
HtmlTextInput stringParameterInput = DomNodeUtil.selectSingleNode(element, ".//input[@name='value']");
assertEquals("defaultValue", stringParameterInput.getAttribute("value"));
assertEquals("string", ((HtmlElement) DomNodeUtil.selectSingleNode(element, "td[@class='setting-name']")).getTextContent());
stringParameterInput.setAttribute("value", "newValue");
element = (HtmlElement) DomNodeUtil.selectSingleNode(form, "//tr[td/div/input/@value='boolean']");
element = DomNodeUtil.selectSingleNode(form, "//tr[td/div/input/@value='boolean']");
assertNotNull(element);
assertEquals("boolean description", ((HtmlElement) DomNodeUtil.selectSingleNode(element.getNextSibling().getNextSibling(), "td[@class='setting-description']")).getTextContent());
Object o = DomNodeUtil.selectSingleNode(element, ".//input[@name='value']");
......@@ -75,12 +75,12 @@ public class ParametersTest {
assertEquals(true, booleanParameterInput.isChecked());
assertEquals("boolean", ((HtmlElement) DomNodeUtil.selectSingleNode(element, "td[@class='setting-name']")).getTextContent());
element = (HtmlElement) DomNodeUtil.selectSingleNode(form, ".//tr[td/div/input/@value='choice']");
element = DomNodeUtil.selectSingleNode(form, ".//tr[td/div/input/@value='choice']");
assertNotNull(element);
assertEquals("choice description", ((HtmlElement) DomNodeUtil.selectSingleNode(element.getNextSibling().getNextSibling(), "td[@class='setting-description']")).getTextContent());
assertEquals("choice", ((HtmlElement) DomNodeUtil.selectSingleNode(element, "td[@class='setting-name']")).getTextContent());
element = (HtmlElement) DomNodeUtil.selectSingleNode(form, ".//tr[td/div/input/@value='run']");
element = DomNodeUtil.selectSingleNode(form, ".//tr[td/div/input/@value='run']");
assertNotNull(element);
assertEquals("run description", ((HtmlElement) DomNodeUtil.selectSingleNode(element.getNextSibling().getNextSibling(), "td[@class='setting-description']")).getTextContent());
assertEquals("run", ((HtmlElement) DomNodeUtil.selectSingleNode(element, "td[@class='setting-name']")).getTextContent());
......@@ -105,16 +105,16 @@ public class ParametersTest {
CaptureEnvironmentBuilder builder = new CaptureEnvironmentBuilder();
project.getBuildersList().add(builder);
WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
HtmlPage page = wc.goTo("job/" + project.getName() + "/build?delay=0sec");
HtmlForm form = page.getFormByName("parameters");
HtmlElement element = (HtmlElement) DomNodeUtil.selectSingleNode(form, ".//tr[td/div/input/@value='choice']");
HtmlElement element = DomNodeUtil.selectSingleNode(form, ".//tr[td/div/input/@value='choice']");
assertNotNull(element);
assertEquals("choice description", ((HtmlElement) DomNodeUtil.selectSingleNode(element.getNextSibling().getNextSibling(), "td[@class='setting-description']")).getTextContent());
assertEquals("choice", ((HtmlElement) DomNodeUtil.selectSingleNode(element, "td[@class='setting-name']")).getTextContent());
HtmlOption opt = (HtmlOption)DomNodeUtil.selectSingleNode(element, "td/div/select/option[@value='Choice <2>']");
HtmlOption opt = DomNodeUtil.selectSingleNode(element, "td/div/select/option[@value='Choice <2>']");
assertNotNull(opt);
assertEquals("Choice <2>", opt.asText());
opt.setSelected(true);
......@@ -192,8 +192,8 @@ public class ParametersTest {
new FileParameterDefinition("filename", "description"));
project.addProperty(pdp);
WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
HtmlPage page = wc.goTo("job/" + project.getName() + "/build?delay=0sec");
HtmlForm form = page.getFormByName("parameters");
......@@ -215,12 +215,13 @@ public class ParametersTest {
);
p.addProperty(pdb);
WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false); // Ignore 405
WebClient wc = j.createWebClient()
// Ignore 405
.withThrowExceptionOnFailingStatusCode(false);
HtmlPage page = wc.getPage(p, "build");
// java.lang.IllegalArgumentException: No such parameter definition: <gibberish>.
wc.getOptions().setThrowExceptionOnFailingStatusCode(true);
wc.setThrowExceptionOnFailingStatusCode(true);
final HtmlForm form = page.getFormByName("parameters");
HtmlFormUtil.submit(form, HtmlFormUtil.getButtonByCaption(form, "Build"));
}
......@@ -233,8 +234,8 @@ public class ParametersTest {
StringParameterDefinition param = new StringParameterDefinition("<param name>", "<param default>", "<param description>");
assertEquals("<b>[</b>param description<b>]</b>", param.getFormattedDescription());
p.addProperty(new ParametersDefinitionProperty(param));
WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
HtmlPage page = wc.getPage(p, "build?delay=0sec");
collector.checkThat(page.getWebResponse().getStatusCode(), is(HttpStatus.SC_METHOD_NOT_ALLOWED)); // 405 to dissuade scripts from thinking this triggered the build
String text = page.getWebResponse().getContentAsString();
......
......@@ -71,8 +71,9 @@ public class PasswordParameterDefinitionTest {
User admin = User.getById("admin", true);
User dev = User.getById("dev", true);
JenkinsRule.WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false); // ParametersDefinitionProperty/index.jelly sends a 405 but really it is OK
JenkinsRule.WebClient wc = j.createWebClient()
// ParametersDefinitionProperty/index.jelly sends a 405 but really it is OK
.withThrowExceptionOnFailingStatusCode(false);
// Control case: admin can use default value.
j.submit(wc.withBasicApiToken(admin).getPage(p, "build?delay=0sec").getFormByName("parameters"));
j.waitUntilNoActivity();
......
......@@ -25,6 +25,7 @@ package hudson.model;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.javascript.host.event.Event;
import hudson.*;
import hudson.model.queue.QueueTaskFuture;
import hudson.security.AccessDeniedException2;
......@@ -252,7 +253,8 @@ public class ProjectTest {
assertEquals("Scm retry count should be the same as global scm retry count.", 6, p.getScmCheckoutRetryCount());
HtmlForm form = j.createWebClient().goTo(p.getUrl() + "/configure").getFormByName("config");
((HtmlElement)form.getByXPath("//div[@class='advancedLink']//button").get(0)).click();
form.getInputByName("hasCustomScmCheckoutRetryCount").click();
// required due to the new default behavior of click
form.getInputByName("hasCustomScmCheckoutRetryCount").click(new Event(), true);
form.getInputByName("scmCheckoutRetryCount").setValueAttribute("7");
j.submit(form);
assertEquals("Scm retry count was set.", 7, p.getScmCheckoutRetryCount());
......
......@@ -59,9 +59,9 @@ public class QueueSEC891Test {
WebRequest request = new WebRequest(new URL(r.getURL() + urlProvider.apply(currentOne)), HttpMethod.POST);
{ // user without right cannot cancel
JenkinsRule.WebClient wc = r.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
wc.getOptions().setRedirectEnabled(false);
JenkinsRule.WebClient wc = r.createWebClient()
.withRedirectEnabled(false)
.withThrowExceptionOnFailingStatusCode(false);
wc.login("user");
Page p = wc.getPage(request);
// currently the endpoint return a redirection to the previously visited page, none in our case
......@@ -71,9 +71,9 @@ public class QueueSEC891Test {
assertFalse(currentOne.getFuture().isCancelled());
}
{ // user with right can
JenkinsRule.WebClient wc = r.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
wc.getOptions().setRedirectEnabled(false);
JenkinsRule.WebClient wc = r.createWebClient()
.withRedirectEnabled(false)
.withThrowExceptionOnFailingStatusCode(false);
wc.login("admin");
Page p = wc.getPage(request);
assertThat(p.getWebResponse().getStatusCode(), lessThan(400));
......
......@@ -32,16 +32,16 @@ public class UserRestartSEC897Test {
User.getById("admin", true).save();
{ // attempt with ".."
JenkinsRule.WebClient wc = rr.j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = rr.j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
WebRequest request = new WebRequest(new URL(rr.j.jenkins.getRootUrl() + "whoAmI/api/xml"));
request.setAdditionalHeader("Authorization", base64("..", "any-password"));
wc.getPage(request);
}
{ // attempt with "../users/.."
JenkinsRule.WebClient wc = rr.j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = rr.j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
WebRequest request = new WebRequest(new URL(rr.j.jenkins.getRootUrl() + "whoAmI/api/xml"));
request.setAdditionalHeader("Authorization", base64("../users/..", "any-password"));
......
......@@ -24,6 +24,7 @@
package hudson.model;
import com.cloudbees.hudson.plugins.folder.Folder;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.html.DomNodeUtil;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
......@@ -31,7 +32,6 @@ import jenkins.model.Jenkins;
import org.jenkins.ui.icon.Icon;
import org.jenkins.ui.icon.IconSet;
import org.jvnet.hudson.test.Issue;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
......@@ -56,6 +56,7 @@ import hudson.util.FormValidation;
import hudson.util.HudsonIsLoading;
import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
......@@ -120,19 +121,19 @@ public class ViewTest {
@Test public void conflictingName() throws Exception {
assertNull(j.jenkins.getView("foo"));
HtmlForm form = j.createWebClient().goTo("newView").getFormByName("createItem");
WebClient wc = j.createWebClient();
HtmlForm form = wc.goTo("newView").getFormByName("createItem");
form.getInputByName("name").setValueAttribute("foo");
form.getRadioButtonsByName("mode").get(0).setChecked(true);
j.submit(form);
assertNotNull(j.jenkins.getView("foo"));
wc.setThrowExceptionOnFailingStatusCode(false);
// do it again and verify an error
try {
j.submit(form);
fail("shouldn't be allowed to create two views of the same name.");
} catch (FailingHttpStatusCodeException e) {
assertEquals(400, e.getStatusCode());
}
Page page = j.submit(form);
assertEquals("shouldn't be allowed to create two views of the same name.",
HttpURLConnection.HTTP_BAD_REQUEST,
page.getWebResponse().getStatusCode());
}
@Test public void privateView() throws Exception {
......@@ -209,23 +210,24 @@ public class ViewTest {
IconSet.icons.addIcon(new Icon("icon-folder icon-md", "24x24/folder.gif", "width: 24px; height: 24px;"));
}
WebClient webClient = j.createWebClient();
WebClient webClient = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
webClient.getOptions().setJavaScriptEnabled(false);
j.assertAllImageLoadSuccessfully(webClient.goTo("asynchPeople"));
}
@Issue("JENKINS-16608")
@Test public void notAllowedName() throws Exception {
HtmlForm form = j.createWebClient().goTo("newView").getFormByName("createItem");
WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
HtmlForm form = wc.goTo("newView").getFormByName("createItem");
form.getInputByName("name").setValueAttribute("..");
form.getRadioButtonsByName("mode").get(0).setChecked(true);
try {
j.submit(form);
fail("\"..\" should not be allowed.");
} catch (FailingHttpStatusCodeException e) {
assertEquals(400, e.getStatusCode());
}
HtmlPage page = j.submit(form);
assertEquals("\"..\" should not be allowed.",
HttpURLConnection.HTTP_BAD_REQUEST,
page.getWebResponse().getStatusCode());
}
@Ignore("verified manually in Winstone but org.mortbay.JettyResponse.sendRedirect (6.1.26) seems to mangle the location")
......@@ -246,7 +248,7 @@ public class ViewTest {
ListView view = listView("v");
view.description = "one";
WebClient wc = j.createWebClient();
String xml = wc.goToXml("view/v/config.xml").getContent();
String xml = wc.goToXml("view/v/config.xml").getWebResponse().getContentAsString();
assertTrue(xml, xml.contains("<description>one</description>"));
xml = xml.replace("<description>one</description>", "<description>two</description>");
WebRequest req = new WebRequest(wc.createCrumbedUrl("view/v/config.xml"), HttpMethod.POST);
......
......@@ -27,12 +27,13 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import hudson.model.FreeStyleProject;
import hudson.model.ListView;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
......@@ -43,7 +44,6 @@ import hudson.model.User;
import hudson.model.View;
import hudson.security.ACL;
import hudson.security.ACLContext;
import hudson.security.AuthorizationStrategy;
import hudson.security.GlobalMatrixAuthorizationStrategy;
import jenkins.model.Jenkins;
import net.sf.json.JSONArray;
......@@ -58,8 +58,6 @@ import org.jvnet.hudson.test.JenkinsRule.WebClient;
import org.jvnet.hudson.test.MockAuthorizationStrategy;
import org.jvnet.hudson.test.MockFolder;
import com.gargoylesoftware.htmlunit.AlertHandler;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.Page;
/**
......@@ -74,12 +72,10 @@ public class SearchTest {
*/
@Test
public void testFailure() throws Exception {
try {
j.search("no-such-thing");
fail("404 expected");
} catch (FailingHttpStatusCodeException e) {
assertEquals(404,e.getResponse().getStatusCode());
}
WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
HtmlPage resultPage = wc.search("no-such-thing");
assertEquals(HttpURLConnection.HTTP_NOT_FOUND, resultPage.getWebResponse().getStatusCode());
}
/**
......@@ -88,18 +84,13 @@ public class SearchTest {
@Issue("JENKINS-3415")
@Test
public void testXSS() throws Exception {
try {
WebClient wc = j.createWebClient();
wc.setAlertHandler(new AlertHandler() {
public void handleAlert(Page page, String message) {
throw new AssertionError();
}
});
wc.search("<script>alert('script');</script>");
fail("404 expected");
} catch (FailingHttpStatusCodeException e) {
assertEquals(404,e.getResponse().getStatusCode());
}
WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
wc.setAlertHandler((page, message) -> {
throw new AssertionError();
});
HtmlPage resultPage = wc.search("<script>alert('script');</script>");
assertEquals(HttpURLConnection.HTTP_NOT_FOUND, resultPage.getWebResponse().getStatusCode());
}
@Test
......
......@@ -6,10 +6,8 @@
package hudson.security.csrf;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import jenkins.model.Jenkins;
import junit.framework.Assert;
import net.sf.json.JSONObject;
import org.junit.Before;
import org.junit.Rule;
......@@ -60,13 +58,11 @@ public class DefaultCrumbIssuerTest {
HtmlPage p = wc.goTo("configure");
wc.removeRequestHeader(HEADER_NAME);
try {
// The crumb should no longer match if we remove the proxy info
r.submit(p.getFormByName("config"));
}
catch (FailingHttpStatusCodeException e) {
assertEquals(403,e.getStatusCode());
}
wc.setThrowExceptionOnFailingStatusCode(false);
// The crumb should no longer match if we remove the proxy info
Page page = r.submit(p.getFormByName("config"));
assertEquals(HttpURLConnection.HTTP_FORBIDDEN, page.getWebResponse().getStatusCode());
}
@Issue("JENKINS-3854")
......@@ -139,17 +135,19 @@ public class DefaultCrumbIssuerTest {
@Issue("JENKINS-34254")
@Test public void testRequirePostErrorPageCrumb() throws Exception {
Jenkins.getInstance().setCrumbIssuer(new DefaultCrumbIssuer(false));
WebClient wc = r.createWebClient();
try {
wc.goTo("quietDown");
fail("expected failure");
} catch (FailingHttpStatusCodeException ex) {
Assert.assertEquals("expect HTTP 405 method not allowed", 405, ex.getStatusCode());
}
r.jenkins.setCrumbIssuer(new DefaultCrumbIssuer(false));
WebClient wc = r.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
Page page = wc.goTo("quietDown");
assertEquals("expect HTTP 405 method not allowed",
HttpURLConnection.HTTP_BAD_METHOD,
page.getWebResponse().getStatusCode());
HtmlPage retry = (HtmlPage) wc.getCurrentWindow().getEnclosedPage();
HtmlPage success = r.submit(retry.getFormByName("retry"));
Assert.assertTrue("quieting down", r.jenkins.isQuietingDown());
assertEquals(HttpURLConnection.HTTP_OK, success.getWebResponse().getStatusCode());
assertTrue("quieting down", r.jenkins.isQuietingDown());
}
}
......@@ -24,7 +24,6 @@
package hudson.tools;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.InteractivePage;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlTextInput;
......@@ -46,6 +45,7 @@ import org.jvnet.hudson.test.MockAuthorizationStrategy;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.reflect.Field;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
......@@ -88,12 +88,12 @@ public class ZipExtractionInstallerTest {
JenkinsRule.WebClient adminWc = j.createWebClient();
adminWc.login(ADMIN);
assertEquals(200, adminWc.getPage(request).getWebResponse().getStatusCode());
assertEquals(HttpURLConnection.HTTP_OK, adminWc.getPage(request).getWebResponse().getStatusCode());
JenkinsRule.WebClient userWc = j.createWebClient();
userWc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient userWc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
userWc.login(USER);
assertEquals(403, userWc.getPage(request).getWebResponse().getStatusCode());
assertEquals(HttpURLConnection.HTTP_FORBIDDEN, userWc.getPage(request).getWebResponse().getStatusCode());
}
@Test
......@@ -148,7 +148,7 @@ public class ZipExtractionInstallerTest {
}
@Override
public Object callFunction(InteractivePage page, Function function, Scriptable scope, Scriptable thisObject, Object[] args) {
public Object callFunction(HtmlPage page, Function function, Scriptable scope, Scriptable thisObject, Object[] args) {
if (thisObject instanceof XMLHttpRequest) {
try {
WebRequest request = getPrivateWebRequestField((XMLHttpRequest) thisObject);
......
......@@ -24,6 +24,7 @@
package hudson.util;
import com.gargoylesoftware.htmlunit.Page;
import hudson.cli.CLICommandInvoker;
import hudson.diagnosis.OldDataMonitor;
import hudson.model.AbstractDescribableImpl;
......@@ -38,6 +39,7 @@ import hudson.model.User;
import hudson.security.ACL;
import java.io.ByteArrayInputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
import java.util.Map;
......@@ -45,7 +47,6 @@ import java.util.Map;
import jenkins.model.Jenkins;
import static org.junit.Assert.*;
import jenkins.security.apitoken.ApiTokenPropertyConfiguration;
import jenkins.security.apitoken.ApiTokenTestHelper;
import net.sf.json.JSONObject;
......@@ -59,7 +60,6 @@ import org.jvnet.hudson.test.recipes.LocalData;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.WebRequest;
......@@ -236,18 +236,17 @@ public class RobustReflectionConverterTest {
// Configure a bad keyword via REST.
r.jenkins.setSecurityRealm(r.createDummySecurityRealm());
WebClient wc = r.createWebClient();
WebClient wc = r.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
wc.withBasicApiToken(test);
WebRequest req = new WebRequest(new URL(wc.getContextPath() + String.format("%s/config.xml", p.getUrl())), HttpMethod.POST);
req.setEncodingType(null);
req.setRequestBody(String.format(CONFIGURATION_TEMPLATE, AcceptOnlySpecificKeyword.ACCEPT_KEYWORD, "badvalue"));
try {
wc.getPage(req);
fail("Submitting unacceptable configuration via REST should fail.");
} catch (FailingHttpStatusCodeException e) {
// pass
}
Page page = wc.getPage(req);
assertEquals("Submitting unacceptable configuration via REST should fail.",
HttpURLConnection.HTTP_INTERNAL_ERROR,
page.getWebResponse().getStatusCode());
// Configuration should not be updated for a failure of the critical field,
assertNotEquals("badvalue", p.getProperty(KeywordProperty.class).getCriticalField().getKeyword());
......
......@@ -41,7 +41,10 @@ public class Jenkins19124Test {
JenkinsRule.WebClient wc = j.createWebClient();
HtmlPage c = wc.getPage(p, "configure");
HtmlTextInput alpha = c.getElementByName("_.alpha");
// the fireEvent is required as setValueAttribute's new behavior is not triggering the onChange event anymore
alpha.setValueAttribute("hello");
alpha.fireEvent("change");
WebClientUtil.waitForJSExec(wc);
assertEquals("hello", d.alpha);
assertEquals("2", d.bravo);
......
......@@ -337,33 +337,30 @@ public class JenkinsTest {
grant(Jenkins.READ).everywhere().to("bob").
grantWithoutImplication(Jenkins.ADMINISTER, Jenkins.READ).everywhere().to("charlie"));
WebClient wc = j.createWebClient();
WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false)
.withBasicApiToken(User.getById("alice", true));
wc.withBasicApiToken(User.getById("alice", true));
wc.assertFails("eval", HttpURLConnection.HTTP_BAD_METHOD);
assertEquals("3", eval(wc));
assertEquals("3", eval(wc).getWebResponse().getContentAsString());
wc.withBasicApiToken(User.getById("bob", true));
try {
eval(wc);
fail("bob has only READ");
} catch (FailingHttpStatusCodeException e) {
assertEquals(HttpURLConnection.HTTP_FORBIDDEN, e.getStatusCode());
}
Page page = eval(wc);
assertEquals("bob has only READ",
HttpURLConnection.HTTP_FORBIDDEN,
page.getWebResponse().getStatusCode());
wc.withBasicApiToken(User.getById("charlie", true));
try {
eval(wc);
fail("charlie has ADMINISTER but not RUN_SCRIPTS");
} catch (FailingHttpStatusCodeException e) {
assertEquals(HttpURLConnection.HTTP_FORBIDDEN, e.getStatusCode());
}
page = eval(wc);
assertEquals("charlie has ADMINISTER but not RUN_SCRIPTS",
HttpURLConnection.HTTP_FORBIDDEN,
page.getWebResponse().getStatusCode());
}
private String eval(WebClient wc) throws Exception {
private Page eval(WebClient wc) throws Exception {
WebRequest req = new WebRequest(new URL(wc.getContextPath() + "eval"), HttpMethod.POST);
req.setEncodingType(null);
req.setRequestBody("<j:jelly xmlns:j='jelly:core'>${1+2}</j:jelly>");
return wc.getPage(req).getWebResponse().getContentAsString();
return wc.getPage(req);
}
@TestExtension("testUnprotectedRootAction")
......@@ -411,13 +408,13 @@ public class JenkinsTest {
j.jenkins.setAuthorizationStrategy(auth);
// no anonymous read access
assertTrue(!Jenkins.getInstance().hasPermission(Jenkins.ANONYMOUS,Jenkins.READ));
assertTrue(!Jenkins.get().hasPermission(Jenkins.ANONYMOUS, Jenkins.READ));
WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
HtmlPage p = wc.goTo("error/reportError");
assertEquals(p.asText(), 400, p.getWebResponse().getStatusCode()); // not 403 forbidden
assertEquals(p.asText(), HttpURLConnection.HTTP_BAD_REQUEST, p.getWebResponse().getStatusCode()); // not 403 forbidden
assertTrue(p.getWebResponse().getContentAsString().contains("My car is black"));
}
......@@ -462,8 +459,8 @@ public class JenkinsTest {
URL url = new URL(j.getURL(), "computer/" + slave.getNodeName() + "/scriptText?script=println(42)");
WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
WebRequest req = new WebRequest(url, HttpMethod.POST);
Page page = wc.getPage(wc.addCrumb(req));
......
......@@ -24,6 +24,8 @@ import hudson.model.FreeStyleProject;
import hudson.model.User;
import hudson.security.ACL;
import hudson.security.ACLContext;
import java.net.HttpURLConnection;
import java.net.URL;
import jenkins.model.Jenkins;
......@@ -139,12 +141,14 @@ public class ApiTokenPropertyTest {
final ApiTokenProperty.DescriptorImpl descriptor = (ApiTokenProperty.DescriptorImpl) t.getDescriptor();
// Make sure that Admin can reset a token of another user
WebClient wc = createClientForUser("bar");
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
WebClient wc = createClientForUser("bar")
.withThrowExceptionOnFailingStatusCode(false);
HtmlPage requirePOST = wc.goTo(foo.getUrl() + "/" + descriptor.getDescriptorUrl()+ "/changeToken");
assertEquals("method should not be allowed", 405, requirePOST.getWebResponse().getStatusCode());
assertEquals("method should not be allowed",
HttpURLConnection.HTTP_BAD_METHOD,
requirePOST.getWebResponse().getStatusCode());
wc.getOptions().setThrowExceptionOnFailingStatusCode(true);
wc.setThrowExceptionOnFailingStatusCode(true);
WebRequest request = new WebRequest(new URL(j.getURL().toString() + foo.getUrl() + "/" + descriptor.getDescriptorUrl()+ "/changeToken"), HttpMethod.POST);
HtmlPage res = wc.getPage(request);
......@@ -163,7 +167,7 @@ public class ApiTokenPropertyTest {
WebClient wc = createClientForUser("foo");
WebRequest wr = new WebRequest(new URL(j.getURL(), "job/bar/build"), HttpMethod.POST);
assertEquals(201, wc.getPage(wr).getWebResponse().getStatusCode());
assertEquals(HttpURLConnection.HTTP_CREATED, wc.getPage(wr).getWebResponse().getStatusCode());
j.waitUntilNoActivity();
......
......@@ -11,7 +11,6 @@ import hudson.Util;
import hudson.util.Secret;
import hudson.util.SecretHelper;
import org.apache.commons.io.FileUtils;
import org.hamcrest.CoreMatchers;
import org.jvnet.hudson.test.HudsonTestCase;
import org.jvnet.hudson.test.recipes.Recipe.Runner;
import org.xml.sax.SAXException;
......@@ -22,8 +21,7 @@ import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.regex.Pattern;
import static org.junit.Assert.assertThat;
import java.util.stream.Stream;
/**
* @author Kohsuke Kawaguchi
......@@ -132,7 +130,18 @@ public class RekeySecretAdminMonitorTest extends HudsonTestCase {
}
private HtmlButton getButton(HtmlForm form, int index) {
return form.<HtmlButton>getHtmlElementsByTagName("button").get(index);
// due to the removal of method HtmlElement.getHtmlElementsByTagName
Stream<HtmlButton> buttonStream = form.getElementsByTagName("button").stream()
.filter(HtmlButton.class::isInstance)
.map(HtmlButton.class::cast);
if (index > 0) {
buttonStream = buttonStream.skip(index - 1);
}
return buttonStream
.findFirst()
.orElse(null);
}
public void testScanOnBoot() throws Exception {
......
......@@ -19,8 +19,8 @@ public class Security177Test {
@Test
public void nosniff() throws Exception {
WebClient wc = jenkins.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
WebClient wc = jenkins.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
URL u = jenkins.getURL();
verifyNoSniff(wc.getPage(new URL(u, "adjuncts/507db12b/nosuch/adjunct.js")));
......
......@@ -67,8 +67,9 @@ public class ApiTokenStatsTest {
assertNotNull(t.getTokenStats());
// test the authentication via Token
WebClient wc = j.createWebClient().withBasicCredentials(u.getId());
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
WebClient wc = j.createWebClient()
.withBasicCredentials(u.getId())
.withThrowExceptionOnFailingStatusCode(false);
final String TOKEN_NAME = "New Token Name";
......
......@@ -33,6 +33,7 @@ import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.TestPluginManager;
import java.net.HttpURLConnection;
import java.net.URL;
import static org.junit.Assert.assertEquals;
......@@ -53,8 +54,8 @@ public class Security914Test {
}
j.createWebClient().goTo("plugin/credentials/images/24x24/credentials.png", "image/png");
JenkinsRule.WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
WebRequest request = new WebRequest(new URL(j.getURL() + "plugin/credentials/.xml"));
// plugin deployed in: test\target\jenkins7375296945862059919tmp
// rootDir is in : test\target\jenkinsTests.tmp\jenkins1274934531848159942test
......@@ -62,7 +63,7 @@ public class Security914Test {
request.setAdditionalHeader("Accept-Language", "../../../../jenkinsTests.tmp/" + j.jenkins.getRootDir().getName() + "/config");
Page p = wc.getPage(request);
assertEquals(p.getWebResponse().getStatusCode(), 404);
assertEquals(HttpURLConnection.HTTP_NOT_FOUND, p.getWebResponse().getStatusCode());
assertNotEquals(p.getWebResponse().getContentType(), "application/xml");
}
......@@ -75,14 +76,14 @@ public class Security914Test {
}
j.createWebClient().goTo("plugin/credentials/images/24x24/credentials.png", "image/png");
JenkinsRule.WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
WebRequest request = new WebRequest(new URL(j.getURL() + "plugin/credentials/.ini"));
// ../ can be multiply to infinity, no impact, we just need to have enough to reach the root
request.setAdditionalHeader("Accept-Language", "../../../../../../../../../../../../windows/win");
Page p = wc.getPage(request);
assertEquals(p.getWebResponse().getStatusCode(), 404);
assertEquals(HttpURLConnection.HTTP_NOT_FOUND, p.getWebResponse().getStatusCode());
assertEquals(p.getWebResponse().getContentType(), "text/html");
}
}
......@@ -99,8 +99,8 @@ public class ExpandableTextboxTest {
private void checkRegularCase(TestRootAction testParams) throws Exception {
testParams.paramName = "testName";
JenkinsRule.WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
HtmlPage p = wc.goTo("test");
HtmlElementUtil.click(getExpandButton(p));
......@@ -110,8 +110,8 @@ public class ExpandableTextboxTest {
private void checkInjectionInName(TestRootAction testParams) throws Exception {
testParams.paramName = "testName',document.title='hacked'+'";
JenkinsRule.WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
HtmlPage p = wc.goTo("test");
HtmlElementUtil.click(getExpandButton(p));
......
......@@ -148,7 +148,7 @@ public class PasswordTest {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String pName = p.getFullName();
getJobCommand.main(Collections.singletonList(pName), Locale.ENGLISH, System.in, new PrintStream(baos), System.err);
assertEquals(xmlAdmin, baos.toString(configXml.getWebResponse().getContentCharset()));
assertEquals(xmlAdmin, baos.toString(configXml.getWebResponse().getContentCharset().name()));
CopyJobCommand copyJobCommand = new CopyJobCommand();
copyJobCommand.setTransportAuth(adminAuth);
String pAdminName = pName + "-admin";
......@@ -171,7 +171,7 @@ public class PasswordTest {
getJobCommand.setTransportAuth(devAuth);
baos = new ByteArrayOutputStream();
getJobCommand.main(Collections.singletonList(pName), Locale.ENGLISH, System.in, new PrintStream(baos), System.err);
assertEquals(xmlDev, baos.toString(configXml.getWebResponse().getContentCharset()));
assertEquals(xmlDev, baos.toString(configXml.getWebResponse().getContentCharset().name()));
copyJobCommand = new CopyJobCommand();
copyJobCommand.setTransportAuth(devAuth);
String pDevName = pName + "-dev";
......@@ -194,7 +194,9 @@ public class PasswordTest {
}
VulnerableProperty.DescriptorImpl.incomingURL = null;
String secret = "s3cr3t";
// the fireEvent is required as setText's new behavior is not triggering the onChange event anymore
field.setText(secret);
field.fireEvent("change");
while (VulnerableProperty.DescriptorImpl.incomingURL == null) {
Thread.sleep(100); // form validation of edited value
}
......
......@@ -128,8 +128,8 @@ public class ValidateButtonTest {
descriptor.paramMethod = "validateInjection";
descriptor.paramWith = "a,b";
JenkinsRule.WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
HtmlPage p = wc.goTo("test");
descriptor.wasCalled = false;
......@@ -142,8 +142,8 @@ public class ValidateButtonTest {
descriptor.paramMethod = "validateInjection',document.title='hacked'+'";
descriptor.paramWith = "a,b";
JenkinsRule.WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(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)
......@@ -156,8 +156,8 @@ public class ValidateButtonTest {
descriptor.paramMethod = "validateInjection";
descriptor.paramWith = "a,b',document.title='hacked'+'";
JenkinsRule.WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
HtmlPage p = wc.goTo("test");
descriptor.wasCalled = false;
......
......@@ -41,6 +41,8 @@ import org.kohsuke.stapler.WebMethod;
import javax.annotation.CheckForNull;
import java.net.HttpURLConnection;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
......@@ -111,8 +113,8 @@ public class ConfirmationLinkTest {
}
private Page getPageAfterClick() throws Exception {
JenkinsRule.WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
HtmlPage p = wc.goTo("test");
return HtmlElementUtil.click(getClickableLink(p));
......@@ -124,15 +126,15 @@ public class ConfirmationLinkTest {
testParams.paramClass = null;
testParams.paramPost = null;
JenkinsRule.WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(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());
assertEquals(HttpURLConnection.HTTP_NOT_FOUND, pageAfterClick.getWebResponse().getStatusCode());
}
private void checkInjectionInMessage(TestRootAction testParams) throws Exception {
......@@ -141,14 +143,14 @@ public class ConfirmationLinkTest {
testParams.paramClass = null;
testParams.paramPost = null;
JenkinsRule.WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(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());
assertEquals(HttpURLConnection.HTTP_OK, pageAfterClick.getWebResponse().getStatusCode());
}
private void checkInjectionInPost(TestRootAction testParams) throws Exception {
......@@ -157,15 +159,15 @@ public class ConfirmationLinkTest {
testParams.paramClass = null;
testParams.paramPost = postPayload;
JenkinsRule.WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(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());
assertEquals(HttpURLConnection.HTTP_OK, pageAfterClick.getWebResponse().getStatusCode());
}
private HtmlAnchor getClickableLink(HtmlPage page){
......
......@@ -77,8 +77,8 @@ public class StopButtonTest {
testParams.paramAlt = "Alternative text for icon";
testParams.paramConfirm = null;
JenkinsRule.WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
HtmlPage p = wc.goTo("test");
HtmlElementUtil.click(getStopLink(p));
......@@ -91,8 +91,8 @@ public class StopButtonTest {
testParams.paramAlt = "Alternative text for icon";
testParams.paramConfirm = "Confirm message";
JenkinsRule.WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
HtmlPage p = wc.goTo("test");
HtmlElementUtil.click(getStopLink(p));
......@@ -105,8 +105,8 @@ public class StopButtonTest {
testParams.paramAlt = "Alternative text for icon";
testParams.paramConfirm = postPayload;
JenkinsRule.WebClient wc = j.createWebClient();
wc.getOptions().setThrowExceptionOnFailingStatusCode(false);
JenkinsRule.WebClient wc = j.createWebClient()
.withThrowExceptionOnFailingStatusCode(false);
HtmlPage p = wc.goTo("test");
HtmlElementUtil.click(getStopLink(p));
......
......@@ -49,7 +49,7 @@ THE SOFTWARE.
<dependency>
<groupId>org.jenkins-ci</groupId>
<artifactId>executable-war</artifactId>
<version>1.44</version>
<version>1.45</version>
<scope>provided</scope>
</dependency>
<dependency>
......@@ -130,7 +130,7 @@ THE SOFTWARE.
<dependency>
<groupId>org.jenkins-ci.modules</groupId>
<artifactId>sshd</artifactId>
<version>2.5</version>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.ui</groupId>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册