Annotation of libwww/Library/src/HTMIMERq.c, revision 2.20
2.1 frystyk 1: /* HTMIMERq.c
2.10 frystyk 2: ** MIME ENTITY HEADERS GENERATION
2.1 frystyk 3: **
2.15 frystyk 4: ** (c) COPYRIGHT MIT 1995.
5: ** Please first read the full copyright statement in the file COPYRIGH.
2.20 ! frystyk 6: ** @(#) $Id: HTMIMERq.c,v 2.19 1996/07/02 22:54:44 frystyk Exp $
2.15 frystyk 7: **
2.1 frystyk 8: ** This module implements the output stream for MIME used for sending
2.10 frystyk 9: ** requests with a entity body to HTTP, NEWS, etc. or for generating
10: ** responses
2.1 frystyk 11: **
12: ** History:
13: ** Jan 95 HFN Written
14: */
15:
16: /* Library Includes */
2.14 frystyk 17: #include "sysdep.h"
2.1 frystyk 18: #include "HTUtils.h"
19: #include "HTString.h"
2.5 frystyk 20: #include "HTWWWStr.h"
2.1 frystyk 21: #include "HTParse.h"
22: #include "HTFormat.h"
2.7 frystyk 23: #include "HTAncMan.h"
2.1 frystyk 24: #include "HTNetMan.h"
25: #include "HTDNS.h"
26: #include "HTTCP.h"
2.2 frystyk 27: #include "HTHeader.h"
2.1 frystyk 28: #include "HTReqMan.h"
29: #include "HTTPReq.h" /* Implements */
30:
2.17 frystyk 31: #define PUTC(c) (*me->target->isa->put_character)(me->target, c)
32: #define PUTS(s) (*me->target->isa->put_string)(me->target, s)
2.1 frystyk 33: #define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l)
34:
35: struct _HTStream {
2.14 frystyk 36: const HTStreamClass * isa;
2.1 frystyk 37: HTStream * target;
38: HTRequest * request;
2.10 frystyk 39: BOOL endHeader;
2.1 frystyk 40: BOOL transparent;
41: };
42:
43: /* ------------------------------------------------------------------------- */
44: /* MIME Output Request Stream */
45: /* ------------------------------------------------------------------------- */
46:
47: /* MIMEMakeRequest
48: ** ---------------
2.10 frystyk 49: ** Generates the BODY parts of a MIME message.
2.1 frystyk 50: */
2.2 frystyk 51: PRIVATE int MIMEMakeRequest (HTStream * me, HTRequest * request)
2.1 frystyk 52: {
2.17 frystyk 53: char crlf[3];
2.10 frystyk 54: char linebuf[256]; /* @@@ */
2.11 frystyk 55: HTParentAnchor *entity = request->source_anchor ?
56: request->source_anchor : request->anchor;
2.17 frystyk 57: *crlf = CR; *(crlf+1) = LF; *(crlf+2) = '\0';
2.1 frystyk 58:
2.10 frystyk 59: if (request->EntityMask & HT_E_ALLOW) {
60: /* @@@@@@@@@@ */
61: }
2.17 frystyk 62: if (request->EntityMask&HT_E_CONTENT_ENCODING && entity->content_encoding){
63: BOOL first = YES;
64: HTList * cur = entity->content_encoding;
65: HTEncoding pres;
66: while ((pres = (HTEncoding) HTList_nextObject(cur))) {
67: if (first) {
68: PUTS("Content-Encoding: ");
69: first = NO;
70: } else
71: PUTC(',');
72: PUTS(HTAtom_name(pres));
73: }
74: if (!first) PUTBLOCK(crlf, 2);
2.1 frystyk 75: }
2.10 frystyk 76:
2.17 frystyk 77: if (request->EntityMask&HT_E_CONTENT_LANGUAGE && entity->content_language){
78: BOOL first = YES;
79: HTList * cur = entity->content_language;
80: HTLanguage pres;
81: while ((pres = (HTLanguage) HTList_nextObject(cur))) {
82: if (first) {
83: PUTS("Content-Language: ");
84: first = NO;
85: } else
86: PUTC(',');
87: PUTS(HTAtom_name(pres));
88: }
89: if (!first) PUTBLOCK(crlf, 2);
2.1 frystyk 90: }
2.20 ! frystyk 91: if (request->EntityMask & HT_E_CONTENT_LENGTH) {
! 92: if (entity->content_length >= 0) {
! 93: sprintf(linebuf, "Content-Length: %ld%c%c",
! 94: entity->content_length, CR, LF);
! 95: PUTBLOCK(linebuf, (int) strlen(linebuf));
! 96: } else {
! 97: HTEncoding chunked = HTAtom_for("chunked");
! 98: HTAnchor_setTransfer(entity, chunked);
! 99: }
2.10 frystyk 100: }
2.18 frystyk 101: if (request->EntityMask & HT_E_CTE && entity->transfer) {
2.20 ! frystyk 102: HTEncoding transfer = HTAnchor_transfer(entity);
! 103: if (!HTFormat_isUnityTransfer(transfer)) {
! 104: sprintf(linebuf, "Transfer-Encoding: %s%c%c",
! 105: HTAtom_name(transfer), CR, LF);
! 106: PUTBLOCK(linebuf, (int) strlen(linebuf));
! 107: }
2.1 frystyk 108: }
2.19 frystyk 109: if (request->EntityMask & HT_E_CONTENT_TYPE && entity->content_type &&
110: entity->content_type != WWW_UNKNOWN) {
111: HTAssocList * parameters = HTAnchor_formatParam(entity);
112:
113: /* Output the content type */
114: PUTS("Content-Type: ");
115: PUTS(HTAtom_name(entity->content_type));
116:
117: /* Add all parameters */
118: if (parameters) {
119: HTAssoc * pres;
120: while ((pres = (HTAssoc *) HTAssocList_nextObject(parameters))) {
121: PUTS(";");
122: PUTS(HTAssoc_name(pres));
123: PUTS("=");
124: PUTS(HTAssoc_value(pres));
125: }
126: }
127: PUTBLOCK(crlf, 2);
128: #if 0
2.10 frystyk 129: if (entity->charset) {
130: strcat(linebuf, "; charset=");
131: strcat(linebuf, HTAtom_name(entity->charset));
132: }
133: if (entity->level) {
134: strcat(linebuf, "; level=");
135: strcat(linebuf, HTAtom_name(entity->level));
136: }
137: len = strlen(linebuf);
138: *(linebuf+len) = CR;
139: *(linebuf+len+1) = LF;
140: *(linebuf+len+2) = '\0';
141: PUTBLOCK(linebuf, (int) len+2);
2.19 frystyk 142: #endif
2.10 frystyk 143: }
144: if (request->EntityMask & HT_E_DERIVED_FROM && entity->derived_from) {
145: sprintf(linebuf, "Derived-From: %s%c%c", entity->derived_from,
146: CR, LF);
2.2 frystyk 147: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 148: }
2.10 frystyk 149: if (request->EntityMask & HT_E_EXPIRES) {
150: if (entity->expires != -1) {
151: sprintf(linebuf, "Expires: %s%c%c",
152: HTDateTimeStr(&entity->expires, NO), CR,LF);
2.2 frystyk 153: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 154: }
2.10 frystyk 155: }
156: if (request->EntityMask & HT_E_LAST_MODIFIED) {
157: if (entity->last_modified != -1) {
158: sprintf(linebuf, "Last-Modified: %s%c%c",
159: HTDateTimeStr(&entity->last_modified, NO), CR,LF);
2.2 frystyk 160: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 161: }
2.10 frystyk 162: }
163: if (request->EntityMask & HT_E_LINK) { /* @@@@@@@@@@ */
2.1 frystyk 164:
2.10 frystyk 165: }
166: if (request->EntityMask & HT_E_TITLE) { /* @@@@@@@@@@ */
2.1 frystyk 167:
2.10 frystyk 168: }
169: if (request->EntityMask & HT_E_URI) { /* @@@@@@@@@@ */
2.1 frystyk 170:
171: }
2.10 frystyk 172: if (request->EntityMask & HT_E_VERSION && entity->version) {
173: sprintf(linebuf, "Version: %s%c%c", entity->version, CR, LF);
174: PUTBLOCK(linebuf, (int) strlen(linebuf));
175: }
176: if (me->endHeader) {
177: sprintf(linebuf, "%c%c", CR, LF); /* Blank line means "end" */
178: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.2 frystyk 179: }
2.20 ! frystyk 180:
! 181: /*
! 182: ** Now make sure that the body has the right format
! 183: */
! 184:
! 185: /* Handle any Transfer encoding */
! 186: {
! 187: HTEncoding transfer = HTAnchor_transfer(entity);
! 188: if (!HTFormat_isUnityTransfer(transfer)) {
! 189: if (STREAM_TRACE) HTTrace("Building.... C-T-E stack\n");
! 190: me->target = HTTransferCodingStack(transfer, me->target,
! 191: request, NULL, YES);
! 192: }
! 193: }
! 194:
! 195: /* Handle any Content Encoding */
! 196: {
! 197: HTList * cc = HTAnchor_encoding(entity);
! 198: if (cc) {
! 199: if (STREAM_TRACE) HTTrace("Building.... C-E stack\n");
! 200: me->target = HTContentDecodingStack(cc, me->target, request, NULL);
! 201: }
! 202: }
! 203:
2.13 eric 204: if (PROT_TRACE) HTTrace("MIME........ Generating Entity Headers\n");
2.2 frystyk 205: return HT_OK;
2.1 frystyk 206: }
207:
2.14 frystyk 208: PRIVATE int MIMERequest_put_block (HTStream * me, const char * b, int l)
2.1 frystyk 209: {
210: if (me->transparent)
211: return b ? PUTBLOCK(b, l) : HT_OK;
212: else {
213: MIMEMakeRequest(me, me->request);
2.9 frystyk 214: if (HTRequest_isDestination(me->request)) {
215: (*me->target->isa->flush)(me->target);
216: HTNet_setBytesWritten(me->request->net, 0);
2.1 frystyk 217: }
2.9 frystyk 218: me->transparent = YES;
2.2 frystyk 219: return b ? PUTBLOCK(b, l) : HT_OK;
2.1 frystyk 220: }
221: }
222:
223: PRIVATE int MIMERequest_put_character (HTStream * me, char c)
224: {
225: return MIMERequest_put_block(me, &c, 1);
226: }
227:
2.14 frystyk 228: PRIVATE int MIMERequest_put_string (HTStream * me, const char * s)
2.1 frystyk 229: {
230: return MIMERequest_put_block(me, s, strlen(s));
231: }
232:
233: /*
234: ** Flushes header but doesn't free stream object
235: */
236: PRIVATE int MIMERequest_flush (HTStream * me)
237: {
238: int status = MIMERequest_put_block(me, NULL, 0);
239: return status==HT_OK ? (*me->target->isa->flush)(me->target) : status;
240: }
241:
242: /*
243: ** Flushes data and frees stream object
244: */
245: PRIVATE int MIMERequest_free (HTStream * me)
246: {
247: int status = MIMERequest_flush(me);
248: if (status != HT_WOULD_BLOCK) {
249: if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
250: return HT_WOULD_BLOCK;
2.12 frystyk 251: HT_FREE(me);
2.1 frystyk 252: }
253: return status;
254: }
255:
2.4 frystyk 256: PRIVATE int MIMERequest_abort (HTStream * me, HTList * e)
2.1 frystyk 257: {
258: if (me->target) (*me->target->isa->abort)(me->target, e);
2.12 frystyk 259: HT_FREE(me);
2.13 eric 260: if (PROT_TRACE) HTTrace("MIMERequest. ABORTING...\n");
2.1 frystyk 261: return HT_ERROR;
262: }
263:
264: /* MIMERequest Stream
265: ** -----------------
266: */
2.14 frystyk 267: PRIVATE const HTStreamClass MIMERequestClass =
2.1 frystyk 268: {
269: "MIMERequest",
270: MIMERequest_flush,
271: MIMERequest_free,
272: MIMERequest_abort,
273: MIMERequest_put_character,
274: MIMERequest_put_string,
275: MIMERequest_put_block
276: };
277:
2.10 frystyk 278: PUBLIC HTStream * HTMIMERequest_new (HTRequest * request, HTStream * target,
279: BOOL endHeader)
2.1 frystyk 280: {
2.12 frystyk 281: HTStream * me;
282: if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
283: HT_OUTOFMEM("HTMIMERequest_new");
2.1 frystyk 284: me->isa = &MIMERequestClass;
285: me->target = target;
286: me->request = request;
2.10 frystyk 287: me->endHeader = endHeader;
2.1 frystyk 288: me->transparent = NO;
289: return me;
290: }
Webmaster