]> granicus.if.org Git - apache/commitdiff
Completes the port of the <Directory /> handling for Win32... there is
authorWilliam A. Rowe Jr <wrowe@apache.org>
Fri, 13 Oct 2000 16:57:21 +0000 (16:57 +0000)
committerWilliam A. Rowe Jr <wrowe@apache.org>
Fri, 13 Oct 2000 16:57:21 +0000 (16:57 +0000)
  still a patch needed for OS2 ... Brian?

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86579 13f79535-47bb-0310-9956-ffa450edef68

STATUS
modules/http/http_core.c
modules/http/http_request.c
os/win32/util_win32.c
server/util.c

diff --git a/STATUS b/STATUS
index 148e9458c5f0385fb3362455681dc91379b242e6..64ed98b4dfa2936e64d2bbb743b8bcb9a1b0b46b 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -1,5 +1,5 @@
 Apache 2.0 STATUS:
-Last modified at [$Date: 2000/10/12 03:59:12 $]
+Last modified at [$Date: 2000/10/13 16:57:08 $]
 
 Release:
 
@@ -14,6 +14,10 @@ Release:
 
 RELEASE SHOWSTOPPERS:
 
+    * Root all file systems with <Directory /> for WIN32/OS2/NW permissions 
+        Status: patch brought forward from 1.3.14
+                WIN32 and OS2 need review [William Rowe, Brian Harvard]
+
     * All of the bucket types must be implemented.  The list can be found
       in src/include/ap_buckets.h. May need to implement a bucket type
       to mark the end of a subrequest content stream, and one to tell
@@ -126,8 +130,15 @@ RELEASE NON-SHOWSTOPPERS BUT WOULD BE REAL NICE TO WRAP THESE UP:
       plus hash tables for speed, with options for more later).
        Status: fanf is working on this.
 
+    * All DBMs suffer from confusion in support/dbmmanage (perl script) since 
+        the dbmmanage employs the first-matched dbm format.  This is not
+        necessarily the library that Apache was built with.  Aught to
+        rewrite dbmmanage upon installation to bin/ with the proper library 
+        for predictable mod_auth_db/dbm administration.
+
     * configuration option to use *DBM
       Status: Greg +1 (volunteers)
+        employ same dbm for mod_auth_dbm? [Win32 is using our own sdbm]
 
     * Integrate mod_dav.
         Message-id: <20000625173247.M29590@lyra.org>
index 5404a9d1054f257c9156409f9176ee64e70e781e..d405e784cee535b5bf46f0248b43e8f9d3ad19d3 100644 (file)
@@ -408,11 +408,20 @@ CORE_EXPORT(void) ap_add_file_conf(core_dir_config *conf, void *url_config)
  * See directory_walk().
  */
 
-#ifdef HAVE_DRIVE_LETTERS
+#if defined(HAVE_DRIVE_LETTERS)
 #define IS_SPECIAL(entry_core) \
     ((entry_core)->r != NULL \
        || ((entry_core)->d[0] != '/' && (entry_core)->d[1] != ':'))
-#else
+#elif defined(NETWARE)
+/* XXX: Fairly certain this is correct... '/' must prefix the path
+ *      or else in the case xyz:/ or abc/xyz:/, '/' must follow the ':'.
+ *      If there is no leading '/' or embedded ':/', then we are special.
+ */
+#define IS_SPECIAL(entry_core) \
+    ((entry_core)->r != NULL \
+       || ((entry_core)->d[0] != '/' \
+            && strchr((entry_core)->d, ':') \
+            && *(strchr((entry_core)->d, ':') + 1) != '/'))
 #define IS_SPECIAL(entry_core) \
     ((entry_core)->r != NULL || (entry_core)->d[0] != '/')
 #endif
@@ -1570,6 +1579,18 @@ static const char *dirsection(cmd_parms *cmd, void *mconfig, const char *arg)
        cmd->path = ap_getword_conf(cmd->pool, &arg);
        r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE);
     }
+#if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE)
+    else if (strcmp(cmd->path, "/") == 0) {
+        /* Treat 'default' path / as an inalienable root */
+        cmd->path = apr_pstrdup(cmd->pool, cmd->path);
+    }
+#endif
+#if defined(HAVE_UNC_PATHS)
+    else if (strcmp(cmd->path, "//") == 0) {
+        /* Treat UNC path // as an inalienable root */
+        cmd->path = apr_pstrdup(cmd->pool, cmd->path);
+    }
+#endif
     else {
        /* Ensure that the pathname is canonical */
        cmd->path = ap_os_canonical_filename(cmd->pool, cmd->path);
index 6262c2df7b66cda70ecf9f5d028d75bc5c0d631e..edcfbe93af9ac308d25ec0d4135df113f93a090e 100644 (file)
@@ -211,7 +211,7 @@ static int get_path_info(request_rec *r)
     char *end = &path[strlen(path)];
     char *last_cp = NULL;
     int rv;
-#ifdef HAVE_DRIVE_LETTERS
+#if defined(HAVE_DRIVE_LETTERS) || defined(HAVE_UNC_PATHS)
     char bStripSlash=1;
 #endif
 
@@ -226,14 +226,15 @@ static int get_path_info(request_rec *r)
      */
     if (strlen(path) == 3 && path[1] == ':' && path[2] == '/')
         bStripSlash = 0;
+#endif
 
-
+#ifdef HAVE_UNC_PATHS
     /* If UNC name == //machine/share/, do not 
      * advance over the trailing slash.  Any other
      * UNC name is OK to strip the slash.
      */
     cp = end;
-    if (strlen(path) > 2 && path[0] == '/' && path[1] == '/' && 
+    if (path[0] == '/' && path[1] == '/' && 
         path[2] != '/' && cp[-1] == '/') {
         char *p;
         int iCount=0;
@@ -246,7 +247,9 @@ static int get_path_info(request_rec *r)
         if (iCount == 4)
             bStripSlash = 0;
     }
-
+#endif
+   
+#if defined(HAVE_DRIVE_LETTERS) || defined(HAVE_UNC_PATHS)
     if (bStripSlash)
 #endif
         /* Advance over trailing slashes ... NOT part of filename 
@@ -255,7 +258,6 @@ static int get_path_info(request_rec *r)
         for (cp = end; cp > path && cp[-1] == '/'; --cp)
             continue;
 
-
     while (cp > path) {
 
         /* See if the pathname ending here exists... */
@@ -361,8 +363,11 @@ static int directory_walk(request_rec *r)
     char *test_filename;
     char *test_dirname;
     int res;
-    unsigned i, num_dirs, iStart;
+    unsigned i, num_dirs;
     int j, test_filename_len;
+#if defined(HAVE_UNC_PATHS) || defined(NETWARE)
+    unsigned iStart = 1;
+#endif
 
     /*
      * Are we dealing with a file? If not, we can (hopefuly) safely assume we
@@ -468,18 +473,46 @@ static int directory_walk(request_rec *r)
      */
     test_dirname = apr_palloc(r->pool, test_filename_len + 2);
 
-    iStart = 1;
-#ifdef WIN32
-    /* If the name is a UNC name, then do not walk through the
-     * machine and share name (e.g. \\machine\share\)
+#if defined(HAVE_UNC_PATHS)
+    /* If the name is a UNC name, then do not perform any true file test
+     * against the machine name (start at //machine/share/)
+     * This is optimized to use the normal walk (skips the redundant '/' root)
      */
     if (num_dirs > 3 && test_filename[0] == '/' && test_filename[1] == '/')
         iStart = 4;
 #endif
 
+#if defined(NETWARE)
+    /* If the name is a fully qualified volume name, then do not perform any
+     * true file test on the machine name (start at machine/share:/)
+     * XXX: The implementation eludes me at this moment... 
+     *      Does this make sense?  Please test!
+     */
+    if (num_dirs > 1 && strchr(test_filename, '/') < strchr(test_filename, ':'))
+        iStart = 2;
+#endif
+
+#if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE)
+    /* Should match <Directory> sections starting from '/', not 'e:/' 
+     * (for example).  WIN32/OS2/NETWARE do not have a single root directory,
+     * they have one for each filesystem.  Traditionally, Apache has treated 
+     * <Directory /> permissions as the base for the whole server, and this 
+     * tradition should probably be preserved. 
+     *
+     * NOTE: MUST SYNC WITH ap_make_dirstr_prefix() CHANGE IN src/main/util.c
+     */
+    if (test_filename[0] == '/')
+        i = 1;
+    else
+        i = 0;
+#else
+    /* Normal File Systems are rooted at / */
+    i = 1;
+#endif /* def HAVE_DRIVE_LETTERS || NETWARE */
+
     /* j keeps track of which section we're on, see core_reorder_directories */
     j = 0;
-    for (i = iStart; i <= num_dirs; ++i) {
+    for (; i <= num_dirs; ++i) {
         int overrides_here;
         core_dir_config *core_dir = (core_dir_config *)
             ap_get_module_config(per_dir_defaults, &core_module);
@@ -495,6 +528,10 @@ static int directory_walk(request_rec *r)
          * permissions appropriate to the *parent* directory...
          */
 
+#if defined(HAVE_UNC_PATHS) || defined(NETWARE)
+        /* Test only legal names against the real filesystem */
+        if (i >= iStart)
+#endif
         if ((res = check_symlinks(test_dirname, core_dir->opts, r->pool))) {
             ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
                         "Symbolic link not allowed: %s", test_dirname);
@@ -518,7 +555,15 @@ static int directory_walk(request_rec *r)
 
             if (entry_core->r
                || !ap_os_is_path_absolute(entry_dir)
+#if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE)
+    /* To account for the top-level "/" directory when i == 0 
+     * XXX: The net test may be wrong... may fail ap_os_is_path_absolute
+     */
+                || (entry_core->d_components > 1
+                    && entry_core->d_components > i))
+#else
                 || entry_core->d_components > i)
+#endif /* def HAVE_DRIVE_LETTERS || NETWARE */                  
                 break;
 
             this_conf = NULL;
@@ -537,11 +582,24 @@ static int directory_walk(request_rec *r)
                 core_dir = (core_dir_config *)
                            ap_get_module_config(per_dir_defaults, &core_module);
             }
+#if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE)
+            /* So that other top-level directory sections (e.g. "e:/") aren't
+             * skipped when i == 0
+             * XXX: I don't get you here, Tim... That's a level 1 section, but
+             *      we are at level 0. Did you mean fast-forward to the next?
+             */
+            else if (!i)
+                break;
+#endif /* def HAVE_DRIVE_LETTERS || NETWARE */
         }
         overrides_here = core_dir->override;
 
         /* If .htaccess files are enabled, check for one. */
 
+#if defined(HAVE_UNC_PATHS) || defined(NETWARE)
+        /* Test only legal names against the real filesystem */
+        if (i >= iStart)
+#endif
         if (overrides_here) {
             void *htaccess_conf = NULL;
 
index 66d1263eae3cb05f3339d28e83e2ef5d2214a794..a8abc52b33976acaecc47b43405facc8dfaa74d3 100644 (file)
@@ -91,7 +91,7 @@ API_EXPORT(char *) ap_os_systemcase_filename(apr_pool_t *pPool,
 {
     char buf[HUGE_STRING_LEN];
     char *pInputName;
-    char *p, *q;
+    char *p, *q, *t;
     BOOL bDone = FALSE;
     BOOL bFileExists = TRUE;
     HANDLE hFind;
@@ -100,7 +100,7 @@ API_EXPORT(char *) ap_os_systemcase_filename(apr_pool_t *pPool,
     if (!szFile || strlen(szFile) == 0 || strlen(szFile) >= sizeof(buf))
         return apr_pstrdup(pPool, "");
 
-    buf[0] = '\0';
+    t = buf;
     pInputName = apr_pstrdup(pPool, szFile);
 
     /* First convert all slashes to \ so Win32 calls work OK */
@@ -109,27 +109,34 @@ API_EXPORT(char *) ap_os_systemcase_filename(apr_pool_t *pPool,
             *p = '\\';
     }
     
-    p = pInputName;
+    q = p = pInputName;
     /* If there is drive information, copy it over. */ 
     if (pInputName[1] == ':') {
-        buf[0] = tolower(*p++);
-        buf[1] = *p++;
-        buf[2] = '\0';
+        /* This is correct - if systemcase is used for
+         * comparison, d: designations will match
+         */                    
+        *(t++) = tolower(*p++);
+        *(t++) = *p++;
+        q = p;
 
         /* If all we have is a drive letter, then we are done */
-        if (strlen(pInputName) == 2)
+        if (!*p)
             bDone = TRUE;
+
+        q = p;
     }
     
-    q = p;
     if (*p == '\\') {
-        p++;
-        if (*p == '\\')  /* Possible UNC name */
+        ++p;
+        if (*p == '\\')  /* UNC name */
         {
             p++;
-            /* Get past the machine name.  FindFirstFile */
-            /* will not find a machine name only */
-            p = strchr(p, '\\'); 
+            /* Get past the machine name.  FindFirstFile
+             * will not find a machine name only 
+             */
+            *(t++) = '\\';
+            ++q;
+            p = strchr(p + 1, '\\');
             if (p)
             {
                 p++;
@@ -137,14 +144,21 @@ API_EXPORT(char *) ap_os_systemcase_filename(apr_pool_t *pPool,
                 /* will not find a \\machine\share name only */
                 p = strchr(p, '\\'); 
                 if (p) {
-                    strncat(buf,q,p-q);
+                    /* This was faulty - as of 1.3.13 \\machine\share 
+                     * name is now always lowercased
+                     */
+                    strncpy(t,q,p-q);
+                    strlwr(t);
+                    t += p - q;
                     q = p;
                     p++;
                 }
             }
 
-            if (!p)
+            if (!p) {
+                bFileExists = FALSE;
                 p = q;
+            }
         }
     }
 
@@ -174,13 +188,18 @@ API_EXPORT(char *) ap_os_systemcase_filename(apr_pool_t *pPool,
                 FindClose(hFind);
 
                 if (*q == '\\')
-                    strcat(buf,"\\");
-                strcat(buf, wfd.cFileName);
+                    *(t++) = '\\';
+                t = strchr(strcpy(t, wfd.cFileName), '\0');
             }
         }
         
         if (!bFileExists || OnlyDots((*q == '.' ? q : q+1))) {
-            strcat(buf, q);
+            /* XXX: Comparison could be faulty ...\unknown
+             * names may not be tested (if they reside outside
+             * of the file system)!
+             */
+            strcpy(t, q);
+            t = strchr(t, '\0');
         }
         
         if (p) {
@@ -192,8 +211,10 @@ API_EXPORT(char *) ap_os_systemcase_filename(apr_pool_t *pPool,
             bDone = TRUE;
         }
     }
-    
-    /* First convert all slashes to / so server code handles it ok */
+    *t = '\0';
+
+    /* Finally, convert all slashes to / so server code handles it ok */
+
     for (p = buf; *p; p++) {
         if (*p == '\\')
             *p = '/';
@@ -271,9 +292,17 @@ API_EXPORT(char *) ap_os_case_canonical_filename(apr_pool_t *pPool,
      *   (where n is a number) and the first three characters 
      *   after the last period."
      *  Here, we attempt to detect and decode these names.
-     */
-    p = strchr(pNewStr, '~');
-    if (p != NULL) {
+     *
+     *  XXX: Netware network clients may have alternate short names,
+     *  simply truncated, with no embedded '~'.  Further, this behavior
+     *  can be modified on WinNT volumes.  This was not a safe test,
+     *  therefore exclude the '~' pretest.
+     */     
+#ifdef WIN32_SHORT_FILENAME_INSECURE_BEHAVIOR
+     p = strchr(pNewStr, '~');
+     if (p != NULL)
+#endif
+     {
         char *pConvertedName, *pQstr, *pPstr;
         char buf[HUGE_STRING_LEN];
         /* We potentially have a short name.  Call 
@@ -319,7 +348,6 @@ API_EXPORT(char *) ap_os_case_canonical_filename(apr_pool_t *pPool,
         }
     }
 
-
     return pNewStr;
 }
 
index dcff682a1d309d382840375b84bc0758696ca897..6f102fd848ca0f1f91cb77e4314d5134a34b00a9 100644 (file)
@@ -555,6 +555,11 @@ API_EXPORT(void) ap_no2slash(char *name)
  * assumes n > 0
  * the return value is the ever useful pointer to the trailing \0 of d
  *
+ * MODIFIED FOR HAVE_DRIVE_LETTERS and NETWARE environments, 
+ * so that if n == 0, "/" is returned in d with n == 1 
+ * and s == "e:/test.html", "e:/" is returned in d
+ * *** See also directory_walk in src/main/http_request.c
+
  * examples:
  *    /a/b, 1  ==> /
  *    /a/b, 2  ==> /a/