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