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

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

Webmaster