⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 htfile.c

📁 www工具包. 这是W3C官方支持的www支撑库. 其中提供通用目的的客户端的WebAPI: complete HTTP/1.1 (with caching, pipelining, PUT, POS
💻 C
📖 第 1 页 / 共 2 页
字号:
**	request		This is the request structure** On exit,**	returns		HT_ERROR	Error has occured in call back**			HT_OK		Call back was OK*/PRIVATE int FileEvent (SOCKET soc, void * pVoid, HTEventType type);PUBLIC int HTLoadFile (SOCKET soc, HTRequest * request){    file_info *file;			      /* Specific access information */    HTNet * net = HTRequest_net(request);    HTParentAnchor * anchor = HTRequest_anchor(request);    HTTRACE(PROT_TRACE, "HTLoadFile.. Looking for `%s\'\n" _ 			    HTAnchor_physical(anchor));    if ((file = (file_info *) HT_CALLOC(1, sizeof(file_info))) == NULL)	HT_OUTOFMEM("HTLoadFILE");    file->state = FS_BEGIN;    file->net = net;    HTNet_setContext(net, file);    HTNet_setEventCallback(net, FileEvent);    HTNet_setEventParam(net, file);  /* callbacks get http* */    return FileEvent(soc, file, HTEvent_BEGIN);	    /* get it started - ops is ignored */}PRIVATE int ReturnEvent (HTTimer * timer, void * param, HTEventType type){    file_info * file = (file_info *) param;    if (timer != file->timer)	HTDEBUGBREAK("File timer %p not in sync\n" _ timer);    HTTRACE(PROT_TRACE, "HTLoadFile.. Continuing %p with timer %p\n" _ file _ timer);    /*    **  Delete the timer    */    HTTimer_delete(file->timer);    file->timer = NULL;    /*    **  Now call the event again    */    return FileEvent(INVSOC, file, HTEvent_READ);}PRIVATE int FileEvent (SOCKET soc, void * pVoid, HTEventType type){    file_info *file = pVoid;			      /* Specific access information */    int status = HT_ERROR;    HTNet * net = file->net;    HTRequest * request = HTNet_request(net);    HTParentAnchor * anchor = HTRequest_anchor(request);    /*    ** Initiate a new file structure and bind to request structure    ** This is actually state FILE_BEGIN, but it can't be in the state    ** machine as we need the structure first.    */    if (type == HTEvent_CLOSE) {				      /* Interrupted */	HTRequest_addError(request, ERR_FATAL, NO, HTERR_INTERRUPTED,			   NULL, 0, "HTLoadFile");	FileCleanup(request, HT_INTERRUPTED);	return HT_OK;    }    /* Now jump into the machine. We know the state from the previous run */    while (1) {	switch (file->state) {	case FS_BEGIN:	    /* We only support safe (GET, HEAD, etc) methods for the moment */	    if (!HTMethod_isSafe(HTRequest_method(request))) {		HTRequest_addError(request, ERR_FATAL, NO, HTERR_NOT_ALLOWED,				   NULL, 0, "HTLoadFile");		file->state = FS_ERROR;		break;	    }	    /* Check whether we have access to local disk at all */	    if (HTLib_secure()) {		HTTRACE(PROT_TRACE, "LoadFile.... No access to local file system\n");		file->state = FS_TRY_FTP;		break;	    }	    file->local = HTWWWToLocal(HTAnchor_physical(anchor), "",				       HTRequest_userProfile(request));	    if (!file->local) {		file->state = FS_TRY_FTP;		break;	    }	    /* Create a new host object and link it to the net object */	    {		HTHost * host = NULL;		if ((host = HTHost_new("localhost", 0)) == NULL) return HT_ERROR;		HTNet_setHost(net, host);		if (HTHost_addNet(host, net) == HT_PENDING) {		    HTTRACE(PROT_TRACE, "HTLoadFile.. Pending...\n");		    /* move to the hack state */		    file->state = FS_PENDING;		    return HT_OK;		}	    }	    file->state = FS_DO_CN;	    break;	case FS_PENDING:	    /*	    ** 2000/08/10 JK : This is a funny state. Because of the	    ** internal libwww stacks, when doing multiple local	    ** requests (e.g., while using the Robot), we need to ask	    ** again for the host object. If we had jumped directly to	    ** the FS_DO_CN state, libwww would have blocked because	    ** of socket starvation.	    ** This state is similar to FS_BEGINNING, but just requests 	    ** the host object. 	    ** YES. THIS IS AN UGLY HACK!!	    */	    {		HTHost * host = NULL;		if ((host = HTHost_new("localhost", 0)) == NULL) return HT_ERROR;		HTNet_setHost(net, host);		if (HTHost_addNet(host, net) == HT_PENDING) {		    HTTRACE(PROT_TRACE, "HTLoadFile.. Pending...\n");		    file->state = FS_PENDING;		    return HT_OK;		}	    }	    file->state = FS_DO_CN;	    break;	case FS_DO_CN:	    /*	    ** If we have to do content negotiation then find the object that	    ** fits best into either what the client has indicated in the	    ** accept headers or what the client has registered on its own.	    ** The object chosen can in fact be a directory! However, content	    ** negotiation only makes sense if we can read the directory!	    ** We stat the file in order to find the size and to see it if	    ** exists.	    */	    if (HTRequest_negotiation(request) &&		HTMethod_isSafe(HTRequest_method(request))) { 		char * conneg = HTMulti(request, file->local,&file->stat_info);		if (conneg) {		    HT_FREE(file->local);		    file->local = conneg;		    HTAnchor_setPhysical(anchor, conneg);		    HTTRACE(PROT_TRACE, "Load File... Found `%s\'\n" _ conneg);		} else {		    HTTRACE(PROT_TRACE, "Load File... Not found - even tried content negotiation\n");		    HTRequest_addError(request, ERR_FATAL, NO, HTERR_NOT_FOUND,				       NULL, 0, "HTLoadFile");		    file->state = FS_ERROR;		    break;		}	    } else {		if (HT_STAT(file->local, &file->stat_info) == -1) {		    HTTRACE(PROT_TRACE, "Load File... Not found `%s\'\n" _ file->local);		    HTRequest_addError(request, ERR_FATAL, NO, HTERR_NOT_FOUND,				       NULL, 0, "HTLoadFile");		    file->state = FS_ERROR;		    break;		}	    }	    /*	    ** Check to see if the 'localname' is in fact a directory.	    ** Note that we can't do a HEAD on a directory	    */	    if (((file->stat_info.st_mode) & S_IFMT) == S_IFDIR) {		if (HTRequest_method(request) == METHOD_GET)		    file->state = FS_PARSE_DIR;		else {		    HTRequest_addError(request, ERR_INFO, NO, HTERR_NO_CONTENT,				       NULL, 0, "HTLoadFile");		    file->state = FS_NO_DATA;		}		break;	    }	    /*	    ** If empty file then only serve it if it is editable. We also get	    ** the bindings for the file suffixes in lack of better bindings	    */	    {		BOOL editable = HTEditable(file->local, &file->stat_info);		if (file_suffix_binding) HTBind_getAnchorBindings(anchor);		if (editable) HTAnchor_appendAllow(anchor, METHOD_PUT);		/* Set the file size */		if (file->stat_info.st_size)		    HTAnchor_setLength(anchor, file->stat_info.st_size);		/* Set the file last modified time stamp */		if (file->stat_info.st_mtime > 0)		    HTAnchor_setLastModified(anchor, file->stat_info.st_mtime);		/* Check to see if we can edit it */		if (!editable && !file->stat_info.st_size) {		    HTRequest_addError(request, ERR_INFO, NO, HTERR_NO_CONTENT,				       NULL, 0, "HTLoadFile");		    file->state = FS_NO_DATA;		} else {		    file->state = (HTRequest_method(request)==METHOD_GET) ? 			FS_NEED_OPEN_FILE : FS_GOT_DATA;		}	    }	    break;	  case FS_NEED_OPEN_FILE:	    status = HTFileOpen(net, file->local, HT_FB_RDONLY);	    if (status == HT_OK) {		/* 		** Create the stream pipe FROM the channel to the application.		** The target for the input stream pipe is set up using the		** stream stack.		*/		{		    HTStream * rstream = HTStreamStack(HTAnchor_format(anchor),						       HTRequest_outputFormat(request),						       HTRequest_outputStream(request),						       request, YES);		    HTNet_setReadStream(net, rstream);		    HTRequest_setOutputConnected(request, YES);		}		/*		** Create the stream pipe TO the channel from the application		** and hook it up to the request object		*/		{		    HTOutputStream * output = HTNet_getOutput(net, NULL, 0);		    HTRequest_setInputStream(request, (HTStream *) output);		}		/*		** Set up concurrent read/write if this request isn't the		** source for a PUT or POST. As source we don't start reading		** before all destinations are ready. If destination then		** register the input stream and get ready for read		*/		if (HTRequest_isSource(request) && !HTRequest_destinationsReady(request))		    return HT_OK;		HTRequest_addError(request, ERR_INFO, NO, HTERR_OK, NULL, 0,				   "HTLoadFile");		file->state = FS_NEED_BODY;		/* If we are _not_ using preemptive mode and we are Unix fd's		** then return here to get the same effect as when we are		** connecting to a socket. That way, HTFile acts just like any		** other protocol module even though we are in fact doing		** blocking connect		*/		if (HTEvent_isCallbacksRegistered()) {		    if (!HTRequest_preemptive(request)) {			if (!HTNet_preemptive(net)) {			    HTTRACE(PROT_TRACE, "HTLoadFile.. Returning\n");			    HTHost_register(HTNet_host(net), net, HTEvent_READ);			} else if (!file->timer) {			    HTTRACE(PROT_TRACE, "HTLoadFile.. Returning\n");			    file->timer =				HTTimer_new(NULL, ReturnEvent, file, 1, YES, NO);			}			return HT_OK;		    }		}	    } else if (status == HT_WOULD_BLOCK || status == HT_PENDING)		return HT_OK;	    else {		HTRequest_addError(request, ERR_INFO, NO, HTERR_INTERNAL,				   NULL, 0, "HTLoadFile");		file->state = FS_ERROR;		       /* Error or interrupt */	    }	    break;	  case FS_NEED_BODY:	    status = HTHost_read(HTNet_host(net), net);	    if (status == HT_WOULD_BLOCK)		return HT_OK;	    else if (status == HT_LOADED || status == HT_CLOSED) {		file->state = FS_GOT_DATA;	    } else {		HTRequest_addError(request, ERR_INFO, NO, HTERR_FORBIDDEN,				   NULL, 0, "HTLoadFile");		file->state = FS_ERROR;	    }	    break;	  case FS_PARSE_DIR:	    status = HTFile_readDir(request, file);	    if (status == HT_LOADED)		file->state = FS_GOT_DATA;	    else		file->state = FS_ERROR;	    break;	  case FS_TRY_FTP:	    {		char *url = HTAnchor_physical(anchor);		HTAnchor *anchor;		char *newname = NULL;		StrAllocCopy(newname, "ftp:");		if (!strncmp(url, "file:", 5))		    StrAllocCat(newname, url+5);		else		    StrAllocCat(newname, url);		anchor = HTAnchor_findAddress(newname);		HTRequest_setAnchor(request, anchor);		HT_FREE(newname);		FileCleanup(request, HT_IGNORE);		return HTLoad(request, YES);	    }	    break;	  case FS_GOT_DATA:	    FileCleanup(request, HT_LOADED);	    return HT_OK;	    break;	  case FS_NO_DATA:	    FileCleanup(request, HT_NO_DATA);	    return HT_OK;	    break;	  case FS_RETRY:	    FileCleanup(request, HT_RETRY);	    return HT_OK;	    break;	  case FS_ERROR:	    FileCleanup(request, HT_ERROR);	    return HT_OK;	    break;	}    } /* End of while(1) */}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -