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

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

Webmaster