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:
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
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>
* 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
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);
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
*/
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;
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
for (cp = end; cp > path && cp[-1] == '/'; --cp)
continue;
-
while (cp > path) {
/* See if the pathname ending here exists... */
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
*/
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);
* 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);
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;
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;
{
char buf[HUGE_STRING_LEN];
char *pInputName;
- char *p, *q;
+ char *p, *q, *t;
BOOL bDone = FALSE;
BOOL bFileExists = TRUE;
HANDLE hFind;
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 */
*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++;
/* 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;
+ }
}
}
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) {
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 = '/';
* (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
}
}
-
return pNewStr;
}
* 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/