Annotation of libwww/Library/src/HTTPRes.c, revision 2.4

2.1       frystyk     1: /*                                                                   HTTPRes.c
2.4     ! frystyk     2: **     HTTP RESPONSE GENERATION
2.1       frystyk     3: **
                      4: **     This module implements the output stream for HTTP used for sending
                      5: **     responces with or without a entity body. It is the server equivalent
                      6: **     to the HTTPReq module
                      7: **
                      8: ** History:
                      9: **     Dec 95 HFN      Written from scratch
                     10: */
                     11: 
                     12: /* Library Includes */
                     13: #include "tcp.h"
                     14: #include "HTUtils.h"
                     15: #include "HTString.h"
                     16: #include "HTWWWStr.h"
                     17: #include "HTAccess.h"
                     18: #include "HTWriter.h"
2.4     ! frystyk    19: #include "HTFWrite.h"
2.1       frystyk    20: #include "HTEvntrg.h"
                     21: #include "HTNetMan.h"
                     22: #include "HTReqMan.h"
2.4     ! frystyk    23: #include "HTTPGen.h"
2.1       frystyk    24: #include "HTTPUtil.h"
                     25: #include "HTTPRes.h"                                          /* Implements */
                     26: 
                     27: #define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l)
                     28: 
                     29: struct _HTStream {
                     30:     CONST HTStreamClass *      isa;
                     31:     HTStream *                 target;
                     32:     HTRequest *                        request;
                     33:     BOOL                       transparent;
                     34: };
                     35: 
                     36: /* ------------------------------------------------------------------------- */
                     37: /*                         HTTP Output Request Stream                       */
                     38: /* ------------------------------------------------------------------------- */
                     39: 
                     40: /*     HTTPMakeResponse
                     41: **     ----------------
                     42: **     Makes a HTTP/1.0-1.1 response header.
                     43: */
2.4     ! frystyk    44: PRIVATE int HTTPMakeResponse (HTStream * me, HTRequest * request)
2.1       frystyk    45: {
                     46:     char linebuf[256];
                     47:     if (request->error_stack) {
                     48: 
                     49:        /* @@@ WRITE A SMALL HTError_response() function */
                     50:        sprintf(linebuf, "HTTP/1.0 404 Not Found%c%c", CR, LF);
                     51:        
                     52:        PUTBLOCK(linebuf, (int) strlen(linebuf));
                     53:     } else {
                     54:        sprintf(linebuf, "HTTP/1.0 200 OK%c%c", CR, LF);
                     55:        PUTBLOCK(linebuf, (int) strlen(linebuf));
                     56: 
                     57:        /* Response Headers */
                     58:        if (request->ResponseMask & HT_S_SERVER) {
                     59:            sprintf(linebuf, "Server: %s/%s %s/%s%c%c",
                     60:                    HTLib_appName(), HTLib_appVersion(),
                     61:                    HTLib_name(), HTLib_version(), CR, LF);
                     62:            PUTBLOCK(linebuf, (int) strlen(linebuf));
                     63:        }
                     64:     }
2.4     ! frystyk    65:     if(PROT_TRACE)TTYPrint(TDEST,"HTTP........ Generating Response Headers\n");
        !            66:     return HT_OK;
2.1       frystyk    67: }
                     68: 
                     69: PRIVATE int HTTPResponse_put_block (HTStream * me, CONST char * b, int l)
                     70: {
2.4     ! frystyk    71:     if (me->target) {
        !            72:        if (me->transparent)
        !            73:            return PUTBLOCK(b, l);
        !            74:        else {
        !            75:            HTTPMakeResponse(me, me->request);            /* Generate header */
        !            76:            me->transparent = YES;
        !            77:            return b ? PUTBLOCK(b, l) : HT_OK;
        !            78:        }
2.1       frystyk    79:     }
2.4     ! frystyk    80:     return HT_WOULD_BLOCK;
2.1       frystyk    81: }
                     82: 
                     83: PRIVATE int HTTPResponse_put_character (HTStream * me, char c)
                     84: {
                     85:     return HTTPResponse_put_block(me, &c, 1);
                     86: }
                     87: 
                     88: PRIVATE int HTTPResponse_put_string (HTStream * me, CONST char * s)
                     89: {
                     90:     return HTTPResponse_put_block(me, s, strlen(s));
                     91: }
                     92: 
                     93: /*
                     94: **     Flushes data but doesn't free stream object
                     95: */
                     96: PRIVATE int HTTPResponse_flush (HTStream * me)
                     97: {
2.4     ! frystyk    98:     if (!me->transparent) {
        !            99:        int status = HTTPMakeResponse(me, me->request);
        !           100:        if (status != HT_OK) return status;
        !           101:     }
        !           102:     return (*me->target->isa->flush)(me->target);
2.1       frystyk   103: }
                    104: 
                    105: /*
                    106: **     Flushes data and frees stream object
                    107: */
                    108: PRIVATE int HTTPResponse_free (HTStream * me)
                    109: {
2.4     ! frystyk   110:     TTYPrint(TDEST, "TESTTESTTEST FREEING RESPONSE STREAM\n");
        !           111:     if (me->target) {
        !           112:        int status;
        !           113:        if (!me->transparent)
        !           114:            if ((status = HTTPMakeResponse(me, me->request)) != HT_OK)
        !           115:                return status;
        !           116:        if ((status = (*me->target->isa->_free)(me->target)) != HT_OK)
        !           117:            return status;
2.1       frystyk   118:     }
2.4     ! frystyk   119:     return HT_OK;
2.1       frystyk   120: }
                    121: 
                    122: PRIVATE int HTTPResponse_abort (HTStream * me, HTList * e)
                    123: {
                    124:     if (me->target) (*me->target->isa->abort)(me->target, e);
                    125:     if (PROT_TRACE) TTYPrint(TDEST, "HTTPResponse ABORTING...\n");
                    126:     return HT_ERROR;
                    127: }
                    128: 
                    129: /*     HTTPResponse Stream
                    130: **     -----------------
                    131: */
                    132: PRIVATE CONST HTStreamClass HTTPResponseClass =
                    133: {              
                    134:     "HTTPResponse",
                    135:     HTTPResponse_flush,
                    136:     HTTPResponse_free,
                    137:     HTTPResponse_abort,
                    138:     HTTPResponse_put_character,
                    139:     HTTPResponse_put_string,
                    140:     HTTPResponse_put_block
                    141: };
                    142: 
2.4     ! frystyk   143: /*
        !           144: **     This stream is responsible for generating a full HTTP/1.x response. It
        !           145: **     may either do so by forwarding a response directly from an origin 
        !           146: **     server (if we are proxying) - or it can generate the response itself.
        !           147: */
        !           148: PUBLIC HTStream * HTTPResponse_new (HTRequest *                request,
        !           149:                                    void *              param,
        !           150:                                    HTFormat            input_format,
        !           151:                                    HTFormat            output_format,
        !           152:                                    HTStream *          output_stream)
        !           153: {
        !           154:     HTStream * me = NULL;
        !           155:     HTdns * dns;
        !           156:     if (!request || !request->net) return HTErrorStream();
        !           157:     /*
        !           158:     ** If we have a HTTP 1.x response then forward untouched
        !           159:     */
        !           160:     if ((dns = request->net->dns)) {
        !           161:        char * s_class = HTDNS_serverClass(dns);
        !           162:        int version = HTDNS_serverVersion(dns);
        !           163:        /* We are not using the version info for the moment */
        !           164:        if (s_class && !strcasecomp(s_class, "http")) {
        !           165:            if (STREAM_TRACE) TTYPrint(TDEST, "HTTPResponse Direct output\n");
        !           166:            return output_stream;
        !           167:        }
        !           168:     }
        !           169:     if ((me = (HTStream *) calloc(1, sizeof(HTStream))) == NULL)
        !           170:        outofmem(__FILE__, "HTTPResponse_new");
2.1       frystyk   171:     me->isa = &HTTPResponseClass;
2.4     ! frystyk   172:     me->target = output_stream;    
2.1       frystyk   173:     me->request = request;
2.4     ! frystyk   174: 
        !           175:     TTYPrint(TDEST, "TESTTESTTEST CREATING RESPONSE STREAM\n");
        !           176: 
        !           177:     /* Here we should also check whether we have content length etc. */
        !           178: 
        !           179:     return me;
2.1       frystyk   180: }

Webmaster