📄 util_win32.c
字号:
} } *p = '\0'; /* Blow away any final trailing '.' since on Win32 * foo.bat == foo.bat. == foo.bat... etc. * Also blow away any trailing spaces since * "filename" == "filename " */ q = p; while (p > pNewStr && (*(p-1) == '.' || *(p-1) == ' ')) p--; if ((p > pNewStr) || (p == pNewStr && q-p > 2)) *p = '\0'; /* One more security issue to deal with. Win32 allows * you to create long filenames. However, alias filenames * are always created so that the filename will * conform to 8.3 rules. According to the Microsoft * Developer's network CD (1/98) * "Automatically generated aliases are composed of the * first six characters of the filename plus ~n * (where n is a number) and the first three characters * after the last period." * Here, we attempt to detect and decode these names. * * 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 /* ap_os_systemcase_filename now changes the case of only * the pathname elements that are found. */ pNewStr = ap_os_systemcase_filename(pPool, pNewStr); return pNewStr;}/* Perform complete canonicalization. */API_EXPORT(char *) ap_os_canonical_filename(pool *pPool, const char *szFile){ char *pNewName; pNewName = ap_os_case_canonical_filename(pPool, szFile); strlwr(pNewName); 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 Windows, this means it fails any * of the tests below. Otherwise returns 1. * * Test for filename validity on Win32. This is of tests come in part from * the MSDN article at "Technical Articles, Windows Platform, Base Services, * Guidelines, Making Room for Long Filenames" although the information * in MSDN about filename testing is incomplete or conflicting. There is a * similar set of tests in "Technical Articles, Windows Platform, Base Services, * Guidelines, Moving Unix Applications to Windows NT". * * The tests are: * * 1) total path length greater than MAX_PATH * * 2) 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). * * 3) anything ending in "." (no matter how many) * (filename doc, doc. and doc... all refer to the same file) * * 4) 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. */API_EXPORT(int) ap_os_is_filename_valid(const char *file){ const char *segstart; unsigned int seglength; const char *pos; static const char * const invalid_characters = "?\"<>*|:"; static const char * const invalid_filenames[] = { "CON", "AUX", "COM1", "COM2", "COM3", "COM4", "LPT1", "LPT2", "LPT3", "PRN", "NUL", NULL }; /* 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). */ if (pos[0] && pos[1] == ':') { /* Skip leading drive letter */ pos += 2; } else { if ((pos[0] == '\\' || pos[0] == '/') && (pos[1] == '\\' || pos[1] == '/')) { /* Is a UNC, so skip the server name and share name */ pos += 2; while (*pos && *pos != '/' && *pos != '\\') pos++; if (!*pos) { /* No share name */ return 0; } pos++; /* Move to start of share name */ while (*pos && *pos != '/' && *pos != '\\') pos++; if (!*pos) { /* No path information */ return 0; } } } 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 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;}API_EXPORT(ap_os_dso_handle_t) ap_os_dso_load(const char *module_name){ UINT em; ap_os_dso_handle_t dsoh; char path[MAX_PATH], *p; /* Load the module... * per PR2555, the LoadLibraryEx function is very picky about slashes. * Debugging on NT 4 SP 6a reveals First Chance Exception within NTDLL. * LoadLibrary in the MS PSDK also reveals that it -explicitly- states * that backslashes must be used. * * Transpose '\' for '/' in the filename. */ ap_cpystrn(path, module_name, MAX_PATH); p = path; while (p = strchr(p, '/')) *p = '\\'; /* First assume the dso/dll's required by -this- dso are sitting in the * same path or can be found in the usual places. Failing that, let's * let that dso look in the apache root. */ em = SetErrorMode(SEM_FAILCRITICALERRORS); dsoh = LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); if (!dsoh) { dsoh = LoadLibraryEx(path, NULL, 0); } SetErrorMode(em); return dsoh;}API_EXPORT(const char *) ap_os_dso_error(void){ int len, nErrorCode; static char errstr[120]; /* This is -not- threadsafe code, but it's about the best we can do. * mostly a potential problem for isapi modules, since LoadModule * errors are handled within a single config thread. */ nErrorCode = GetLastError(); len = ap_snprintf(errstr, sizeof(errstr), "(%d) ", nErrorCode); len += FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, nErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ (LPTSTR) errstr + len, sizeof(errstr) - len, NULL ); /* FormatMessage may have appended a newline (\r\n). So remove it * and use ": " instead like the Unix errors. The error may also * end with a . before the return - if so, trash it. */ if (len > 1 && errstr[len-2] == '\r' && errstr[len-1] == '\n') { if (len > 2 && errstr[len-3] == '.') len--; errstr[len-2] = ':'; errstr[len-1] = ' '; } return errstr;}#endif /* WIN32 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -