Annotation of libwww/Library/src/HTInit.c, revision 2.59

2.20      frystyk     1: /*                                                                    HTInit.c
                      2: **     CONFIGURATION-SPECIFIC INITIALIALIZATION
                      3: **
2.25      frystyk     4: **     (c) COPYRIGHT MIT 1995.
2.20      frystyk     5: **     Please first read the full copyright statement in the file COPYRIGH.
2.59    ! frystyk     6: **     @(#) $Id: HTInit.c,v 2.58 1996/06/04 14:16:45 eric Exp $
2.9       duns        7: **
2.20      frystyk     8: **     Define a basic set of suffixes and presentations
2.1       timbl       9: */
                     10: 
2.22      frystyk    11: /* Library include files */
2.52      frystyk    12: #include "sysdep.h"
2.59    ! frystyk    13: #include "WWWUtil.h"
        !            14: #include "WWWCore.h"
        !            15: #include "HTReqMan.h"          /* @@@ Should be removed */
2.22      frystyk    16: #include "HTInit.h"                                     /* Implemented here */
2.1       timbl      17: 
2.29      frystyk    18: /* ------------------------------------------------------------------------- */
                     19: 
2.23      frystyk    20: /*     BINDINGS BETWEEN A SOURCE MEDIA TYPE AND A DEST MEDIA TYPE (CONVERSION)
                     21: **     ----------------------------------------------------------------------
2.47      frystyk    22: **     Not done automaticly - may be done by application!
2.23      frystyk    23: */
2.38      frystyk    24: PUBLIC void HTConverterInit (HTList * c)
2.23      frystyk    25: {
2.31      frystyk    26:     /*
2.49      frystyk    27:     ** You can get debug information out through the debug stream if you set
                     28:     ** the debug format appropriately
                     29:     */
                     30:     HTConversion_add(c,"*/*",                  "www/debug",    HTBlackHoleConverter,   1.0, 0.0, 0.0);
                     31: 
                     32:     /*
2.31      frystyk    33:     ** These are converters that converts to something other than www/present,
                     34:     ** that is not directly outputting someting to the user on the screen
                     35:     */
2.43      frystyk    36:     HTConversion_add(c,"message/rfc822",       "*/*",          HTMIMEConvert,  1.0, 0.0, 0.0);
2.55      frystyk    37:     HTConversion_add(c,"message/x-rfc822-foot",        "*/*",          HTMIMEFooter,   1.0, 0.0, 0.0);
2.43      frystyk    38:     HTConversion_add(c,"multipart/*",          "*/*",          HTBoundary,     1.0, 0.0, 0.0);
2.38      frystyk    39:     HTConversion_add(c,"text/plain",           "text/html",    HTPlainToHTML,  1.0, 0.0, 0.0);
2.39      frystyk    40: 
                     41:     /*
                     42:     ** The following conversions are converting ASCII output from various
                     43:     ** protocols to HTML objects.
                     44:     */
2.51      frystyk    45:     HTConversion_add(c,"text/x-http",          "*/*",          HTTPStatus_new, 1.0, 0.0, 0.0);
2.42      frystyk    46: #if 0
                     47:     HTConversion_add(c,"text/x-gopher",                "www/present",  HTGopherMenu,   1.0, 0.0, 0.0);
                     48:     HTConversion_add(c,"text/x-cso",           "www/present",  HTGopherCSO,    1.0, 0.0, 0.0);
2.48      frystyk    49:     HTConversion_add(c,"text/x-nntp-list",     "*/*",          HTNewsList,     1.0, 0.0, 0.0);
                     50:     HTConversion_add(c,"text/x-nntp-over",     "*/*",          HTNewsGroup,    1.0, 0.0, 0.0);
                     51:     HTConversion_add(c,"text/x-wais-source",   "*/*",          HTWSRCConvert,  1.0, 0.0, 0.0);
2.53      frystyk    52: #endif
2.43      frystyk    53: 
2.31      frystyk    54:     /*
2.45      frystyk    55:     ** We also register a special content type guess stream that can figure out
                     56:     ** the content type by reading the first bytes of the stream
                     57:     */
                     58:     HTConversion_add(c,"www/unknown",          "*/*",          HTGuess_new,    1.0, 0.0, 0.0);
2.46      frystyk    59: 
                     60:     /*
                     61:     ** Handling Rule files is handled just like any other stream
                     62:     ** This converter reads a rule file and generates the rules
                     63:     */
2.48      frystyk    64:     HTConversion_add(c,"application/x-www-rules","*/*",                HTRules,        1.0, 0.0, 0.0);
2.46      frystyk    65: 
2.45      frystyk    66:     /*
2.34      frystyk    67:     ** This dumps all other formats to local disk without any further
2.31      frystyk    68:     ** action taken
                     69:     */
2.38      frystyk    70:     HTConversion_add(c,"*/*",                  "www/present",  HTSaveLocally,  0.3, 0.0, 0.0);
2.23      frystyk    71: }
                     72: 
                     73: /*     BINDINGS BETWEEN MEDIA TYPES AND EXTERNAL VIEWERS/PRESENTERS
                     74: **     ------------------------------------------------------------
2.47      frystyk    75: **     Not done automaticly - may be done by application!
2.23      frystyk    76: **     The data objects are stored in temporary files before the external
                     77: **     program is called
                     78: */
2.38      frystyk    79: PUBLIC void HTPresenterInit (HTList * c)
2.1       timbl      80: {
                     81: #ifdef NeXT
2.38      frystyk    82:     HTPresentation_add(c,"application/postscript", "open %s",  NULL, 1.0, 2.0, 0.0);
2.10      luotonen   83:     /* The following needs the GIF previewer -- you might not have it. */
2.19      howcome    84: 
2.38      frystyk    85:     HTPresentation_add(c,"image/gif",          "open %s",      NULL, 0.3, 2.0, 0.0);
2.44      frystyk    86:     HTPresentation_add(c,"image/tiff",         "open %s",      NULL, 1.0, 2.0, 0.0);
2.41      frystyk    87:     HTPresentation_add(c,"audio/basic",        "open %s",      NULL, 1.0, 2.0, 0.0);
                     88:     HTPresentation_add(c,"*/*",                "open %s",      NULL, 0.05, 0.0, 0.0); 
2.1       timbl      89: #else
2.10      luotonen   90:     if (getenv("DISPLAY")) {   /* Must have X11 */
2.38      frystyk    91:        HTPresentation_add(c,"application/postscript", "ghostview %s",  NULL, 1.0, 3.0, 0.0);
2.41      frystyk    92:        HTPresentation_add(c,"image/gif",       "xv %s",        NULL, 1.0, 3.0, 0.0);
2.44      frystyk    93:        HTPresentation_add(c,"image/tiff",      "xv %s",        NULL, 1.0, 3.0, 0.0);
2.38      frystyk    94:        HTPresentation_add(c,"image/jpeg",      "xv %s",        NULL, 1.0, 3.0, 0.0);
2.44      frystyk    95:        HTPresentation_add(c,"image/png",       "xv %s",        NULL, 1.0, 3.0, 0.0);
2.10      luotonen   96:     }
2.1       timbl      97: #endif
2.15      frystyk    98: }
                     99: 
                    100: 
2.23      frystyk   101: /*     PRESENTERS AND CONVERTERS AT THE SAME TIME
                    102: **     ------------------------------------------
2.47      frystyk   103: **     Not done automaticly - may be done by application!
2.23      frystyk   104: **     This function is only defined in order to preserve backward
                    105: **     compatibility.
                    106: */
2.38      frystyk   107: PUBLIC void HTFormatInit (HTList * c)
2.15      frystyk   108: {
2.23      frystyk   109:     HTConverterInit(c);
                    110:     HTPresenterInit(c);
                    111: 
2.1       timbl     112: }
                    113: 
2.55      frystyk   114: /*     BINDINGS BETWEEN A ENCODING AND CODERS / DECODERS
                    115: **     --------------------------- ---------------------
                    116: **     Not done automaticly - may be done by application!
                    117: */
                    118: PUBLIC void HTEncoderInit (HTList * c)
                    119: {
                    120:     HTCoding_add(c, "chunked", NULL, HTChunkedDecoder, 1.0);
                    121: }
2.47      frystyk   122: 
                    123: /*     REGISTER CALLBACKS FOR THE NET MANAGER
                    124: **     --------------------------------------
                    125: **     We register two often used callback functions:
                    126: **     a BEFORE and a AFTER callback
                    127: **     Not done automaticly - may be done by application!
                    128: */
                    129: PUBLIC void HTNetInit (void)
                    130: {
2.54      frystyk   131:     HTNetCall_addBefore(HTLoadStart, NULL, 0);
                    132:     HTNetCall_addAfter(HTLoadTerminate, NULL, HT_ALL);
2.47      frystyk   133: }
                    134: 
                    135: 
                    136: /*     REGISTER CALLBACKS FOR THE ALERT MANAGER
                    137: **     ----------------------------------------
                    138: **     We register a set of alert messages
                    139: **     Not done automaticly - may be done by application!
                    140: */
                    141: PUBLIC void HTAlertInit (void)
                    142: {
                    143:     HTAlert_add(HTProgress, HT_A_PROGRESS);
                    144:     HTAlert_add(HTError_print, HT_A_MESSAGE);
                    145:     HTAlert_add(HTConfirm, HT_A_CONFIRM);
                    146:     HTAlert_add(HTPrompt, HT_A_PROMPT);
                    147:     HTAlert_add(HTPromptPassword, HT_A_SECRET);
                    148:     HTAlert_add(HTPromptUsernameAndPassword, HT_A_USER_PW);
                    149: }
                    150: 
2.53      frystyk   151: /*     REGISTER ALL KNOWN TRANSPORTS IN THE LIBRARY
                    152: **     --------------------------------------------
                    153: **     Not done automaticly - may be done by application!
                    154: */
                    155: PUBLIC void HTTransportInit (void)
                    156: {
2.54      frystyk   157:     HTTransport_add("tcp", HT_CH_SINGLE, HTReader_new, HTWriter_new);
                    158:     HTTransport_add("buffered_tcp", HT_CH_SINGLE, HTReader_new, HTBufferWriter_new);
                    159: #ifndef NO_UNIX_IO
                    160:     HTTransport_add("local", HT_CH_SINGLE, HTReader_new, HTWriter_new);
                    161: #else
                    162:     HTTransport_add("local", HT_CH_SINGLE, HTANSIReader_new, HTANSIWriter_new);
                    163: #endif
2.53      frystyk   164: }
2.47      frystyk   165: 
2.24      frystyk   166: /*     REGISTER ALL KNOWN PROTOCOLS IN THE LIBRARY
                    167: **     -------------------------------------------
2.47      frystyk   168: **     Not done automaticly - may be done by application!
2.24      frystyk   169: */
2.33      frystyk   170: PUBLIC void HTAccessInit (void)
2.24      frystyk   171: {
                    172: #ifndef DECNET
2.53      frystyk   173:     HTProtocol_add("ftp", "tcp", NO, HTLoadFTP, NULL);
                    174:     HTProtocol_add("nntp", "tcp", NO, HTLoadNews, NULL);
                    175:     HTProtocol_add("news", "tcp", NO, HTLoadNews, NULL);
                    176:     HTProtocol_add("gopher", "tcp", NO, HTLoadGopher, NULL);
2.24      frystyk   177: #ifdef HT_DIRECT_WAIS
2.53      frystyk   178:     HTProtocol_add("wais", "", YES, HTLoadWAIS, NULL);
2.24      frystyk   179: #endif
                    180: #endif /* DECNET */
                    181: 
2.54      frystyk   182:     HTProtocol_add("http", "buffered_tcp", NO, HTLoadHTTP, NULL);
2.53      frystyk   183:     HTProtocol_add("file", "local", NO, HTLoadFile, NULL);
                    184:     HTProtocol_add("telnet", "", YES, HTLoadTelnet, NULL);
                    185:     HTProtocol_add("tn3270", "", YES, HTLoadTelnet, NULL);
                    186:     HTProtocol_add("rlogin", "", YES, HTLoadTelnet, NULL);
2.56      frystyk   187: }
                    188: 
                    189: /*     REGISTER DEFULT EVENT MANAGER
                    190: **     -----------------------------
                    191: **     Not done automaticly - may be done by application!
                    192: */
                    193: PUBLIC void HTEventInit (void)
                    194: {
                    195:     HTEvent_setRegisterCallback(HTEventrg_register);
                    196:     HTEvent_setUnregisterCallback(HTEventrg_unregister);
2.24      frystyk   197: }
2.1       timbl     198: 
2.48      frystyk   199: #if 0
                    200: /*     BINDINGS BETWEEN ICONS AND MEDIA TYPES
                    201: **     --------------------------------------
                    202: **     Not done automaticly - may be done by application!
                    203: **     For directory listings etc. you can bind a set of icons to a set of
                    204: **     media types and special icons for directories and other objects that
                    205: **     do not have a media type.
                    206: */
2.52      frystyk   207: /* PUBLIC void HTStdIconInit (const char * url_prefix) */
2.48      frystyk   208: {
2.52      frystyk   209:     const char * p = url_prefix ? url_prefix : "/internal-icon/";
2.48      frystyk   210: 
                    211:     HTAddBlankIcon  (prefixed(p,"blank.xbm"),  NULL    );
                    212:     HTAddDirIcon    (prefixed(p,"directory.xbm"),"DIR" );
                    213:     HTAddParentIcon (prefixed(p,"back.xbm"),   "UP"    );
                    214:     HTAddUnknownIcon(prefixed(p,"unknown.xbm"),        NULL    );
                    215:     HTAddIcon(prefixed(p,"unknown.xbm"),       NULL,   "*/*");
                    216:     HTAddIcon(prefixed(p,"binary.xbm"),                "BIN",  "binary");
                    217:     HTAddIcon(prefixed(p,"unknown.xbm"),       NULL,   "www/unknown");
                    218:     HTAddIcon(prefixed(p,"text.xbm"),          "TXT",  "text/*");
                    219:     HTAddIcon(prefixed(p,"image.xbm"),         "IMG",  "image/*");
                    220:     HTAddIcon(prefixed(p,"movie.xbm"),         "MOV",  "video/*");
                    221:     HTAddIcon(prefixed(p,"sound.xbm"),         "AU",   "audio/*");
                    222:     HTAddIcon(prefixed(p,"tar.xbm"),           "TAR",  "multipart/x-tar");
                    223:     HTAddIcon(prefixed(p,"tar.xbm"),           "TAR",  "multipart/x-gtar");
                    224:     HTAddIcon(prefixed(p,"compressed.xbm"),    "CMP",  "x-compress");
                    225:     HTAddIcon(prefixed(p,"compressed.xbm"),    "GZP",  "x-gzip");
                    226:     HTAddIcon(prefixed(p,"index.xbm"),         "IDX",  "application/x-gopher-index");
                    227:     HTAddIcon(prefixed(p,"index2.xbm"),                "CSO",  "application/x-gopher-cso");
                    228:     HTAddIcon(prefixed(p,"telnet.xbm"),                "TEL",  "application/x-gopher-telnet");
                    229:     HTAddIcon(prefixed(p,"unknown.xbm"),               "DUP",  "application/x-gopher-duplicate");
                    230:     HTAddIcon(prefixed(p,"unknown.xbm"),       "TN",   "application/x-gopher-tn3270");
                    231: }
                    232: #endif
2.57      eric      233: 
2.58      eric      234: /*     standard MIME parsers
                    235:  */
                    236: PRIVATE int allow (HTRequest * request, char * token, char * value)
                    237: {
                    238:     char * field;
                    239:     HTParentAnchor * anchor = HTRequest_anchor(request);
                    240:     while ((field = HTNextField(&value)) != NULL) {
                    241:         HTMethod new_method;
                    242:        /* We treat them as case-insensitive! */
                    243:        if ((new_method = HTMethod_enum(field)) != METHOD_INVALID)
                    244:            HTAnchor_appendMethods(anchor, new_method);
                    245:     }
                    246:     if (STREAM_TRACE)
                    247:         HTTrace("MIMEParser.. Methods allowed: %d\n",
                    248:                HTAnchor_methods(anchor));
                    249:     return HT_OK;
                    250: }
                    251: 
                    252: PRIVATE int authenticate (HTRequest * request, char * token, char * value)
                    253: {
                    254:     if (!request->challenge) request->challenge = HTAssocList_new();
                    255: 
                    256:     StrAllocCopy(request->scheme, "basic");    /* @@@@@@@@@ */
                    257: 
                    258:     HTAssocList_add(request->challenge, "WWW-authenticate", value);
                    259:     return HT_OK;
                    260: }
                    261: 
                    262: PRIVATE int connection (HTRequest * request, char * token, char * value)
                    263: {
                    264:     char * field;
                    265:     if ((field = HTNextField(&value)) != NULL) {
                    266:         if (!strcasecomp(field, "keep-alive")) {
                    267:            HTNet_setPersistent(request->net, YES);
                    268:            if (STREAM_TRACE) HTTrace("MIMEParser.. Persistent Connection\n");
                    269:        }
                    270:     }
                    271:     return HT_OK;
                    272: }
                    273: 
                    274: PRIVATE int content_encoding (HTRequest * request, char * token, char * value)
                    275: {
                    276:     char * field;
                    277:     HTParentAnchor * anchor = HTRequest_anchor(request);
                    278:     while ((field = HTNextField(&value)) != NULL) {
                    279:         char * lc = field;
                    280:        while ((*lc = TOLOWER(*lc))) lc++;
                    281:        HTAnchor_addEncoding(anchor, HTAtom_for(field));
                    282:     }
                    283:     return HT_OK;
                    284: }
                    285: 
                    286: PRIVATE int content_language (HTRequest * request, char * token, char * value)
                    287: {
                    288:     char * field;
                    289:     HTParentAnchor * anchor = HTRequest_anchor(request);
                    290:     while ((field = HTNextField(&value)) != NULL) {
                    291:         char * lc = field;
                    292:        while ((*lc = TOLOWER(*lc))) lc++;
                    293:        HTAnchor_addLanguage(anchor, HTAtom_for(field));
                    294:     }
                    295:     return HT_OK;
                    296: }
                    297: 
                    298: PRIVATE int content_length (HTRequest * request, char * token, char * value)
                    299: {
                    300:     char * field;
                    301:     HTParentAnchor * anchor = HTRequest_anchor(request);
                    302:     if ((field = HTNextField(&value)) != NULL)
                    303:         HTAnchor_setLength(anchor, atol(field));
                    304:     return HT_OK;
                    305: }
                    306: 
                    307: PRIVATE int content_transfer_encoding (HTRequest * request, char * token, char * value)
                    308: {
                    309:     char * field;
                    310:     HTParentAnchor * anchor = HTRequest_anchor(request);
                    311:     if ((field = HTNextField(&value)) != NULL) {
                    312:         char *lc = field;
                    313:        while ((*lc = TOLOWER(*lc))) lc++;
                    314:        HTAnchor_setTransfer(anchor, HTAtom_for(field));
                    315:     }
                    316:     return HT_OK;
                    317: }
                    318: 
                    319: PRIVATE int content_type (HTRequest * request, char * token, char * value)
                    320: {
                    321:     char * field;
                    322:     HTParentAnchor * anchor = HTRequest_anchor(request);
                    323:     if ((field = HTNextField(&value)) != NULL) {
                    324:         char *lc = field;
                    325:        while ((*lc = TOLOWER(*lc))) lc++; 
                    326:        HTAnchor_setFormat(anchor, HTAtom_for(field));
                    327:        while ((field = HTNextField(&value)) != NULL) {
                    328:            if (!strcasecomp(field, "charset")) {
                    329:                if ((field = HTNextField(&value)) != NULL) {
                    330:                    lc = field;
                    331:                    while ((*lc = TOLOWER(*lc))) lc++;
                    332:                    HTAnchor_setCharset(anchor, HTAtom_for(field));
                    333:                }
                    334:            } else if (!strcasecomp(field, "level")) {
                    335:                if ((field = HTNextField(&value)) != NULL) {
                    336:                    lc = field;
                    337:                    while ((*lc = TOLOWER(*lc))) lc++;
                    338:                    HTAnchor_setLevel(anchor, HTAtom_for(field));
                    339:                }
                    340:            } else if (!strcasecomp(field, "boundary")) {
                    341:                if ((field = HTNextField(&value)) != NULL) {
                    342:                    StrAllocCopy(request->boundary, field);
                    343:                }
                    344:            }
                    345:        }
                    346:     }
                    347:     return HT_OK;
                    348: }
                    349: 
                    350: PRIVATE int derived_from (HTRequest * request, char * token, char * value)
                    351: {
                    352:     char * field;
                    353:     HTParentAnchor * anchor = HTRequest_anchor(request);
                    354:     if ((field = HTNextField(&value)) != NULL)
                    355:         HTAnchor_setDerived(anchor, field);
                    356:     return HT_OK;
                    357: }
                    358: 
                    359: PRIVATE int expires (HTRequest * request, char * token, char * value)
                    360: {
                    361:     HTParentAnchor * anchor = HTRequest_anchor(request);
                    362:     HTAnchor_setExpires(anchor, HTParseTime(value, 
                    363:                                            HTRequest_userProfile(request)));
                    364:     return HT_OK;
                    365: }
                    366: 
                    367: PRIVATE int last_modified (HTRequest * request, char * token, char * value)
                    368: {
                    369:     HTParentAnchor * anchor = HTRequest_anchor(request);
                    370:     HTAnchor_setLastModified(anchor, HTParseTime(value, 
                    371:                                            HTRequest_userProfile(request)));
                    372:     return HT_OK;
                    373: }
                    374: 
                    375: PRIVATE int location (HTRequest * request, char * token, char * value)
                    376: {
                    377:     request->redirectionAnchor = HTAnchor_findAddress(HTStrip(value));
                    378:     return HT_OK;
                    379: }
                    380: 
                    381: PRIVATE int message_digest (HTRequest * request, char * token, char * value)
                    382: {
                    383:     if (!request->challenge) request->challenge = HTAssocList_new();
                    384:     HTAssocList_add(request->challenge, "Digest-MessageDigest", value);
                    385:     return HT_OK;
                    386: }
                    387: 
                    388: PRIVATE int mime_date (HTRequest * request, char * token, char * value)
                    389: {
                    390:     HTParentAnchor * anchor = HTRequest_anchor(request);
                    391:     HTAnchor_setDate(anchor, HTParseTime(value, 
                    392:                                         HTRequest_userProfile(request)));
                    393:     return HT_OK;
                    394: }
                    395: 
                    396: PRIVATE int newsgroups (HTRequest * request, char * token, char * value)
                    397: {
                    398:     /* HTRequest_net(request)->nntp = YES; */          /* Due to news brain damage */
                    399:     return HT_OK;
                    400: }
                    401: 
                    402: PRIVATE int retry_after (HTRequest * request, char * token, char * value)
                    403: {
                    404:     request->retry_after = HTParseTime(value, 
                    405:                                       HTRequest_userProfile(request));
                    406:     return HT_OK;
                    407: }
                    408: 
                    409: PRIVATE int title (HTRequest * request, char * token, char * value)
                    410: {
                    411:     char * field;
                    412:     HTParentAnchor * anchor = HTRequest_anchor(request);
                    413:     if ((field = HTNextField(&value)) != NULL)
                    414:         HTAnchor_setTitle(anchor, field);
                    415:     return HT_OK;
                    416: }
                    417: 
                    418: PRIVATE int version (HTRequest * request, char * token, char * value)
                    419: {
                    420:     char * field;
                    421:     HTParentAnchor * anchor = HTRequest_anchor(request);
                    422:     if ((field = HTNextField(&value)) != NULL)
                    423:         HTAnchor_setVersion(anchor, field);
                    424:     return HT_OK;
                    425: }
                    426: 
                    427: 
2.57      eric      428: /*     REGISTER ALL HTTP/1.1 MIME HEADERS
                    429: **     --------------------------------------------
                    430: **     Not done automaticly - may be done by application!
                    431: */
                    432: PUBLIC void HTMIMEInit()
                    433: {
                    434:     struct {
                    435:         char * string;
                    436:        HTParserCallback * pHandler;
                    437:     } fixedHandlers[] = {
                    438:        {"allow", &allow}, 
                    439:        {"accept-language", NULL}, 
                    440:        {"accept-charset", NULL}, 
                    441:        {"accept", NULL}, 
                    442:        {"accept-encoding", NULL}, 
                    443:        {"connection", &connection}, 
                    444:        {"content-encoding", &content_encoding}, 
                    445:        {"content-language", &content_language}, 
                    446:        {"content-length", &content_length}, 
                    447:        {"content-transfer-encoding", &content_transfer_encoding}, 
                    448:        {"content-type", &content_type},
                    449:        {"date", &mime_date}, 
                    450:        {"derived-from", &derived_from}, 
                    451:        {"digest-MessageDigest", &message_digest}, 
                    452:         {"expires", &expires}, 
                    453:        {"keep-alive", NULL}, 
                    454:        {"last-modified", &last_modified}, 
                    455: /*     {"link", &link},  */
                    456:        {"location", &location}, 
                    457:        {"mime-version", NULL}, 
                    458:        {"newsgroups", &newsgroups}, 
                    459:        {"retry-after", &retry_after}, 
                    460:        {"server", NULL}, 
                    461:        {"title", &title}, 
                    462:        {"transfer-encoding", &content_transfer_encoding}, 
                    463: /*     {"uri", &uri_header},  */
                    464:        {"version", &version}, 
                    465:        {"www-authenticate", &authenticate}, 
                    466:     };
                    467:     int i;
                    468: 
                    469:     for (i = 0; i < sizeof(fixedHandlers)/sizeof(fixedHandlers[0]); i++)
                    470:         HTHeader_addParser(fixedHandlers[i].string, NO, 
                    471:                           fixedHandlers[i].pHandler);
                    472: }
                    473: 

Webmaster