Annotation of libwww/Library/src/HTMIMERq.c, revision 2.7
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"
2.5 frystyk 15: #include "HTWWWStr.h"
2.1 frystyk 16: #include "HTParse.h"
17: #include "HTFormat.h"
2.7 ! frystyk 18: #include "HTAncMan.h"
2.1 frystyk 19: #include "HTNetMan.h"
20: #include "HTDNS.h"
21: #include "HTTCP.h"
22: #include "HTWriter.h"
2.2 frystyk 23: #include "HTHeader.h"
2.1 frystyk 24: #include "HTReqMan.h"
25: #include "HTTPReq.h" /* Implements */
26:
27: #define MIME_VERSION "MIME/1.0"
28: #define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l)
29:
30: struct _HTStream {
31: CONST HTStreamClass * isa;
32: HTStream * target;
33: HTRequest * request;
2.6 frystyk 34: SOCKET sockfd;
2.1 frystyk 35: int version;
36: BOOL transparent;
37: };
38:
39: /* ------------------------------------------------------------------------- */
40: /* MIME Output Request Stream */
41: /* ------------------------------------------------------------------------- */
42:
43: /* MIMEMakeRequest
44: ** ---------------
45: ** Makes a MIME/1.0 request header.
46: */
2.2 frystyk 47: PRIVATE int MIMEMakeRequest (HTStream * me, HTRequest * request)
2.1 frystyk 48: {
49: char linebuf[256];
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);
2.2 frystyk 57: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 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);
2.2 frystyk 66: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 67: }
68: }
69: if (request->GenMask & HT_MIME) {
70: sprintf(linebuf, "MIME-Version: %s%c%c", MIME_VERSION, CR, LF);
2.2 frystyk 71: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 72: }
73: if (request->GenMask & HT_CONNECTION) {
74: sprintf(linebuf, "Connection: Keep-Alive%c%c", CR, LF);
2.2 frystyk 75: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 76: }
77: if (request->RequestMask & HT_NO_CACHE) {
78: sprintf(linebuf, "Pragma: %s%c%c", "no-cache", CR, LF);
2.2 frystyk 79: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 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);
2.2 frystyk 96: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 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);
2.2 frystyk 104: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 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);
2.2 frystyk 109: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 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);
2.2 frystyk 114: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 115: }
116: if (request->EntityMask & HT_CONTENT_TYPE && entity->content_type) {
2.2 frystyk 117: int len;
2.1 frystyk 118: sprintf(linebuf, "Content-Type: %s",
119: HTAtom_name(entity->content_type));
120: if (entity->charset) {
121: strcat(linebuf, "; charset=");
122: strcat(linebuf, HTAtom_name(entity->charset));
123: }
124: if (entity->level) {
125: strcat(linebuf, "; level=");
126: strcat(linebuf, HTAtom_name(entity->level));
127: }
2.2 frystyk 128: len = strlen(linebuf);
129: *(linebuf+len) = CR;
130: *(linebuf+len+1) = LF;
131: *(linebuf+len+2) = '\0';
132: PUTBLOCK(linebuf, (int) len+2);
2.1 frystyk 133: }
134: if (request->EntityMask & HT_DERIVED_FROM && entity->derived_from) {
135: sprintf(linebuf, "Derived-From: %s%c%c", entity->derived_from,
136: CR, LF);
2.2 frystyk 137: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 138: }
139: if (request->EntityMask & HT_EXPIRES) {
140: if (entity->expires != -1) {
141: sprintf(linebuf, "Expires: %s%c%c",
142: HTDateTimeStr(&entity->expires, NO), CR,LF);
2.2 frystyk 143: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 144: }
145: }
146: if (request->EntityMask & HT_LAST_MODIFIED) {
147: if (entity->last_modified != -1) {
148: sprintf(linebuf, "Last-Modified: %s%c%c",
149: HTDateTimeStr(&entity->last_modified, NO), CR,LF);
2.2 frystyk 150: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 151: }
152: }
153: if (request->EntityMask & HT_LINK) { /* @@@@@@@@@@ */
154:
155: }
156: if (request->EntityMask & HT_TITLE) { /* @@@@@@@@@@ */
157:
158: }
159: if (request->EntityMask & HT_URI) { /* @@@@@@@@@@ */
160:
161: }
162: if (request->EntityMask & HT_VERSION && entity->version) {
163: sprintf(linebuf, "Version: %s%c%c", entity->version, CR, LF);
2.2 frystyk 164: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 165: }
166: }
167:
168: /* Put out extra information if any */
2.2 frystyk 169: {
170: HTList * list;
171: BOOL override;
172: if ((list = HTRequest_generator(request, &override))) {
173: HTList *local = list;
174: HTPostCallback *pres;
2.3 frystyk 175: if (STREAM_TRACE) TTYPrint(TDEST,"MIMEGen..... Extra local\n");
2.2 frystyk 176: while ((pres = (HTPostCallback *) HTList_nextObject(local)))
177: (*pres)(request, me->target);
178: } else if (!override && (list = HTHeader_generator())) {
179: HTList *global = list;
180: HTPostCallback *pres;
2.3 frystyk 181: if (STREAM_TRACE) TTYPrint(TDEST,"MIMEGen..... Extra global\n");
2.2 frystyk 182: while ((pres = (HTPostCallback *) HTList_nextObject(global)))
183: (*pres)(request, me->target);
184: }
185: }
2.1 frystyk 186:
187: /* Blank line means "end" */
2.2 frystyk 188: sprintf(linebuf, "%c%c", CR, LF);
189: PUTBLOCK(linebuf, (int) strlen(linebuf));
190: return HT_OK;
2.1 frystyk 191: }
192:
193: PRIVATE int MIMERequest_put_block (HTStream * me, CONST char * b, int l)
194: {
195: if (me->transparent)
196: return b ? PUTBLOCK(b, l) : HT_OK;
197: else {
198: MIMEMakeRequest(me, me->request);
2.2 frystyk 199: #if 0
2.1 frystyk 200: if ((status = PUTBLOCK(HTChunkData(me->buffer),
201: HTChunkSize(me->buffer))) == HT_OK) {
202: me->transparent = YES;
203: return b ? PUTBLOCK(b, l) : HT_OK;
204: }
2.2 frystyk 205: #endif
206: me->transparent = YES;
207: return b ? PUTBLOCK(b, l) : HT_OK;
2.1 frystyk 208: }
209: }
210:
211: PRIVATE int MIMERequest_put_character (HTStream * me, char c)
212: {
213: return MIMERequest_put_block(me, &c, 1);
214: }
215:
216: PRIVATE int MIMERequest_put_string (HTStream * me, CONST char * s)
217: {
218: return MIMERequest_put_block(me, s, strlen(s));
219: }
220:
221: /*
222: ** Flushes header but doesn't free stream object
223: */
224: PRIVATE int MIMERequest_flush (HTStream * me)
225: {
226: int status = MIMERequest_put_block(me, NULL, 0);
227: return status==HT_OK ? (*me->target->isa->flush)(me->target) : status;
228: }
229:
230: /*
231: ** Flushes data and frees stream object
232: */
233: PRIVATE int MIMERequest_free (HTStream * me)
234: {
235: int status = MIMERequest_flush(me);
236: if (status != HT_WOULD_BLOCK) {
237: if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
238: return HT_WOULD_BLOCK;
239: free(me);
240: }
241: return status;
242: }
243:
2.4 frystyk 244: PRIVATE int MIMERequest_abort (HTStream * me, HTList * e)
2.1 frystyk 245: {
246: if (me->target) (*me->target->isa->abort)(me->target, e);
247: free(me);
2.3 frystyk 248: if (PROT_TRACE) TTYPrint(TDEST, "MIMERequest. ABORTING...\n");
2.1 frystyk 249: return HT_ERROR;
250: }
251:
252: /* MIMERequest Stream
253: ** -----------------
254: */
255: PRIVATE CONST HTStreamClass MIMERequestClass =
256: {
257: "MIMERequest",
258: MIMERequest_flush,
259: MIMERequest_free,
260: MIMERequest_abort,
261: MIMERequest_put_character,
262: MIMERequest_put_string,
263: MIMERequest_put_block
264: };
265:
266: PUBLIC HTStream * HTMIMERequest_new (HTRequest * request, HTStream * target)
267: {
268: HTStream * me = (HTStream *) calloc(1, sizeof(HTStream));
269: if (!me) outofmem(__FILE__, "HTMIMERequest_new");
270: me->isa = &MIMERequestClass;
271: me->target = target;
272: me->request = request;
273: me->transparent = NO;
274: return me;
275: }
Webmaster