Annotation of libwww/Library/src/HTMIMERq.c, revision 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"
        !            15: #include "HTParse.h"
        !            16: #include "HTFormat.h"
        !            17: #include "HTNetMan.h"
        !            18: #include "HTDNS.h"
        !            19: #include "HTTCP.h"
        !            20: #include "HTWriter.h"
        !            21: #include "HTReqMan.h"
        !            22: #include "HTChunk.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:     HTChunk *                          buffer;
        !            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: */
        !            46: PRIVATE void MIMEMakeRequest (HTStream * me, HTRequest * request)
        !            47: {
        !            48:     char linebuf[256];
        !            49:     HTChunk *header = me->buffer;
        !            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);
        !            57:        HTChunkPuts(header, linebuf);
        !            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);
        !            66:            HTChunkPuts(header, linebuf);
        !            67:        }
        !            68:     }
        !            69:     if (request->GenMask & HT_MIME) {
        !            70:        sprintf(linebuf, "MIME-Version: %s%c%c", MIME_VERSION, CR, LF);
        !            71:        HTChunkPuts(header, linebuf);
        !            72:     }
        !            73:     if (request->GenMask & HT_CONNECTION) {
        !            74:        sprintf(linebuf, "Connection: Keep-Alive%c%c", CR, LF);
        !            75:        HTChunkPuts(header, linebuf);
        !            76:     }
        !            77:     if (request->RequestMask & HT_NO_CACHE) {
        !            78:        sprintf(linebuf, "Pragma: %s%c%c", "no-cache", CR, LF);
        !            79:        HTChunkPuts(header, linebuf);
        !            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);
        !            96:            HTChunkPuts(header, linebuf);
        !            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);
        !           104:            HTChunkPuts(header, linebuf);
        !           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);
        !           109:            HTChunkPuts(header, linebuf);       
        !           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);
        !           114:            HTChunkPuts(header, linebuf);
        !           115:        }
        !           116:        if (request->EntityMask & HT_CONTENT_TYPE && entity->content_type) {
        !           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:            }
        !           127:            HTChunkPuts(header, linebuf);
        !           128:            HTChunkPutc(header, CR);
        !           129:            HTChunkPutc(header, LF);
        !           130:        }
        !           131:        if (request->EntityMask & HT_DERIVED_FROM && entity->derived_from) {
        !           132:            sprintf(linebuf, "Derived-From: %s%c%c", entity->derived_from,
        !           133:                    CR, LF);
        !           134:            HTChunkPuts(header, linebuf);
        !           135:        }
        !           136:        if (request->EntityMask & HT_EXPIRES) {
        !           137:            if (entity->expires != -1) {
        !           138:                sprintf(linebuf, "Expires: %s%c%c",
        !           139:                        HTDateTimeStr(&entity->expires, NO), CR,LF);
        !           140:                HTChunkPuts(header, linebuf);
        !           141:            }
        !           142:        }
        !           143:        if (request->EntityMask & HT_LAST_MODIFIED) {
        !           144:            if (entity->last_modified != -1) {
        !           145:                sprintf(linebuf, "Last-Modified: %s%c%c",
        !           146:                        HTDateTimeStr(&entity->last_modified, NO), CR,LF);
        !           147:                HTChunkPuts(header, linebuf);
        !           148:            }
        !           149:        }
        !           150:        if (request->EntityMask & HT_LINK) {            /* @@@@@@@@@@ */
        !           151: 
        !           152:        }
        !           153:        if (request->EntityMask & HT_TITLE) {           /* @@@@@@@@@@ */
        !           154: 
        !           155:        }
        !           156:        if (request->EntityMask & HT_URI) {             /* @@@@@@@@@@ */
        !           157: 
        !           158:        }
        !           159:        if (request->EntityMask & HT_VERSION && entity->version) {
        !           160:            sprintf(linebuf, "Version: %s%c%c", entity->version, CR, LF);
        !           161:            HTChunkPuts(header, linebuf);
        !           162:        }
        !           163:     }
        !           164: 
        !           165:     /* Put out extra information if any */
        !           166:     if (request->ExtraHeaders) HTChunkPuts(header, request->ExtraHeaders);
        !           167: 
        !           168:     /* Blank line means "end" */
        !           169:     HTChunkPutc(header, CR);
        !           170:     HTChunkPutc(header, LF);
        !           171:     if (PROT_TRACE) fprintf(TDEST, "MIME Tx..... %s", header->data);
        !           172: }
        !           173: 
        !           174: PRIVATE int MIMERequest_put_block (HTStream * me, CONST char * b, int l)
        !           175: {
        !           176:     if (me->transparent)
        !           177:        return b ? PUTBLOCK(b, l) : HT_OK;
        !           178:     else {
        !           179:        int status;
        !           180:        MIMEMakeRequest(me, me->request);
        !           181:        if ((status = PUTBLOCK(HTChunkData(me->buffer),
        !           182:                               HTChunkSize(me->buffer))) == HT_OK) {
        !           183:            me->transparent = YES;
        !           184:            return b ? PUTBLOCK(b, l) : HT_OK;
        !           185:        }
        !           186:        return status;
        !           187:     }
        !           188: }
        !           189: 
        !           190: PRIVATE int MIMERequest_put_character (HTStream * me, char c)
        !           191: {
        !           192:     return MIMERequest_put_block(me, &c, 1);
        !           193: }
        !           194: 
        !           195: PRIVATE int MIMERequest_put_string (HTStream * me, CONST char * s)
        !           196: {
        !           197:     return MIMERequest_put_block(me, s, strlen(s));
        !           198: }
        !           199: 
        !           200: /*
        !           201: **     Flushes header but doesn't free stream object
        !           202: */
        !           203: PRIVATE int MIMERequest_flush (HTStream * me)
        !           204: {
        !           205:     int status = MIMERequest_put_block(me, NULL, 0);
        !           206:     return status==HT_OK ? (*me->target->isa->flush)(me->target) : status;
        !           207: }
        !           208: 
        !           209: /*
        !           210: **     Flushes data and frees stream object
        !           211: */
        !           212: PRIVATE int MIMERequest_free (HTStream * me)
        !           213: {
        !           214:     int status = MIMERequest_flush(me);
        !           215:     if (status != HT_WOULD_BLOCK) {
        !           216:        if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
        !           217:            return HT_WOULD_BLOCK;
        !           218:        HTChunkFree(me->buffer);
        !           219:        free(me);
        !           220:     }
        !           221:     return status;
        !           222: }
        !           223: 
        !           224: PRIVATE int MIMERequest_abort (HTStream * me, HTError e)
        !           225: {
        !           226:     if (me->target) (*me->target->isa->abort)(me->target, e);
        !           227:     HTChunkFree(me->buffer);
        !           228:     free(me);
        !           229:     if (PROT_TRACE) fprintf(TDEST, "MIMERequest. ABORTING...\n");
        !           230:     return HT_ERROR;
        !           231: }
        !           232: 
        !           233: /*     MIMERequest Stream
        !           234: **     -----------------
        !           235: */
        !           236: PRIVATE CONST HTStreamClass MIMERequestClass =
        !           237: {              
        !           238:     "MIMERequest",
        !           239:     MIMERequest_flush,
        !           240:     MIMERequest_free,
        !           241:     MIMERequest_abort,
        !           242:     MIMERequest_put_character,
        !           243:     MIMERequest_put_string,
        !           244:     MIMERequest_put_block
        !           245: };
        !           246: 
        !           247: PUBLIC HTStream * HTMIMERequest_new (HTRequest * request, HTStream * target)
        !           248: {
        !           249:     HTStream * me = (HTStream *) calloc(1, sizeof(HTStream));
        !           250:     if (!me) outofmem(__FILE__, "HTMIMERequest_new");
        !           251:     me->isa = &MIMERequestClass;
        !           252:     me->target = target;
        !           253:     me->request = request;
        !           254:     me->buffer = HTChunkCreate(256);
        !           255:     me->transparent = NO;
        !           256:     return me;
        !           257: }

Webmaster