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

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 */
2.8       frystyk    54:     if (request->GenMask & HT_G_DATE) {
2.1       frystyk    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:     }
2.8       frystyk    59:     if (request->GenMask & HT_G_FORWARDED) {
2.1       frystyk    60:        /* @@@@@@ */
                     61:     }
2.8       frystyk    62:     if (request->GenMask & HT_G_MESSAGE_ID) {
2.1       frystyk    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:     }
2.8       frystyk    69:     if (request->GenMask & HT_G_MIME) {
2.1       frystyk    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:     }
2.8       frystyk    73:     if (request->GenMask & HT_G_CONNECTION) {
2.1       frystyk    74:        sprintf(linebuf, "Connection: Keep-Alive%c%c", CR, LF);
2.2       frystyk    75:        PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk    76:     }
2.8       frystyk    77:     if (request->RequestMask & HT_G_NO_CACHE) {
2.1       frystyk    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: 
2.8       frystyk    82:     /* Now put out entity headers if we are using PUT or POST or is a server
                     83:     ** If we have a
2.1       frystyk    84:     ** PostAnchor then we take the information from this and uses the
                     85:     ** destination anchor to contain the reply. Otherwise, we have created an
                     86:     ** anchor (using internal editing etc) and we can use the destination
                     87:     ** anchor directly.
                     88:     */
2.8       frystyk    89:     if (HTMethod_hasEntity(request->method) || request->access) {
                     90:        if (request->EntityMask & HT_E_ALLOW) {
2.1       frystyk    91:            /* @@@@@@@@@@ */
                     92:        }
2.8       frystyk    93:        if (request->EntityMask & HT_E_CONTENT_ENCODING &&
2.1       frystyk    94:            entity->content_encoding) {
                     95:            sprintf(linebuf, "Content-Encoding: %s%c%c",
                     96:                    HTAtom_name(entity->content_encoding), CR, LF);
2.2       frystyk    97:            PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk    98:        }
                     99: 
                    100:        /* @@@ SHOULD BE A LIST @@@ */
2.8       frystyk   101:        if (request->EntityMask & HT_E_CONTENT_LANGUAGE &&
2.1       frystyk   102:            entity->content_language) {
                    103:            sprintf(linebuf, "Content-Language: %s%c%c",
                    104:                    HTAtom_name(entity->content_language), CR, LF);
2.2       frystyk   105:            PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk   106:        }
2.8       frystyk   107:        if (request->EntityMask & HT_E_CONTENT_LENGTH) { /* Must be there!!! */
2.1       frystyk   108:            sprintf(linebuf, "Content-Length: %ld%c%c",
                    109:                    entity->content_length, CR, LF);
2.2       frystyk   110:            PUTBLOCK(linebuf, (int) strlen(linebuf));   
2.1       frystyk   111:        }
2.8       frystyk   112:        if (request->EntityMask & HT_E_CTE && entity->cte) {
2.1       frystyk   113:            sprintf(linebuf, "Content-Transfer-Encoding: %s%c%c",
                    114:                    HTAtom_name(entity->cte), CR, LF);
2.2       frystyk   115:            PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk   116:        }
2.8       frystyk   117:        if (request->EntityMask & HT_E_CONTENT_TYPE && entity->content_type) {
2.2       frystyk   118:            int len;
2.1       frystyk   119:            sprintf(linebuf, "Content-Type: %s",
                    120:                    HTAtom_name(entity->content_type));
                    121:            if (entity->charset) {
                    122:                strcat(linebuf, "; charset=");
                    123:                strcat(linebuf, HTAtom_name(entity->charset));
                    124:            }
                    125:            if (entity->level) {
                    126:                strcat(linebuf, "; level=");
                    127:                strcat(linebuf, HTAtom_name(entity->level));
                    128:            }
2.2       frystyk   129:            len = strlen(linebuf);
                    130:            *(linebuf+len) = CR;
                    131:            *(linebuf+len+1) = LF;
                    132:            *(linebuf+len+2) = '\0';
                    133:            PUTBLOCK(linebuf, (int) len+2);
2.1       frystyk   134:        }
2.8       frystyk   135:        if (request->EntityMask & HT_E_DERIVED_FROM && entity->derived_from) {
2.1       frystyk   136:            sprintf(linebuf, "Derived-From: %s%c%c", entity->derived_from,
                    137:                    CR, LF);
2.2       frystyk   138:            PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk   139:        }
2.8       frystyk   140:        if (request->EntityMask & HT_E_EXPIRES) {
2.1       frystyk   141:            if (entity->expires != -1) {
                    142:                sprintf(linebuf, "Expires: %s%c%c",
                    143:                        HTDateTimeStr(&entity->expires, NO), CR,LF);
2.2       frystyk   144:                PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk   145:            }
                    146:        }
2.8       frystyk   147:        if (request->EntityMask & HT_E_LAST_MODIFIED) {
2.1       frystyk   148:            if (entity->last_modified != -1) {
                    149:                sprintf(linebuf, "Last-Modified: %s%c%c",
                    150:                        HTDateTimeStr(&entity->last_modified, NO), CR,LF);
2.2       frystyk   151:                PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk   152:            }
                    153:        }
2.8       frystyk   154:        if (request->EntityMask & HT_E_LINK) {          /* @@@@@@@@@@ */
2.1       frystyk   155: 
                    156:        }
2.8       frystyk   157:        if (request->EntityMask & HT_E_TITLE) {         /* @@@@@@@@@@ */
2.1       frystyk   158: 
                    159:        }
2.8       frystyk   160:        if (request->EntityMask & HT_E_URI) {           /* @@@@@@@@@@ */
2.1       frystyk   161: 
                    162:        }
2.8       frystyk   163:        if (request->EntityMask & HT_E_VERSION && entity->version) {
2.1       frystyk   164:            sprintf(linebuf, "Version: %s%c%c", entity->version, CR, LF);
2.2       frystyk   165:            PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1       frystyk   166:        }
                    167:     }
                    168: 
                    169:     /* Put out extra information if any */
2.2       frystyk   170:     {
                    171:        HTList * list;
                    172:        BOOL override;
                    173:        if ((list = HTRequest_generator(request, &override))) {
                    174:            HTList *local = list;
                    175:            HTPostCallback *pres;
2.3       frystyk   176:            if (STREAM_TRACE) TTYPrint(TDEST,"MIMEGen..... Extra local\n");
2.2       frystyk   177:            while ((pres = (HTPostCallback *) HTList_nextObject(local)))
                    178:                (*pres)(request, me->target);
                    179:        } else if (!override && (list = HTHeader_generator())) {
                    180:            HTList *global = list;
                    181:            HTPostCallback *pres;
2.3       frystyk   182:            if (STREAM_TRACE) TTYPrint(TDEST,"MIMEGen..... Extra global\n");
2.2       frystyk   183:            while ((pres = (HTPostCallback *) HTList_nextObject(global)))
                    184:                (*pres)(request, me->target);
                    185:        }
                    186:     }
2.1       frystyk   187: 
                    188:     /* Blank line means "end" */
2.2       frystyk   189:     sprintf(linebuf, "%c%c", CR, LF);
                    190:     PUTBLOCK(linebuf, (int) strlen(linebuf));
                    191:     return HT_OK;
2.1       frystyk   192: }
                    193: 
                    194: PRIVATE int MIMERequest_put_block (HTStream * me, CONST char * b, int l)
                    195: {
                    196:     if (me->transparent)
                    197:        return b ? PUTBLOCK(b, l) : HT_OK;
                    198:     else {
                    199:        MIMEMakeRequest(me, me->request);
2.8.2.1 ! frystyk   200:        if (HTRequest_isDestination(me->request)) {
        !           201:            (*me->target->isa->flush)(me->target);
        !           202:            HTNet_setBytesWritten(me->request->net, 0);
2.1       frystyk   203:        }
2.8.2.1 ! frystyk   204:        me->transparent = YES;  
2.2       frystyk   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: 
2.4       frystyk   242: PRIVATE int MIMERequest_abort (HTStream * me, HTList * e)
2.1       frystyk   243: {
                    244:     if (me->target) (*me->target->isa->abort)(me->target, e);
                    245:     free(me);
2.3       frystyk   246:     if (PROT_TRACE) TTYPrint(TDEST, "MIMERequest. ABORTING...\n");
2.1       frystyk   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