Index: java/org/apache/catalina/servlets/CGIServlet.java =================================================================== --- java/org/apache/catalina/servlets/CGIServlet.java (Revision 1811444) +++ java/org/apache/catalina/servlets/CGIServlet.java (Arbeitskopie) @@ -276,6 +276,15 @@ private Pattern envHttpHeadersPattern = Pattern.compile( "ACCEPT[-0-9A-Z]*|CACHE-CONTROL|COOKIE|HOST|IF-[-0-9A-Z]*|REFERER|USER-AGENT"); + /** Additional methods (other than GET and PUT) to handle by the servlet. */ + private Pattern additionalMethodsPattern = null; + + /** Methods that may require request body data (a. k. a. "POST data") */ + private Pattern requestBodyMethodsPattern = Pattern.compile("POST"); + + /** Additional methods for OPTIONS method */ + private String additionalMethodsForOptions = ""; + /** object used to ensure multiple threads don't try to expand same file */ private static final Object expandFileLock = new Object(); @@ -360,6 +369,28 @@ Pattern.compile(getServletConfig().getInitParameter("envHttpHeaders")); } + if (getServletConfig().getInitParameter("additionalMethods") != null) { + String methodsConf = getServletConfig().getInitParameter("additionalMethods") + ","; + if (!methodsConf.matches("([\\-\\+][A-Z]+,)+")) { + throw new ServletException(sm.getString("cgiServlet.badAdditionalMethodsConfig")); + } + String withAndWithoutRequestBody = methodsConf.replaceAll(".([A-Z]+),", "|$1"); + String withRequestBody + = methodsConf.replaceAll("(?:-[A-Z]+,)*\\+([A-Z]+),(?:-[A-Z]+,)*", "|$1"); + + additionalMethodsPattern = withAndWithoutRequestBody.isEmpty() ? null + : Pattern.compile(withAndWithoutRequestBody.substring(1)); + + if (!withRequestBody.isEmpty()) { + requestBodyMethodsPattern = Pattern.compile("POST|" + withRequestBody.substring(1)); + } + + additionalMethodsForOptions = methodsConf.replaceAll( + "(?:.GET,|.HEAD,|.POST,|.TRACE,|.OPTIONS,)*" + + ".(?!GET,|HEAD,|POST,|TRACE,|OPTIONS,)([A-Z]+)," + + "(?:.GET,|.HEAD,|.POST,|.TRACE,|.OPTIONS,)*", ", $1"); + } + if (getServletConfig().getInitParameter("enableCmdLineArguments") != null) { enableCmdLineArguments = Boolean.parseBoolean(config.getInitParameter("enableCmdLineArguments")); @@ -496,6 +527,30 @@ } } + /** + * Handle special WebDAV and other methods. + */ + @Override + protected void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + if (additionalMethodsPattern != null + && additionalMethodsPattern.matcher(req.getMethod()).matches()) { + doGet(req, resp); + } + else { + super.service(req, resp); // DefaultServlet processing + } + } + + /** + * Return header with allowed HTTP methods. + */ + @Override + protected void doOptions(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + super.doOptions(req, resp); + resp.setHeader("Allow", resp.getHeader("Allow") + additionalMethodsForOptions); + } /** * Provides CGI Gateway service -- delegates to @@ -535,7 +590,7 @@ cgiEnv.getWorkingDirectory(), cgiEnv.getParameters()); - if ("POST".equals(req.getMethod())) { + if (requestBodyMethodsPattern.matcher(req.getMethod()).matches()) { cgi.setInput(req.getInputStream()); } cgi.setResponse(res); @@ -1524,9 +1579,7 @@ cmdAndArgs.toArray(new String[cmdAndArgs.size()]), hashToStringArray(env), wd); - String sContentLength = env.get("CONTENT_LENGTH"); - - if(!"".equals(sContentLength)) { + if(stdin != null) { commandsStdIn = new BufferedOutputStream(proc.getOutputStream()); IOTools.flow(stdin, commandsStdIn); commandsStdIn.flush(); Index: java/org/apache/catalina/servlets/LocalStrings.properties =================================================================== --- java/org/apache/catalina/servlets/LocalStrings.properties (Revision 1811444) +++ java/org/apache/catalina/servlets/LocalStrings.properties (Arbeitskopie) @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +cgiServlet.badAdditionalMethodsConfig=Additional method names must be upper case, separated by comma (,), no white space allowed [additionalMethods] cgiServlet.emptyEnvVarName=Empty environment variable name in initialisation parameter [environment-variable-] cgiServlet.expandCloseFail=Failed to close input stream for script at path [{0}] cgiServlet.expandCreateDirFail=Failed to create destination directory [{0}] for script expansion Index: webapps/docs/cgi-howto.xml =================================================================== --- webapps/docs/cgi-howto.xml (Revision 1811444) +++ webapps/docs/cgi-howto.xml (Arbeitskopie) @@ -117,6 +117,18 @@ name must match the pattern. Default is ACCEPT[-0-9A-Z]*|CACHE-CONTROL|COOKIE|HOST|IF-[-0-9A-Z]*|REFERER|USER-AGENT +
  • additionalMethods - A list of additionally allowed HTTP +methods. Default handles: + +List items are separarated by comma (,) and must be prefixed by + or -, ++ meaning "handle request body data", - meaning "forbid request body data". If +the list contains HEAD, TRACE or OPTIONS, the request is forwarded to the CGI +script and not handled by HttpServlet. Example (for Nextcloud version 12): +-DELETE,+MKCALENDAR,+MKCOL,+PROPFIND,+PROPPATCH,+PUT,+REPORT +
  • parameterEncoding - Name of the parameter encoding to be used with the CGI servlet. Default is System.getProperty("file.encoding","UTF-8"). That is the system