Annotation of libwww/Library/src/HTAccess.c, revision 1.122

1.120     eric        1: /*                                                                  htaccess.c
1.61      frystyk     2: **     ACCESS MANAGER
                      3: **
1.75      frystyk     4: **     (c) COPYRIGHT MIT 1995.
1.61      frystyk     5: **     Please first read the full copyright statement in the file COPYRIGH.
1.122   ! frystyk     6: **     @(#) $Id: HTAccess.c,v 1.121 1996/05/20 15:06:18 frystyk Exp $
1.1       timbl       7: **
                      8: ** Authors
1.79      frystyk     9: **     TBL     Tim Berners-Lee timbl@w3.org
1.4       timbl      10: **     JFG     Jean-Francois Groff jfg@dxcern.cern.ch
1.1       timbl      11: **     DD      Denis DeLaRoca (310) 825-4580  <CSP1DWD@mvs.oac.ucla.edu>
1.122   ! frystyk    12: **     HFN     Henrik Frystyk, frystyk@w3.org
1.1       timbl      13: ** History
                     14: **       8 Jun 92 Telnet hopping prohibited as telnet is not secure TBL
                     15: **     26 Jun 92 When over DECnet, suppressed FTP, Gopher and News. JFG
1.42      frystyk    16: **      6 Oct 92 Moved HTClientHost and HTlogfile into here. TBL
1.1       timbl      17: **     17 Dec 92 Tn3270 added, bug fix. DD
1.2       timbl      18: **      4 Feb 93 Access registration, Search escapes bad chars TBL
1.9       timbl      19: **               PARAMETERS TO HTSEARCH AND HTLOADRELATIVE CHANGED
                     20: **     28 May 93 WAIS gateway explicit if no WAIS library linked in.
1.19      timbl      21: **        Dec 93 Bug change around, more reentrant, etc
1.42      frystyk    22: **     09 May 94 logfile renamed to HTlogfile to avoid clash with WAIS
1.114     frystyk    23: **      8 Jul 94 Insulate HT_FREE();
1.88      frystyk    24: **        Sep 95 Rewritten, HFN
1.1       timbl      25: */
                     26: 
1.67      frystyk    27: /* Library include files */
1.122   ! frystyk    28: #include "WWWUtil.h"
        !            29: #include "WWWCore.h"
        !            30: #include "WWWStream.h"
1.93      frystyk    31: #include "HTReqMan.h"
                     32: #include "HTAccess.h"                                   /* Implemented here */
1.88      frystyk    33: 
1.111     frystyk    34: #define PUTBLOCK(b, l) (*target->isa->put_block)(target, b, l)
                     35: 
                     36: struct _HTStream {
                     37:     HTStreamClass * isa;
                     38: };
                     39: 
1.122   ! frystyk    40: /* ------------------------------------------------------------------------- */
1.33      luotonen   41: 
1.90      frystyk    42: /*     Request a document
                     43: **     -----------------
                     44: **     Private version that requests a document from the request manager
                     45: **     Returns YES if request accepted, else NO
1.88      frystyk    46: */
1.101     frystyk    47: PRIVATE BOOL HTLoadDocument (HTRequest * request, BOOL recursive)
1.88      frystyk    48: {
                     49:     if (PROT_TRACE) {
1.90      frystyk    50:        HTParentAnchor *anchor = HTRequest_anchor(request);
                     51:        char * full_address = HTAnchor_address((HTAnchor *) anchor);
1.115     eric       52:        HTTrace("HTAccess.... Accessing document %s\n", full_address);
1.114     frystyk    53:        HT_FREE(full_address);
1.88      frystyk    54:     }
1.96      frystyk    55:     return HTLoad(request, recursive);
1.58      frystyk    56: }
1.1       timbl      57: 
                     58: 
1.90      frystyk    59: /*     Request a document from absolute name
                     60: **     -------------------------------------
                     61: **     Request a document referencd by an absolute URL.
                     62: **     Returns YES if request accepted, else NO
                     63: */
1.122   ! frystyk    64: PUBLIC BOOL HTLoadAbsolute (const char * url, HTRequest * request)
1.90      frystyk    65: {
                     66:     if (url && request) {
                     67:        HTAnchor * anchor = HTAnchor_findAddress(url);
                     68:        HTRequest_setAnchor(request, anchor);
                     69:        return HTLoadDocument(request, NO);
                     70:     }
                     71:     return NO;
                     72: }
                     73: 
                     74: 
                     75: /*     Request a document from absolute name to stream
                     76: **     -----------------------------------------------
                     77: **     Request a document referencd by an absolute URL and sending the data
                     78: **     down a stream. This is _excactly_ the same as HTLoadAbsolute as
                     79: **     the ourputstream is specified using the function
                     80: **     HTRequest_setOutputStream(). 'filter' is ignored!
                     81: **     Returns YES if request accepted, else NO
                     82: */
1.117     frystyk    83: PUBLIC BOOL HTLoadToStream (const char * url, BOOL filter, HTRequest *request)
1.90      frystyk    84: {
                     85:     return HTLoadAbsolute(url, request);
                     86: }
                     87: 
1.122   ! frystyk    88: /*
        !            89: **     Load a URL to a mem buffer
        !            90: **     --------------------------
        !            91: **     Load a request and store the result in a memory buffer.
        !            92: **     Returns chunk if OK - else NULL
        !            93: */
        !            94: PUBLIC HTChunk * HTLoadToChunk (const char * url, HTRequest * request)
        !            95: {
        !            96:     if (url && request) {
        !            97:        HTChunk * chunk = NULL;
        !            98:        HTStream * target = HTStreamToChunk(request, &chunk, 0);
        !            99:        HTAnchor * anchor = HTAnchor_findAddress(url);
        !           100:        HTRequest_setAnchor(request, anchor);
        !           101:        HTRequest_setOutputStream(request, target);
        !           102:        if (HTLoadDocument(request, NO) == YES)
        !           103:            return chunk;
        !           104:        else {
        !           105:            HTChunk_delete(chunk);
        !           106:            return NULL;
        !           107:        }
        !           108:     }
        !           109:     return NULL;
        !           110: }
1.90      frystyk   111: 
                    112: /*     Request a document from relative name
                    113: **     -------------------------------------
                    114: **     Request a document referenced by a relative URL. The relative URL is 
                    115: **     made absolute by resolving it relative to the address of the 'base' 
                    116: **     anchor.
                    117: **     Returns YES if request accepted, else NO
                    118: */
1.117     frystyk   119: PUBLIC BOOL HTLoadRelative (const char *       relative,
1.90      frystyk   120:                            HTParentAnchor *    base,
                    121:                            HTRequest *         request)
                    122: {
                    123:     BOOL status = NO;
                    124:     if (relative && base && request) {
                    125:        char * rel = NULL;
                    126:        char * full_url = NULL;
                    127:        char * base_url = HTAnchor_address((HTAnchor *) base);
                    128:        StrAllocCopy(rel, relative);
                    129:        full_url = HTParse(HTStrip(rel), base_url,
                    130:                         PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
                    131:        status = HTLoadAbsolute(full_url, request);
1.114     frystyk   132:        HT_FREE(rel);
                    133:        HT_FREE(full_url);
                    134:        HT_FREE(base_url);
1.90      frystyk   135:     }
                    136:     return status;
                    137: }
                    138: 
                    139: 
                    140: /*     Request an anchor
                    141: **     -----------------
                    142: **     Request the document referenced by the anchor
                    143: **     Returns YES if request accepted, else NO
                    144: */
                    145: PUBLIC BOOL HTLoadAnchor (HTAnchor * anchor, HTRequest * request)
                    146: {
                    147:     if (anchor && request) {
                    148:        HTRequest_setAnchor(request, anchor);
                    149:        return HTLoadDocument(request, NO);
                    150:     }
                    151:     return NO;
                    152: }
                    153: 
                    154: 
                    155: /*     Request an anchor
                    156: **     -----------------
                    157: **     Same as HTLoadAnchor but any information in the Error Stack in the 
                    158: **     request object is kept, so that any error messages in one 
1.52      frystyk   159: **     This function is almost identical to HTLoadAnchor, but it doesn't
                    160: **     clear the error stack so that the information in there is kept.
1.90      frystyk   161: **     Returns YES if request accepted, else NO
                    162: */
                    163: PUBLIC BOOL HTLoadAnchorRecursive (HTAnchor * anchor, HTRequest * request)
                    164: {
                    165:     if (anchor && request) {
                    166:        HTRequest_setAnchor(request, anchor);
                    167:         return HTLoadDocument(request, YES);
                    168:     }
                    169:     return NO;
                    170: }
                    171: 
1.122   ! frystyk   172: 
        !           173: /*
        !           174: **     Load a URL to a mem buffer
        !           175: **     --------------------------
        !           176: **     Load a request and store the result in a memory buffer.
        !           177: **     Returns chunk if OK - else NULL
        !           178: */
        !           179: PUBLIC HTChunk * HTLoadAnchorToChunk (HTAnchor * anchor, HTRequest * request)
        !           180: {
        !           181:     if (anchor && request) {
        !           182:        HTChunk * chunk = NULL;
        !           183:        HTStream * target = HTStreamToChunk(request, &chunk, 0);
        !           184:        HTRequest_setAnchor(request, anchor);
        !           185:        HTRequest_setOutputStream(request, target);
        !           186:        if (HTLoadDocument(request, NO) == YES)
        !           187:            return chunk;
        !           188:        else {
        !           189:            HTChunk_delete(chunk);
        !           190:            return NULL;
        !           191:        }
        !           192:     }
        !           193:     return NULL;
        !           194: }
1.90      frystyk   195: 
                    196: /*     Search an Anchor
                    197: **     ----------------
                    198: **     Performs a keyword search on word given by the user. Adds the keyword
                    199: **     to the end of the current address and attempts to open the new address.
                    200: **     The list of keywords must be a space-separated list and spaces will
                    201: **     be converted to '+' before the request is issued.
                    202: **     Search can also be performed by HTLoadAbsolute() etc.
                    203: **     Returns YES if request accepted, else NO
                    204: */
1.117     frystyk   205: PUBLIC BOOL HTSearch (const char *     keywords,
1.90      frystyk   206:                      HTParentAnchor *  base,
                    207:                      HTRequest *       request)
                    208: {
1.99      frystyk   209:     BOOL status = NO;
1.90      frystyk   210:     if (keywords && base && request) {
                    211:        char *base_url = HTAnchor_address((HTAnchor *) base);
                    212:        if (*keywords) {
                    213:            char *plus;
                    214:            StrAllocCat(base_url, "?");
                    215:            StrAllocCat(base_url, keywords);
                    216:            plus = strchr(base_url, '?');
                    217:            while (*plus) {
                    218:                if (*plus == ' ') *plus = '+';
                    219:                plus++;
                    220:            }
1.2       timbl     221:        }
1.99      frystyk   222:        status = HTLoadAbsolute(base_url, request);
1.114     frystyk   223:        HT_FREE(base_url);
1.90      frystyk   224:     }
1.99      frystyk   225:     return status;
1.2       timbl     226: }
                    227: 
                    228: 
1.90      frystyk   229: /*     Search a document from absolute name
                    230: **     ------------------------------------
                    231: **     Request a document referencd by an absolute URL appended with the
                    232: **     keywords given. The URL can NOT contain any fragment identifier!
                    233: **     The list of keywords must be a space-separated list and spaces will
                    234: **     be converted to '+' before the request is issued.
                    235: **     Returns YES if request accepted, else NO
                    236: */
1.117     frystyk   237: PUBLIC BOOL HTSearchAbsolute (const char *     keywords,
                    238:                              const char *      url,
1.90      frystyk   239:                              HTRequest *       request)
                    240: {
                    241:     if (url && request) {
                    242:        HTAnchor * anchor = HTAnchor_findAddress(url);
                    243:        return HTSearch(keywords, HTAnchor_parent(anchor), request);
                    244:     }
                    245:     return NO;
1.57      howcome   246: }
                    247: 
1.70      frystyk   248: /* --------------------------------------------------------------------------*/
1.104     frystyk   249: /*                             Post Access Functions                        */
1.70      frystyk   250: /* --------------------------------------------------------------------------*/
                    251: 
1.90      frystyk   252: /*     Copy an anchor
1.70      frystyk   253: **     --------------
1.90      frystyk   254: **     Fetch the URL (possibly local file URL) and send it using either PUT
                    255: **     or POST to the remote destination using HTTP. The caller can decide the
                    256: **     exact method used and which HTTP header fields to transmit by setting
                    257: **     the user fields in the request structure.
1.92      frystyk   258: **     If posting to NNTP then we can't dispatch at this level but must pass
                    259: **     the source anchor to the news module that then takes all the refs
                    260: **     to NNTP and puts into the "newsgroups" header
1.90      frystyk   261: **     Returns YES if request accepted, else NO
1.70      frystyk   262: */
1.109     frystyk   263: PUBLIC BOOL HTCopyAnchor (HTAnchor * src_anchor, HTRequest * main_dest)
1.80      frystyk   264: { 
1.106     frystyk   265:     HTRequest * src_req;
                    266:     HTList * cur;
1.109     frystyk   267:     if (!src_anchor || !main_dest) {
1.115     eric      268:        if (WWWTRACE) HTTrace("Copy........ BAD ARGUMENT\n");
1.90      frystyk   269:        return NO;
1.109     frystyk   270:     }
1.70      frystyk   271: 
1.112     frystyk   272:     /* Set the source anchor */
                    273:     main_dest->source_anchor = HTAnchor_parent(src_anchor);
                    274: 
1.80      frystyk   275:     /* Build the POST web if not already there */
1.109     frystyk   276:     if (!main_dest->source) {
                    277:        src_req = HTRequest_dupInternal(main_dest);       /* Get a duplicate */
1.80      frystyk   278:        HTAnchor_clearHeader((HTParentAnchor *) src_anchor);
1.109     frystyk   279:        src_req->method = METHOD_GET;
1.85      frystyk   280:        src_req->reload = HT_MEM_REFRESH;
1.104     frystyk   281:        src_req->output_stream = NULL;
1.80      frystyk   282:        src_req->output_format = WWW_SOURCE;     /* We want source (for now) */
                    283: 
                    284:        /* Set up the main link in the source anchor */
                    285:        {
1.106     frystyk   286:            HTLink * main_link = HTAnchor_mainLink((HTAnchor *) src_anchor);
                    287:            HTAnchor *main_anchor = HTLink_destination(main_link);
                    288:            HTMethod method = HTLink_method(main_link);
1.85      frystyk   289:            if (!main_link || method==METHOD_INVALID) {
1.91      frystyk   290:                if (WWWTRACE)
1.115     eric      291:                    HTTrace("Copy Anchor. No destination found or unspecified method\n");
1.80      frystyk   292:                HTRequest_delete(src_req);
1.90      frystyk   293:                return NO;
1.80      frystyk   294:            }
1.109     frystyk   295:            main_dest->GenMask |= HT_G_DATE;             /* Send date header */
                    296:            main_dest->reload = HT_CACHE_REFRESH;
                    297:            main_dest->method = method;
                    298:            main_dest->input_format = WWW_SOURCE;
                    299:            HTRequest_addDestination(src_req, main_dest);
                    300:            if (HTLoadAnchor(main_anchor, main_dest) == NO)
                    301:                return NO;
1.80      frystyk   302:        }
1.78      frystyk   303: 
1.80      frystyk   304:        /* For all other links in the source anchor */
1.106     frystyk   305:        if ((cur = HTAnchor_subLinks(src_anchor))) {
                    306:            HTLink * pres;
1.109     frystyk   307:            while ((pres = (HTLink *) HTList_nextObject(cur))) {
1.106     frystyk   308:                HTAnchor *dest = HTLink_destination(pres);
                    309:                HTMethod method = HTLink_method(pres);
1.80      frystyk   310:                HTRequest *dest_req;
                    311:                if (!dest || method==METHOD_INVALID) {
1.91      frystyk   312:                    if (WWWTRACE)
1.115     eric      313:                        HTTrace("Copy Anchor. Bad anchor setup %p\n",
1.80      frystyk   314:                                dest);
1.90      frystyk   315:                    return NO;
1.80      frystyk   316:                }
1.109     frystyk   317:                dest_req = HTRequest_dupInternal(main_dest);
1.107     frystyk   318:                dest_req->GenMask |= HT_G_DATE;          /* Send date header */
1.85      frystyk   319:                dest_req->reload = HT_CACHE_REFRESH;
1.80      frystyk   320:                dest_req->method = method;
1.104     frystyk   321:                dest_req->output_stream = NULL;
                    322:                dest_req->output_format = WWW_SOURCE;
1.109     frystyk   323:                HTRequest_addDestination(src_req, dest_req);
1.104     frystyk   324: 
1.90      frystyk   325:                if (HTLoadAnchor(dest, dest_req) == NO)
                    326:                    return NO;
1.80      frystyk   327:            }
                    328:        }
                    329:     } else {                    /* Use the existing Post Web and restart it */
1.109     frystyk   330:        src_req = main_dest->source;
1.80      frystyk   331:        if (src_req->mainDestination)
1.109     frystyk   332:            if (HTLoadDocument(main_dest, NO) == NO)
1.90      frystyk   333:                return NO;
1.80      frystyk   334:        if (src_req->destinations) {
1.106     frystyk   335:            HTRequest * pres;
                    336:            cur = HTAnchor_subLinks(src_anchor);
1.80      frystyk   337:            while ((pres = (HTRequest *) HTList_nextObject(cur)) != NULL) {
1.90      frystyk   338:                if (HTLoadDocument(pres, NO) == NO)
                    339:                    return NO;
1.80      frystyk   340:            }
                    341:        }
1.78      frystyk   342:     }
                    343: 
1.80      frystyk   344:     /* Now open the source */
                    345:     return HTLoadAnchor(src_anchor, src_req);
1.70      frystyk   346: }
                    347: 
                    348: 
1.90      frystyk   349: /*     Upload an Anchor
1.70      frystyk   350: **     ----------------
1.111     frystyk   351: **     This function can be used to send data along with a request to a remote
                    352: **     server. It can for example be used to POST form data to a remote HTTP
                    353: **     server - or it can be used to post a newsletter to a NNTP server. In
                    354: **     either case, you pass a callback function which the request calls when
                    355: **     the remote destination is ready to accept data. In this callback
                    356: **     you get the current request object and a stream into where you can 
                    357: **     write data. It is very important that you return the value returned
                    358: **     by this stream to the Library so that it knows what to do next. The
                    359: **     reason is that the outgoing stream might block or an error may
                    360: **     occur and in that case the Library must know about it. The source
                    361: **     anchor represents the data object in memory and it points to 
                    362: **     the destination anchor by using the POSTWeb method. The source anchor
                    363: **     contains metainformation about the data object in memory and the 
                    364: **     destination anchor represents the reponse from the remote server.
1.90      frystyk   365: **     Returns YES if request accepted, else NO
                    366: */
1.111     frystyk   367: PUBLIC BOOL HTUploadAnchor (HTAnchor *         source_anchor,
                    368:                            HTRequest *         request,
                    369:                            HTPostCallback *    callback)
                    370: {
                    371:     HTLink * link = HTAnchor_mainLink((HTAnchor *) source_anchor);
                    372:     HTAnchor * dest_anchor = HTLink_destination(link);
                    373:     HTMethod method = HTLink_method(link);
                    374:     if (!link || method==METHOD_INVALID || !callback) {
                    375:        if (WWWTRACE)
1.115     eric      376:            HTTrace("Upload...... No destination found or unspecified method\n");
1.90      frystyk   377:        return NO;
1.109     frystyk   378:     }
1.111     frystyk   379:     request->GenMask |= HT_G_DATE;                      /* Send date header */
                    380:     request->reload = HT_CACHE_REFRESH;
                    381:     request->method = method;
                    382:     request->source_anchor = HTAnchor_parent(source_anchor);
                    383:     request->PostCallback = callback;
                    384:     return HTLoadAnchor(dest_anchor, request);
                    385: }
                    386: 
                    387: /*     POST Callback Handler
                    388: **     ---------------------
                    389: **     If you do not want to handle the stream interface on your own, you
                    390: **     can use this function which writes the source anchor hyperdoc to the
                    391: **     target stream for the anchor upload and also handles the return value
                    392: **     from the stream. If you don't want to write the source anchor hyperdoc
                    393: **     then you can register your own callback function that can get the data
                    394: **     you want.
                    395: */
                    396: PUBLIC int HTUpload_callback (HTRequest * request, HTStream * target)
                    397: {
1.115     eric      398:     if (WWWTRACE) HTTrace("Uploading... from callback function\n");
1.111     frystyk   399:     if (!request || !request->source_anchor || !target) return HT_ERROR;
                    400:     {
                    401:        int status;
                    402:        HTParentAnchor * source = request->source_anchor;
                    403:        char * document = (char *) HTAnchor_document(request->source_anchor);
                    404:        int len = HTAnchor_length(source);
                    405:        if (len < 0) {
                    406:            len = strlen(document);
                    407:            HTAnchor_setLength(source, len);
                    408:        }
                    409:        status = (*target->isa->put_block)(target, document, len);
                    410:        if (status == HT_OK)
                    411:            return (*target->isa->flush)(target);
                    412:        if (status == HT_WOULD_BLOCK) {
1.115     eric      413:            if (PROT_TRACE)HTTrace("POST Anchor. Target WOULD BLOCK\n");
1.111     frystyk   414:            return HT_WOULD_BLOCK;
                    415:        } else if (status == HT_PAUSE) {
1.115     eric      416:            if (PROT_TRACE) HTTrace("POST Anchor. Target PAUSED\n");
1.111     frystyk   417:            return HT_PAUSE;
                    418:        } else if (status > 0) {              /* Stream specific return code */
                    419:            if (PROT_TRACE)
1.115     eric      420:                HTTrace("POST Anchor. Target returns %d\n", status);
1.111     frystyk   421:            return status;
1.120     eric      422:        } else {                                     /* we have a real error */
1.115     eric      423:            if (PROT_TRACE) HTTrace("POST Anchor. Target ERROR\n");
1.111     frystyk   424:            return status;
                    425:        }
1.70      frystyk   426:     }
1.1       timbl     427: }

Webmaster