Annotation of libwww/Library/src/HTTPGen.c, revision 2.3
2.1 frystyk 1: /* HTTPGen.c
2: ** HTTP GENERAL HEADER GENERATION
3: **
4: ** This module implements the output stream for General HTTP headers
5: **
6: ** History:
7: ** Jan 96 HFN Written
8: */
9:
10: /* Library Includes */
11: #include "tcp.h"
12: #include "HTUtils.h"
13: #include "HTString.h"
14: #include "HTWWWStr.h"
15: #include "HTParse.h"
16: #include "HTFormat.h"
17: #include "HTAncMan.h"
18: #include "HTNetMan.h"
19: #include "HTTCP.h"
20: #include "HTWriter.h"
21: #include "HTHeader.h"
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: BOOL endHeader;
33: BOOL transparent;
34: };
35:
36: /* ------------------------------------------------------------------------- */
37: /* HTTP General Header Stream */
38: /* ------------------------------------------------------------------------- */
39:
40: /* HTTPGenMake
41: ** ------------
42: ** Makes a MIME/1.0 request header.
43: */
44: PRIVATE int HTTPGenMake (HTStream * me, HTRequest * request)
45: {
46: char linebuf[256];
47: if (request->GenMask & HT_G_DATE) {
48: time_t local = time(NULL);
49: sprintf(linebuf, "Date: %s%c%c", HTDateTimeStr(&local, NO), CR,LF);
50: PUTBLOCK(linebuf, (int) strlen(linebuf));
51: }
52: if (request->GenMask & HT_G_FORWARDED) {
53: /* @@@@@@ */
54: }
55: if (request->GenMask & HT_G_MESSAGE_ID) {
56: CONST char *msgid = HTMessageIdStr();
57: if (msgid) {
58: sprintf(linebuf, "Message-ID: %s%c%c", msgid, CR, LF);
59: PUTBLOCK(linebuf, (int) strlen(linebuf));
60: }
61: }
62: if (request->GenMask & HT_G_MIME) {
63: sprintf(linebuf, "MIME-Version: %s%c%c", MIME_VERSION, CR, LF);
64: PUTBLOCK(linebuf, (int) strlen(linebuf));
65: }
66: if (request->GenMask & HT_G_CONNECTION) {
67: sprintf(linebuf, "Connection: Keep-Alive%c%c", CR, LF);
68: PUTBLOCK(linebuf, (int) strlen(linebuf));
69: }
70: if (request->RequestMask & HT_G_NO_CACHE) {
71: sprintf(linebuf, "Pragma: %s%c%c", "no-cache", CR, LF);
72: PUTBLOCK(linebuf, (int) strlen(linebuf));
73: }
74:
75: /* Put out extra information if any */
76: {
77: HTList * list;
78: BOOL override;
79: if ((list = HTRequest_generator(request, &override))) {
80: HTList *local = list;
81: HTPostCallback *pres;
2.3 ! eric 82: if (STREAM_TRACE) HTTrace("HTTPGen..... Extra local\n");
2.1 frystyk 83: while ((pres = (HTPostCallback *) HTList_nextObject(local)))
84: (*pres)(request, me->target);
85: } else if (!override && (list = HTHeader_generator())) {
86: HTList *global = list;
87: HTPostCallback *pres;
2.3 ! eric 88: if (STREAM_TRACE) HTTrace("HTTPGen..... Extra global\n");
2.1 frystyk 89: while ((pres = (HTPostCallback *) HTList_nextObject(global)))
90: (*pres)(request, me->target);
91: }
92: }
93: if (me->endHeader) {
94: sprintf(linebuf, "%c%c", CR, LF); /* Blank line means "end" */
95: PUTBLOCK(linebuf, (int) strlen(linebuf));
96: }
2.3 ! eric 97: if (PROT_TRACE)HTTrace("HTTP........ Generating General Headers\n");
2.1 frystyk 98: return HT_OK;
99: }
100:
101: PRIVATE int HTTPGen_put_block (HTStream * me, CONST char * b, int l)
102: {
103: if (me->transparent)
104: return b ? PUTBLOCK(b, l) : HT_OK;
105: else {
106: HTTPGenMake(me, me->request);
107: me->transparent = YES;
108: return b ? PUTBLOCK(b, l) : HT_OK;
109: }
110: }
111:
112: PRIVATE int HTTPGen_put_character (HTStream * me, char c)
113: {
114: return HTTPGen_put_block(me, &c, 1);
115: }
116:
117: PRIVATE int HTTPGen_put_string (HTStream * me, CONST char * s)
118: {
119: return HTTPGen_put_block(me, s, strlen(s));
120: }
121:
122: /*
123: ** Flushes header but doesn't free stream object
124: */
125: PRIVATE int HTTPGen_flush (HTStream * me)
126: {
127: int status = HTTPGen_put_block(me, NULL, 0);
128: return status==HT_OK ? (*me->target->isa->flush)(me->target) : status;
129: }
130:
131: /*
132: ** Flushes data and frees stream object
133: */
134: PRIVATE int HTTPGen_free (HTStream * me)
135: {
136: int status = HTTPGen_flush(me);
137: if (status != HT_WOULD_BLOCK) {
138: if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
139: return HT_WOULD_BLOCK;
2.2 frystyk 140: HT_FREE(me);
2.1 frystyk 141: }
142: return status;
143: }
144:
145: PRIVATE int HTTPGen_abort (HTStream * me, HTList * e)
146: {
147: if (me->target) (*me->target->isa->abort)(me->target, e);
2.2 frystyk 148: HT_FREE(me);
2.3 ! eric 149: if (PROT_TRACE) HTTrace("HTTPGen..... ABORTING...\n");
2.1 frystyk 150: return HT_ERROR;
151: }
152:
153: /* HTTPGen Stream
154: ** -----------------
155: */
156: PRIVATE CONST HTStreamClass HTTPGenClass =
157: {
158: "HTTPGen",
159: HTTPGen_flush,
160: HTTPGen_free,
161: HTTPGen_abort,
162: HTTPGen_put_character,
163: HTTPGen_put_string,
164: HTTPGen_put_block
165: };
166:
167: PUBLIC HTStream * HTTPGen_new (HTRequest * request, HTStream * target,
168: BOOL endHeader)
169: {
2.2 frystyk 170: HTStream * me;
171: if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
172: HT_OUTOFMEM("HTTPGen_new");
2.1 frystyk 173: me->isa = &HTTPGenClass;
174: me->target = target;
175: me->request = request;
176: me->endHeader = endHeader;
177: me->transparent = NO;
178: return me;
179: }
Webmaster