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

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.121   ! frystyk     6: **     @(#) $Id: HTAccess.c,v 1.120 1996/05/15 22:33:58 eric 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>
                     12: ** History
                     13: **       8 Jun 92 Telnet hopping prohibited as telnet is not secure TBL
                     14: **     26 Jun 92 When over DECnet, suppressed FTP, Gopher and News. JFG
1.42      frystyk    15: **      6 Oct 92 Moved HTClientHost and HTlogfile into here. TBL
1.1       timbl      16: **     17 Dec 92 Tn3270 added, bug fix. DD
1.2       timbl      17: **      4 Feb 93 Access registration, Search escapes bad chars TBL
1.9       timbl      18: **               PARAMETERS TO HTSEARCH AND HTLOADRELATIVE CHANGED
                     19: **     28 May 93 WAIS gateway explicit if no WAIS library linked in.
1.19      timbl      20: **        Dec 93 Bug change around, more reentrant, etc
1.42      frystyk    21: **     09 May 94 logfile renamed to HTlogfile to avoid clash with WAIS
1.114     frystyk    22: **      8 Jul 94 Insulate HT_FREE();
1.88      frystyk    23: **        Sep 95 Rewritten, HFN
1.1       timbl      24: */
                     25: 
1.68      frystyk    26: #if !defined(HT_DIRECT_WAIS) && !defined(HT_DEFAULT_WAIS_GATEWAY)
                     27: #define HT_DEFAULT_WAIS_GATEWAY "http://www.w3.org:8001/"
1.54      frystyk    28: #endif
1.8       timbl      29: 
1.67      frystyk    30: /* Library include files */
1.88      frystyk    31: #include "WWWLib.h"
1.93      frystyk    32: #include "HTReqMan.h"
                     33: #include "HTAccess.h"                                   /* Implemented here */
1.88      frystyk    34: 
1.117     frystyk    35: #ifndef W3C_VERSION
                     36: #define W3C_VERSION    "unknown"
1.99      frystyk    37: #endif
                     38: 
1.121   ! frystyk    39: #ifndef HT_DEFAULT_USER
        !            40: #define HT_DEFAULT_USER                "LIBWWW_GENERIC_USER"
        !            41: #endif
        !            42: 
1.93      frystyk    43: PRIVATE char * HTAppName = NULL;         /* Application name: please supply */
                     44: PRIVATE char * HTAppVersion = NULL;    /* Application version: please supply */
1.2       timbl      45: 
1.99      frystyk    46: PRIVATE char * HTLibName = "libwww";
1.117     frystyk    47: PRIVATE char * HTLibVersion = W3C_VERSION;
1.99      frystyk    48: 
                     49: PRIVATE BOOL   HTSecure = NO;           /* Can we access local file system? */
                     50: 
1.121   ! frystyk    51: PRIVATE HTUserProfile * UserProfile = NULL;         /* Default user profile */
        !            52: 
1.111     frystyk    53: #define PUTBLOCK(b, l) (*target->isa->put_block)(target, b, l)
                     54: 
                     55: struct _HTStream {
                     56:     HTStreamClass * isa;
                     57: };
                     58: 
1.59      frystyk    59: /* --------------------------------------------------------------------------*/
1.61      frystyk    60: /*                Initialization and Termination of the Library             */
                     61: /* --------------------------------------------------------------------------*/
                     62: 
1.99      frystyk    63: /*     Information about the Application
                     64: **     ---------------------------------
1.93      frystyk    65: */
1.117     frystyk    66: PUBLIC const char * HTLib_appName (void)
1.93      frystyk    67: {
1.99      frystyk    68:     return HTAppName ? HTAppName : "UNKNOWN";
                     69: }
                     70: 
1.117     frystyk    71: PUBLIC const char * HTLib_appVersion (void)
1.99      frystyk    72: {
                     73:     return HTAppVersion ? HTAppVersion : "0.0";
1.93      frystyk    74: }
                     75: 
1.99      frystyk    76: /*     Information about libwww
                     77: **     ------------------------
                     78: */
1.117     frystyk    79: PUBLIC const char * HTLib_name (void)
1.99      frystyk    80: {
                     81:     return HTLibName ? HTLibName : "UNKNOWN";
                     82: }
                     83: 
1.117     frystyk    84: PUBLIC const char * HTLib_version (void)
1.99      frystyk    85: {
                     86:     return HTLibVersion ? HTLibVersion : "0.0";
                     87: }
                     88: 
1.121   ! frystyk    89: /*     Default User Profile
        !            90: **     --------------------
        !            91: */
        !            92: PUBLIC HTUserProfile * HTLib_userProfile (void)
        !            93: {
        !            94:     return UserProfile;
        !            95: }
        !            96: 
        !            97: PUBLIC BOOL HTLib_setUserProfile (HTUserProfile * up)
        !            98: {
        !            99:     if (up) {
        !           100:        UserProfile = up;
        !           101:        return YES;
        !           102:     }
        !           103:     return NO;
        !           104: }
        !           105: 
1.99      frystyk   106: /*     Access Local File System
                    107: **     ------------------------
                    108: **     In this mode we do not tough the local file system at all
1.93      frystyk   109: */
1.99      frystyk   110: PUBLIC BOOL HTLib_secure (void)
                    111: {
                    112:     return HTSecure;
                    113: }
                    114: 
                    115: PUBLIC void HTLib_setSecure (BOOL mode)
1.93      frystyk   116: {
1.99      frystyk   117:     HTSecure = mode;
1.93      frystyk   118: }
                    119: 
1.61      frystyk   120: /*                                                                  HTLibInit
                    121: **
                    122: **     This function initiates the Library and it MUST be called when
                    123: **     starting up an application. See also HTLibTerminate()
                    124: */
1.117     frystyk   125: PUBLIC BOOL HTLibInit (const char * AppName, const char * AppVersion)
1.61      frystyk   126: {
1.91      frystyk   127:     if (WWWTRACE)
1.115     eric      128:        HTTrace("WWWLibInit.. INITIALIZING LIBRARY OF COMMON CODE\n");
1.63      frystyk   129: 
1.93      frystyk   130:     /* Set the application name and version */
                    131:     if (AppName) {
                    132:        char *ptr;
                    133:        StrAllocCopy(HTAppName, AppName);
                    134:        ptr = HTAppName;
                    135:        while (*ptr) {
                    136:            if (WHITE(*ptr)) *ptr = '_';
                    137:            ptr++;
                    138:        }
                    139:     }
                    140:     if (AppVersion) {
                    141:        char *ptr;
                    142:        StrAllocCopy(HTAppVersion, AppVersion);
                    143:        ptr = HTAppVersion;
                    144:        while (*ptr) {
                    145:            if (WHITE(*ptr)) *ptr = '_';
                    146:            ptr++;
                    147:        }
                    148:     }
                    149: 
1.121   ! frystyk   150:     /* Create a default user profile */
        !           151:     UserProfile = HTUserProfile_new(HT_DEFAULT_USER, NULL);
        !           152:     
        !           153:     /* Initialize bindings */
        !           154:     HTBind_init();
1.61      frystyk   155: 
1.62      frystyk   156: #ifdef WWWLIB_SIG
1.61      frystyk   157:     /* On Solaris (and others?) we get a BROKEN PIPE signal when connecting
1.67      frystyk   158:     ** to a port where we should get `connection refused'. We ignore this 
1.61      frystyk   159:     ** using the following function call
                    160:     */
                    161:     HTSetSignal();                                /* Set signals in library */
1.1       timbl     162: #endif
                    163: 
1.105     frystyk   164: 
1.108     frystyk   165: #ifdef _WINSOCKAPI_
1.67      frystyk   166:     /*
                    167:     ** Initialise WinSock DLL. This must also be shut down! PMH
                    168:     */
                    169:     {
                    170:         WSADATA            wsadata;
                    171:        if (WSAStartup(DESIRED_WINSOCK_VERSION, &wsadata)) {
1.91      frystyk   172:            if (WWWTRACE)
1.115     eric      173:                HTTrace("WWWLibInit.. Can't initialize WinSoc\n");
1.67      frystyk   174:             WSACleanup();
                    175:             return NO;
                    176:         }
                    177:         if (wsadata.wVersion < MINIMUM_WINSOCK_VERSION) {
1.91      frystyk   178:             if (WWWTRACE)
1.115     eric      179:                HTTrace("WWWLibInit.. Bad version of WinSoc\n");
1.67      frystyk   180:             WSACleanup();
                    181:             return NO;
                    182:         }
                    183:     }
1.108     frystyk   184: #endif /* _WINSOCKAPI_ */
1.67      frystyk   185: 
1.61      frystyk   186:     return YES;
                    187: }
                    188: 
                    189: 
1.90      frystyk   190: /*     HTLibTerminate
                    191: **     --------------
1.117     frystyk   192: **     This function HT_FREEs memory kept by the Library and should be called
1.63      frystyk   193: **     before exit of an application (if you are on a PC platform)
1.61      frystyk   194: */
1.101     frystyk   195: PUBLIC BOOL HTLibTerminate (void)
1.61      frystyk   196: {
1.116     frystyk   197:     if (WWWTRACE) HTTrace("WWWLibTerm.. Cleaning up LIBRARY OF COMMON CODE\n");
                    198: 
                    199:     HT_FREE(HTAppName);                /* Freed thanks to Wade Ogden <wade@ebt.com> */
                    200:     HT_FREE(HTAppVersion);
                    201: 
1.101     frystyk   202:     HTAtom_deleteAll();                                         /* Remove the atoms */
                    203:     HTDNS_deleteAll();                         /* Remove the DNS host cache */
                    204:     HTAnchor_deleteAll(NULL);          /* Delete anchors and drop hyperdocs */
1.73      frystyk   205: 
1.81      frystyk   206:     HTProtocol_deleteAll();  /* Remove bindings between access and protocols */
1.73      frystyk   207:     HTBind_deleteAll();            /* Remove bindings between suffixes, media types */
                    208: 
1.121   ! frystyk   209:     HTUserProfile_delete(UserProfile);     /* Free our default User profile */
1.67      frystyk   210: 
1.108     frystyk   211: #ifdef _WINSOCKAPI_
1.67      frystyk   212:     WSACleanup();
1.105     frystyk   213: #endif
                    214: 
1.61      frystyk   215:     return YES;
                    216: }
                    217: 
1.59      frystyk   218: /* --------------------------------------------------------------------------*/
1.104     frystyk   219: /*                             Load Access functions                        */
1.59      frystyk   220: /* --------------------------------------------------------------------------*/
1.33      luotonen  221: 
1.90      frystyk   222: /*     Request a document
                    223: **     -----------------
                    224: **     Private version that requests a document from the request manager
                    225: **     Returns YES if request accepted, else NO
1.88      frystyk   226: */
1.101     frystyk   227: PRIVATE BOOL HTLoadDocument (HTRequest * request, BOOL recursive)
1.88      frystyk   228: {
                    229:     if (PROT_TRACE) {
1.90      frystyk   230:        HTParentAnchor *anchor = HTRequest_anchor(request);
                    231:        char * full_address = HTAnchor_address((HTAnchor *) anchor);
1.115     eric      232:        HTTrace("HTAccess.... Accessing document %s\n", full_address);
1.114     frystyk   233:        HT_FREE(full_address);
1.88      frystyk   234:     }
1.96      frystyk   235:     return HTLoad(request, recursive);
1.58      frystyk   236: }
1.1       timbl     237: 
                    238: 
1.90      frystyk   239: /*     Request a document from absolute name
                    240: **     -------------------------------------
                    241: **     Request a document referencd by an absolute URL.
                    242: **     Returns YES if request accepted, else NO
                    243: */
1.117     frystyk   244: PUBLIC BOOL HTLoadAbsolute (const char * url, HTRequest* request)
1.90      frystyk   245: {
                    246:     if (url && request) {
                    247:        HTAnchor * anchor = HTAnchor_findAddress(url);
                    248:        HTRequest_setAnchor(request, anchor);
                    249:        return HTLoadDocument(request, NO);
                    250:     }
                    251:     return NO;
                    252: }
                    253: 
                    254: 
                    255: /*     Request a document from absolute name to stream
                    256: **     -----------------------------------------------
                    257: **     Request a document referencd by an absolute URL and sending the data
                    258: **     down a stream. This is _excactly_ the same as HTLoadAbsolute as
                    259: **     the ourputstream is specified using the function
                    260: **     HTRequest_setOutputStream(). 'filter' is ignored!
                    261: **     Returns YES if request accepted, else NO
                    262: */
1.117     frystyk   263: PUBLIC BOOL HTLoadToStream (const char * url, BOOL filter, HTRequest *request)
1.90      frystyk   264: {
                    265:     return HTLoadAbsolute(url, request);
                    266: }
                    267: 
                    268: 
                    269: /*     Request a document from relative name
                    270: **     -------------------------------------
                    271: **     Request a document referenced by a relative URL. The relative URL is 
                    272: **     made absolute by resolving it relative to the address of the 'base' 
                    273: **     anchor.
                    274: **     Returns YES if request accepted, else NO
                    275: */
1.117     frystyk   276: PUBLIC BOOL HTLoadRelative (const char *       relative,
1.90      frystyk   277:                            HTParentAnchor *    base,
                    278:                            HTRequest *         request)
                    279: {
                    280:     BOOL status = NO;
                    281:     if (relative && base && request) {
                    282:        char * rel = NULL;
                    283:        char * full_url = NULL;
                    284:        char * base_url = HTAnchor_address((HTAnchor *) base);
                    285:        StrAllocCopy(rel, relative);
                    286:        full_url = HTParse(HTStrip(rel), base_url,
                    287:                         PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
                    288:        status = HTLoadAbsolute(full_url, request);
1.114     frystyk   289:        HT_FREE(rel);
                    290:        HT_FREE(full_url);
                    291:        HT_FREE(base_url);
1.90      frystyk   292:     }
                    293:     return status;
                    294: }
                    295: 
                    296: 
                    297: /*     Request an anchor
                    298: **     -----------------
                    299: **     Request the document referenced by the anchor
                    300: **     Returns YES if request accepted, else NO
                    301: */
                    302: PUBLIC BOOL HTLoadAnchor (HTAnchor * anchor, HTRequest * request)
                    303: {
                    304:     if (anchor && request) {
                    305:        HTRequest_setAnchor(request, anchor);
                    306:        return HTLoadDocument(request, NO);
                    307:     }
                    308:     return NO;
                    309: }
                    310: 
                    311: 
                    312: /*     Request an anchor
                    313: **     -----------------
                    314: **     Same as HTLoadAnchor but any information in the Error Stack in the 
                    315: **     request object is kept, so that any error messages in one 
1.52      frystyk   316: **     This function is almost identical to HTLoadAnchor, but it doesn't
                    317: **     clear the error stack so that the information in there is kept.
1.90      frystyk   318: **     Returns YES if request accepted, else NO
                    319: */
                    320: PUBLIC BOOL HTLoadAnchorRecursive (HTAnchor * anchor, HTRequest * request)
                    321: {
                    322:     if (anchor && request) {
                    323:        HTRequest_setAnchor(request, anchor);
                    324:         return HTLoadDocument(request, YES);
                    325:     }
                    326:     return NO;
                    327: }
                    328: 
                    329: 
                    330: /*     Search an Anchor
                    331: **     ----------------
                    332: **     Performs a keyword search on word given by the user. Adds the keyword
                    333: **     to the end of the current address and attempts to open the new address.
                    334: **     The list of keywords must be a space-separated list and spaces will
                    335: **     be converted to '+' before the request is issued.
                    336: **     Search can also be performed by HTLoadAbsolute() etc.
                    337: **     Returns YES if request accepted, else NO
                    338: */
1.117     frystyk   339: PUBLIC BOOL HTSearch (const char *     keywords,
1.90      frystyk   340:                      HTParentAnchor *  base,
                    341:                      HTRequest *       request)
                    342: {
1.99      frystyk   343:     BOOL status = NO;
1.90      frystyk   344:     if (keywords && base && request) {
                    345:        char *base_url = HTAnchor_address((HTAnchor *) base);
                    346:        if (*keywords) {
                    347:            char *plus;
                    348:            StrAllocCat(base_url, "?");
                    349:            StrAllocCat(base_url, keywords);
                    350:            plus = strchr(base_url, '?');
                    351:            while (*plus) {
                    352:                if (*plus == ' ') *plus = '+';
                    353:                plus++;
                    354:            }
1.2       timbl     355:        }
1.99      frystyk   356:        status = HTLoadAbsolute(base_url, request);
1.114     frystyk   357:        HT_FREE(base_url);
1.90      frystyk   358:     }
1.99      frystyk   359:     return status;
1.2       timbl     360: }
                    361: 
                    362: 
1.90      frystyk   363: /*     Search a document from absolute name
                    364: **     ------------------------------------
                    365: **     Request a document referencd by an absolute URL appended with the
                    366: **     keywords given. The URL can NOT contain any fragment identifier!
                    367: **     The list of keywords must be a space-separated list and spaces will
                    368: **     be converted to '+' before the request is issued.
                    369: **     Returns YES if request accepted, else NO
                    370: */
1.117     frystyk   371: PUBLIC BOOL HTSearchAbsolute (const char *     keywords,
                    372:                              const char *      url,
1.90      frystyk   373:                              HTRequest *       request)
                    374: {
                    375:     if (url && request) {
                    376:        HTAnchor * anchor = HTAnchor_findAddress(url);
                    377:        return HTSearch(keywords, HTAnchor_parent(anchor), request);
                    378:     }
                    379:     return NO;
1.57      howcome   380: }
                    381: 
1.70      frystyk   382: /* --------------------------------------------------------------------------*/
1.104     frystyk   383: /*                             Post Access Functions                        */
1.70      frystyk   384: /* --------------------------------------------------------------------------*/
                    385: 
1.90      frystyk   386: /*     Copy an anchor
1.70      frystyk   387: **     --------------
1.90      frystyk   388: **     Fetch the URL (possibly local file URL) and send it using either PUT
                    389: **     or POST to the remote destination using HTTP. The caller can decide the
                    390: **     exact method used and which HTTP header fields to transmit by setting
                    391: **     the user fields in the request structure.
1.92      frystyk   392: **     If posting to NNTP then we can't dispatch at this level but must pass
                    393: **     the source anchor to the news module that then takes all the refs
                    394: **     to NNTP and puts into the "newsgroups" header
1.90      frystyk   395: **     Returns YES if request accepted, else NO
1.70      frystyk   396: */
1.109     frystyk   397: PUBLIC BOOL HTCopyAnchor (HTAnchor * src_anchor, HTRequest * main_dest)
1.80      frystyk   398: { 
1.106     frystyk   399:     HTRequest * src_req;
                    400:     HTList * cur;
1.109     frystyk   401:     if (!src_anchor || !main_dest) {
1.115     eric      402:        if (WWWTRACE) HTTrace("Copy........ BAD ARGUMENT\n");
1.90      frystyk   403:        return NO;
1.109     frystyk   404:     }
1.70      frystyk   405: 
1.112     frystyk   406:     /* Set the source anchor */
                    407:     main_dest->source_anchor = HTAnchor_parent(src_anchor);
                    408: 
1.80      frystyk   409:     /* Build the POST web if not already there */
1.109     frystyk   410:     if (!main_dest->source) {
                    411:        src_req = HTRequest_dupInternal(main_dest);       /* Get a duplicate */
1.80      frystyk   412:        HTAnchor_clearHeader((HTParentAnchor *) src_anchor);
1.109     frystyk   413:        src_req->method = METHOD_GET;
1.85      frystyk   414:        src_req->reload = HT_MEM_REFRESH;
1.104     frystyk   415:        src_req->output_stream = NULL;
1.80      frystyk   416:        src_req->output_format = WWW_SOURCE;     /* We want source (for now) */
                    417: 
                    418:        /* Set up the main link in the source anchor */
                    419:        {
1.106     frystyk   420:            HTLink * main_link = HTAnchor_mainLink((HTAnchor *) src_anchor);
                    421:            HTAnchor *main_anchor = HTLink_destination(main_link);
                    422:            HTMethod method = HTLink_method(main_link);
1.85      frystyk   423:            if (!main_link || method==METHOD_INVALID) {
1.91      frystyk   424:                if (WWWTRACE)
1.115     eric      425:                    HTTrace("Copy Anchor. No destination found or unspecified method\n");
1.80      frystyk   426:                HTRequest_delete(src_req);
1.90      frystyk   427:                return NO;
1.80      frystyk   428:            }
1.109     frystyk   429:            main_dest->GenMask |= HT_G_DATE;             /* Send date header */
                    430:            main_dest->reload = HT_CACHE_REFRESH;
                    431:            main_dest->method = method;
                    432:            main_dest->input_format = WWW_SOURCE;
                    433:            HTRequest_addDestination(src_req, main_dest);
                    434:            if (HTLoadAnchor(main_anchor, main_dest) == NO)
                    435:                return NO;
1.80      frystyk   436:        }
1.78      frystyk   437: 
1.80      frystyk   438:        /* For all other links in the source anchor */
1.106     frystyk   439:        if ((cur = HTAnchor_subLinks(src_anchor))) {
                    440:            HTLink * pres;
1.109     frystyk   441:            while ((pres = (HTLink *) HTList_nextObject(cur))) {
1.106     frystyk   442:                HTAnchor *dest = HTLink_destination(pres);
                    443:                HTMethod method = HTLink_method(pres);
1.80      frystyk   444:                HTRequest *dest_req;
                    445:                if (!dest || method==METHOD_INVALID) {
1.91      frystyk   446:                    if (WWWTRACE)
1.115     eric      447:                        HTTrace("Copy Anchor. Bad anchor setup %p\n",
1.80      frystyk   448:                                dest);
1.90      frystyk   449:                    return NO;
1.80      frystyk   450:                }
1.109     frystyk   451:                dest_req = HTRequest_dupInternal(main_dest);
1.107     frystyk   452:                dest_req->GenMask |= HT_G_DATE;          /* Send date header */
1.85      frystyk   453:                dest_req->reload = HT_CACHE_REFRESH;
1.80      frystyk   454:                dest_req->method = method;
1.104     frystyk   455:                dest_req->output_stream = NULL;
                    456:                dest_req->output_format = WWW_SOURCE;
1.109     frystyk   457:                HTRequest_addDestination(src_req, dest_req);
1.104     frystyk   458: 
1.90      frystyk   459:                if (HTLoadAnchor(dest, dest_req) == NO)
                    460:                    return NO;
1.80      frystyk   461:            }
                    462:        }
                    463:     } else {                    /* Use the existing Post Web and restart it */
1.109     frystyk   464:        src_req = main_dest->source;
1.80      frystyk   465:        if (src_req->mainDestination)
1.109     frystyk   466:            if (HTLoadDocument(main_dest, NO) == NO)
1.90      frystyk   467:                return NO;
1.80      frystyk   468:        if (src_req->destinations) {
1.106     frystyk   469:            HTRequest * pres;
                    470:            cur = HTAnchor_subLinks(src_anchor);
1.80      frystyk   471:            while ((pres = (HTRequest *) HTList_nextObject(cur)) != NULL) {
1.90      frystyk   472:                if (HTLoadDocument(pres, NO) == NO)
                    473:                    return NO;
1.80      frystyk   474:            }
                    475:        }
1.78      frystyk   476:     }
                    477: 
1.80      frystyk   478:     /* Now open the source */
                    479:     return HTLoadAnchor(src_anchor, src_req);
1.70      frystyk   480: }
                    481: 
                    482: 
1.90      frystyk   483: /*     Upload an Anchor
1.70      frystyk   484: **     ----------------
1.111     frystyk   485: **     This function can be used to send data along with a request to a remote
                    486: **     server. It can for example be used to POST form data to a remote HTTP
                    487: **     server - or it can be used to post a newsletter to a NNTP server. In
                    488: **     either case, you pass a callback function which the request calls when
                    489: **     the remote destination is ready to accept data. In this callback
                    490: **     you get the current request object and a stream into where you can 
                    491: **     write data. It is very important that you return the value returned
                    492: **     by this stream to the Library so that it knows what to do next. The
                    493: **     reason is that the outgoing stream might block or an error may
                    494: **     occur and in that case the Library must know about it. The source
                    495: **     anchor represents the data object in memory and it points to 
                    496: **     the destination anchor by using the POSTWeb method. The source anchor
                    497: **     contains metainformation about the data object in memory and the 
                    498: **     destination anchor represents the reponse from the remote server.
1.90      frystyk   499: **     Returns YES if request accepted, else NO
                    500: */
1.111     frystyk   501: PUBLIC BOOL HTUploadAnchor (HTAnchor *         source_anchor,
                    502:                            HTRequest *         request,
                    503:                            HTPostCallback *    callback)
                    504: {
                    505:     HTLink * link = HTAnchor_mainLink((HTAnchor *) source_anchor);
                    506:     HTAnchor * dest_anchor = HTLink_destination(link);
                    507:     HTMethod method = HTLink_method(link);
                    508:     if (!link || method==METHOD_INVALID || !callback) {
                    509:        if (WWWTRACE)
1.115     eric      510:            HTTrace("Upload...... No destination found or unspecified method\n");
1.90      frystyk   511:        return NO;
1.109     frystyk   512:     }
1.111     frystyk   513:     request->GenMask |= HT_G_DATE;                      /* Send date header */
                    514:     request->reload = HT_CACHE_REFRESH;
                    515:     request->method = method;
                    516:     request->source_anchor = HTAnchor_parent(source_anchor);
                    517:     request->PostCallback = callback;
                    518:     return HTLoadAnchor(dest_anchor, request);
                    519: }
                    520: 
                    521: /*     POST Callback Handler
                    522: **     ---------------------
                    523: **     If you do not want to handle the stream interface on your own, you
                    524: **     can use this function which writes the source anchor hyperdoc to the
                    525: **     target stream for the anchor upload and also handles the return value
                    526: **     from the stream. If you don't want to write the source anchor hyperdoc
                    527: **     then you can register your own callback function that can get the data
                    528: **     you want.
                    529: */
                    530: PUBLIC int HTUpload_callback (HTRequest * request, HTStream * target)
                    531: {
1.115     eric      532:     if (WWWTRACE) HTTrace("Uploading... from callback function\n");
1.111     frystyk   533:     if (!request || !request->source_anchor || !target) return HT_ERROR;
                    534:     {
                    535:        int status;
                    536:        HTParentAnchor * source = request->source_anchor;
                    537:        char * document = (char *) HTAnchor_document(request->source_anchor);
                    538:        int len = HTAnchor_length(source);
                    539:        if (len < 0) {
                    540:            len = strlen(document);
                    541:            HTAnchor_setLength(source, len);
                    542:        }
                    543:        status = (*target->isa->put_block)(target, document, len);
                    544:        if (status == HT_OK)
                    545:            return (*target->isa->flush)(target);
                    546:        if (status == HT_WOULD_BLOCK) {
1.115     eric      547:            if (PROT_TRACE)HTTrace("POST Anchor. Target WOULD BLOCK\n");
1.111     frystyk   548:            return HT_WOULD_BLOCK;
                    549:        } else if (status == HT_PAUSE) {
1.115     eric      550:            if (PROT_TRACE) HTTrace("POST Anchor. Target PAUSED\n");
1.111     frystyk   551:            return HT_PAUSE;
                    552:        } else if (status > 0) {              /* Stream specific return code */
                    553:            if (PROT_TRACE)
1.115     eric      554:                HTTrace("POST Anchor. Target returns %d\n", status);
1.111     frystyk   555:            return status;
1.120     eric      556:        } else {                                     /* we have a real error */
1.115     eric      557:            if (PROT_TRACE) HTTrace("POST Anchor. Target ERROR\n");
1.111     frystyk   558:            return status;
                    559:        }
1.70      frystyk   560:     }
1.1       timbl     561: }

Webmaster