📄 htfile.c
字号:
/* HTFile.c** FILE ACCESS**** (c) COPYRIGHT MIT 1995.** Please first read the full copyright statement in the file COPYRIGH.** @(#) $Id: HTFile.c,v 1.158 2000/08/10 16:05:39 kahan Exp $**** This is unix-specific code in general, with some VMS bits.** These are routines for file access used by browsers.**** History:** Feb 91 Written Tim Berners-Lee CERN/CN** Apr 91 vms-vms access included using DECnet syntax** 26 Jun 92 (JFG) When running over DECnet, suppressed FTP.** Fixed access bug for relative names on VMS.** Sep 93 (MD) Access to VMS files allows sharing.** 15 Nov 93 (MD) Moved HTVMSname to HTVMSUTILS.C** 22 Feb 94 (MD) Excluded two routines if we are not READING directories** 18 May 94 (HF) Directory stuff removed and stream handling updated,** error messages introduced etc.** HFN Separated transport**** Bugs:** FTP: Cannot access VMS files from a unix machine.** How can we know that the** target machine runs VMS?*//* Library Includes */#include "wwwsys.h"#include "WWWUtil.h"#include "WWWCore.h"#include "WWWDir.h"#include "WWWTrans.h"#include "HTReqMan.h"#include "HTBind.h"#include "HTMulti.h"#include "HTFile.h" /* Implemented here *//* Final states have negative value */typedef enum _FileState { FS_RETRY = -4, FS_ERROR = -3, FS_NO_DATA = -2, FS_GOT_DATA = -1, FS_BEGIN = 0, FS_PENDING, FS_DO_CN, FS_NEED_OPEN_FILE, FS_NEED_BODY, FS_PARSE_DIR, FS_TRY_FTP} FileState;/* This is the context structure for the this module */typedef struct _file_info { FileState state; /* Current state of the connection */ char * local; /* Local representation of file name */ struct stat stat_info; /* Contains actual file chosen */ HTNet * net; HTTimer * timer;} file_info;struct _HTStream { const HTStreamClass * isa;};struct _HTInputStream { const HTInputStreamClass * isa;};PRIVATE HTDirReadme dir_readme = HT_DIR_README_TOP;PRIVATE HTDirAccess dir_access = HT_DIR_OK;PRIVATE HTDirShow dir_show = HT_DS_SIZE+HT_DS_DATE+HT_DS_DES+HT_DS_ICON;PRIVATE HTDirKey dir_key = HT_DK_CINS;PRIVATE BOOL file_suffix_binding = YES;/* ------------------------------------------------------------------------- *//* Directory Access** ----------------*/PUBLIC BOOL HTFile_setDirAccess (HTDirAccess mode){ dir_access = mode; return YES;}PUBLIC HTDirAccess HTFile_dirAccess (void){ return dir_access;}/* Directory Readme** ----------------*/PUBLIC BOOL HTFile_setDirReadme (HTDirReadme mode){ dir_readme = mode; return YES;}PUBLIC HTDirReadme HTFile_dirReadme (void){ return dir_readme;}/*** Should we find the bindings between file suffixes and media types** here or not?*/PUBLIC BOOL HTFile_doFileSuffixBinding (BOOL mode){ file_suffix_binding = mode; return YES;}PUBLIC BOOL HTFile_fileSuffixBinding (void){ return file_suffix_binding;}/* HTFile_readDir** --------------** Reads the directory "path"** Returns:** HT_ERROR Error** HT_FORBIDDEN Directory reading not allowed** HT_LOADED Successfully read the directory*/PRIVATE int HTFile_readDir (HTRequest * request, file_info *file){#ifdef HAVE_READDIR DIR * dp; struct stat file_info; HTParentAnchor * anchor = HTRequest_anchor(request); char *url = HTAnchor_physical(anchor); char fullname[HT_MAX_PATH+1]; char *name; HTTRACE(PROT_TRACE, "Reading..... directory\n"); if (dir_access == HT_DIR_FORBID) { HTRequest_addError(request, ERR_FATAL, NO, HTERR_FORBIDDEN, NULL, 0, "HTFile_readDir"); return HT_FORBIDDEN; } /* Initialize path name for stat() */ if (*(name = (url+strlen(url)-1)) != '/') { char *newurl = NULL; StrAllocCopy(newurl, url); StrAllocCat(newurl, "/"); HT_FREE(file->local); file->local = HTWWWToLocal(newurl, "", HTRequest_userProfile(request)); HT_FREE(newurl); } strcpy(fullname, file->local); name = fullname+strlen(fullname); /* Point to end of fullname */ /* Check if access is enabled */ if (dir_access == HT_DIR_SELECTIVE) { strcpy(name, DEFAULT_DIR_FILE); if (HT_STAT(fullname, &file_info)) { HTTRACE(PROT_TRACE, "Read dir.... `%s\' not found\n" _ DEFAULT_DIR_FILE); HTRequest_addError(request, ERR_FATAL, NO, HTERR_FORBIDDEN, NULL, 0, "HTFile_readDir"); return HT_FORBIDDEN; } } if ((dp = opendir(file->local))) { struct dirent * dirbuf; HTDir *dir = HTDir_new(request, dir_show, dir_key); char datestr[20]; char sizestr[10]; HTFileMode mode;#ifdef HT_REENTRANT struct dirent result; /* For readdir_r */#endif#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 */ { /* Current and parent directories are never shown in list */#ifdef HAVE_DIRENT_INO if (!dirbuf->d_ino || !strcmp(dirbuf->d_name, ".") || !strcmp(dirbuf->d_name, ".."))#else if (!strcmp(dirbuf->d_name, ".") || !strcmp(dirbuf->d_name, ".."))#endif continue; /* Make a lstat on the file */ strcpy(name, dirbuf->d_name); if (HT_LSTAT(fullname, &file_info)) { HTTRACE(PROT_TRACE, "Read dir.... lstat failed: %s\n" _ fullname); continue; } /* Convert stat info to fit our setup */ if (((mode_t) file_info.st_mode & S_IFMT) == S_IFDIR) {#ifdef VMS char *dot = strstr(name, ".DIR"); /* strip .DIR part... */ if (dot) *dot = '\0';#endif /* VMS */ mode = HT_IS_DIR; if (dir_show & HT_DS_SIZE) strcpy(sizestr, "-"); } else { mode = HT_IS_FILE; if (dir_show & HT_DS_SIZE) HTNumToStr(file_info.st_size, sizestr, 10); } if (dir_show & HT_DS_DATE) HTDateDirStr(&file_info.st_mtime, datestr, 20); /* Add to the list */ if (HTDir_addElement(dir, name, datestr, sizestr, mode) != YES) break; } closedir(dp); HTDir_free(dir); return HT_LOADED; } else { HTRequest_addSystemError(request, ERR_FATAL, errno, NO, "opendir"); return HT_ERROR; }#else return HT_ERROR; /* needed for WWW_MSWINDOWS */#endif /* HAVE_READDIR */}/* Determine write access to a file** --------------------------------** If stat_info is NULL then the function calls stat() on it's own,** otherwise it uses the information found in stat_info** On exit,** return value YES if file can be accessed and can be written to.**** Bugs:** 1. No code for non-unix systems.** 2. Isn't there a quicker way?*/PRIVATE BOOL HTEditable (const char * filename, struct stat * stat_info){#ifdef GETGROUPS_T int i; uid_t myUid; int ngroups; /* The number of groups */ struct stat fileStatus; struct stat *fileptr = stat_info ? stat_info : &fileStatus; GETGROUPS_T groups[NGROUPS]; if (!stat_info) { if (HT_STAT(filename, &fileStatus)) return NO; /* Can't even access file! */ } ngroups = getgroups(NGROUPS, groups); /* Groups to which I belong */ myUid = geteuid(); /* Get my user identifier */#ifdef HTDEBUG if (PROT_TRACE) { int i; HTTRACE(PROT_TRACE, "File mode is 0%o, uid=%d, gid=%d. My uid=%d, %d groups (" _ (unsigned int) fileptr->st_mode _ (int) fileptr->st_uid _ (int) fileptr->st_gid _ (int) myUid _ ngroups); for (i=0; i<ngroups; i++) HTTRACE(PROT_TRACE, " %d" _ (int) groups[i]); HTTRACE(PROT_TRACE, ")\n"); }#endif /* HTDEBUG */ if (fileptr->st_mode & 0002) /* I can write anyway? */ return YES; if ((fileptr->st_mode & 0200) /* I can write my own file? */ && (fileptr->st_uid == myUid)) return YES; if (fileptr->st_mode & 0020) /* Group I am in can write? */ { for (i=0; i<ngroups; i++) { if (groups[i] == fileptr->st_gid) return YES; } } HTTRACE(PROT_TRACE, "\tFile is not editable.\n"); return NO; /* If no excuse, can't do */#else /* ** We don't know and can't find out. Can we be sure that when opening ** a file in mode "a" that the file is not modified? */ return NO;#endif /* GETGROUPS_T */}/* FileCleanup** -----------** This function closes the connection and frees memory.** Returns YES on OK, else NO*/PRIVATE int FileCleanup (HTRequest *req, int status){ HTNet * net = HTRequest_net(req); file_info * file = (file_info *) HTNet_context(net); HTStream * input = HTRequest_inputStream(req); /* Free stream with data TO Local file system */ if (input) { if (status == HT_INTERRUPTED) (*input->isa->abort)(input, NULL); else (*input->isa->_free)(input); HTRequest_setInputStream(req, NULL); } /* ** Remove if we have registered a timer function as a callback */ if (file->timer) { HTTimer_delete(file->timer); file->timer = NULL; } if (file) { HT_FREE(file->local); HT_FREE(file); } HTNet_delete(net, status); return YES;}/* Load a document** ---------------**** On entry,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -