diff options
Diffstat (limited to 'APACHE_1_3_42/src/os/netware/os.c')
-rw-r--r-- | APACHE_1_3_42/src/os/netware/os.c | 467 |
1 files changed, 467 insertions, 0 deletions
diff --git a/APACHE_1_3_42/src/os/netware/os.c b/APACHE_1_3_42/src/os/netware/os.c new file mode 100644 index 0000000000..b45b373de2 --- /dev/null +++ b/APACHE_1_3_42/src/os/netware/os.c @@ -0,0 +1,467 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define WS_SSL + +#include "httpd.h" +#include "ap_config.h" +#include "http_config.h" +#include "http_log.h" +#include <dirent.h> + +extern char ap_server_root[MAX_STRING_LEN]; + +void ap_os_dso_init(void) +{ +} + +void *ap_os_dso_load(const char *path) +{ + unsigned int nlmHandle; + char *moduleName = NULL; + + moduleName = strrchr(path, '/'); + + if (moduleName) { + moduleName++; + } + + nlmHandle = FindNLMHandleInAddressSpace((char*)moduleName, NULL); + + if (nlmHandle == NULL) { + spawnlp(P_NOWAIT | P_SPAWN_IN_CURRENT_DOMAIN, path, NULL); + nlmHandle = FindNLMHandleInAddressSpace((char*)moduleName, NULL); + } + + return (void *)nlmHandle; +} + +void ap_os_dso_unload(void *handle) +{ + KillMe(handle); +} + +void *ap_os_dso_sym(void *handle, const char *symname) +{ + return ImportSymbol((int)GetNLMHandle(), (char *)symname); +} + +void ap_os_dso_unsym(void *handle, const char *symname) +{ + UnimportSymbol((int)GetNLMHandle(), (char *)symname); +} + +const char *ap_os_dso_error(void) +{ + return NULL; +} + +char *remove_filename(char* str) +{ + int i, len = strlen(str); + + for (i=len; i; i--) { + if (str[i] == '\\' || str[i] == '/') { + str[i] = NULL; + break; + } + } + return str; +} + +char *bslash2slash(char* str) +{ + int i, len = strlen(str); + + for (i=0; i<len; i++) { + if (str[i] == '\\') { + str[i] = '/'; + break; + } + } + return str; +} + +void check_clean_load(module *top_module) +{ + if (top_module != NULL) { + module *m; + + ap_log_error(APLOG_MARK, APLOG_CRIT, NULL, + "abnormal shutdown detected, performing a clean shutdown: please restart apache"); + for (m = top_module; m; m = m->next) + ap_os_dso_unload((ap_os_dso_handle_t)m->dynamic_load_handle); + exit(1); + } +} + +void init_name_space() +{ + UnAugmentAsterisk(TRUE); + SetCurrentNameSpace(NW_NS_LONG); + SetTargetNameSpace(NW_NS_LONG); +} + +/* Perform complete canonicalization. On NetWare we are just + lower casing the file name so that the comparisons will match. + NetWare assumes that all physical paths are fully qualified. + Each file path must include a volume name. + */ +static char *os_canonical_filename(pool *pPool, const char *szFile) +{ + char *pNewName = ap_pstrdup(pPool, szFile); + char *slash_test; + + bslash2slash(pNewName); + /* Don't try to canonicalize a filename that isn't even valid + This way we don't mess up proxy requests or other kinds + of special filenames. + */ + if (ap_os_is_filename_valid(pNewName)) { + if ((pNewName[0] == '/') && (strchr (pNewName, ':') == NULL)) + { + char vol[256]; + + _splitpath (ap_server_root, vol, NULL, NULL, NULL); + pNewName = ap_pstrcat (pPool, vol, pNewName, NULL); + } + if ((slash_test = strchr(pNewName, ':')) && (*(slash_test+1) != '/') + && (*(slash_test+1) != '\0')) + { + char vol[_MAX_VOLUME+1]; + + _splitpath (pNewName, vol, NULL, NULL, NULL); + pNewName = ap_pstrcat (pPool, vol, "/", pNewName+strlen(vol), NULL); + } + } + return pNewName; +} + +char *ap_os_canonical_filename(pool *pPool, const char *szFile) +{ + char *pNewName = os_canonical_filename(pPool, szFile); + + /* Lower case the name so that the interal string compares work */ + strlwr(pNewName); + return pNewName; +} + + +char *ap_os_case_canonical_filename(pool *pPool, const char *szFile) +{ + /* First thing we need to do is get a copy of the + canonicalized path */ + char *pNewName = os_canonical_filename(pPool, szFile); + int volnum=0; + long dirnum=0; + long pathcount=0; + char *path; + char vol[_MAX_VOLUME+1]; + int retval, x, y; + + /* See if path exists by trying to get the volume and directory number */ + retval = FEMapPathVolumeDirToVolumeDir(pNewName, 0, 0, &volnum, &dirnum); + if (retval == 0) { + /* allocate a buffer and ask the file system for the real name of + the directory and file */ + path = ap_palloc(pPool, strlen(pNewName)+2); + FEMapVolumeAndDirectoryToPath (volnum, dirnum, path, &pathcount); + + /* The file system gives it back in a lengh preceded string so we + need to convert it to a null terminated string. */ + x = 0; + while (pathcount-- > 0) { + y = path[x]; + path[x] = '/'; + x += y + 1; + } + path[x] = '\0'; /* null terminate the full path */ + + /* Get the name of the volume so that we can prepend it onto the path */ + FEMapVolumeNumberToName (volnum, vol); + vol[vol[0]+1] = '\0'; + pNewName = ap_pstrcat (pPool, &(vol[1]), ":", path, NULL); + } + + /* At this point we either have a real case accurate canonical path or + the original name canonicalized */ + return pNewName; +} + + +/* + * ap_os_is_filename_valid is given a filename, and returns 0 if the filename + * is not valid for use on this system. On NetWare, this means it fails any + * of the tests below. Otherwise returns 1. + * + * The tests are: + * + * 1) total path length greater than MAX_PATH + * + * 2) the file path must contain a volume specifier and no / or \ + * can appear before the volume specifier. + * + * 3) anything using the octets 0-31 or characters " < > | : + * (these are reserved for Windows use in filenames. In addition + * each file system has its own additional characters that are + * invalid. See KB article Q100108 for more details). + * + * 4) anything ending in "." (no matter how many) + * (filename doc, doc. and doc... all refer to the same file) + * + * 5) any segment in which the basename (before first period) matches + * one of the DOS device names + * (the list comes from KB article Q100108 although some people + * reports that additional names such as "COM5" are also special + * devices). + * + * If the path fails ANY of these tests, the result must be to deny access. + */ + +int ap_os_is_filename_valid(const char *file) +{ + const char *segstart; + unsigned int seglength; + const char *pos; + char *colonpos, *fslashpos, *bslashpos; + static const char * const invalid_characters = "?\"<>*|:"; + static const char * const invalid_filenames[] = { + "CON", "AUX", "COM1", "COM2", "COM3", + "COM4", "LPT1", "LPT2", "LPT3", "PRN", "NUL", NULL + }; + + /* First check to make sure that we have a file so that we don't abend */ + if (file == NULL) + return 0; + + /* Test 1 */ + if (strlen(file) >= _MAX_PATH) { + /* Path too long for Windows. Note that this test is not valid + * if the path starts with //?/ or \\?\. */ + return 0; + } + + pos = file; + + /* Skip any leading non-path components. This can be either a + * drive letter such as C:, or a UNC path such as \\SERVER\SHARE\. + * We continue and check the rest of the path based on the rules above. + * This means we could eliminate valid filenames from servers which + * are not running NT (such as Samba). + */ + + colonpos = strchr (file, ':'); + + if (!colonpos) + return 0; + + pos = ++colonpos; + if (!*pos) { + /* No path information */ + /* Same as specifying volume:\ */ + return 1; + } + + while (*pos) { + unsigned int idx; + unsigned int baselength; + + while (*pos == '/' || *pos == '\\') { + pos++; + } + if (*pos == '\0') { + break; + } + segstart = pos; /* start of segment */ + while (*pos && *pos != '/' && *pos != '\\') { + pos++; + } + seglength = pos - segstart; + /* + * Now we have a segment of the path, starting at position "segstart" + * and length "seglength" + */ + + /* Test 2 */ + for (idx = 0; idx < seglength; idx++) { + if ((segstart[idx] > 0 && segstart[idx] < 32) || + strchr(invalid_characters, segstart[idx])) { + return 0; + } + } + + /* Test 2.5 */ + if (seglength == 2) { + if ( (segstart[0] == '.') && (segstart[1] == '.') ) { + return 1; + } + + } + + /* Test 3 */ + if (segstart[seglength-1] == '.') { + return 0; + } + + /* Test 4 */ + for (baselength = 0; baselength < seglength; baselength++) { + if (segstart[baselength] == '.') { + break; + } + } + + /* baselength is the number of characters in the base path of + * the segment (which could be the same as the whole segment length, + * if it does not include any dot characters). */ + if (baselength == 3 || baselength == 4) { + for (idx = 0; invalid_filenames[idx]; idx++) { + if (strlen(invalid_filenames[idx]) == baselength && + !strnicmp(invalid_filenames[idx], segstart, baselength)) { + return 0; + } + } + } + } + + return 1; +} + +#undef opendir_411 +DIR *os_opendir (const char *pathname) +{ + struct stat s; + DIR *d = opendir_411 (pathname); + + if (d) { + strcpy (d->d_name, "<<**"); + } + + if (!d) { + /* Let's check if this is an empty directory */ + if (stat(pathname, &s) != 0) + return NULL; + if (!(S_ISDIR(s.st_mode))) + return NULL; + + /* If we are here, then this appears to be a directory */ + /* We allocate a name */ + d = NULL; + d = (DIR *)malloc(sizeof(DIR)); + if (d) { + memset(d, 0, sizeof(DIR)); + strcpy(d->d_name, "**<<"); + d->d_cdatetime = 50; + + } + + } + + return d; + +} + +#undef readdir_411 +DIR *os_readdir (DIR *dirP) +{ + +/* + * First three if statements added for empty directory support. + * + */ + if ( (dirP->d_cdatetime == 50) && (dirP->d_name[0] == '*') && + (dirP->d_name[2] == '<') ) + { + strcpy (dirP->d_name, "."); + strcpy (dirP->d_nameDOS, "."); + return (dirP); + } + else if ((dirP->d_cdatetime == 50) && + (dirP->d_name[0] == '.') && + (dirP->d_name[1] == '\0')) { + strcpy (dirP->d_name, ".."); + strcpy (dirP->d_nameDOS, ".."); + return (dirP); + } + else if ( (dirP->d_cdatetime == 50) && + (dirP->d_name[0] == '.') && + (dirP->d_name[1] == '.') && + (dirP->d_name[2] == '\0') ) { + return (NULL); + } + else if ((dirP->d_name[0] == '<') && (dirP->d_name[2] == '*')) { + strcpy (dirP->d_name, "."); + strcpy (dirP->d_nameDOS, "."); + return (dirP); + } + else if ((dirP->d_name[0] == '.') && (dirP->d_name[1] == '\0')) { + strcpy (dirP->d_name, ".."); + strcpy (dirP->d_nameDOS, ".."); + return (dirP); + } + else + return readdir_411 (dirP); +} + + +#undef closedir_510 +int os_closedir (DIR *dirP) +{ +/* + * Modified to handle empty directories. + * + */ + + if (dirP == NULL) { + return 0; + } + + if ( ( (dirP->d_cdatetime == 50) && (dirP->d_name[0] == '*') && + (dirP->d_name[2] == '<') + ) || + ( (dirP->d_cdatetime == 50) && (dirP->d_name[0] == '.') && + (dirP->d_name[1] == '\0') + ) || + ( (dirP->d_cdatetime == 50) && (dirP->d_name[0] == '.') && + (dirP->d_name[1] == '.') && (dirP->d_name[2] == '\0') + ) + ) + { + + free(dirP); + dirP = NULL; + return 0; + } + else { + return closedir_510(dirP); + } + + +} + +char *ap_os_http_method(void *r) +{ + int s = ((request_rec*)r)->connection->client->fd; + unsigned int optParam; + + if (!WSAIoctl(s, SO_SSL_GET_FLAGS, NULL, 0, &optParam, sizeof(optParam), NULL, NULL, NULL)) + if (optParam & (SO_SSL_ENABLE | SO_SSL_SERVER)) return "https"; + return "http"; +} + +unsigned short ap_os_default_port(void *r) +{ + return ap_default_port_for_scheme(ap_os_http_method(r)); +} |