Annotation of libwww/Library/src/HTMIMERq.c, revision 2.2

2.1       frystyk     1: /*                                                                  HTMIMERq.c
                      2: **     MIME MESSAGE GENERATION
                      3: **
                      4: **     This module implements the output stream for MIME used for sending
                      5: **     requests with or without a entity body to HTTP, NEWS, etc.
                      6: **
                      7: ** History:
                      8: **     Jan 95 HFN      Written
                      9: */
                     10: 
                     11: /* Library Includes */
                     12: #include "tcp.h"
                     13: #include "HTUtils.h"
                     14: #include "HTString.h"
                     15: #include "HTParse.h"
                     16: #include "HTFormat.h"
                     17: #include "HTNetMan.h"
                     18: #include "HTDNS.h"
                     19: #include "HTTCP.h"
                     20: #include "HTWriter.h"
2.2     ! frystyk    21: #include "HTHeader.h"
2.1       frystyk    22: #include "HTReqMan.h"
                     23: #include "HTTPReq.h"                                          /* Implements */
                     24: 
                     25: #define MIME_VERSION   "MIME/1.0"
                     26: #define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l)
                     27: 
                     28: struct _HTStream {
                     29:     CONST HTStreamClass *      isa;
                     30:     HTStream *                 target;
                     31:     HTRequest *                        request;
                     32:     SOCKFD                     sockfd;
                     33:     int                                version;
                     34:     BOOL                       transparent;
                     35: };
                     36: 
                     37: /* ------------------------------------------------------------------------- */
                     38: /*                         MIME Output Request Stream                       */
                     39: /* ------------------------------------------------------------------------- */
                     40: 
                     41: /*     MIMEMakeRequest
                     42: **     ---------------
                     43: **     Makes a MIME/1.0 request header.
                     44: */
2.2     ! frystyk    45: PRIVATE int MIMEMakeRequest (HTStream * me, HTRequest * request)
2.1       frystyk    46: {
                     47:     char linebuf[256];
                     48:     HTParentAnchor *entity = (request->source && request->source->anchor) ?
                     49:        request->source->anchor : request->anchor;
                     50: 
                     51:     /* General Headers */
                     52:     if (request->GenMask & HT_DATE) {
                     53:        time_t local = time(NULL);
                     54:        sprintf(linebuf, "Date: %s%c%c", HTDateTimeStr(&local, NO), CR,LF);
2.2     ! frystyk    55:        PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk    56:     }
                     57:     if (request->GenMask & HT_FORWARDED) {
                     58:        /* @@@@@@ */
                     59:     }
                     60:     if (request->GenMask & HT_MESSAGE_ID) {
                     61:        CONST char *msgid = HTMessageIdStr();
                     62:        if (msgid) {
                     63:            sprintf(linebuf, "Message-ID: %s%c%c", msgid, CR, LF);
2.2     ! frystyk    64:            PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk    65:        }
                     66:     }
                     67:     if (request->GenMask & HT_MIME) {
                     68:        sprintf(linebuf, "MIME-Version: %s%c%c", MIME_VERSION, CR, LF);
2.2     ! frystyk    69:        PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk    70:     }
                     71:     if (request->GenMask & HT_CONNECTION) {
                     72:        sprintf(linebuf, "Connection: Keep-Alive%c%c", CR, LF);
2.2     ! frystyk    73:        PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk    74:     }
                     75:     if (request->RequestMask & HT_NO_CACHE) {
                     76:        sprintf(linebuf, "Pragma: %s%c%c", "no-cache", CR, LF);
2.2     ! frystyk    77:        PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk    78:     }
                     79: 
                     80:     /* Now put out entity headers if we are using PUT or POST. If we have a
                     81:     ** PostAnchor then we take the information from this and uses the
                     82:     ** destination anchor to contain the reply. Otherwise, we have created an
                     83:     ** anchor (using internal editing etc) and we can use the destination
                     84:     ** anchor directly.
                     85:     */
                     86:     if (request->method==METHOD_PUT || request->method==METHOD_POST) {
                     87:        if (request->EntityMask & HT_ALLOW) {
                     88:            /* @@@@@@@@@@ */
                     89:        }
                     90:        if (request->EntityMask & HT_CONTENT_ENCODING &&
                     91:            entity->content_encoding) {
                     92:            sprintf(linebuf, "Content-Encoding: %s%c%c",
                     93:                    HTAtom_name(entity->content_encoding), CR, LF);
2.2     ! frystyk    94:            PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk    95:        }
                     96: 
                     97:        /* @@@ SHOULD BE A LIST @@@ */
                     98:        if (request->EntityMask & HT_CONTENT_LANGUAGE &&
                     99:            entity->content_language) {
                    100:            sprintf(linebuf, "Content-Language: %s%c%c",
                    101:                    HTAtom_name(entity->content_language), CR, LF);
2.2     ! frystyk   102:            PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk   103:        }
                    104:        if (request->EntityMask & HT_CONTENT_LENGTH) {   /* Must be there!!! */
                    105:            sprintf(linebuf, "Content-Length: %ld%c%c",
                    106:                    entity->content_length, CR, LF);
2.2     ! frystyk   107:            PUTBLOCK(linebuf, (int) strlen(linebuf));   
2.1       frystyk   108:        }
                    109:        if (request->EntityMask & HT_CTE && entity->cte) {
                    110:            sprintf(linebuf, "Content-Transfer-Encoding: %s%c%c",
                    111:                    HTAtom_name(entity->cte), CR, LF);
2.2     ! frystyk   112:            PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk   113:        }
                    114:        if (request->EntityMask & HT_CONTENT_TYPE && entity->content_type) {
2.2     ! frystyk   115:            int len;
2.1       frystyk   116:            sprintf(linebuf, "Content-Type: %s",
                    117:                    HTAtom_name(entity->content_type));
                    118:            if (entity->charset) {
                    119:                strcat(linebuf, "; charset=");
                    120:                strcat(linebuf, HTAtom_name(entity->charset));
                    121:            }
                    122:            if (entity->level) {
                    123:                strcat(linebuf, "; level=");
                    124:                strcat(linebuf, HTAtom_name(entity->level));
                    125:            }
2.2     ! frystyk   126:            len = strlen(linebuf);
        !           127:            *(linebuf+len) = CR;
        !           128:            *(linebuf+len+1) = LF;
        !           129:            *(linebuf+len+2) = '\0';
        !           130:            PUTBLOCK(linebuf, (int) len+2);
2.1       frystyk   131:        }
                    132:        if (request->EntityMask & HT_DERIVED_FROM && entity->derived_from) {
                    133:            sprintf(linebuf, "Derived-From: %s%c%c", entity->derived_from,
                    134:                    CR, LF);
2.2     ! frystyk   135:            PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk   136:        }
                    137:        if (request->EntityMask & HT_EXPIRES) {
                    138:            if (entity->expires != -1) {
                    139:                sprintf(linebuf, "Expires: %s%c%c",
                    140:                        HTDateTimeStr(&entity->expires, NO), CR,LF);
2.2     ! frystyk   141:                PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk   142:            }
                    143:        }
                    144:        if (request->EntityMask & HT_LAST_MODIFIED) {
                    145:            if (entity->last_modified != -1) {
                    146:                sprintf(linebuf, "Last-Modified: %s%c%c",
                    147:                        HTDateTimeStr(&entity->last_modified, NO), CR,LF);
2.2     ! frystyk   148:                PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk   149:            }
                    150:        }
                    151:        if (request->EntityMask & HT_LINK) {            /* @@@@@@@@@@ */
                    152: 
                    153:        }
                    154:        if (request->EntityMask & HT_TITLE) {           /* @@@@@@@@@@ */
                    155: 
                    156:        }
                    157:        if (request->EntityMask & HT_URI) {             /* @@@@@@@@@@ */
                    158: 
                    159:        }
                    160:        if (request->EntityMask & HT_VERSION && entity->version) {
                    161:            sprintf(linebuf, "Version: %s%c%c", entity->version, CR, LF);
2.2     ! frystyk   162:            PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk   163:        }
                    164:     }
                    165: 
                    166:     /* Put out extra information if any */
2.2     ! frystyk   167:     {
        !           168:        HTList * list;
        !           169:        BOOL override;
        !           170:        if ((list = HTRequest_generator(request, &override))) {
        !           171:            HTList *local = list;
        !           172:            HTPostCallback *pres;
        !           173:            if (STREAM_TRACE) fprintf(TDEST,"MIMEGen..... Extra local\n");
        !           174:            while ((pres = (HTPostCallback *) HTList_nextObject(local)))
        !           175:                (*pres)(request, me->target);
        !           176:        } else if (!override && (list = HTHeader_generator())) {
        !           177:            HTList *global = list;
        !           178:            HTPostCallback *pres;
        !           179:            if (STREAM_TRACE) fprintf(TDEST,"MIMEGen..... Extra global\n");
        !           180:            while ((pres = (HTPostCallback *) HTList_nextObject(global)))
        !           181:                (*pres)(request, me->target);
        !           182:        }
        !           183:     }
2.1       frystyk   184: 
                    185:     /* Blank line means "end" */
2.2     ! frystyk   186:     sprintf(linebuf, "%c%c", CR, LF);
        !           187:     PUTBLOCK(linebuf, (int) strlen(linebuf));
        !           188:     return HT_OK;
2.1       frystyk   189: }
                    190: 
                    191: PRIVATE int MIMERequest_put_block (HTStream * me, CONST char * b, int l)
                    192: {
                    193:     if (me->transparent)
                    194:        return b ? PUTBLOCK(b, l) : HT_OK;
                    195:     else {
                    196:        MIMEMakeRequest(me, me->request);
2.2     ! frystyk   197: #if 0
2.1       frystyk   198:        if ((status = PUTBLOCK(HTChunkData(me->buffer),
                    199:                               HTChunkSize(me->buffer))) == HT_OK) {
                    200:            me->transparent = YES;
                    201:            return b ? PUTBLOCK(b, l) : HT_OK;
                    202:        }
2.2     ! frystyk   203: #endif
        !           204:        me->transparent = YES;
        !           205:        return b ? PUTBLOCK(b, l) : HT_OK;
2.1       frystyk   206:     }
                    207: }
                    208: 
                    209: PRIVATE int MIMERequest_put_character (HTStream * me, char c)
                    210: {
                    211:     return MIMERequest_put_block(me, &c, 1);
                    212: }
                    213: 
                    214: PRIVATE int MIMERequest_put_string (HTStream * me, CONST char * s)
                    215: {
                    216:     return MIMERequest_put_block(me, s, strlen(s));
                    217: }
                    218: 
                    219: /*
                    220: **     Flushes header but doesn't free stream object
                    221: */
                    222: PRIVATE int MIMERequest_flush (HTStream * me)
                    223: {
                    224:     int status = MIMERequest_put_block(me, NULL, 0);
                    225:     return status==HT_OK ? (*me->target->isa->flush)(me->target) : status;
                    226: }
                    227: 
                    228: /*
                    229: **     Flushes data and frees stream object
                    230: */
                    231: PRIVATE int MIMERequest_free (HTStream * me)
                    232: {
                    233:     int status = MIMERequest_flush(me);
                    234:     if (status != HT_WOULD_BLOCK) {
                    235:        if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
                    236:            return HT_WOULD_BLOCK;
                    237:        free(me);
                    238:     }
                    239:     return status;
                    240: }
                    241: 
                    242: PRIVATE int MIMERequest_abort (HTStream * me, HTError e)
                    243: {
                    244:     if (me->target) (*me->target->isa->abort)(me->target, e);
                    245:     free(me);
                    246:     if (PROT_TRACE) fprintf(TDEST, "MIMERequest. ABORTING...\n");
                    247:     return HT_ERROR;
                    248: }
                    249: 
                    250: /*     MIMERequest Stream
                    251: **     -----------------
                    252: */
                    253: PRIVATE CONST HTStreamClass MIMERequestClass =
                    254: {              
                    255:     "MIMERequest",
                    256:     MIMERequest_flush,
                    257:     MIMERequest_free,
                    258:     MIMERequest_abort,
                    259:     MIMERequest_put_character,
                    260:     MIMERequest_put_string,
                    261:     MIMERequest_put_block
                    262: };
                    263: 
                    264: PUBLIC HTStream * HTMIMERequest_new (HTRequest * request, HTStream * target)
                    265: {
                    266:     HTStream * me = (HTStream *) calloc(1, sizeof(HTStream));
                    267:     if (!me) outofmem(__FILE__, "HTMIMERequest_new");
                    268:     me->isa = &MIMERequestClass;
                    269:     me->target = target;
                    270:     me->request = request;
                    271:     me->transparent = NO;
                    272:     return me;
                    273: }

Webmaster