📄 htmulti.c
字号:
PRIVATE HTArray * dir_matches (char * path){ static char * required[MAX_SUFF+1]; static char * actual[MAX_SUFF+1]; int m,n; char * dirname = NULL; char * basename = NULL; int baselen; char * multi = NULL; DIR * dp; struct dirent * dirbuf; HTArray * matches = NULL;#ifdef HT_REENTRANT struct dirent result; /* For readdir_r */#endif if (!path) return NULL; StrAllocCopy(dirname, path); basename = (strrchr(dirname, '/')); if (!basename) goto dir_match_failed; *basename++ = 0; multi = strrchr(basename, MULTI_SUFFIX[0]); if (multi && !strcasecomp(multi, MULTI_SUFFIX)) *multi = 0; baselen = strlen(basename); m = HTSplitFilename(basename, required); dp = opendir(dirname); if (!dp) { HTTRACE(PROT_TRACE, "Warning..... Can't open directory %s\n" _ dirname); goto dir_match_failed; } matches = HTArray_new(VARIANTS);#ifdef HAVE_READDIR_R_2 while ((dirbuf = (struct dirent *) readdir_r(dp, &result))) {#elif defined(HAVE_READDIR_R_3) while (readdir_r(dp, &result, &dirbuf) == 0) {#else while ((dirbuf = readdir(dp))) {#endif /* HAVE_READDIR_R_2 */ if (!dirbuf->d_ino) continue; /* Not in use */ if (!strcmp(dirbuf->d_name,".") || !strcmp(dirbuf->d_name,"..") || !strcmp(dirbuf->d_name, DEFAULT_DIR_FILE)) continue; /* Use of direct->namlen is only valid in BSD'ish system */ /* Thanks to chip@chinacat.unicom.com (Chip Rosenthal) */ /* if ((int)(dirbuf->d_namlen) >= baselen) { */ if ((int) strlen(dirbuf->d_name) >= baselen) { n = HTSplitFilename(dirbuf->d_name, actual); if (multi_match(required, m, actual, n)) { HTContentDescription * cd; if ((cd = (HTContentDescription *) HT_CALLOC(1, sizeof(HTContentDescription))) == NULL) HT_OUTOFMEM("dir_matches"); if (HTBind_getFormat(dirbuf->d_name, &cd->content_type, &cd->content_encoding, &cd->content_transfer, &cd->content_language, &cd->quality)) { if (cd->content_type) { if ((cd->filename = (char *) HT_MALLOC(strlen(dirname) + 2 + strlen(dirbuf->d_name))) == NULL) HT_OUTOFMEM("dir_matches"); sprintf(cd->filename, "%s/%s", dirname, dirbuf->d_name); HTArray_addObject(matches, (void *) cd); } else { HT_FREE(cd); } } else { HT_FREE(cd); } } } } closedir(dp); dir_match_failed: HT_FREE(dirname); return matches;}/*** Get the best match for a given file** -----------------------------------** On entry:** req->conversions accepted content-types** req->encodings accepted content-transfer-encodings** req->languages accepted content-languages** path absolute pathname of the filename for** which the match is desired.** On exit:** returns a newly allocated absolute filepath.*/PRIVATE char * HTGetBest (HTRequest * req, char * path){ HTArray * variants = NULL; char * representation = NULL; if (!path || !*path) return NULL; if ((variants = dir_matches(path)) == NULL) { HTTRACE(PROT_TRACE, "No matches.. for \"%s\"\n" _ path); return NULL; }#ifdef HTDEBUG if (PROT_TRACE) { void ** data; HTContentDescription * cd = HTArray_firstObject(variants, data); HTTRACE(PROT_TRACE, "Multi....... Possibilities for \"%s\"\n" _ path); HTTRACE(PROT_TRACE, " QUALITY CONTENT-TYPE LANGUAGE ENCODING FILE\n"); while (cd) { HTTRACE(PROT_TRACE, " %.4f %-20.20s %-8.8s %-10.10s %s\n" _ cd->quality _ cd->content_type ?HTAtom_name(cd->content_type) :"-\t" _ cd->content_language?HTAtom_name(cd->content_language):"-" _ cd->content_encoding?HTAtom_name(cd->content_encoding):"-" _ cd->filename ?cd->filename :"-"); cd = (HTContentDescription *) HTArray_nextObject(variants, data); } }#endif /* HTDEBUG */ /* ** Finally get the best variant which is readable */ if (HTRank(req, variants)) { void ** data; HTContentDescription * cd = HTArray_firstObject(variants, data); while (cd) { if (cd->filename) { if (access(cd->filename, R_OK) != -1) StrAllocCopy(representation, cd->filename); else HTTRACE(PROT_TRACE, "Multi....... `%s\' is not readable\n" _ cd->filename); } HT_FREE(cd->filename); HT_FREE(cd); cd = (HTContentDescription *) HTArray_nextObject(variants, data); } } HTArray_delete(variants); return representation;}PRIVATE int welcome_value (char * name){ HTList * cur = welcome_names; char * welcome; int v = 0; while ((welcome = (char*)HTList_nextObject(cur))) { v++; if (!strcmp(welcome,name)) return v; } return 0;}PRIVATE char * get_best_welcome (char * path){ char * best_welcome = NULL; int best_value = 0; DIR * dp; struct dirent * dirbuf; char * last = strrchr(path, '/'); if (!welcome_names) { HTAddWelcome("Welcome.html"); HTAddWelcome("welcome.html");#if 0 HTAddWelcome("Index.html");#endif HTAddWelcome("index.html"); } if (last && last!=path) *last = 0; dp = opendir(path); if (last && last!=path) *last='/'; if (!dp) { HTTRACE(PROT_TRACE, "Warning..... Can't open directory %s\n" _ path); return NULL; } while ((dirbuf = readdir(dp))) { if (!dirbuf->d_ino || !strcmp(dirbuf->d_name,".") || !strcmp(dirbuf->d_name,"..") || !strcmp(dirbuf->d_name, DEFAULT_DIR_FILE)) continue; else { int v = welcome_value(dirbuf->d_name); if (v > best_value) { best_value = v; StrAllocCopy(best_welcome, dirbuf->d_name); } } } closedir(dp); if (best_welcome) { char * welcome; if ((welcome = (char *) HT_MALLOC(strlen(path) + strlen(best_welcome)+2)) == NULL) HT_OUTOFMEM("get_best_welcome"); sprintf(welcome, "%s%s%s", path, last ? "" : "/", best_welcome); HT_FREE(best_welcome); HTTRACE(PROT_TRACE, "Welcome..... \"%s\"\n" _ welcome); return welcome; } return NULL;}#endif /* HAVE_READDIR *//*** Do multiformat handling** -----------------------** On entry:** req->conversions accepted content-types** req->encodings accepted content-transfer-encodings** req->languages accepted content-languages** path absolute pathname of the filename for** which the match is desired.** stat_info pointer to result space.**** On exit:** returns a newly allocated absolute filepath of the best** match, or NULL if no match.** stat_info will contain inode information as** returned by stat().*/PUBLIC char * HTMulti (HTRequest * req, char * path, struct stat * stat_info){ char * new_path = NULL; int stat_status = -1; if (!req || !path || !*path || !stat_info) return NULL;#ifdef HAVE_READDIR if (*(path+strlen(path)-1) == '/') { /* Find welcome page */ new_path = get_best_welcome(path); if (new_path) path = new_path; } else{ char * multi = strrchr(path, MULTI_SUFFIX[0]); if (multi && !strcasecomp(multi, MULTI_SUFFIX)) { HTTRACE(PROT_TRACE, "Multi....... by %s suffix\n" _ MULTI_SUFFIX); if (!(new_path = HTGetBest(req, path))) { HTTRACE(PROT_TRACE, "Multi....... failed -- giving up\n"); return NULL; } path = new_path; } else { stat_status = HT_STAT(path, stat_info); if (stat_status == -1) { HTTRACE(PROT_TRACE, "AutoMulti... can't stat \"%s\"(errno %d)\n" _ path _ errno); if (!(new_path = HTGetBest(req, path))) { HTTRACE(PROT_TRACE, "AutoMulti... failed -- giving up\n"); return NULL; } path = new_path; } } }#endif /* HAVE_READDIR */ if (stat_status == -1) stat_status = HT_STAT(path, stat_info); if (stat_status == -1) { HTTRACE(PROT_TRACE, "Stat fails.. on \"%s\" -- giving up (errno %d)\n" _ path _ errno); return NULL; } else { if (!new_path) { StrAllocCopy(new_path, path); return new_path; } else return path; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -