📄 htfile.c
字号:
#ifdef _WINDOWS /* * Someone claims that stat() doesn't give the proper result for a * directory on Windows. */ if (result == -1 && access(filename, 0) == 0) { data->st_mode = S_IFDIR; result = 0; }#endif } return result;}#endif/* Load a document.** ----------------**** On entry:** addr must point to the fully qualified hypertext reference.** This is the physical address of the file**** On exit:** returns <0 Error has occurred.** HTLOADED OK***/PUBLIC int HTLoadFile ARGS4( CONST char *, addr, HTParentAnchor *, anchor, HTFormat, format_out, HTStream *, sink){ char * filename = NULL; char * acc_method = NULL; char * ftp_newhost; HTFormat format; char * nodename = NULL; char * newname = NULL; /* Simplified name of file */ HTAtom * encoding; /* @@ not used yet */ HTAtom * myEncoding = NULL; /* enc of this file, may be gzip etc. */ int status = -1; char *dot;#ifdef VMS struct stat stat_info;#endif /* VMS */#ifdef USE_ZLIB gzFile gzfp = 0;#endif /* USE_ZLIB */#ifdef USE_BZLIB BZFILE *bzfp = 0;#endif /* USE_ZLIB */#if defined(USE_ZLIB) || defined(USE_BZLIB) CompressFileType internal_decompress = cftNone; BOOL failed_decompress = NO;#endif /* ** Reduce the filename to a basic form (hopefully unique!). */ StrAllocCopy(newname, addr); filename=HTParse(newname, "", PARSE_PATH|PARSE_PUNCTUATION); nodename=HTParse(newname, "", PARSE_HOST); /* ** If access is ftp, or file is on another host, invoke ftp now. */ acc_method = HTParse(newname, "", PARSE_ACCESS); if (strcmp("ftp", acc_method) == 0 || (!LYSameHostname("localhost", nodename) && !LYSameHostname(nodename, HTHostName()))) { status = -1; FREE(newname); FREE(filename); FREE(nodename); FREE(acc_method);#ifndef DISABLE_FTP ftp_newhost = HTParse(addr, "", PARSE_HOST); if (strcmp(ftp_lasthost, ftp_newhost)) ftp_local_passive = ftp_passive; status = HTFTPLoad(addr, anchor, format_out, sink); if ( ftp_passive == ftp_local_passive ) { if (( status >= 400 ) || ( status < 0 )) { ftp_local_passive = !ftp_passive; status = HTFTPLoad(addr, anchor, format_out, sink); } } free(ftp_lasthost); ftp_lasthost = ftp_newhost;#endif /* DISABLE_FTP */ return status; } else { FREE(newname); FREE(acc_method); }#if defined(VMS) || defined(USE_DOS_DRIVES) HTUnEscape(filename);#endif /* VMS */ /* ** Determine the format and encoding mapped to any suffix. */ if (anchor->content_type && anchor->content_encoding) { /* * If content_type and content_encoding are BOTH already set * in the anchor object, we believe it and don't try to * derive format and encoding from the filename. - kw */ format = HTAtom_for(anchor->content_type); myEncoding = HTAtom_for(anchor->content_encoding); } else { int default_UCLYhndl = UCLYhndl_HTFile_for_unspec; if (force_old_UCLYhndl_on_reload) { force_old_UCLYhndl_on_reload = FALSE; default_UCLYhndl = forced_UCLYhdnl; } format = HTFileFormat(filename, &myEncoding, NULL); /* ** Check the format for an extended MIME charset value, and ** act on it if present. Otherwise, assume what is indicated ** by the last parameter (fallback will effectively be ** UCLYhndl_for_unspec, by default ISO-8859-1). - kw */ format = HTCharsetFormat(format, anchor, default_UCLYhndl ); }#ifdef VMS /* ** Check to see if the 'filename' is in fact a directory. If it is ** create a new hypertext object containing a list of files and ** subdirectories contained in the directory. All of these are links ** to the directories or files listed. */ if (HTStat(filename, &stat_info) == -1) { CTRACE((tfp, "HTLoadFile: Can't stat %s\n", filename)); } else { if (S_ISDIR(stat_info.st_mode)) { if (HTDirAccess == HT_DIR_FORBID) { FREE(filename); FREE(nodename); return HTLoadError(sink, 403, DISALLOWED_DIR_SCAN); } if (HTDirAccess == HT_DIR_SELECTIVE) { char * enable_file_name = NULL; HTSprintf0(&enable_file_name, "%s/%s", filename, HT_DIR_ENABLE_FILE); if (HTStat(enable_file_name, &stat_info) == -1) { FREE(filename); FREE(nodename); FREE(enable_file_name); return HTLoadError(sink, 403, DISALLOWED_SELECTIVE_ACCESS); } } FREE(filename); FREE(nodename); return HTVMSBrowseDir(addr, anchor, format_out, sink); } } /* ** Assume that the file is in Unix-style syntax if it contains a '/' ** after the leading one. @@ */ { FILE * fp; char * vmsname = strchr(filename + 1, '/') ? HTVMS_name(nodename, filename) : filename + 1; fp = fopen(vmsname, "r", "shr=put", "shr=upd"); /* ** If the file wasn't VMS syntax, then perhaps it is Ultrix. */ if (!fp) { char * ultrixname = 0; CTRACE((tfp, "HTLoadFile: Can't open as %s\n", vmsname)); HTSprintf0(&ultrixname, "%s::\"%s\"", nodename, filename); fp = fopen(ultrixname, "r", "shr=put", "shr=upd"); if (!fp) { CTRACE((tfp, "HTLoadFile: Can't open as %s\n", ultrixname)); } FREE(ultrixname); } if (fp) { char *semicolon = NULL; if (HTEditable(vmsname)) { HTAtom * put = HTAtom_for("PUT"); HTList * methods = HTAnchor_methods(anchor); if (HTList_indexOf(methods, put) == (-1)) { HTList_addObject(methods, put); } } /* ** Trim vmsname at semicolon if a version number was ** included, so it doesn't interfere with the check ** for a compressed file. - FM */ if ((semicolon = strchr(vmsname, ';')) != NULL) *semicolon = '\0'; /* ** Fake a Content-Encoding for compressed files. - FM */ if (!IsUnityEnc(myEncoding)) { /* * We already know from the call to HTFileFormat above * that this is a compressed file, no need to look at * the filename again. - kw */#ifdef USE_ZLIB if (strcmp(format_out->name, "www/download") != 0 && (!strcmp(HTAtom_name(myEncoding), "gzip") || !strcmp(HTAtom_name(myEncoding), "x-gzip"))) { fclose(fp); if (semicolon != NULL) *semicolon = ';'; gzfp = gzopen(vmsname, BIN_R); CTRACE((tfp, "HTLoadFile: gzopen of `%s' gives %p\n", vmsname, (void*)gzfp)); internal_decompress = cftGzip; } else#endif /* USE_ZLIB */#ifdef USE_BZLIB if (strcmp(format_out->name, "www/download") != 0 && (!strcmp(HTAtom_name(myEncoding), "bzip2") || !strcmp(HTAtom_name(myEncoding), "x-bzip2"))) { fclose(fp); if (semicolon != NULL) *semicolon = ';'; bzfp = BZ2_bzopen(vmsname, BIN_R); CTRACE((tfp, "HTLoadFile: bzopen of `%s' gives %p\n", vmsname, (void*)bzfp)); use_zread = YES; } else#endif /* USE_BZLIB */ { StrAllocCopy(anchor->content_type, format->name); StrAllocCopy(anchor->content_encoding, HTAtom_name(myEncoding)); format = HTAtom_for("www/compressed"); } } else { /* FIXME: should we check if suffix is after ']' or ':' ? */ CompressFileType cft = HTCompressFileType(vmsname, "._-", &dot); if (cft != cftNone) { char *cp = NULL; StrAllocCopy(cp, vmsname); cp[dot - vmsname] = '\0'; format = HTFileFormat(cp, &encoding, NULL); FREE(cp); format = HTCharsetFormat(format, anchor, UCLYhndl_HTFile_for_unspec); StrAllocCopy(anchor->content_type, format->name); } switch (cft) { case cftCompress: StrAllocCopy(anchor->content_encoding, "x-compress"); format = HTAtom_for("www/compressed"); break; case cftGzip: StrAllocCopy(anchor->content_encoding, "x-gzip");#ifdef USE_ZLIB if (strcmp(format_out->name, "www/download") != 0) { fclose(fp); if (semicolon != NULL) *semicolon = ';'; gzfp = gzopen(vmsname, BIN_R); CTRACE((tfp, "HTLoadFile: gzopen of `%s' gives %p\n", vmsname, (void*)gzfp)); internal_decompress = cftGzip; }#else /* USE_ZLIB */ format = HTAtom_for("www/compressed");#endif /* USE_ZLIB */ break; case cftBzip2: StrAllocCopy(anchor->content_encoding, "x-bzip2");#ifdef USE_BZLIB if (strcmp(format_out->name, "www/download") != 0) { fclose(fp); if (semicolon != NULL) *semicolon = ';'; bzfp = BZ2_bzopen(vmsname, BIN_R); CTRACE((tfp, "HTLoadFile: bzopen of `%s' gives %p\n", vmsname, (void*)bzfp)); internal_decompress = cfgBzip2; }#else /* USE_BZLIB */ format = HTAtom_for("www/compressed");#endif /* USE_BZLIB */ break; case cftNone: break; } } if (semicolon != NULL) *semicolon = ';'; FREE(filename); FREE(nodename);#if defined(USE_ZLIB) || defined(USE_BZLIB) if (internal_decompress != cftNone) { switch (internal_decompress) {#ifdef USE_ZLIB case cftCompress: case cftGzip: failed_decompress = (gzfp == 0); break;#endif#ifdef USE_BZLIB case cftBzip2: failed_decompress = (bzfp == 0); break;#endif default: failed_decompress = YES; break; } if (failed_decompress) { status = HTLoadError(NULL, -(HT_ERROR), FAILED_OPEN_COMPRESSED_FILE); } else { char * sugfname = NULL; if (anchor->SugFname) { StrAllocCopy(sugfname, anchor->SugFname); } else { char * anchor_path = HTParse(anchor->address, "", PARSE_PATH + PARSE_PUNCTUATION); char * lastslash; HTUnEscape(anchor_path); lastslash = strrchr(anchor_path, '/'); if (lastslash) StrAllocCopy(sugfname, lastslash + 1); FREE(anchor_path); } FREE(anchor->content_encoding); if (sugfname && *sugfname) HTCheckFnameForCompression(&sugfname, anchor, TRUE); if (sugfname && *sugfname) StrAllocCopy(anchor->SugFname, sugfname); FREE(sugfname);#ifdef USE_BZLIB if (bzfp) status = HTParseBzFile(format, format_out, anchor, bzfp, sink);#endif#ifdef USE_ZLIB if (gzfp) status = HTParseGzFile(format, format_out, anchor, gzfp, sink);#endif } } else#endif /* USE_ZLIB || USE_BZLIB */ { status = HTParseFile(format, format_out, anchor, fp, sink); fclose(fp); } return status; } /* If successful open */ FREE(filename); }#else /* not VMS: */ FREE(filename); /* ** For unix, we try to translate the name into the name of a ** transparently mounted file. ** ** Not allowed in secure (HTClientHost) situations. TBL 921019 */#ifndef NO_UNIX_IO /* Need protection here for telnet server but not httpd server. */ if (!HTSecure) { /* try local file system */ char * localname = HTLocalName(addr); struct stat dir_info;#ifdef HAVE_READDIR /* ** Multiformat handling. ** ** If needed, scan directory to find a good file. ** Bug: We don't stat the file to find the length. */ if ((strlen(localname) > strlen(MULTI_SUFFIX)) && (0 == strcmp(localname + strlen(localname) - strlen(MULTI_SUFFIX), MULTI_SUFFIX))) { DIR *dp = 0; BOOL forget_multi = NO; STRUCT_DIRENT * dirbuf; float best = (float) NO_VALUE_FOUND; /* So far best is bad */ HTFormat best_rep = NULL; /* Set when rep found */ HTAtom * best_enc = NULL; char * best_name = NULL; /* Best dir entry so far */ char *base = strrchr(localname, '/'); int baselen = 0; if (!base || base == localname) { forget_multi = YES; } else { *base++ = '\0'; /* Just got directory name */ baselen = strlen(base)- strlen(MULTI_SUFFIX); base[baselen] = '\0'; /* Chop off suffix */ dp = opendir(localname); } if (forget_multi || !dp) { FREE(localname); FREE(nodename); return HTLoadError(sink, 500, FAILED_DIR_SCAN); } while ((dirbuf = readdir(dp)) != NULL) { /* ** While there are directory entries to be read... */#if !(defined(DOSPATH) || defined(__EMX__)) if (dirbuf->d_ino == 0) continue; /* if the entry is not being used, skip it */#endif if ((int)strlen(dirbuf->d_name) > baselen && /* Match? */ !strncmp(dirbuf->d_name, base, baselen)) { HTAtom * enc; HTFormat rep = HTFileFormat(dirbuf->d_name, &enc, NULL); float filevalue = HTFileValue(dirbuf->d_name); float value = HTStackValue(rep, format_out, filevalue, 0L /* @@@@@@ */); if (value <= 0.0) { char *atomname = NULL; CompressFileType cft = HTCompressFileType(dirbuf->d_name, ".", &dot); char * cp = NULL; enc = NULL; if (cft != cftNone) { StrAllocCopy(cp, dirbuf->d_name); cp[dot - dirbuf->d_name] = '\0'; format = HTFileFormat(cp, NULL, NULL); FREE(cp); value = HTStackValue(format, format_out, filevalue, 0); switch (cft) { case cftCompress: atomname = "application/x-compressed"; break; case cftGzip: atomname = "application/x-gzip"; break; case cftBzip2: atomname = "application/x-bzip2"; break; case cftNone: break; } } if (atomname != NULL) { value = HTStackValue(format, format_out, filevalue, 0); if (value <= 0.0) { format = HTAtom_for(atomname); value = HTStackValue(format, format_out, filevalue, 0); } if (value <= 0.0) { format = HTAtom_for("www/compressed"); value = HTStackValue(format, format_out, filevalue, 0); } } } if (value != NO_VALUE_FOUND) { CTRACE((tfp, "HTLoadFile: value of presenting %s is %f\n", HTAtom_name(rep), value)); if (value > best) { best_rep = rep; best_enc = enc; best = value; StrAllocCopy(best_name, dirbuf->d_name); } } /* if best so far */ } /* if match */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -