Annotation of libwww/Library/src/HTMIMERq.c, revision 2.33
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.33 ! frystyk 6: ** @(#) $Id: HTMIMERq.c,v 2.32 1998/02/27 18:35:47 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:
2.27 frystyk 38: #define HT_MAX_WAIT 8 /* Max number of secs to wait for PUT */
2.25 frystyk 39:
2.32 frystyk 40: PRIVATE int MIMERequest_put_block (HTStream * me, const char * b, int l);
41:
2.1 frystyk 42: /* ------------------------------------------------------------------------- */
43: /* MIME Output Request Stream */
44: /* ------------------------------------------------------------------------- */
45:
46: /* MIMEMakeRequest
47: ** ---------------
2.10 frystyk 48: ** Generates the BODY parts of a MIME message.
2.1 frystyk 49: */
2.2 frystyk 50: PRIVATE int MIMEMakeRequest (HTStream * me, HTRequest * request)
2.1 frystyk 51: {
2.17 frystyk 52: char crlf[3];
2.10 frystyk 53: char linebuf[256]; /* @@@ */
2.21 frystyk 54: HTParentAnchor * entity = HTRequest_entityAnchor(request);
55: HTEnHd EntityMask = HTRequest_enHd(request);
2.17 frystyk 56: *crlf = CR; *(crlf+1) = LF; *(crlf+2) = '\0';
2.1 frystyk 57:
2.21 frystyk 58: if (EntityMask & HT_E_ALLOW) {
2.10 frystyk 59: /* @@@@@@@@@@ */
60: }
2.21 frystyk 61: if (EntityMask & HT_E_CONTENT_ENCODING && entity->content_encoding){
2.17 frystyk 62: BOOL first = YES;
63: HTList * cur = entity->content_encoding;
64: HTEncoding pres;
65: while ((pres = (HTEncoding) HTList_nextObject(cur))) {
66: if (first) {
67: PUTS("Content-Encoding: ");
68: first = NO;
69: } else
70: PUTC(',');
71: PUTS(HTAtom_name(pres));
72: }
73: if (!first) PUTBLOCK(crlf, 2);
2.1 frystyk 74: }
2.10 frystyk 75:
2.21 frystyk 76: if (EntityMask & HT_E_CONTENT_LANGUAGE && entity->content_language){
2.17 frystyk 77: BOOL first = YES;
78: HTList * cur = entity->content_language;
79: HTLanguage pres;
80: while ((pres = (HTLanguage) HTList_nextObject(cur))) {
81: if (first) {
82: PUTS("Content-Language: ");
83: first = NO;
84: } else
85: PUTC(',');
86: PUTS(HTAtom_name(pres));
87: }
88: if (!first) PUTBLOCK(crlf, 2);
2.1 frystyk 89: }
2.21 frystyk 90: if (EntityMask & HT_E_CONTENT_LENGTH) {
2.20 frystyk 91: if (entity->content_length >= 0) {
92: sprintf(linebuf, "Content-Length: %ld%c%c",
93: entity->content_length, CR, LF);
94: PUTBLOCK(linebuf, (int) strlen(linebuf));
95: } else {
96: HTEncoding chunked = HTAtom_for("chunked");
97: HTAnchor_setTransfer(entity, chunked);
98: }
2.10 frystyk 99: }
2.21 frystyk 100: if (EntityMask & HT_E_CTE && entity->transfer) {
2.20 frystyk 101: HTEncoding transfer = HTAnchor_transfer(entity);
102: if (!HTFormat_isUnityTransfer(transfer)) {
2.31 frystyk 103: sprintf(linebuf, "Content-Transfer-Encoding: %s%c%c",
2.20 frystyk 104: HTAtom_name(transfer), CR, LF);
105: PUTBLOCK(linebuf, (int) strlen(linebuf));
106: }
2.1 frystyk 107: }
2.33 ! frystyk 108: if (EntityMask & HT_E_CONTENT_TYPE && entity->content_type) {
! 109: HTFormat format = entity->content_type != WWW_UNKNOWN ?
! 110: entity->content_type : WWW_BINARY;
2.19 frystyk 111: HTAssocList * parameters = HTAnchor_formatParam(entity);
112:
113: /* Output the content type */
114: PUTS("Content-Type: ");
2.33 ! frystyk 115: PUTS(HTAtom_name(format));
2.19 frystyk 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);
2.10 frystyk 128: }
2.21 frystyk 129: if (EntityMask & HT_E_DERIVED_FROM && entity->derived_from) {
2.10 frystyk 130: sprintf(linebuf, "Derived-From: %s%c%c", entity->derived_from,
131: CR, LF);
2.2 frystyk 132: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 133: }
2.21 frystyk 134: if (EntityMask & HT_E_EXPIRES) {
2.10 frystyk 135: if (entity->expires != -1) {
136: sprintf(linebuf, "Expires: %s%c%c",
137: HTDateTimeStr(&entity->expires, NO), CR,LF);
2.2 frystyk 138: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 139: }
2.10 frystyk 140: }
2.21 frystyk 141: if (EntityMask & HT_E_LAST_MODIFIED) {
2.10 frystyk 142: if (entity->last_modified != -1) {
143: sprintf(linebuf, "Last-Modified: %s%c%c",
144: HTDateTimeStr(&entity->last_modified, NO), CR,LF);
2.2 frystyk 145: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 146: }
2.10 frystyk 147: }
2.21 frystyk 148: if (EntityMask & HT_E_LINK) { /* @@@@@@@@@@ */
2.1 frystyk 149:
2.10 frystyk 150: }
2.21 frystyk 151: if (EntityMask & HT_E_TITLE) { /* @@@@@@@@@@ */
2.1 frystyk 152:
2.10 frystyk 153: }
2.21 frystyk 154: if (EntityMask & HT_E_URI) { /* @@@@@@@@@@ */
2.1 frystyk 155:
156: }
2.21 frystyk 157: if (EntityMask & HT_E_VERSION && entity->version) {
2.10 frystyk 158: sprintf(linebuf, "Version: %s%c%c", entity->version, CR, LF);
159: PUTBLOCK(linebuf, (int) strlen(linebuf));
160: }
161: if (me->endHeader) {
162: sprintf(linebuf, "%c%c", CR, LF); /* Blank line means "end" */
163: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.2 frystyk 164: }
2.20 frystyk 165:
166: /*
167: ** Now make sure that the body has the right format
168: */
169:
170: /* Handle any Transfer encoding */
171: {
172: HTEncoding transfer = HTAnchor_transfer(entity);
173: if (!HTFormat_isUnityTransfer(transfer)) {
174: if (STREAM_TRACE) HTTrace("Building.... C-T-E stack\n");
175: me->target = HTTransferCodingStack(transfer, me->target,
176: request, NULL, YES);
177: }
178: }
179:
180: /* Handle any Content Encoding */
181: {
182: HTList * cc = HTAnchor_encoding(entity);
183: if (cc) {
184: if (STREAM_TRACE) HTTrace("Building.... C-E stack\n");
2.33 ! frystyk 185: me->target = HTContentEncodingStack(cc, me->target, request, NULL);
2.20 frystyk 186: }
187: }
188:
2.13 eric 189: if (PROT_TRACE) HTTrace("MIME........ Generating Entity Headers\n");
2.2 frystyk 190: return HT_OK;
2.1 frystyk 191: }
192:
2.32 frystyk 193: /*
194: ** Flushes header but doesn't free stream object
195: */
196: PRIVATE int MIMERequest_flush (HTStream * me)
197: {
198: int status = MIMERequest_put_block(me, NULL, 0);
199: return status==HT_OK ? (*me->target->isa->flush)(me->target) : status;
200: }
201:
2.14 frystyk 202: PRIVATE int MIMERequest_put_block (HTStream * me, const char * b, int l)
2.1 frystyk 203: {
2.23 frystyk 204: HTNet * net = HTRequest_net(me->request);
2.32 frystyk 205: if (!me->transparent) {
2.1 frystyk 206: MIMEMakeRequest(me, me->request);
2.9 frystyk 207: me->transparent = YES;
2.22 frystyk 208:
209: /*
2.32 frystyk 210: ** First we only send the header
2.22 frystyk 211: */
212: if (HTMethod_hasEntity(HTRequest_method(me->request))) {
213: HTHost * host = HTNet_host(net);
214: char * class = HTHost_class(host);
2.23 frystyk 215: if (class && !strcmp(class, "http")) {
2.32 frystyk 216: MIMERequest_flush(me);
217: return HT_PAUSE;
2.22 frystyk 218: }
219: }
2.1 frystyk 220: }
2.32 frystyk 221:
2.23 frystyk 222: /* Check if we have written it all */
223: if (b) {
224: HTParentAnchor * entity = HTRequest_entityAnchor(me->request);
225: long cl = HTAnchor_length(entity);
226: return (cl>=0 && HTNet_bytesWritten(net) >= cl) ?
227: HT_LOADED : PUTBLOCK(b, l);
228: }
229: return HT_OK;
2.1 frystyk 230: }
231:
232: PRIVATE int MIMERequest_put_character (HTStream * me, char c)
233: {
234: return MIMERequest_put_block(me, &c, 1);
235: }
236:
2.14 frystyk 237: PRIVATE int MIMERequest_put_string (HTStream * me, const char * s)
2.1 frystyk 238: {
239: return MIMERequest_put_block(me, s, strlen(s));
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