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