Annotation of libwww/Library/src/HTMIMERq.c, revision 2.5
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"
18: #include "HTNetMan.h"
19: #include "HTDNS.h"
20: #include "HTTCP.h"
21: #include "HTWriter.h"
2.2 frystyk 22: #include "HTHeader.h"
2.1 frystyk 23: #include "HTReqMan.h"
24: #include "HTTPReq.h" /* Implements */
25:
26: #define MIME_VERSION "MIME/1.0"
27: #define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l)
28:
29: struct _HTStream {
30: CONST HTStreamClass * isa;
31: HTStream * target;
32: HTRequest * request;
33: SOCKFD sockfd;
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: */
2.2 frystyk 46: PRIVATE int MIMEMakeRequest (HTStream * me, HTRequest * request)
2.1 frystyk 47: {
48: char linebuf[256];
49: HTParentAnchor *entity = (request->source && request->source->anchor) ?
50: request->source->anchor : request->anchor;
51:
52: /* General Headers */
53: if (request->GenMask & HT_DATE) {
54: time_t local = time(NULL);
55: sprintf(linebuf, "Date: %s%c%c", HTDateTimeStr(&local, NO), CR,LF);
2.2 frystyk 56: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 57: }
58: if (request->GenMask & HT_FORWARDED) {
59: /* @@@@@@ */
60: }
61: if (request->GenMask & HT_MESSAGE_ID) {
62: CONST char *msgid = HTMessageIdStr();
63: if (msgid) {
64: sprintf(linebuf, "Message-ID: %s%c%c", msgid, CR, LF);
2.2 frystyk 65: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 66: }
67: }
68: if (request->GenMask & HT_MIME) {
69: sprintf(linebuf, "MIME-Version: %s%c%c", MIME_VERSION, CR, LF);
2.2 frystyk 70: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 71: }
72: if (request->GenMask & HT_CONNECTION) {
73: sprintf(linebuf, "Connection: Keep-Alive%c%c", CR, LF);
2.2 frystyk 74: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 75: }
76: if (request->RequestMask & HT_NO_CACHE) {
77: sprintf(linebuf, "Pragma: %s%c%c", "no-cache", CR, LF);
2.2 frystyk 78: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 79: }
80:
81: /* Now put out entity headers if we are using PUT or POST. If we have a
82: ** PostAnchor then we take the information from this and uses the
83: ** destination anchor to contain the reply. Otherwise, we have created an
84: ** anchor (using internal editing etc) and we can use the destination
85: ** anchor directly.
86: */
87: if (request->method==METHOD_PUT || request->method==METHOD_POST) {
88: if (request->EntityMask & HT_ALLOW) {
89: /* @@@@@@@@@@ */
90: }
91: if (request->EntityMask & HT_CONTENT_ENCODING &&
92: entity->content_encoding) {
93: sprintf(linebuf, "Content-Encoding: %s%c%c",
94: HTAtom_name(entity->content_encoding), CR, LF);
2.2 frystyk 95: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 96: }
97:
98: /* @@@ SHOULD BE A LIST @@@ */
99: if (request->EntityMask & HT_CONTENT_LANGUAGE &&
100: entity->content_language) {
101: sprintf(linebuf, "Content-Language: %s%c%c",
102: HTAtom_name(entity->content_language), CR, LF);
2.2 frystyk 103: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 104: }
105: if (request->EntityMask & HT_CONTENT_LENGTH) { /* Must be there!!! */
106: sprintf(linebuf, "Content-Length: %ld%c%c",
107: entity->content_length, CR, LF);
2.2 frystyk 108: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 109: }
110: if (request->EntityMask & HT_CTE && entity->cte) {
111: sprintf(linebuf, "Content-Transfer-Encoding: %s%c%c",
112: HTAtom_name(entity->cte), CR, LF);
2.2 frystyk 113: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 114: }
115: if (request->EntityMask & HT_CONTENT_TYPE && entity->content_type) {
2.2 frystyk 116: int len;
2.1 frystyk 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: }
2.2 frystyk 127: len = strlen(linebuf);
128: *(linebuf+len) = CR;
129: *(linebuf+len+1) = LF;
130: *(linebuf+len+2) = '\0';
131: PUTBLOCK(linebuf, (int) len+2);
2.1 frystyk 132: }
133: if (request->EntityMask & HT_DERIVED_FROM && entity->derived_from) {
134: sprintf(linebuf, "Derived-From: %s%c%c", entity->derived_from,
135: CR, LF);
2.2 frystyk 136: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 137: }
138: if (request->EntityMask & HT_EXPIRES) {
139: if (entity->expires != -1) {
140: sprintf(linebuf, "Expires: %s%c%c",
141: HTDateTimeStr(&entity->expires, NO), CR,LF);
2.2 frystyk 142: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 143: }
144: }
145: if (request->EntityMask & HT_LAST_MODIFIED) {
146: if (entity->last_modified != -1) {
147: sprintf(linebuf, "Last-Modified: %s%c%c",
148: HTDateTimeStr(&entity->last_modified, NO), CR,LF);
2.2 frystyk 149: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 150: }
151: }
152: if (request->EntityMask & HT_LINK) { /* @@@@@@@@@@ */
153:
154: }
155: if (request->EntityMask & HT_TITLE) { /* @@@@@@@@@@ */
156:
157: }
158: if (request->EntityMask & HT_URI) { /* @@@@@@@@@@ */
159:
160: }
161: if (request->EntityMask & HT_VERSION && entity->version) {
162: sprintf(linebuf, "Version: %s%c%c", entity->version, CR, LF);
2.2 frystyk 163: PUTBLOCK(linebuf, (int) strlen(linebuf));
2.1 frystyk 164: }
165: }
166:
167: /* Put out extra information if any */
2.2 frystyk 168: {
169: HTList * list;
170: BOOL override;
171: if ((list = HTRequest_generator(request, &override))) {
172: HTList *local = list;
173: HTPostCallback *pres;
2.3 frystyk 174: if (STREAM_TRACE) TTYPrint(TDEST,"MIMEGen..... Extra local\n");
2.2 frystyk 175: while ((pres = (HTPostCallback *) HTList_nextObject(local)))
176: (*pres)(request, me->target);
177: } else if (!override && (list = HTHeader_generator())) {
178: HTList *global = list;
179: HTPostCallback *pres;
2.3 frystyk 180: if (STREAM_TRACE) TTYPrint(TDEST,"MIMEGen..... Extra global\n");
2.2 frystyk 181: while ((pres = (HTPostCallback *) HTList_nextObject(global)))
182: (*pres)(request, me->target);
183: }
184: }
2.1 frystyk 185:
186: /* Blank line means "end" */
2.2 frystyk 187: sprintf(linebuf, "%c%c", CR, LF);
188: PUTBLOCK(linebuf, (int) strlen(linebuf));
189: return HT_OK;
2.1 frystyk 190: }
191:
192: PRIVATE int MIMERequest_put_block (HTStream * me, CONST char * b, int l)
193: {
194: if (me->transparent)
195: return b ? PUTBLOCK(b, l) : HT_OK;
196: else {
197: MIMEMakeRequest(me, me->request);
2.2 frystyk 198: #if 0
2.1 frystyk 199: if ((status = PUTBLOCK(HTChunkData(me->buffer),
200: HTChunkSize(me->buffer))) == HT_OK) {
201: me->transparent = YES;
202: return b ? PUTBLOCK(b, l) : HT_OK;
203: }
2.2 frystyk 204: #endif
205: me->transparent = YES;
206: return b ? PUTBLOCK(b, l) : HT_OK;
2.1 frystyk 207: }
208: }
209:
210: PRIVATE int MIMERequest_put_character (HTStream * me, char c)
211: {
212: return MIMERequest_put_block(me, &c, 1);
213: }
214:
215: PRIVATE int MIMERequest_put_string (HTStream * me, CONST char * s)
216: {
217: return MIMERequest_put_block(me, s, strlen(s));
218: }
219:
220: /*
221: ** Flushes header but doesn't free stream object
222: */
223: PRIVATE int MIMERequest_flush (HTStream * me)
224: {
225: int status = MIMERequest_put_block(me, NULL, 0);
226: return status==HT_OK ? (*me->target->isa->flush)(me->target) : status;
227: }
228:
229: /*
230: ** Flushes data and frees stream object
231: */
232: PRIVATE int MIMERequest_free (HTStream * me)
233: {
234: int status = MIMERequest_flush(me);
235: if (status != HT_WOULD_BLOCK) {
236: if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
237: return HT_WOULD_BLOCK;
238: free(me);
239: }
240: return status;
241: }
242:
2.4 frystyk 243: PRIVATE int MIMERequest_abort (HTStream * me, HTList * e)
2.1 frystyk 244: {
245: if (me->target) (*me->target->isa->abort)(me->target, e);
246: free(me);
2.3 frystyk 247: if (PROT_TRACE) TTYPrint(TDEST, "MIMERequest. ABORTING...\n");
2.1 frystyk 248: return HT_ERROR;
249: }
250:
251: /* MIMERequest Stream
252: ** -----------------
253: */
254: PRIVATE CONST HTStreamClass MIMERequestClass =
255: {
256: "MIMERequest",
257: MIMERequest_flush,
258: MIMERequest_free,
259: MIMERequest_abort,
260: MIMERequest_put_character,
261: MIMERequest_put_string,
262: MIMERequest_put_block
263: };
264:
265: PUBLIC HTStream * HTMIMERequest_new (HTRequest * request, HTStream * target)
266: {
267: HTStream * me = (HTStream *) calloc(1, sizeof(HTStream));
268: if (!me) outofmem(__FILE__, "HTMIMERequest_new");
269: me->isa = &MIMERequestClass;
270: me->target = target;
271: me->request = request;
272: me->transparent = NO;
273: return me;
274: }
Webmaster