Annotation of libwww/Library/src/HTTPReq.c, revision 2.32
2.1 frystyk 1: /* HTTPReq.c
2.23 frystyk 2: ** HTTP REQUEST GENERATION
2.1 frystyk 3: **
2.32 ! frystyk 4: ** (c) COPYRIGHT MIT 1995.
! 5: ** Please first read the full copyright statement in the file COPYRIGH.
! 6: ** @(#) $Id: Date Author State $
! 7: **
2.1 frystyk 8: ** This module implements the output stream for HTTP used for sending
9: ** requests with or without a entity body.
10: **
11: ** History:
12: ** Jan 95 HFN Written from scratch
13: */
14:
15: /* Library Includes */
2.29 frystyk 16: #include "sysdep.h"
2.28 frystyk 17: #include "WWWUtil.h"
2.32 ! frystyk 18: #include "WWWCore.h"
! 19:
2.11 frystyk 20: #include "HTNetMan.h"
2.10 frystyk 21: #include "HTReqMan.h"
2.23 frystyk 22: #include "HTTPGen.h"
2.21 frystyk 23: #include "HTTPUtil.h"
2.1 frystyk 24: #include "HTTPReq.h" /* Implements */
25:
2.24 frystyk 26: #define PUTC(c) (*me->target->isa->put_character)(me->target, c)
27: #define PUTS(s) (*me->target->isa->put_string)(me->target, s)
2.1 frystyk 28: #define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l)
29:
30: struct _HTStream {
2.29 frystyk 31: const HTStreamClass * isa;
2.1 frystyk 32: HTStream * target;
33: HTRequest * request;
2.18 frystyk 34: SOCKET sockfd;
2.11 frystyk 35: int version;
2.1 frystyk 36: BOOL transparent;
37: };
38:
39: /* ------------------------------------------------------------------------- */
40: /* HTTP Output Request Stream */
41: /* ------------------------------------------------------------------------- */
42:
2.11 frystyk 43: /* HTTP09Request
44: ** -------------
45: ** Makes a HTTP/0.9 request
2.1 frystyk 46: */
2.11 frystyk 47: PRIVATE void HTTP09Request (HTStream * me, HTRequest * request)
48: {
49: char *addr = HTAnchor_physical(request->anchor);
50: char *fullurl = HTParse(addr, "", PARSE_PATH|PARSE_PUNCTUATION);
2.24 frystyk 51: PUTS("GET ");
52: PUTS(fullurl);
53: PUTC(CR);
54: PUTC(LF);
2.11 frystyk 55: }
56:
57: /* HTTPMakeRequest
58: ** ---------------
59: ** Makes a HTTP/1.0-1.1 request header.
60: */
61: PRIVATE void HTTPMakeRequest (HTStream * me, HTRequest * request)
2.1 frystyk 62: {
2.24 frystyk 63: char crlf[3];
64: char qstr[10];
2.13 frystyk 65: HTParentAnchor *anchor = HTRequest_anchor(request);
2.24 frystyk 66: *crlf = CR; *(crlf+1) = LF; *(crlf+2) = '\0';
2.1 frystyk 67:
68: /* Generate the HTTP/1.0 RequestLine */
69: if (request->method != METHOD_INVALID) {
2.24 frystyk 70: PUTS(HTMethod_name(request->method));
71: PUTC(' ');
2.1 frystyk 72: } else
2.24 frystyk 73: PUTS("GET ");
2.1 frystyk 74:
75: /* If we are using a proxy then only take the `path' info in the URL */
76: {
2.13 frystyk 77: char *addr = HTAnchor_physical(anchor);
2.6 frystyk 78: char *fullurl = HTParse(addr, "", PARSE_PATH|PARSE_PUNCTUATION);
2.1 frystyk 79: if (request->using_proxy) {
2.24 frystyk 80: PUTS(fullurl+1);
2.1 frystyk 81: } else {
2.24 frystyk 82: PUTS(fullurl);
2.1 frystyk 83: }
2.26 frystyk 84: HT_FREE(fullurl);
2.1 frystyk 85: }
2.25 frystyk 86: PUTC(' ');
87: PUTS(HTTP_VERSION);
2.24 frystyk 88: PUTBLOCK(crlf, 2);
2.1 frystyk 89:
2.4 frystyk 90: /* Request Headers */
2.22 frystyk 91: if (request->RequestMask & HT_C_ACCEPT_TYPE) {
2.1 frystyk 92: int list;
93: HTList *cur;
2.24 frystyk 94: BOOL first=YES;
2.1 frystyk 95: for (list=0; list<2; list++) {
2.14 frystyk 96: if ((!list && ((cur = HTFormat_conversion()) != NULL)) ||
97: (list && ((cur = HTRequest_conversion(request)) != NULL))) {
2.4 frystyk 98: HTPresentation *pres;
2.24 frystyk 99: while ((pres = (HTPresentation *) HTList_nextObject(cur))) {
2.19 frystyk 100: if (pres->rep_out==WWW_PRESENT && pres->quality <= 1.0) {
2.24 frystyk 101: if (first) {
102: PUTS("Accept: ");
103: first=NO;
104: } else
105: PUTC(',');
106: PUTS(HTAtom_name(pres->rep));
2.1 frystyk 107: if (pres->quality != 1.0) {
2.24 frystyk 108: sprintf(qstr, ";q=%1.1f", pres->quality);
109: PUTS(qstr);
2.1 frystyk 110: }
111: }
112: }
113: }
114: }
2.31 frystyk 115: if (!first) PUTBLOCK(crlf, 2);
2.1 frystyk 116: }
2.22 frystyk 117: if (request->RequestMask & HT_C_ACCEPT_CHAR) {
2.4 frystyk 118: int list;
119: HTList *cur;
2.24 frystyk 120: BOOL first=YES;
2.4 frystyk 121: for (list=0; list<2; list++) {
2.14 frystyk 122: if ((!list && ((cur = HTFormat_charset()) != NULL)) ||
123: (list && ((cur = HTRequest_charset(request)) != NULL))) {
2.4 frystyk 124: HTAcceptNode *pres;
125: while ((pres = (HTAcceptNode *) HTList_nextObject(cur))) {
2.5 frystyk 126: if (first) {
2.24 frystyk 127: PUTS("Accept-Charset: ");
2.5 frystyk 128: first=NO;
2.24 frystyk 129: } else
130: PUTC(',');
131: PUTS(HTAtom_name(pres->atom));
2.4 frystyk 132: }
133: }
134: }
2.31 frystyk 135: if (!first) PUTBLOCK(crlf, 2);
2.4 frystyk 136: }
2.22 frystyk 137: if (request->RequestMask & HT_C_ACCEPT_ENC) {
2.4 frystyk 138: int list;
139: HTList *cur;
2.24 frystyk 140: BOOL first=YES;
2.4 frystyk 141: for (list=0; list<2; list++) {
2.14 frystyk 142: if ((!list && ((cur = HTFormat_encoding()) != NULL)) ||
143: (list && ((cur = HTRequest_encoding(request)) != NULL))) {
2.32 ! frystyk 144: HTContentCoding * pres;
! 145: while ((pres = (HTContentCoding *) HTList_nextObject(cur))) {
2.5 frystyk 146: if (first) {
2.24 frystyk 147: PUTS("Accept-Encoding: ");
2.32 ! frystyk 148: first = NO;
2.24 frystyk 149: } else
150: PUTC(',');
2.32 ! frystyk 151: PUTS(HTContentCoding_name(pres));
2.4 frystyk 152: }
153: }
154: }
2.31 frystyk 155: if (!first) PUTBLOCK(crlf, 2);
2.4 frystyk 156: }
2.22 frystyk 157: if (request->RequestMask & HT_C_ACCEPT_LAN) {
2.4 frystyk 158: int list;
159: HTList *cur;
2.24 frystyk 160: BOOL first=YES;
2.4 frystyk 161: for (list=0; list<2; list++) {
2.14 frystyk 162: if ((!list && ((cur = HTFormat_language()) != NULL)) ||
163: (list && ((cur = HTRequest_language(request)) != NULL))) {
2.4 frystyk 164: HTAcceptNode *pres;
165: while ((pres = (HTAcceptNode *) HTList_nextObject(cur))) {
2.5 frystyk 166: if (first) {
2.24 frystyk 167: PUTS("Accept-Language: ");
2.5 frystyk 168: first=NO;
2.24 frystyk 169: } else
170: PUTC(',');
171: PUTS(HTAtom_name(pres->atom));
172: if (pres->quality != 1.0) {
173: sprintf(qstr, ";q=%1.1f", pres->quality);
174: PUTS(qstr);
2.5 frystyk 175: }
2.4 frystyk 176: }
177: }
178: }
2.31 frystyk 179: if (!first) PUTBLOCK(crlf, 2);
2.4 frystyk 180: }
2.28 frystyk 181: if (request->credentials) { /* Access authentication */
182: HTAssocList * cur = request->credentials;
183: HTAssoc * pres;
184: while ((pres = (HTAssoc *) HTAssocList_nextObject(cur))) {
185: PUTS(HTAssoc_name(pres));
186: PUTS(": ");
187: PUTS(HTAssoc_value(pres));
188: PUTBLOCK(crlf, 2);
189: }
2.1 frystyk 190: }
2.22 frystyk 191: if (request->RequestMask & HT_C_FROM) {
2.29 frystyk 192: const char *mailaddress = HTGetMailAddress();
2.1 frystyk 193: if (mailaddress) {
2.24 frystyk 194: PUTS("From: ");
195: PUTS(mailaddress);
196: PUTBLOCK(crlf, 2);
2.1 frystyk 197: }
198: }
2.22 frystyk 199: if (request->RequestMask & HT_C_IMS) {
2.21 frystyk 200: time_t lm = HTAnchor_lastModified(anchor);
2.24 frystyk 201: if (lm > 0) {
202: PUTS("If-Modified-Since: ");
203: PUTS(HTDateTimeStr(&lm, NO));
204: PUTBLOCK(crlf, 2);
2.8 frystyk 205: }
206: }
2.22 frystyk 207: if (request->RequestMask & HT_C_HOST) {
2.13 frystyk 208: char *orig = HTAnchor_address((HTAnchor *) anchor);
2.12 frystyk 209: char *host = HTParse(orig, "", PARSE_HOST);
210: char *ptr = strchr(host, ':'); /* Chop off port number */
211: if (ptr) *ptr = '\0';
2.24 frystyk 212: PUTS("Host: ");
213: PUTS(host);
214: PUTBLOCK(crlf, 2);
2.26 frystyk 215: HT_FREE(orig);
216: HT_FREE(host);
2.1 frystyk 217: }
2.22 frystyk 218: if (request->RequestMask & HT_C_REFERER && request->parentAnchor) {
2.13 frystyk 219: char *act = HTAnchor_address((HTAnchor *) anchor);
2.1 frystyk 220: char *parent = HTAnchor_address((HTAnchor *) request->parentAnchor);
221: char *relative = HTParse(parent, act,
222: PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
223: if (relative && *relative) {
2.24 frystyk 224: PUTS("Referer: ");
225: PUTS(parent);
226: PUTBLOCK(crlf, 2);
2.1 frystyk 227: }
2.26 frystyk 228: HT_FREE(act);
229: HT_FREE(parent);
230: HT_FREE(relative);
2.1 frystyk 231: }
2.22 frystyk 232: if (request->RequestMask & HT_C_USER_AGENT) {
2.24 frystyk 233: PUTS("User-Agent: ");
234: PUTS(HTLib_appName());
235: PUTC('/');
236: PUTS(HTLib_appVersion());
237: PUTC(' ');
238: PUTS(HTLib_name());
239: PUTC('/');
240: PUTS(HTLib_version());
241: PUTBLOCK(crlf, 2);
2.1 frystyk 242: }
2.27 eric 243: if (PROT_TRACE)HTTrace("HTTP........ Generating Request Headers\n");
2.1 frystyk 244: }
245:
2.29 frystyk 246: PRIVATE int HTTPRequest_put_block (HTStream * me, const char * b, int l)
2.1 frystyk 247: {
2.7 frystyk 248: if (!me->target) {
2.1 frystyk 249: return HT_WOULD_BLOCK;
2.7 frystyk 250: } else if (me->transparent)
2.11 frystyk 251: return b ? PUTBLOCK(b, l) : HT_OK;
2.1 frystyk 252: else {
253: int status;
2.11 frystyk 254: if (me->version == HTTP_09)
255: HTTP09Request(me, me->request);
2.24 frystyk 256: else {
2.11 frystyk 257: HTTPMakeRequest(me, me->request); /* Generate header */
2.1 frystyk 258: me->transparent = YES;
2.11 frystyk 259: return b ? PUTBLOCK(b, l) : HT_OK;
2.1 frystyk 260: }
261: return status;
262: }
263: }
264:
2.16 frystyk 265: PRIVATE int HTTPRequest_put_character (HTStream * me, char c)
2.1 frystyk 266: {
2.11 frystyk 267: return HTTPRequest_put_block(me, &c, 1);
2.1 frystyk 268: }
269:
2.29 frystyk 270: PRIVATE int HTTPRequest_put_string (HTStream * me, const char * s)
2.1 frystyk 271: {
2.11 frystyk 272: return HTTPRequest_put_block(me, s, strlen(s));
2.1 frystyk 273: }
274:
275: /*
276: ** Flushes data but doesn't free stream object
277: */
2.16 frystyk 278: PRIVATE int HTTPRequest_flush (HTStream * me)
2.1 frystyk 279: {
2.13 frystyk 280: int status = HTTPRequest_put_block(me, NULL, 0);
281: return status==HT_OK ? (*me->target->isa->flush)(me->target) : status;
2.1 frystyk 282: }
283:
284: /*
285: ** Flushes data and frees stream object
286: */
2.16 frystyk 287: PRIVATE int HTTPRequest_free (HTStream * me)
2.1 frystyk 288: {
2.11 frystyk 289: int status = HTTPRequest_flush(me);
290: if (status != HT_WOULD_BLOCK) {
291: if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
292: return HT_WOULD_BLOCK;
2.26 frystyk 293: HT_FREE(me);
2.1 frystyk 294: }
2.7 frystyk 295: return status;
2.1 frystyk 296: }
297:
2.16 frystyk 298: PRIVATE int HTTPRequest_abort (HTStream * me, HTList * e)
2.1 frystyk 299: {
2.13 frystyk 300: if (me->target) (*me->target->isa->abort)(me->target, e);
2.26 frystyk 301: HT_FREE(me);
2.27 eric 302: if (PROT_TRACE) HTTrace("HTTPRequest. ABORTING...\n");
2.1 frystyk 303: return HT_ERROR;
304: }
305:
306: /* HTTPRequest Stream
307: ** -----------------
308: */
2.29 frystyk 309: PRIVATE const HTStreamClass HTTPRequestClass =
2.1 frystyk 310: {
311: "HTTPRequest",
312: HTTPRequest_flush,
313: HTTPRequest_free,
314: HTTPRequest_abort,
315: HTTPRequest_put_character,
316: HTTPRequest_put_string,
317: HTTPRequest_put_block
318: };
319:
2.23 frystyk 320: PUBLIC HTStream * HTTPRequest_new (HTRequest * request, HTStream * target,
321: BOOL endHeader)
2.1 frystyk 322: {
2.32 ! frystyk 323: HTHost * host = HTNet_host(request->net);
2.26 frystyk 324: HTStream * me;
325: if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
326: HT_OUTOFMEM("HTTPRequest_new");
2.1 frystyk 327: me->isa = &HTTPRequestClass;
328: me->target = target;
329: me->request = request;
2.32 ! frystyk 330: me->version = HTHost_version(host);
2.1 frystyk 331: me->transparent = NO;
2.23 frystyk 332:
333: /* Return general HTTP header stream */
334: return HTTPGen_new(request, me, endHeader);
2.1 frystyk 335: }
Webmaster