📄 htfile.c
字号:
if (HTDirReadme == HT_DIR_README_BOTTOM) do_readme(target, localname); FREE_TARGET; } else { ABORT_TARGET; } } HTFinishDisplayPartial(); return status; /* document loaded, maybe partial */}#endif /* HAVE_READDIR */#ifndef VMSPUBLIC int HTStat ARGS2( CONST char *, filename, struct stat *, data){ int result = -1; char *temp_name = NULL; size_t len = strlen(filename); if (len != 0 && LYIsPathSep(filename[len-1])) { HTSprintf0(&temp_name, "%s.", filename); } else { temp_name = (char *)filename; }#ifdef _WINDOWS /* * Someone claims that stat() doesn't give the proper result for a * directory on Windows. */ if (access(temp_name, 0) == 0) { if (stat(temp_name, data) == -1) data->st_mode = S_IFDIR; result = 0; }#else result = stat(temp_name, data);#endif if (temp_name != filename) { FREE(temp_name); } 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; 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; char *dot;#ifdef VMS struct stat stat_info;#endif /* VMS */#ifdef USE_ZLIB gzFile gzfp = 0; BOOL use_gzread = NO;#endif /* USE_ZLIB */ /* ** 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 || (strcmp("localhost", nodename) != 0 &&#ifdef VMS strcasecomp(nodename, HTHostName()) != 0#else strcmp(nodename, HTHostName()) != 0#endif /* VMS */ )) { status = -1; FREE(newname); FREE(filename); FREE(nodename); FREE(acc_method);#ifndef DISABLE_FTP status = HTFTPLoad(addr, anchor, format_out, sink);#endif /* DISABLE_FTP */ return status; } else { FREE(newname); FREE(acc_method); }#if defined(VMS) || defined(DOSPATH) 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)); use_gzread = YES; } else#endif /* USE_ZLIB */ { 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)); use_gzread = YES; }#else /* USE_ZLIB */ format = HTAtom_for("www/compressed");#endif /* USE_ZLIB */ break; case cftBzip2: StrAllocCopy(anchor->content_encoding, "x-bzip2"); format = HTAtom_for("www/compressed"); break; case cftNone: break; } } if (semicolon != NULL) *semicolon = ';'; FREE(filename); FREE(nodename);#ifdef USE_ZLIB if (use_gzread) { if (gzfp) { 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); status = HTParseGzFile(format, format_out, anchor, gzfp, sink); } else { status = HTLoadError(NULL, -(HT_ERROR), FAILED_OPEN_COMPRESSED_FILE); } } else#endif /* USE_ZLIB */ { 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 (HTClienntHost) 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... */#ifndef DOSPATH 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 */ } /* end while directory entries left to read */ closedir(dp); if (best_rep) { format = best_rep; myEncoding = best_enc; base[-1] = '/'; /* Restore directory name */ base[0] = '\0'; StrAllocCat(localname, best_name); FREE(best_name); } else { /* If not found suitable file */ FREE(localname); FREE(nodename); return HTLoadError(sink, 403, FAILED_NO_REPRESENTATION); } /*NOTREACHED*/ } /* if multi suffix */ /* ** Check to see if the 'localname' 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. ** NB This assumes the existence of a type 'STRUCT_DIRENT', which ** will hold the directory entry, and a type 'DIR' which is used ** to point to the current directory being read. */ if (HTStat(localname,&dir_info) == -1) /* get file information */ { /* if can't read file information */ CTRACE((tfp, "HTLoadFile: can't stat %s\n", localname)); } else { /* Stat was OK */ if (S_ISDIR(dir_info.st_mode)) { /* ** If localname is a directory. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -