Annotation of libwww/Library/src/HTTPGen.c, revision 2.15
2.1 frystyk 1: /* HTTPGen.c
2: ** HTTP GENERAL HEADER GENERATION
3: **
2.5 frystyk 4: ** (c) COPYRIGHT MIT 1995.
5: ** Please first read the full copyright statement in the file COPYRIGH.
2.15 ! frystyk 6: ** @(#) $Id: HTTPGen.c,v 2.14 1999/01/27 13:56:31 frystyk Exp $
2.5 frystyk 7: **
2.1 frystyk 8: ** This module implements the output stream for General HTTP headers
9: **
10: ** History:
11: ** Jan 96 HFN Written
12: */
13:
14: /* Library Includes */
2.13 frystyk 15: #include "wwwsys.h"
2.8 frystyk 16: #include "WWWUtil.h"
17: #include "WWWCore.h"
2.15 ! frystyk 18: #include "HTHeader.h"
2.10 frystyk 19: #include "HTTPUtil.h"
2.1 frystyk 20: #include "HTTPReq.h" /* Implements */
21:
22: #define MIME_VERSION "MIME/1.0"
2.8 frystyk 23:
24: #define PUTC(c) (*me->target->isa->put_character)(me->target, c)
25: #define PUTS(s) (*me->target->isa->put_string)(me->target, s)
2.1 frystyk 26: #define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l)
27:
28: struct _HTStream {
2.4 frystyk 29: const HTStreamClass * isa;
2.1 frystyk 30: HTStream * target;
31: HTRequest * request;
2.10 frystyk 32: int version;
2.1 frystyk 33: BOOL endHeader;
34: BOOL transparent;
35: };
36:
37: /* ------------------------------------------------------------------------- */
38: /* HTTP General Header Stream */
39: /* ------------------------------------------------------------------------- */
40:
41: /* HTTPGenMake
42: ** ------------
43: ** Makes a MIME/1.0 request header.
44: */
45: PRIVATE int HTTPGenMake (HTStream * me, HTRequest * request)
46: {
2.8 frystyk 47: char linebuf[256]; /* @@@ */
48: char crlf[3];
49: HTGnHd gen_mask = HTRequest_gnHd(request);
50: *crlf = CR; *(crlf+1) = LF; *(crlf+2) = '\0';
51: if (gen_mask & HT_G_CC) { /* Cache control */
52: HTAssocList * cur = HTRequest_cacheControl(request);
53: if (cur) {
54: BOOL first=YES;
55: HTAssoc * pres;
56: while ((pres = (HTAssoc *) HTAssocList_nextObject(cur))) {
57: char * value = HTAssoc_value(pres);
58: if (first) {
59: PUTS("Cache-Control: ");
60: first = NO;
61: } else
62: PUTC(',');
63:
64: /* Output the name */
65: PUTS(HTAssoc_name(pres));
66:
67: /* Only output the value if not empty string */
68: if (*value) {
69: PUTS("=");
70: PUTS(value);
71: }
72: }
73: PUTBLOCK(crlf, 2);
74: }
75: }
76: if (gen_mask & HT_G_CONNECTION) {
2.10 frystyk 77: HTAssocList * cur = HTRequest_connection(request);
2.8 frystyk 78: if (cur) {
79: BOOL first=YES;
80: HTAssoc * pres;
81: while ((pres = (HTAssoc *) HTAssocList_nextObject(cur))) {
82: char * value = HTAssoc_value(pres);
83: if (first) {
84: PUTS("Connection: ");
85: first = NO;
86: } else
87: PUTC(',');
88:
89: /* Output the name */
90: PUTS(HTAssoc_name(pres));
91:
92: /* Only output the value if not empty string */
93: if (*value) {
94: PUTS("=");
95: PUTS(value);
96: }
97: }
98: PUTBLOCK(crlf, 2);
99: }
100: }
101: if (gen_mask & HT_G_DATE) {
2.9 frystyk 102: time_t local = HTRequest_date(request);
2.1 frystyk 103: sprintf(linebuf, "Date: %s%c%c", HTDateTimeStr(&local, NO), CR,LF);
104: PUTBLOCK(linebuf, (int) strlen(linebuf));
105: }
2.8 frystyk 106: if (gen_mask & HT_G_FORWARDED) {
2.1 frystyk 107: /* @@@@@@ */
108: }
2.8 frystyk 109: if (gen_mask & HT_G_PRAGMA_NO_CACHE) {
110: sprintf(linebuf, "Pragma: %s%c%c", "no-cache", CR, LF);
111: PUTBLOCK(linebuf, (int) strlen(linebuf));
112: }
113: if (gen_mask & HT_G_MESSAGE_ID) {
2.6 frystyk 114: const char *msgid = HTMessageIdStr(HTRequest_userProfile(request));
2.1 frystyk 115: if (msgid) {
116: sprintf(linebuf, "Message-ID: %s%c%c", msgid, CR, LF);
117: PUTBLOCK(linebuf, (int) strlen(linebuf));
118: }
119: }
2.8 frystyk 120: if (gen_mask & HT_G_MIME) {
2.1 frystyk 121: sprintf(linebuf, "MIME-Version: %s%c%c", MIME_VERSION, CR, LF);
122: PUTBLOCK(linebuf, (int) strlen(linebuf));
123: }
124:
125: /* Put out extra information if any */
126: {
127: HTList * list;
128: BOOL override;
129: if ((list = HTRequest_generator(request, &override))) {
130: HTList *local = list;
131: HTPostCallback *pres;
2.3 eric 132: if (STREAM_TRACE) HTTrace("HTTPGen..... Extra local\n");
2.1 frystyk 133: while ((pres = (HTPostCallback *) HTList_nextObject(local)))
134: (*pres)(request, me->target);
135: } else if (!override && (list = HTHeader_generator())) {
136: HTList *global = list;
137: HTPostCallback *pres;
2.3 eric 138: if (STREAM_TRACE) HTTrace("HTTPGen..... Extra global\n");
2.1 frystyk 139: while ((pres = (HTPostCallback *) HTList_nextObject(global)))
140: (*pres)(request, me->target);
141: }
142: }
143: if (me->endHeader) {
144: sprintf(linebuf, "%c%c", CR, LF); /* Blank line means "end" */
145: PUTBLOCK(linebuf, (int) strlen(linebuf));
146: }
2.3 eric 147: if (PROT_TRACE)HTTrace("HTTP........ Generating General Headers\n");
2.1 frystyk 148: return HT_OK;
149: }
150:
2.4 frystyk 151: PRIVATE int HTTPGen_put_block (HTStream * me, const char * b, int l)
2.1 frystyk 152: {
153: if (me->transparent)
154: return b ? PUTBLOCK(b, l) : HT_OK;
155: else {
156: HTTPGenMake(me, me->request);
157: me->transparent = YES;
158: return b ? PUTBLOCK(b, l) : HT_OK;
159: }
160: }
161:
162: PRIVATE int HTTPGen_put_character (HTStream * me, char c)
163: {
164: return HTTPGen_put_block(me, &c, 1);
165: }
166:
2.4 frystyk 167: PRIVATE int HTTPGen_put_string (HTStream * me, const char * s)
2.1 frystyk 168: {
169: return HTTPGen_put_block(me, s, strlen(s));
170: }
171:
172: /*
173: ** Flushes header but doesn't free stream object
174: */
175: PRIVATE int HTTPGen_flush (HTStream * me)
176: {
177: int status = HTTPGen_put_block(me, NULL, 0);
178: return status==HT_OK ? (*me->target->isa->flush)(me->target) : status;
179: }
180:
181: /*
182: ** Flushes data and frees stream object
183: */
184: PRIVATE int HTTPGen_free (HTStream * me)
185: {
186: int status = HTTPGen_flush(me);
187: if (status != HT_WOULD_BLOCK) {
188: if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
189: return HT_WOULD_BLOCK;
2.2 frystyk 190: HT_FREE(me);
2.1 frystyk 191: }
192: return status;
193: }
194:
195: PRIVATE int HTTPGen_abort (HTStream * me, HTList * e)
196: {
2.3 eric 197: if (PROT_TRACE) HTTrace("HTTPGen..... ABORTING...\n");
2.12 frystyk 198: if (me) {
199: if (me->target) (*me->target->isa->abort)(me->target, e);
200: HT_FREE(me);
201: }
2.1 frystyk 202: return HT_ERROR;
203: }
204:
205: /* HTTPGen Stream
206: ** -----------------
207: */
2.4 frystyk 208: PRIVATE const HTStreamClass HTTPGenClass =
2.1 frystyk 209: {
210: "HTTPGen",
211: HTTPGen_flush,
212: HTTPGen_free,
213: HTTPGen_abort,
214: HTTPGen_put_character,
215: HTTPGen_put_string,
216: HTTPGen_put_block
217: };
218:
219: PUBLIC HTStream * HTTPGen_new (HTRequest * request, HTStream * target,
2.10 frystyk 220: BOOL endHeader, int version)
2.1 frystyk 221: {
2.2 frystyk 222: HTStream * me;
223: if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
224: HT_OUTOFMEM("HTTPGen_new");
2.1 frystyk 225: me->isa = &HTTPGenClass;
226: me->target = target;
227: me->request = request;
228: me->endHeader = endHeader;
229: me->transparent = NO;
2.10 frystyk 230:
231: /*
232: ** For backwards compatibility with HTTP applications that understand
233: ** Connection: Keep-Alive, we send it along. However, we do NOT send
2.14 frystyk 234: ** it to a proxy as it may confuse HTTP/1.0 proxies. Also we do not
235: ** send it if the app has set Connection: close
2.10 frystyk 236: */
237: me->version = version;
2.14 frystyk 238: if (me->version == HTTP_10 && HTRequest_proxy(request) == NULL) {
239: HTAssocList * alist = HTRequest_connection(request);
240: if (!(alist && HTAssocList_findObject(alist, "close")))
241: HTRequest_addConnection(request, "Keep-Alive", "");
242: }
2.11 frystyk 243:
244: /*
245: ** Check for any TE headers that are also hop-by-hop
246: */
247: if (HTFormat_transferCoding() != NULL || HTRequest_transfer(request) != NULL)
248: HTRequest_addConnection(request, "TE", "");
2.10 frystyk 249:
2.1 frystyk 250: return me;
251: }
Webmaster