Annotation of libwww/Library/src/HTTPServ.c, revision 2.15

2.1       frystyk     1: /*                                                                 HTTPServ.c
                      2: **     HTTP SERVER MODULE
                      3: **
                      4: **     (c) COPYRIGHT MIT 1995.
                      5: **     Please first read the full copyright statement in the file COPYRIGH.
                      6: **
                      7: **     This module implments the HTTP protocol as a state machine
                      8: **
                      9: ** History:
                     10: **     Dec 95 HFN      Written with Christmas in my eyes
                     11: **
                     12: */
                     13: 
                     14: /* Library include files */
2.14      frystyk    15: #include "sysdep.h"
2.1       frystyk    16: #include "HTUtils.h"
                     17: #include "HTString.h"
                     18: #include "HTParse.h"
                     19: #include "HTWWWStr.h"
                     20: #include "HTTCP.h"
                     21: #include "HTSocket.h"
                     22: #include "HTAlert.h"
                     23: #include "HTError.h"
                     24: #include "HTAccess.h"
2.2       frystyk    25: #include "HTWriter.h"
2.1       frystyk    26: #include "HTChunk.h"
                     27: #include "HTReqMan.h"
2.9       frystyk    28: #include "HTConLen.h"
2.1       frystyk    29: #include "HTNetMan.h"
2.9       frystyk    30: #include "HTMIMERq.h"
2.1       frystyk    31: #include "HTTPUtil.h"
2.2       frystyk    32: #include "HTTPRes.h"
2.1       frystyk    33: #include "HTTPServ.h"                                         /* Implements */
                     34: 
                     35: /* Macros and other defines */
                     36: #define PUTC(c)                (*me->target->isa->put_character)(me->target, c)
                     37: #define PUTS(s)                (*me->target->isa->put_string)(me->target, s)
                     38: #define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l)
                     39: #define FREE_TARGET    (*me->target->isa->_free)(me->target)
                     40: #define ABORT_TARGET   (*me->target->isa->abort)(me->target, e)
                     41: 
                     42: /* Final states have negative value */
                     43: typedef enum _HTTPState {
2.6       frystyk    44:     HTTPS_ERROR                = -2,
                     45:     HTTPS_OK           = -1,
2.1       frystyk    46:     HTTPS_BEGIN                = 0,
2.3       frystyk    47:     HTTPS_NEED_REQUEST
2.1       frystyk    48: } HTTPState;
                     49: 
                     50: /* This is the context object for the this module */
                     51: typedef struct _https_info {
                     52:     HTTPState  state;                    /* Current State of the connection */
2.9       frystyk    53:     char *     version;                            /* Version for the reply */
2.10      frystyk    54:     HTRequest *        client;                        /* This is out client request */
2.1       frystyk    55: } https_info;
                     56: 
                     57: /* The HTTP Receive Stream */
                     58: struct _HTStream {
2.14      frystyk    59:     const HTStreamClass *      isa;
2.1       frystyk    60:     HTStream *                 target;
                     61:     HTRequest *                        request;
2.9       frystyk    62:     https_info *               http;
                     63:     HTRequest *                        client;
2.15    ! frystyk    64:     HTEOLState                 state;
2.1       frystyk    65:     HTChunk *                  buffer;
                     66:     BOOL                       transparent;
                     67: };
                     68: 
                     69: /* ------------------------------------------------------------------------- */
2.8       frystyk    70: 
                     71: /*     ServerCleanup
                     72: **     -------------
                     73: **      This function cleans up after the request
                     74: **      Returns YES on OK, else NO
                     75: */
                     76: PRIVATE int ServerCleanup (HTRequest * req, HTNet * net, int status)
                     77: {
                     78:     https_info * http = (https_info *) net->context;
                     79: 
                     80:     /* Free stream with data TO network */
                     81:     if (req->input_stream) {
                     82:        if (status == HT_INTERRUPTED)
                     83:            (*req->input_stream->isa->abort)(req->input_stream, NULL);
                     84:        else
                     85:            (*req->input_stream->isa->_free)(req->input_stream);
                     86:        req->input_stream = NULL;
                     87:     }
                     88: 
                     89:     /* Remove the net object and our own context structure for http */
                     90:     HTNet_delete(net, req->internal ? HT_IGNORE : status);
2.11      frystyk    91:     HT_FREE(http->version);
                     92:     HT_FREE(http);
2.8       frystyk    93:     return YES;
                     94: }
                     95: 
                     96: /* ------------------------------------------------------------------------- */
2.6       frystyk    97: /*                             REPLY STREAM                                 */
                     98: /* ------------------------------------------------------------------------- */
2.1       frystyk    99: 
2.6       frystyk   100: /*
                    101: **     This is our handle to the server reply stream when data is coming
2.9       frystyk   102: **     back from our "client" request. It is responsible for setting up the
                    103: **     remaining streams in order to produce a complete HTTP output.
                    104: **     If we have a HTTP 1.x response then forward untouched.
                    105: **
                    106: **     BUG: We should look at the version string before generating response!
2.6       frystyk   107: */
2.9       frystyk   108: PRIVATE int MakeReplyPipe (HTStream *me, HTRequest *server, HTRequest *client)
                    109: {
                    110:     char * response_line = NULL;
                    111:     me->transparent = YES;
                    112: 
                    113:     /* Check if we can forward the response untouched */
                    114:     if (client->net) {
                    115:        HTdns * cdns = client->net->dns;
                    116:        char * s_class = HTDNS_serverClass(cdns);
                    117:        int version = HTDNS_serverVersion(cdns);
                    118:        /* We are not using the version info for the moment */
                    119:        if (s_class && !strcasecomp(s_class, "http")) {
2.12      eric      120:            if (STREAM_TRACE) HTTrace("HTTP Reply.. Direct output\n");
2.9       frystyk   121:            return HT_OK;
                    122:        }
                    123:     }
                    124: 
                    125:     /* Set up a small buffer for the response headers */
                    126:     me->target = HTBuffer_new(me->target, server, 256);
                    127: 
                    128:     /* Generate the Response line */
                    129:     {
                    130:        HTAlertCallback *cbf = HTAlert_find(HT_A_MESSAGE);
                    131:        if (cbf) {
                    132:            HTAlertPar * reply = HTAlert_newReply();
                    133:            if ((*cbf)(client, HT_A_MESSAGE, HT_MSG_NULL, NULL,
                    134:                       client->error_stack, reply))
                    135:                response_line = HTAlert_replyMessage(reply);
                    136:            HTAlert_deleteReply(reply);
                    137:        }
                    138: 
                    139:        /* Output the response */
                    140:        if (response_line) {
                    141:            PUTS(response_line);
2.11      frystyk   142:            HT_FREE(response_line);
2.9       frystyk   143:        } else {        
2.13      frystyk   144:            PUTS("HTTP/1.0 500 Internal");
2.9       frystyk   145:            PUTC(CR);
                    146:            PUTC(LF);
                    147:        }
                    148:     }
                    149: 
                    150:     /*
                    151:     ** We now have to create the rest of the response stream. We see whether
                    152:     ** there is a data object or not by looking at the Content Type of the
                    153:     ** client anchor.
                    154:     */
                    155:     me->target = (HTAnchor_format(client->anchor) == WWW_UNKNOWN) ?
                    156:        HTTPResponse_new(server, me->target, YES) :
                    157:        HTMIMERequest_new(server, HTTPResponse_new(server,me->target,NO), YES);
                    158: 
                    159:     /* Here we should put out any BODY for the error message */
                    160: 
                    161:     return (*me->target->isa->flush)(me->target);
                    162: }
2.6       frystyk   163: 
2.14      frystyk   164: PRIVATE int HTTPReply_put_block (HTStream * me, const char * b, int l)
2.1       frystyk   165: {
2.9       frystyk   166:     if (me->transparent)
                    167:        return b ? PUTBLOCK(b, l) : HT_OK;
                    168:     else {
                    169:        MakeReplyPipe(me, me->request, me->client);
                    170:        return b ? PUTBLOCK(b, l) : HT_OK;
                    171:     }
2.6       frystyk   172: }
                    173: 
2.14      frystyk   174: PRIVATE int HTTPReply_put_string (HTStream * me, const char * s)
2.6       frystyk   175: {
2.9       frystyk   176:     return HTTPReply_put_block(me, s, strlen(s));
2.6       frystyk   177: }
                    178: 
                    179: PRIVATE int HTTPReply_put_character (HTStream * me, char c)
                    180: {
2.9       frystyk   181:     return HTTPReply_put_block(me, &c, 1);
2.6       frystyk   182: }
                    183: 
                    184: PRIVATE int HTTPReply_flush (HTStream * me)
                    185: {
2.9       frystyk   186:     int status = HTTPReply_put_block(me, NULL, 0);
                    187:     return status==HT_OK ? (*me->target->isa->flush)(me->target) : status;
2.6       frystyk   188: }
2.1       frystyk   189: 
2.6       frystyk   190: PRIVATE int HTTPReply_free (HTStream * me)
                    191: {
2.9       frystyk   192:     int status = HTTPReply_flush(me);
2.12      eric      193:     if (STREAM_TRACE) HTTrace("HTTPReply... Freeing server stream\n");
2.9       frystyk   194:     if (status != HT_WOULD_BLOCK) {
                    195:        HTNet * snet = me->request->net;
                    196:        if ((status = FREE_TARGET) == HT_WOULD_BLOCK) return HT_WOULD_BLOCK;
                    197: #if 0
                    198:        /* We can't do this until we get a better event loop */
2.15    ! frystyk   199:        if (HTNet_persistent(snet)) {
2.9       frystyk   200:            if (STREAM_TRACE)
2.12      eric      201:                HTTrace("HTTPReply... Persistent conenction\n");
2.9       frystyk   202:            HTEvent_Register(snet->sockfd, me->request, (SockOps) FD_READ,
                    203:                             snet->cbf, snet->priority);
                    204:            HTRequest_clear(me->request);
                    205:        } else {
                    206:            ServerCleanup(me->request, snet, HT_IGNORE);
2.8       frystyk   207:            HTRequest_delete(me->request);
2.9       frystyk   208:            HTRequest_removeDest(me->client);
                    209:        }
                    210: #else
                    211:        ServerCleanup(me->request, snet, HT_IGNORE);
                    212:        HTRequest_delete(me->request);
                    213: #endif
2.1       frystyk   214:     }
2.11      frystyk   215:     HT_FREE(me);
2.6       frystyk   216:     return HT_OK;
                    217: }
                    218: 
                    219: PRIVATE int HTTPReply_abort (HTStream * me, HTList * e)
                    220: {
2.9       frystyk   221:     HTNet * snet = me->request->net;
                    222:     if (!me->transparent) {
                    223:        HTRequest_addError(me->client, ERR_FATAL, NO, HTERR_INTERNAL,
                    224:                           NULL, 0, "HTTPReply_abort");
                    225:        MakeReplyPipe(me, me->request, me->client);
                    226:     }
2.12      eric      227:     if (STREAM_TRACE) HTTrace("HTTPReply... ABORTING\n");
2.6       frystyk   228:     if (me->target) ABORT_TARGET;
2.9       frystyk   229: #if 0
                    230:     /* We can't do this until we get a better event loop */
2.15    ! frystyk   231:     if (HTNet_persistent(snet)) {
2.9       frystyk   232:        if (STREAM_TRACE)
2.12      eric      233:            HTTrace("HTTPReply... Persistent conenction\n");
2.9       frystyk   234:        HTEvent_Register(snet->sockfd, me->request, (SockOps) FD_READ,
                    235:                         snet->cbf, snet->priority);
                    236:        HTRequest_clear(me->request);
                    237:     } else {
                    238:        ServerCleanup(me->request, snet, HT_IGNORE);
                    239:        HTRequest_delete(me->request);
                    240:        HTRequest_removeDest(me->client);
                    241:     }
                    242: #else
                    243:     ServerCleanup(me->request, snet, HT_IGNORE);
                    244:     HTRequest_delete(me->request);
                    245: #endif
2.11      frystyk   246:     HT_FREE(me);
2.6       frystyk   247:     return HT_ERROR;
                    248: }
                    249: 
                    250: /*     HTTPReply Stream
                    251: **     -----------------
                    252: */
2.14      frystyk   253: PRIVATE const HTStreamClass HTTPReplyClass =
2.6       frystyk   254: {              
                    255:     "HTTPReply",
                    256:     HTTPReply_flush,
                    257:     HTTPReply_free,
                    258:     HTTPReply_abort,
                    259:     HTTPReply_put_character,
                    260:     HTTPReply_put_string,
                    261:     HTTPReply_put_block
                    262: };
2.1       frystyk   263: 
2.9       frystyk   264: PRIVATE HTStream * HTTPReply_new (HTRequest * request, HTRequest * client,
                    265:                                  HTStream * target)
2.6       frystyk   266: {
2.11      frystyk   267:     HTStream * me;
                    268:     if ((me = (HTStream  *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
                    269:         HT_OUTOFMEM("HTTPReply_new");
2.6       frystyk   270:     me->isa = &HTTPReplyClass;
                    271:     me->target = target;
                    272:     me->request = request;
2.9       frystyk   273:     me->client = client;
2.6       frystyk   274:     return me;
2.1       frystyk   275: }
                    276: 
2.6       frystyk   277: /* ------------------------------------------------------------------------- */
                    278: /*                             RECEIVE STREAM                               */
                    279: /* ------------------------------------------------------------------------- */
                    280: 
2.1       frystyk   281: /*
                    282: **     Scan the request line for METHOD, URI and VERSION
                    283: **     Returns:        HT_OK           if 1.x request and OK
                    284: **                     HT_LOADED       if 0.9 request and OK
                    285: **                     HT_ERROR        if invalid request line
                    286: */
                    287: PRIVATE int ParseRequest (HTStream * me)
                    288: {
2.3       frystyk   289:     HTRequest * request = me->request;
2.2       frystyk   290:     char * line = HTChunk_data(me->buffer);
2.6       frystyk   291:     char * method_str = HTNextField(&line);
                    292:     char * request_uri = HTNextField(&line);
                    293:     char * version_str = HTNextField(&line);
                    294: 
                    295:     /* Check if method is allowed */
                    296:     if (!method_str || (request->method=HTMethod_enum(method_str))==METHOD_INVALID) {
                    297:        HTRequest_addError(request, ERR_FATAL, NO, HTERR_NOT_ALLOWED,
                    298:                           NULL, 0, "ParseRequest");
                    299:        return HT_ERROR;
                    300:     }
2.2       frystyk   301: 
2.6       frystyk   302:     /* Find an anchor for the request URI */
                    303:     if (request_uri) {
                    304:        char * uri = HTParse(request_uri, "file:", PARSE_ALL);
                    305:        request->anchor = (HTParentAnchor *) HTAnchor_findAddress(uri);
2.11      frystyk   306:        HT_FREE(uri);
2.1       frystyk   307:     } else {
2.6       frystyk   308:        HTRequest_addError(request, ERR_FATAL, NO, HTERR_BAD_REQUEST,
2.1       frystyk   309:                           NULL, 0, "ParseRequest");
                    310:        return HT_ERROR;
                    311:     }
                    312: 
2.6       frystyk   313:     /* Get ready to get the rest of the request */
                    314:     if (version_str) {
2.8       frystyk   315:        me->target = HTStreamStack(WWW_MIME_HEAD, request->debug_format,
                    316:                                   request->debug_stream, request, NO);
2.9       frystyk   317:        StrAllocCopy(me->http->version, version_str);
2.1       frystyk   318:        return HT_OK;
2.2       frystyk   319:     } else {
2.12      eric      320:        if (PROT_TRACE) HTTrace("Request Line is formatted as 0.9\n");
2.3       frystyk   321:        return HT_LOADED;
2.1       frystyk   322:     }
                    323: }
                    324: 
                    325: /*
                    326: **     Searches for HTTP Request Line before going into transparent mode
                    327: */
2.14      frystyk   328: PRIVATE int HTTPReceive_put_block (HTStream * me, const char * b, int l)
2.1       frystyk   329: {
2.6       frystyk   330:     if (!me->transparent) {
2.14      frystyk   331:        const char *p=b;
2.6       frystyk   332:        while (l>0 && *p!=CR && *p!=LF) l--, p++;
                    333:        HTChunk_putb(me->buffer, b, p-b);
                    334:        if (*p==CR || *p==LF) {
                    335:            int status = ParseRequest(me);
                    336:            HTChunk_clear(me->buffer);
                    337:            if (status != HT_OK) return status;
                    338:            me->transparent = YES;
                    339:            b=p;
                    340:        }
                    341:     }
                    342:     if (l > 0) {
                    343:        int status = PUTBLOCK(b, l);
                    344:        if (status == HT_LOADED) me->transparent = NO;
                    345:        return status;
2.1       frystyk   346:     }
                    347:     return HT_OK;
                    348: }
                    349: 
2.14      frystyk   350: PRIVATE int HTTPReceive_put_string (HTStream * me, const char * s)
2.1       frystyk   351: {
                    352:     return HTTPReceive_put_block(me, s, (int) strlen(s));
                    353: }
                    354: 
                    355: PRIVATE int HTTPReceive_put_character (HTStream * me, char c)
                    356: {
                    357:     return HTTPReceive_put_block(me, &c, 1);
                    358: }
                    359: 
                    360: PRIVATE int HTTPReceive_flush (HTStream * me)
                    361: {
                    362:     return (*me->target->isa->flush)(me->target);
                    363: }
                    364: 
                    365: PRIVATE int HTTPReceive_free (HTStream * me)
                    366: {
                    367:     int status = HT_OK;
                    368:     if (me->target) {
                    369:        if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
                    370:            return HT_WOULD_BLOCK;
                    371:     }
2.2       frystyk   372:     HTChunk_delete(me->buffer);
2.11      frystyk   373:     HT_FREE(me);
2.1       frystyk   374:     return status;
                    375: }
                    376: 
                    377: PRIVATE int HTTPReceive_abort (HTStream * me, HTList * e)
                    378: {
                    379:     if (me->target) ABORT_TARGET;
2.2       frystyk   380:     HTChunk_delete(me->buffer);
2.11      frystyk   381:     HT_FREE(me);
2.12      eric      382:     if (PROT_TRACE) HTTrace("HTTPReceive. ABORTING...\n");
2.1       frystyk   383:     return HT_ERROR;
                    384: }
                    385: 
                    386: /*     HTTPReceive Stream
                    387: **     -----------------
                    388: */
2.14      frystyk   389: PRIVATE const HTStreamClass HTTPReceiveClass =
2.1       frystyk   390: {              
                    391:     "HTTPReceive",
                    392:     HTTPReceive_flush,
                    393:     HTTPReceive_free,
                    394:     HTTPReceive_abort,
                    395:     HTTPReceive_put_character,
                    396:     HTTPReceive_put_string,
                    397:     HTTPReceive_put_block
                    398: };
                    399: 
                    400: PRIVATE HTStream * HTTPReceive_new (HTRequest * request, https_info * http)
                    401: {
2.11      frystyk   402:     HTStream * me;
                    403:     if ((me = (HTStream  *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
                    404:         HT_OUTOFMEM("HTTPReceive_new");
2.1       frystyk   405:     me->isa = &HTTPReceiveClass;
                    406:     me->request = request;
2.9       frystyk   407:     me->http = http;
2.1       frystyk   408:     me->state = EOL_BEGIN;    
2.2       frystyk   409:     me->buffer = HTChunk_new(128);              /* Sufficiant for most URLs */
2.1       frystyk   410:     return me;
                    411: }
                    412: 
                    413: /* ------------------------------------------------------------------------- */
                    414: 
                    415: /*     HTServHTTP
                    416: **     ----------
                    417: **     Serv Document using HTTP.
                    418: **     returns HT_ERROR or HT_OK
                    419: */
                    420: PUBLIC int HTServHTTP (SOCKET soc, HTRequest * request, SockOps ops)
                    421: {
                    422:     int status = HT_ERROR;
2.6       frystyk   423:     HTNet * net = request->net;                       /* Server information */
2.1       frystyk   424:     https_info * http;                     /* Specific protocol information */
                    425:     
                    426:     /*
                    427:     ** Initiate a new https object and bind to request object
                    428:     ** This is actually state HTTPS_BEGIN, but it can't be in the state
                    429:     ** machine as we need the object first (chicken and egg problem).
                    430:     */
                    431:     if (ops == FD_NONE) {
                    432:        if (PROT_TRACE)
2.12      eric      433:            HTTrace("HTTP Serve.. request %p on socket %d\n",
2.1       frystyk   434:                     request, soc);
2.11      frystyk   435:        if ((http = (https_info *) HT_CALLOC(1, sizeof(https_info))) == NULL)
                    436:            HT_OUTOFMEM("HTServHTTP");
2.1       frystyk   437:        http->state = HTTPS_BEGIN;
                    438:        net->context = http;
                    439:     } else if (ops == FD_CLOSE) {                            /* Interrupted */
2.6       frystyk   440:        ServerCleanup(request, net, HT_INTERRUPTED);
2.1       frystyk   441:        return HT_OK;
                    442:     } else
                    443:        http = (https_info *) net->context;             /* Get existing copy */
                    444:  
                    445:     /* Now jump into the machine. We know the state from the previous run */
                    446:     while (1) {
                    447:        switch (http->state) {
                    448:          case HTTPS_BEGIN:
                    449:            status = HTDoAccept(net);
                    450:            if (status == HT_OK) {
2.6       frystyk   451: 
                    452:                /* Setup Request parser stream */
                    453:                net->target = HTTPReceive_new(request, http);
                    454: 
                    455:                http->state = HTTPS_NEED_REQUEST;
2.1       frystyk   456:            } else {
2.6       frystyk   457:                ServerCleanup(request, net, HT_ERROR);
2.1       frystyk   458:                return HT_ERROR;
                    459:            }       
                    460:            break;
                    461: 
                    462:          case HTTPS_NEED_REQUEST:
2.3       frystyk   463:            if (ops == FD_READ || ops == FD_NONE) {
2.15    ! frystyk   464:                status = HTChannel_readSocket(request, net);
2.3       frystyk   465:                if (status == HT_WOULD_BLOCK)
                    466:                    return HT_OK;
2.8       frystyk   467:                else if (status == HT_PAUSE) {
2.10      frystyk   468:                    http->client = HTRequest_dup(request);
2.9       frystyk   469: 
                    470:                    /* Set the right client headers */
2.10      frystyk   471:                    HTRequest_setGnHd(http->client, DEFAULT_GENERAL_HEADERS);
2.9       frystyk   472: 
2.8       frystyk   473:                    /*
                    474:                    ** If we have a data object in the request then link the
                    475:                    ** two request objects together
                    476:                    */
                    477:                    if (HTMethod_hasEntity(request->method))
2.10      frystyk   478:                        HTRequest_addDestination(request, http->client);
2.9       frystyk   479: 
                    480:                    /*
                    481:                    ** Set up our reply stream. This is responsible for
                    482:                    ** generating a HTTP reply
                    483:                    */
2.10      frystyk   484:                    http->client->output_stream = request->output_stream =
                    485:                        HTTPReply_new(request, http->client,
2.9       frystyk   486:                                      HTWriter_new(request->net,YES));
                    487: 
                    488:                    /* Start the load of the "client" request */
2.10      frystyk   489:                    return HTLoad(http->client, NO) == YES ? HT_OK : HT_ERROR;
2.6       frystyk   490:                } else if (status == HT_CLOSED)
                    491:                    http->state = HTTPS_OK;
                    492:                else
2.3       frystyk   493:                    http->state = HTTPS_ERROR;
2.6       frystyk   494:            } else if (ops == FD_WRITE) {
2.10      frystyk   495: #if 0
2.7       frystyk   496:                if (HTRequest_mainDestination(request)) {
2.3       frystyk   497:                    HTNet * dest = request->mainDestination->net;
                    498:                    HTEvent_Register(dest->sockfd, dest->request,
                    499:                                     (SockOps) FD_READ,
                    500:                                     dest->cbf, dest->priority);
                    501:                }
2.10      frystyk   502: #else
                    503:                if (http->client && http->client->net) {
                    504:                    HTNet * dnet = http->client->net;
                    505:                    HTEvent_Register(dnet->sockfd, http->client,
                    506:                                     (SockOps) FD_READ, dnet->cbf, dnet->priority);
                    507:                }
                    508: #endif             
2.1       frystyk   509:                return HT_OK;
2.3       frystyk   510:            } else
2.2       frystyk   511:                http->state = HTTPS_ERROR;
2.1       frystyk   512:            break;
                    513: 
2.6       frystyk   514:          case HTTPS_OK:
2.8       frystyk   515:            ServerCleanup(request, net, HT_IGNORE);
2.6       frystyk   516:            break;
                    517: 
2.1       frystyk   518:          case HTTPS_ERROR:
2.8       frystyk   519:            if (HTRequest_isPostWeb(request)) HTRequest_killPostWeb(request);
2.6       frystyk   520:            ServerCleanup(request, net, HT_ERROR);
2.1       frystyk   521:            return HT_OK;
                    522:            break;
                    523:        }
                    524:     }
2.3       frystyk   525: }
2.6       frystyk   526: 

Webmaster