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

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

Webmaster