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