📄 htaccess.c
字号:
/*** ACCESS MANAGER**** (c) COPYRIGHT MIT 1995.** Please first read the full copyright statement in the file COPYRIGH.** @(#) $Id: HTAccess.c,v 1.154 1999/02/22 22:10:10 frystyk Exp $**** Authors** TBL Tim Berners-Lee timbl@w3.org** JFG Jean-Francois Groff jfg@dxcern.cern.ch** DD Denis DeLaRoca (310) 825-4580 <CSP1DWD@mvs.oac.ucla.edu>** HFN Henrik Frystyk, frystyk@w3.org** History** 8 Jun 92 Telnet hopping prohibited as telnet is not secure TBL** 26 Jun 92 When over DECnet, suppressed FTP, Gopher and News. JFG** 6 Oct 92 Moved HTClientHost and HTlogfile into here. TBL** 17 Dec 92 Tn3270 added, bug fix. DD** 4 Feb 93 Access registration, Search escapes bad chars TBL** PARAMETERS TO HTSEARCH AND HTLOADRELATIVE CHANGED** 28 May 93 WAIS gateway explicit if no WAIS library linked in.** Dec 93 Bug change around, more reentrant, etc** 09 May 94 logfile renamed to HTlogfile to avoid clash with WAIS** 8 Jul 94 Insulate HT_FREE();** Sep 95 Rewritten, HFN*//* Library include files */#include "WWWUtil.h"#include "WWWCore.h"#include "WWWStream.h"#include "HTProxy.h"#include "HTRules.h"#include "HTReqMan.h"#include "HTAccess.h" /* Implemented here */#define PUTBLOCK(b, l) (*target->isa->put_block)(target, b, l)struct _HTStream { HTStreamClass * isa;};typedef enum _HTPutState { HT_LOAD_SOURCE = 0, HT_SAVE_DEST, HT_ABORT_SAVE} HTPutState;typedef struct _HTPutContext { HTParentAnchor * source; HTAnchor * destination; HTChunk * document; HTFormat format; HTStream * target; /* Any existing output stream */ void * placeholder; /* Any existing doc in anchor */ HTPutState state;} HTPutContext;/* --------------------------------------------------------------------------*//* THE GET METHOD *//* --------------------------------------------------------------------------*//* Request a document** -----------------** Private version that requests a document from the request manager** Returns YES if request accepted, else NO*/PRIVATE BOOL launch_request (HTRequest * request, BOOL recursive){#ifdef HTDEBUG if (PROT_TRACE) { HTParentAnchor *anchor = HTRequest_anchor(request); char * full_address = HTAnchor_address((HTAnchor *) anchor); HTTRACE(PROT_TRACE, "HTAccess.... Accessing document %s\n" _ full_address); HT_FREE(full_address); }#endif / * HTDEBUG */ return HTLoad(request, recursive);}/* Request a document from absolute name** -------------------------------------** Request a document referencd by an absolute URL.** Returns YES if request accepted, else NO*/PUBLIC BOOL HTLoadAbsolute (const char * url, HTRequest * request){ if (url && request) { HTAnchor * anchor = HTAnchor_findAddress(url); HTRequest_setAnchor(request, anchor); return launch_request(request, NO); } return NO;}/* Request a document from relative name** -------------------------------------** Request a document referenced by a relative URL. The relative URL is ** made absolute by resolving it relative to the address of the 'base' ** anchor.** Returns YES if request accepted, else NO*/PUBLIC BOOL HTLoadRelative (const char * relative, HTParentAnchor * base, HTRequest * request){ BOOL status = NO; if (relative && base && request) { char * full_url = NULL; char * base_url = HTAnchor_address((HTAnchor *) base); full_url = HTParse(relative, base_url, PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION); status = HTLoadAbsolute(full_url, request); HT_FREE(full_url); HT_FREE(base_url); } return status;}/* Request a document from absolute name to stream** -----------------------------------------------** Request a document referencd by an absolute URL and sending the data** down a stream.** Returns YES if request accepted, else NO*/PUBLIC BOOL HTLoadToStream (const char * url, HTStream * output, HTRequest * request){ if (url && output && request) { HTRequest_setOutputStream(request, output); return HTLoadAbsolute(url, request); } return NO;}/* Load a document and save it ASIS in a local file** ------------------------------------------------** Returns YES if request accepted, else NO*/PUBLIC BOOL HTLoadToFile (const char * url, HTRequest * request, const char * filename){ if (url && filename && request) { FILE * fp = NULL; /* Check if file exists. If so then ask user if we can replace it */ if (access(filename, F_OK) != -1) { HTAlertCallback * prompt = HTAlert_find(HT_A_CONFIRM); if (prompt) { if ((*prompt)(request, HT_A_CONFIRM, HT_MSG_FILE_REPLACE, NULL, NULL, NULL) != YES) return NO; } } /* If replace then open the file */ if ((fp = fopen(filename, "wb")) == NULL) { HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_NO_FILE, (char *) filename, strlen(filename), "HTLoadToFile"); return NO; } /* Set the output stream and start the request */ HTRequest_setOutputFormat(request, WWW_SOURCE); HTRequest_setOutputStream(request, HTFWriter_new(request, fp, NO)); if (HTLoadAbsolute(url, request) == NO) { fclose(fp); return NO; } else return YES; } return NO;}/*** Load a URL to a mem buffer** --------------------------** Load a request and store the result in a memory buffer.** Returns chunk if OK - else NULL*/PUBLIC HTChunk * HTLoadToChunk (const char * url, HTRequest * request){ if (url && request) { HTChunk * chunk = NULL; HTStream * target = HTStreamToChunk(request, &chunk, 0); HTAnchor * anchor = HTAnchor_findAddress(url); HTRequest_setAnchor(request, anchor); HTRequest_setOutputStream(request, target); if (launch_request(request, NO) == YES) return chunk; else { HTChunk_delete(chunk); return NULL; } } return NULL;}/* Request an anchor** -----------------** Request the document referenced by the anchor** Returns YES if request accepted, else NO*/PUBLIC BOOL HTLoadAnchor (HTAnchor * anchor, HTRequest * request){ if (anchor && request) { HTRequest_setAnchor(request, anchor); return launch_request(request, NO); } return NO;}/* Request an anchor** -----------------** Same as HTLoadAnchor but any information in the Error Stack in the ** request object is kept, so that any error messages in one ** This function is almost identical to HTLoadAnchor, but it doesn't** clear the error stack so that the information in there is kept.** Returns YES if request accepted, else NO*/PUBLIC BOOL HTLoadAnchorRecursive (HTAnchor * anchor, HTRequest * request){ if (anchor && request) { HTRequest_setAnchor(request, anchor); return launch_request(request, YES); } return NO;}/*** Load a URL to a mem buffer** --------------------------** Load a request and store the result in a memory buffer.** Returns chunk if OK - else NULL*/PUBLIC HTChunk * HTLoadAnchorToChunk (HTAnchor * anchor, HTRequest * request){ HTChunk * chunk = NULL; if (anchor && request) { HTStream * target = HTStreamToChunk(request, &chunk, 0); HTRequest_setAnchor(request, anchor); HTRequest_setOutputStream(request, target); if (launch_request(request, NO) == YES) return chunk; else { HTChunk_delete(chunk); return NULL; } } return NULL;}/*** Load a Rule File** ----------------** Load a rule find with the URL specified and add the set of rules to** the existing set.*/PUBLIC BOOL HTLoadRules (const char * url){ BOOL status = NO; if (url) { HTList * list = HTList_new(); HTRequest * request = HTRequest_new(); HTRequest_setPreemptive(request, YES); /* ** We do only accept a new rules files when we are in interactive ** mode and can ask the user for it. If HT_AUTOMATIC_RULES is ** defined then we accept new rules files without explicit ack ** from the user */#ifdef HT_AUTOMATIC_RULES HTAlert_setInteractive(NO);#endif /* ** Add the rules parsing stream for this particular request only. ** That is, we only accept a rules file when we have explicitly ** asked for it using this function. */ HTConversion_add(list, "application/x-www-rules", "*/*", HTRules, 1.0, 0.0, 0.0); HTRequest_setConversion(request, list, YES); status = HTLoadAbsolute(url, request); HTConversion_deleteAll(list); HTRequest_delete(request); } return status;}/*** Load a Rule File without asking the user ** ----------------------------------------** Load a rule find with the URL specified and add the set of rules to** the existing set. We don't ask the user as she would have to call this** method explicitly anyway.*/PUBLIC BOOL HTLoadRulesAutomatically (const char * url){ BOOL status = NO; if (url) { HTList * list = HTList_new(); HTRequest * request = HTRequest_new(); /* ** Stop all other loads and concentrate on this one */ HTRequest_setPreemptive(request, YES); /* ** Add the rules parsing stream for this particular request only. */ HTConversion_add(list, "application/x-www-rules", "*/*", HTRules_parseAutomatically, 1.0, 0.0, 0.0); HTRequest_setConversion(request, list, YES); status = HTLoadAbsolute(url, request); HTConversion_deleteAll(list); HTRequest_delete(request); } return status;}/* --------------------------------------------------------------------------*//* GET WITH KEYWORDS (SEARCH) *//* --------------------------------------------------------------------------*//*** This function creates a URL with a searh part as defined by RFC 1866** Both the baseurl and the keywords must be escaped.**** 1. The form field names and values are escaped: space** characters are replaced by `+', and then reserved characters** are escaped as per [URL]; that is, non-alphanumeric** characters are replaced by `%HH', a percent sign and two** hexadecimal digits representing the ASCII code of the** character. Line breaks, as in multi-line text field values,** are represented as CR LF pairs, i.e. `%0D%0A'.**** 2. The fields are listed in the order they appear in the** document with the name separated from the value by `=' and** the pairs separated from each other by `&'. Fields with null** values may be omitted. In particular, unselected radio** buttons and checkboxes should not appear in the encoded** data, but hidden fields with VALUE attributes present** should.**** NOTE - The URI from a query form submission can be** used in a normal anchor style hyperlink.** Unfortunately, the use of the `&' character to** separate form fields interacts with its use in SGML** attribute values as an entity reference delimiter.** For example, the URI `http://host/?x=1&y=2' must be** written `<a href="http://host/?x=1&y=2"' or `<a** href="http://host/?x=1&y=2">'.**** HTTP server implementors, and in particular, CGI** implementors are encouraged to support the use of** `;' in place of `&' to save users the trouble of** escaping `&' characters this way.*/PRIVATE char * query_url_encode (const char * baseurl, HTChunk * keywords){ char * fullurl = NULL; if (baseurl && keywords && HTChunk_size(keywords)) { int len = strlen(baseurl); fullurl = (char *) HT_MALLOC(len + HTChunk_size(keywords) + 2); sprintf(fullurl, "%s?%s", baseurl, HTChunk_data(keywords)); { char * ptr = fullurl+len; while (*ptr) { if (*ptr == ' ') *ptr = '+'; ptr++; } } } return fullurl;}PRIVATE char * form_url_encode (const char * baseurl, HTAssocList * formdata){ if (formdata) { BOOL first = YES; int cnt = HTList_count((HTList *) formdata); HTChunk * fullurl = HTChunk_new(128); HTAssoc * pres; if (baseurl) { HTChunk_puts(fullurl, baseurl); HTChunk_putc(fullurl, '?'); } while (cnt > 0) { pres = (HTAssoc *) HTList_objectAt((HTList *) formdata, --cnt); if (first) first = NO; else HTChunk_putc(fullurl, '&'); /* Could use ';' instead */ HTChunk_puts(fullurl, HTAssoc_name(pres)); HTChunk_putc(fullurl, '='); HTChunk_puts(fullurl, HTAssoc_value(pres)); } return HTChunk_toCString(fullurl); } return NULL;}/* Search a document from absolute name** ------------------------------------** Request a document referencd by an absolute URL appended with the** keywords given. The URL can NOT contain any fragment identifier!** The list of keywords must be a space-separated list and spaces will** be converted to '+' before the request is issued.** Returns YES if request accepted, else NO*/PUBLIC BOOL HTSearchAbsolute (HTChunk * keywords, const char * base, HTRequest * request){ if (keywords && base && request) { char * full = query_url_encode(base, keywords); if (full) { HTAnchor * anchor = HTAnchor_findAddress(full); HTRequest_setAnchor(request, anchor); HT_FREE(full); return launch_request(request, NO); } } return NO;}/* Search a document from relative name** -------------------------------------** Request a document referenced by a relative URL. The relative URL is ** made absolute by resolving it relative to the address of the 'base' ** anchor.** Returns YES if request accepted, else NO*/PUBLIC BOOL HTSearchRelative (HTChunk * keywords, const char * relative, HTParentAnchor * base, HTRequest * request){ BOOL status = NO; if (keywords && relative && base && request) { char * full_url = NULL; char * base_url = HTAnchor_address((HTAnchor *) base);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -