This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/10.1.x by this push:
     new 2c6800111e Refactor CGI servlet to access resources via WebResources
2c6800111e is described below

commit 2c6800111e7d8d8d5403c07978ea9bff3db5a5a5
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Mon Apr 28 12:58:21 2025 +0100

    Refactor CGI servlet to access resources via WebResources
---
 java/org/apache/catalina/servlets/CGIServlet.java  | 233 ++++++++-------------
 .../catalina/servlets/LocalStrings.properties      |   1 -
 .../catalina/servlets/LocalStrings_fr.properties   |   1 -
 .../catalina/servlets/LocalStrings_ja.properties   |   1 -
 .../catalina/servlets/LocalStrings_ko.properties   |   1 -
 .../servlets/LocalStrings_zh_CN.properties         |   1 -
 webapps/docs/changelog.xml                         |   4 +
 7 files changed, 97 insertions(+), 145 deletions(-)

diff --git a/java/org/apache/catalina/servlets/CGIServlet.java 
b/java/org/apache/catalina/servlets/CGIServlet.java
index 3c1b7bd6d2..b005d5621e 100644
--- a/java/org/apache/catalina/servlets/CGIServlet.java
+++ b/java/org/apache/catalina/servlets/CGIServlet.java
@@ -24,6 +24,8 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.net.URLDecoder;
 import java.nio.file.Files;
 import java.util.ArrayList;
@@ -621,9 +623,6 @@ public final class CGIServlet extends HttpServlet {
         /** pathInfo for the current request */
         private String pathInfo = null;
 
-        /** real file system directory of the enclosing servlet's web app */
-        private String webAppRootDir = null;
-
         /** tempdir for context - used to expand scripts in unexpanded wars */
         private File tmpDir = null;
 
@@ -677,7 +676,6 @@ public final class CGIServlet extends HttpServlet {
          */
         protected void setupFromContext(ServletContext context) {
             this.context = context;
-            this.webAppRootDir = context.getRealPath("/");
             this.tmpDir = (File) context.getAttribute(ServletContext.TEMPDIR);
         }
 
@@ -781,10 +779,9 @@ public final class CGIServlet extends HttpServlet {
          * cgiPathPrefix is defined by setting this servlet's cgiPathPrefix 
init parameter
          * </p>
          *
-         * @param pathInfo      String from HttpServletRequest.getPathInfo()
-         * @param webAppRootDir String from context.getRealPath("/")
          * @param contextPath   String as from 
HttpServletRequest.getContextPath()
          * @param servletPath   String as from 
HttpServletRequest.getServletPath()
+         * @param pathInfo      String from HttpServletRequest.getPathInfo()
          * @param cgiPathPrefix subdirectory of webAppRootDir below which the 
web app's CGIs may be stored; can be null.
          *                          The CGI search path will start at 
webAppRootDir + File.separator + cgiPathPrefix (or
          *                          webAppRootDir alone if cgiPathPrefix is 
null). cgiPathPrefix is defined by setting
@@ -801,59 +798,108 @@ public final class CGIServlet extends HttpServlet {
          *             found
          *             </ul>
          */
-        protected String[] findCGI(String pathInfo, String webAppRootDir, 
String contextPath, String servletPath,
-                String cgiPathPrefix) {
-            String path;
-            String name;
-            String scriptname;
-
-            if (webAppRootDir.lastIndexOf(File.separator) == 
(webAppRootDir.length() - 1)) {
-                // strip the trailing "/" from the webAppRootDir
-                webAppRootDir = webAppRootDir.substring(0, 
(webAppRootDir.length() - 1));
-            }
+        protected String[] findCGI(String contextPath, String servletPath, 
String pathInfo, String cgiPathPrefix) {
 
-            if (cgiPathPrefix != null) {
-                webAppRootDir = webAppRootDir + File.separator + cgiPathPrefix;
-            }
+            StringBuilder cgiPath = new StringBuilder();
+            StringBuilder urlPath = new StringBuilder();
 
-            if (log.isTraceEnabled()) {
-                log.trace(sm.getString("cgiServlet.find.path", pathInfo, 
webAppRootDir));
-            }
+            URL cgiScriptURL = null;
 
-            File currentLocation = new File(webAppRootDir);
-            StringTokenizer dirWalker = new StringTokenizer(pathInfo, "/");
-            if (log.isTraceEnabled()) {
-                log.trace(sm.getString("cgiServlet.find.location", 
currentLocation.getAbsolutePath()));
+            if (cgiPathPrefix == null || cgiPathPrefix.isEmpty()) {
+                cgiPath.append(servletPath);
+            } else {
+                cgiPath.append('/');
+                cgiPath.append(cgiPathPrefix);
             }
-            StringBuilder cginameBuilder = new StringBuilder();
-            while (!currentLocation.isFile() && dirWalker.hasMoreElements()) {
-                String nextElement = (String) dirWalker.nextElement();
-                currentLocation = new File(currentLocation, nextElement);
-                cginameBuilder.append('/').append(nextElement);
+            urlPath.append(servletPath);
+
+            StringTokenizer pathWalker = new StringTokenizer(pathInfo, "/");
+
+            while (pathWalker.hasMoreElements() && cgiScriptURL == null) {
+                String urlSegment = pathWalker.nextToken();
+                cgiPath.append('/');
+                cgiPath.append(urlSegment);
+                urlPath.append('/');
+                urlPath.append(urlSegment);
                 if (log.isTraceEnabled()) {
-                    log.trace(sm.getString("cgiServlet.find.location", 
currentLocation.getAbsolutePath()));
+                    log.trace(sm.getString("cgiServlet.find.location", 
cgiPath.toString()));
+                }
+                try {
+                    cgiScriptURL = context.getResource(cgiPath.toString());
+                } catch (MalformedURLException e) {
+                    // Ignore - should never happen
                 }
             }
-            String cginame = cginameBuilder.toString();
-            if (!currentLocation.isFile()) {
+
+            // No script was found
+            if (cgiScriptURL == null) {
                 return new String[] { null, null, null, null };
             }
 
-            path = currentLocation.getAbsolutePath();
-            name = currentLocation.getName();
+            // Set-up return values
+            String path = null;
+            String scriptName = null;
+            String cgiName = null;
+            String name = null;
 
-            if (servletPath.startsWith(cginame)) {
-                scriptname = contextPath + cginame;
-            } else {
-                scriptname = contextPath + servletPath + cginame;
+            path = context.getRealPath(cgiPath.toString());
+            if (path == null) {
+                /*
+                 * The script doesn't exist directly on the file system. It 
might be located in an archive or similar.
+                 * Such scripts are extracted to the web application's 
temporary file location.
+                 */
+                File tmpCgiFile = new File(tmpDir + cgiPath.toString());
+                if (!tmpCgiFile.exists()) {
+
+                    // Create directories
+                    File parent = tmpCgiFile.getParentFile();
+                    if (!parent.mkdirs() && !parent.isDirectory()) {
+                        
log.warn(sm.getString("cgiServlet.expandCreateDirFail", 
parent.getAbsolutePath()));
+                        return new String[] { null, null, null, null };
+                    }
+
+                    try (InputStream is = 
context.getResourceAsStream(cgiPath.toString())) {
+                        synchronized (expandFileLock) {
+                            // Check if file was created by concurrent request
+                            if (!tmpCgiFile.exists()) {
+                                try {
+                                    Files.copy(is, tmpCgiFile.toPath());
+                                } catch (IOException ioe) {
+                                    
log.warn(sm.getString("cgiServlet.expandFail", cgiScriptURL,
+                                            tmpCgiFile.getAbsolutePath()), 
ioe);
+                                    if (tmpCgiFile.exists()) {
+                                        if (!tmpCgiFile.delete()) {
+                                            
log.warn(sm.getString("cgiServlet.expandDeleteFail",
+                                                    
tmpCgiFile.getAbsolutePath()));
+                                        }
+                                    }
+                                    return new String[] { null, null, null, 
null };
+                                }
+                                if (log.isDebugEnabled()) {
+                                    
log.debug(sm.getString("cgiServlet.expandOk", cgiScriptURL,
+                                            tmpCgiFile.getAbsolutePath()));
+                                }
+                            }
+                        }
+                    } catch (IOException ioe) {
+                        log.warn(sm.getString("cgiServlet.expandCloseFail", 
cgiScriptURL), ioe);
+                    }
+                }
+                path = tmpCgiFile.getAbsolutePath();
             }
 
+            scriptName = urlPath.toString();
+            cgiName = scriptName.substring(servletPath.length());
+            name = scriptName.substring(scriptName.lastIndexOf('/') + 1);
+
             if (log.isTraceEnabled()) {
-                log.trace(sm.getString("cgiServlet.find.found", name, path, 
scriptname, cginame));
+                log.trace(sm.getString("cgiServlet.find.found", name, path, 
scriptName, cgiName));
             }
-            return new String[] { path, scriptname, cginame, name };
+
+            return new String[] { path, scriptName, cgiName, name };
         }
 
+
         /**
          * Constructs the CGI environment to be supplied to the invoked CGI 
script; relies heavily on Servlet API
          * methods and findCGI
@@ -888,13 +934,7 @@ public final class CGIServlet extends HttpServlet {
             sPathInfoOrig = this.pathInfo;
             sPathInfoOrig = sPathInfoOrig == null ? "" : sPathInfoOrig;
 
-            if (webAppRootDir == null) {
-                // The app has not been deployed in exploded form
-                webAppRootDir = tmpDir.toString();
-                expandCGIScript();
-            }
-
-            sCGINames = findCGI(sPathInfoOrig, webAppRootDir, contextPath, 
servletPath, cgiPathPrefix);
+            sCGINames = findCGI(contextPath, servletPath, sPathInfoOrig, 
cgiPathPrefix);
 
             sCGIFullPath = sCGINames[0];
             sCGIScriptName = sCGINames[1];
@@ -1020,93 +1060,6 @@ public final class CGIServlet extends HttpServlet {
             return true;
         }
 
-        /**
-         * Extracts requested resource from web app archive to context work 
directory to enable CGI script to be
-         * executed.
-         */
-        protected void expandCGIScript() {
-            StringBuilder srcPath = new StringBuilder();
-            StringBuilder destPath = new StringBuilder();
-            InputStream is = null;
-
-            // paths depend on mapping
-            if (cgiPathPrefix == null) {
-                srcPath.append(pathInfo);
-                is = context.getResourceAsStream(srcPath.toString());
-                destPath.append(tmpDir);
-                destPath.append(pathInfo);
-            } else {
-                // essentially same search algorithm as findCGI()
-                srcPath.append(cgiPathPrefix);
-                StringTokenizer pathWalker = new StringTokenizer(pathInfo, 
"/");
-                // start with first element
-                while (pathWalker.hasMoreElements() && (is == null)) {
-                    srcPath.append('/');
-                    srcPath.append(pathWalker.nextElement());
-                    is = context.getResourceAsStream(srcPath.toString());
-                }
-                destPath.append(tmpDir);
-                destPath.append('/');
-                destPath.append(srcPath);
-            }
-
-            if (is == null) {
-                // didn't find anything, give up now
-                log.warn(sm.getString("cgiServlet.expandNotFound", srcPath));
-                return;
-            }
-
-            try {
-                File f = new File(destPath.toString());
-                if (f.exists()) {
-                    // Don't need to expand if it already exists
-                    return;
-                }
-
-                // create directories
-                File dir = f.getParentFile();
-                if (!dir.mkdirs() && !dir.isDirectory()) {
-                    log.warn(sm.getString("cgiServlet.expandCreateDirFail", 
dir.getAbsolutePath()));
-                    return;
-                }
-
-                try {
-                    synchronized (expandFileLock) {
-                        // make sure file doesn't exist
-                        if (f.exists()) {
-                            return;
-                        }
-
-                        // create file
-                        if (!f.createNewFile()) {
-                            return;
-                        }
-
-                        Files.copy(is, f.toPath());
-
-                        if (log.isDebugEnabled()) {
-                            log.debug(sm.getString("cgiServlet.expandOk", 
srcPath, destPath));
-                        }
-                    }
-                } catch (IOException ioe) {
-                    log.warn(sm.getString("cgiServlet.expandFail", srcPath, 
destPath), ioe);
-                    // delete in case file is corrupted
-                    if (f.exists()) {
-                        if (!f.delete()) {
-                            
log.warn(sm.getString("cgiServlet.expandDeleteFail", f.getAbsolutePath()));
-                        }
-                    }
-                }
-            } finally {
-                try {
-                    is.close();
-                } catch (IOException e) {
-                    log.warn(sm.getString("cgiServlet.expandCloseFail", 
srcPath), e);
-                }
-            }
-        }
-
-
         /**
          * Returns important CGI environment information in a multi-line text 
format.
          *
@@ -1402,9 +1355,9 @@ public final class CGIServlet extends HttpServlet {
          * <LI><u>Allowed characters in path segments</u>: This implementation 
does not allow non-terminal NULL segments
          * in the path -- IOExceptions may be thrown;
          * <LI><u>"<code>.</code>" and "<code>..</code>" path segments</u>: 
This implementation does not allow
-         * "<code>.</code>" and "<code>..</code>" in the path, and such 
characters will result in an IOException
-         * being thrown (this should never happen since Tomcat normalises the 
requestURI before determining the
-         * contextPath, servletPath and pathInfo);
+         * "<code>.</code>" and "<code>..</code>" in the path, and such 
characters will result in an IOException being
+         * thrown (this should never happen since Tomcat normalises the 
requestURI before determining the contextPath,
+         * servletPath and pathInfo);
          * <LI><u>Implementation limitations</u>: This implementation does not 
impose any limitations except as
          * documented above. This implementation may be limited by the servlet 
container used to house this
          * implementation. In particular, all the primary CGI variable values 
are derived either directly or indirectly
@@ -1442,7 +1395,7 @@ public final class CGIServlet extends HttpServlet {
             Runtime rt;
             BufferedReader cgiHeaderReader = null;
             InputStream cgiOutput = null;
-            BufferedReader commandsStdErr ;
+            BufferedReader commandsStdErr;
             Thread errReaderThread = null;
             BufferedOutputStream commandsStdIn;
             Process proc = null;
diff --git a/java/org/apache/catalina/servlets/LocalStrings.properties 
b/java/org/apache/catalina/servlets/LocalStrings.properties
index 5a3158afd3..5fb786b3ba 100644
--- a/java/org/apache/catalina/servlets/LocalStrings.properties
+++ b/java/org/apache/catalina/servlets/LocalStrings.properties
@@ -21,7 +21,6 @@ cgiServlet.expandCloseFail=Failed to close input stream for 
script at path [{0}]
 cgiServlet.expandCreateDirFail=Failed to create destination directory [{0}] 
for script expansion
 cgiServlet.expandDeleteFail=Failed to delete file at [{0}] after IOException 
during expansion
 cgiServlet.expandFail=Failed to expand script at path [{0}] to [{1}]
-cgiServlet.expandNotFound=Unable to expand [{0}] as it could not be found
 cgiServlet.expandOk=Expanded script at path [{0}] to [{1}]
 cgiServlet.find.found=Found CGI: name [{0}], path [{1}], script name [{2}] and 
CGI name [{3}]
 cgiServlet.find.location=Looking for a file at [{0}]
diff --git a/java/org/apache/catalina/servlets/LocalStrings_fr.properties 
b/java/org/apache/catalina/servlets/LocalStrings_fr.properties
index f61a81ce60..328b72eac8 100644
--- a/java/org/apache/catalina/servlets/LocalStrings_fr.properties
+++ b/java/org/apache/catalina/servlets/LocalStrings_fr.properties
@@ -21,7 +21,6 @@ cgiServlet.expandCloseFail=Impossible de fermer le flux 
d''entrée du script ave
 cgiServlet.expandCreateDirFail=Echec de la création du répertoire de 
destination [{0}] pour la décompression du script
 cgiServlet.expandDeleteFail=Impossible d''effacer le fichier [{0}] suite à une 
IOException pendant la décompression
 cgiServlet.expandFail=Impossible de faire l''expansion du script au chemin 
[{0}] vers [{1}]
-cgiServlet.expandNotFound=Impossible de décompresser [{0}] car il n''a pas été 
trouvé
 cgiServlet.expandOk=Extrait le script du chemin [{0}] vers [{1}]
 cgiServlet.find.found=Trouvé le CGI : nom [{0}], chemin [{1}], nom de script 
[{2}] et nom du CGI [{3}]
 cgiServlet.find.location=Recherche d''un fichier en [{0}]
diff --git a/java/org/apache/catalina/servlets/LocalStrings_ja.properties 
b/java/org/apache/catalina/servlets/LocalStrings_ja.properties
index 87d7334ad6..f90a9d2fe9 100644
--- a/java/org/apache/catalina/servlets/LocalStrings_ja.properties
+++ b/java/org/apache/catalina/servlets/LocalStrings_ja.properties
@@ -21,7 +21,6 @@ cgiServlet.expandCloseFail=パス [{0}] のスクリプトの入力ストリー
 cgiServlet.expandCreateDirFail=スクリプトの展開先ディレクトリ[{0}]の作成に失敗しました。
 cgiServlet.expandDeleteFail=拡張中にIOExceptionの後に [{0}] でファイルを削除できませんでした
 cgiServlet.expandFail=パス [{0}] のスクリプトを [{1}] に展開できませんでした
-cgiServlet.expandNotFound=見つけることができなかったため [{0}] を展開できません
 cgiServlet.expandOk=パス [{0}] の [{1}] に展開されたスクリプト
 cgiServlet.find.found=見つかったCGI: 名前 [{0}]、パス [{1}]、スクリプト名 [{2}]、CGI名 [{3}]
 cgiServlet.find.location=ファイル [{0}] を探しています。
diff --git a/java/org/apache/catalina/servlets/LocalStrings_ko.properties 
b/java/org/apache/catalina/servlets/LocalStrings_ko.properties
index aeb3d720d6..547c842722 100644
--- a/java/org/apache/catalina/servlets/LocalStrings_ko.properties
+++ b/java/org/apache/catalina/servlets/LocalStrings_ko.properties
@@ -21,7 +21,6 @@ cgiServlet.expandCloseFail=경로 [{0}]에 위치한 스크립트를 위한, 입
 cgiServlet.expandCreateDirFail=스크립트를 압축해제 하기 위한 대상 디렉토리 [{0}]을(를) 생성하지 못했습니다.
 cgiServlet.expandDeleteFail=압축해제 중 IOException이 발생한 후, [{0}]에 위치한 해당 파일을 삭제하지 
못했습니다.
 cgiServlet.expandFail=경로 [{0}]의 스크립트를 [{1}](으)로 압축해제 하지 못했습니다.
-cgiServlet.expandNotFound=[{0}]을(를) 찾을 수 없어서 압축해제 할 수 없습니다.
 cgiServlet.expandOk=[{0}] 경로에 있는 스트립트가 [{1}](으)로 압축 해제되었습니다.
 cgiServlet.find.found=CGI 발견: 이름 [{0}], 경로 [{1}], 스크립트 이름 [{2}], CGI 이름 [{3}]
 cgiServlet.find.location=[{0}]에 위치한 파일을 찾는 중
diff --git a/java/org/apache/catalina/servlets/LocalStrings_zh_CN.properties 
b/java/org/apache/catalina/servlets/LocalStrings_zh_CN.properties
index 72ee5c9266..700617cccd 100644
--- a/java/org/apache/catalina/servlets/LocalStrings_zh_CN.properties
+++ b/java/org/apache/catalina/servlets/LocalStrings_zh_CN.properties
@@ -21,7 +21,6 @@ cgiServlet.expandCloseFail=无法关闭路径[{0}]处脚本的输入流
 cgiServlet.expandCreateDirFail=无法为脚本扩展创建目标目录[{0}]
 cgiServlet.expandDeleteFail=扩展期间,发生IOException异常后删除文件[{0}]失败
 cgiServlet.expandFail=在路径[{0}] 到[{1}] 展开脚本失败.
-cgiServlet.expandNotFound=无法展开[{0}],因为找不到它。
 cgiServlet.expandOk=从路径[{0}]到[{1}]扩展脚本
 cgiServlet.find.found=找到CGI:name[{0}]、path[{1}]、script name[{2}]和CGI name[{3}]
 cgiServlet.find.location=在 [{0}] 查找文件
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 87e68953ad..c823412761 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -138,6 +138,10 @@
         <code>org.apache.catalina.connector.InputBuffer</code> with a static,
         zero length buffer. (markt)
       </scode>
+      <scode>
+        Refactor GCI servlet to access resources via the
+        <code>WebResource</code> API. (markt)
+      </scode>
     </changelog>
   </subsection>
   <subsection name="Coyote">


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to