* Also checks if .cvspass file contains the entry for this. */ - public void doCheckCvsRoot(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { - new FormFieldValidator(req,rsp,false) { - protected void check() throws IOException, ServletException { - String v = fixEmpty(request.getParameter("value")); - if(v==null) { - error(Messages.CVSSCM_MissingCvsroot()); - return; - } - - Matcher m = CVSROOT_PSERVER_PATTERN.matcher(v); + public FormValidation doCheckCvsRoot(@QueryParameter String value) throws IOException { + String v = fixEmpty(value); + if(v==null) + return FormValidation.error(Messages.CVSSCM_MissingCvsroot()); + + Matcher m = CVSROOT_PSERVER_PATTERN.matcher(v); + + // CVSROOT format isn't really that well defined. So it's hard to check this rigorously. + if(v.startsWith(":pserver") || v.startsWith(":ext")) { + if(!m.matches()) + return FormValidation.error(Messages.CVSSCM_InvalidCvsroot()); + // I can't really test if the machine name exists, either. + // some cvs, such as SOCKS-enabled cvs can resolve host names that Hudson might not + // be able to. If :ext is used, all bets are off anyway. + } - // CVSROOT format isn't really that well defined. So it's hard to check this rigorously. - if(v.startsWith(":pserver") || v.startsWith(":ext")) { - if(!m.matches()) { - error(Messages.CVSSCM_InvalidCvsroot()); - return; - } - // I can't really test if the machine name exists, either. - // some cvs, such as SOCKS-enabled cvs can resolve host names that Hudson might not - // be able to. If :ext is used, all bets are off anyway. + // check .cvspass file to see if it has entry. + // CVS handles authentication only if it's pserver. + if(v.startsWith(":pserver")) { + if(m.group(2)==null) {// if password is not specified in CVSROOT + String cvspass = getCvspassFile(); + File passfile; + if(cvspass.equals("")) { + passfile = new File(new File(System.getProperty("user.home")),".cvspass"); + } else { + passfile = new File(cvspass); } - // check .cvspass file to see if it has entry. - // CVS handles authentication only if it's pserver. - if(v.startsWith(":pserver")) { - if(m.group(2)==null) {// if password is not specified in CVSROOT - String cvspass = getCvspassFile(); - File passfile; - if(cvspass.equals("")) { - passfile = new File(new File(System.getProperty("user.home")),".cvspass"); - } else { - passfile = new File(cvspass); - } - - if(passfile.exists()) { - // It's possible that we failed to locate the correct .cvspass file location, - // so don't report an error if we couldn't locate this file. - // - // if this is explicitly specified, then our system config page should have - // reported an error. - if(!scanCvsPassFile(passfile, v)) { - error(Messages.CVSSCM_PasswordNotSet()); - return; - } - } - } + if(passfile.exists()) { + // It's possible that we failed to locate the correct .cvspass file location, + // so don't report an error if we couldn't locate this file. + // + // if this is explicitly specified, then our system config page should have + // reported an error. + if(!scanCvsPassFile(passfile, v)) + return FormValidation.error(Messages.CVSSCM_PasswordNotSet()); } - - // all tests passed so far - ok(); } - }.process(); + } + return FormValidation.ok(); } - /** + /** * Validates the excludeRegions Regex */ - public void doExcludeRegionsCheck(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { - new FormFieldValidator(req,rsp,false) { - protected void check() throws IOException, ServletException { - String v = fixEmptyAndTrim(request.getParameter("value")); - - if(v != null) { - String[] regions = v.split("[\\r\\n]+"); - for (String region : regions) { - try { - Pattern.compile(region); - } - catch (PatternSyntaxException e) { - error("Invalid regular expression. " + e.getMessage()); - } - } - } - ok(); + public FormValidation doExcludeRegionsCheck(@QueryParameter String value) { + String v = fixNull(value).trim(); + + for (String region : v.split("[\\r\\n]+")) + try { + Pattern.compile(region); + } catch (PatternSyntaxException e) { + return FormValidation.error("Invalid regular expression. " + e.getMessage()); } - }.process(); + return FormValidation.ok(); } /** diff --git a/core/src/main/java/hudson/util/FormValidation.java b/core/src/main/java/hudson/util/FormValidation.java new file mode 100644 index 0000000000000000000000000000000000000000..c1dc14127772383ee1a15d5f15dd0f90a1b9ee59 --- /dev/null +++ b/core/src/main/java/hudson/util/FormValidation.java @@ -0,0 +1,173 @@ +/* + * The MIT License + * + * Copyright (c) 2004-2009, Sun Microsystems, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package hudson.util; + +import org.kohsuke.stapler.HttpResponse; +import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerResponse; + +import javax.servlet.ServletException; +import java.io.IOException; + +import hudson.Util; +import hudson.scm.CVSSCM; +import hudson.model.Hudson; + +/** + * Represents the result of the form field validation. + * + *
+ * Use one of the factory methods to create an instance, then return it from your doCheckXyz + * method. (Via {@link HttpResponse}, the returned object will render the result into {@link StaplerResponse}.) + * This way of designing form field validation allows you to reuse {@code doCheckXyz()} methods + * programmatically as well (by using {@link #kind}. + * + *
+ * See {@link CVSSCM.DescriptorImpl#doCheckCvsRoot(String)} as an example. + * + * @author Kohsuke Kawaguchi + * @since 1.294 + */ +public abstract class FormValidation implements HttpResponse { + /** + * Indicates the kind of result. + */ + public enum Kind { + /** + * Form field value was OK and no problem was detected. + */ + OK, + /** + * Form field value contained something suspicious. For some limited use cases + * the value could be valid, but we suspect the user made a mistake. + */ + WARNING, + /** + * Form field value contained a problem that should be corrected. + */ + ERROR + } + + public static FormValidation ok() { + return OK; + } + + /** + * Sends out a string error message that indicates an error. + * + * @param message + * Human readable message to be sent. error(null) + * can be used as ok(). + */ + public static FormValidation error(String message) { + return errorWithMarkup(message==null?null: Util.escape(message)); + } + + public static FormValidation warning(String message) { + return warningWithMarkup(message==null?null:Util.escape(message)); + } + + public static FormValidation ok(String message) { + return okWithMarkup(message==null?null:Util.escape(message)); + } + + /** + * Sends out a string error message that indicates an error, + * by formatting it with {@link String#format(String, Object[])} + */ + public static FormValidation error(String format, Object... args) { + return error(String.format(format,args)); + } + + public static FormValidation warning(String format, Object... args) { + return warning(String.format(format,args)); + } + + public static FormValidation ok(String format, Object... args) { + return ok(String.format(format,args)); + } + + /** + * Sends out an HTML fragment that indicates an error. + * + *
+ * This method must be used with care to avoid cross-site scripting + * attack. + * + * @param message + * Human readable message to be sent. error(null) + * can be used as ok(). + */ + public static FormValidation errorWithMarkup(String message) { + return _errorWithMarkup(message,Kind.ERROR); + } + + public static FormValidation warningWithMarkup(String message) { + return _errorWithMarkup(message,Kind.WARNING); + } + + public static FormValidation okWithMarkup(String message) { + return _errorWithMarkup(message,Kind.OK); + } + + private static FormValidation _errorWithMarkup(final String message, final Kind kind) { + if(message==null) + return ok(); + return new FormValidation(kind) { + public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) throws IOException, ServletException { + // 1x16 spacer needed for IE since it doesn't support min-height + respond(rsp,"