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