From: William A. Rowe Jr Date: Fri, 13 Oct 2000 16:57:21 +0000 (+0000) Subject: Completes the port of the handling for Win32... there is X-Git-Tag: APACHE_2_0_ALPHA_8~376 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a286d71463e9bfef29b3666f615f21f8fd7351e2;p=apache Completes the port of the handling for Win32... there is 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 --- diff --git a/STATUS b/STATUS index 148e9458c5..64ed98b4df 100644 --- 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 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> diff --git a/modules/http/http_core.c b/modules/http/http_core.c index 5404a9d105..d405e784ce 100644 --- a/modules/http/http_core.c +++ b/modules/http/http_core.c @@ -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); diff --git a/modules/http/http_request.c b/modules/http/http_request.c index 6262c2df7b..edcfbe93af 100644 --- a/modules/http/http_request.c +++ b/modules/http/http_request.c @@ -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 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 + * 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; diff --git a/os/win32/util_win32.c b/os/win32/util_win32.c index 66d1263eae..a8abc52b33 100644 --- a/os/win32/util_win32.c +++ b/os/win32/util_win32.c @@ -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; } diff --git a/server/util.c b/server/util.c index dcff682a1d..6f102fd848 100644 --- a/server/util.c +++ b/server/util.c @@ -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/