Annotation of libwww/Library/src/HTTPReq.c, revision 2.37
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.
2.37 ! frystyk 6: ** @(#) $Id: HTTPReq.c,v 2.36 1996/07/02 22:55:13 frystyk Exp $
2.32 frystyk 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.23 frystyk 20: #include "HTTPGen.h"
2.21 frystyk 21: #include "HTTPUtil.h"
2.1 frystyk 22: #include "HTTPReq.h" /* Implements */
23:
2.24 frystyk 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.29 frystyk 29: const HTStreamClass * isa;
2.1 frystyk 30: HTStream * target;
31: HTRequest * request;
2.18 frystyk 32: SOCKET sockfd;
2.11 frystyk 33: int version;
2.1 frystyk 34: BOOL transparent;
35: };
36:
37: /* ------------------------------------------------------------------------- */
38: /* HTTP Output Request Stream */
39: /* ------------------------------------------------------------------------- */
40:
2.11 frystyk 41: /* HTTP09Request
42: ** -------------
43: ** Makes a HTTP/0.9 request
2.1 frystyk 44: */
2.11 frystyk 45: PRIVATE void HTTP09Request (HTStream * me, HTRequest * request)
46: {
2.34 frystyk 47: HTParentAnchor * anchor = HTRequest_anchor(request);
48: char * addr = HTAnchor_physical(anchor);
49: char * fullurl = HTParse(addr, "", PARSE_PATH|PARSE_PUNCTUATION);
2.24 frystyk 50: PUTS("GET ");
51: PUTS(fullurl);
52: PUTC(CR);
53: PUTC(LF);
2.11 frystyk 54: }
55:
56: /* HTTPMakeRequest
57: ** ---------------
58: ** Makes a HTTP/1.0-1.1 request header.
59: */
60: PRIVATE void HTTPMakeRequest (HTStream * me, HTRequest * request)
2.1 frystyk 61: {
2.24 frystyk 62: char crlf[3];
63: char qstr[10];
2.34 frystyk 64: HTRqHd request_mask = HTRequest_rqHd(request);
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 */
2.34 frystyk 69: {
70: HTMethod method = HTRequest_method(request);
71: if (method != METHOD_INVALID) {
72: PUTS(HTMethod_name(method));
73: PUTC(' ');
74: } else
75: PUTS("GET ");
76: }
2.1 frystyk 77:
78: /* If we are using a proxy then only take the `path' info in the URL */
79: {
2.13 frystyk 80: char *addr = HTAnchor_physical(anchor);
2.6 frystyk 81: char *fullurl = HTParse(addr, "", PARSE_PATH|PARSE_PUNCTUATION);
2.35 frystyk 82: if (HTRequest_fullURI(request)) {
2.24 frystyk 83: PUTS(fullurl+1);
2.1 frystyk 84: } else {
2.24 frystyk 85: PUTS(fullurl);
2.1 frystyk 86: }
2.26 frystyk 87: HT_FREE(fullurl);
2.1 frystyk 88: }
2.25 frystyk 89: PUTC(' ');
90: PUTS(HTTP_VERSION);
2.24 frystyk 91: PUTBLOCK(crlf, 2);
2.1 frystyk 92:
2.4 frystyk 93: /* Request Headers */
2.34 frystyk 94: if (request_mask & HT_C_ACCEPT_TYPE) {
2.37 ! frystyk 95: /*
! 96: ** If caller has specified a specific output format then use this.
! 97: ** Otherwise use all the registered converters to generate the
! 98: ** accept header
! 99: */
! 100: if (HTRequest_outputFormat(request) == WWW_PRESENT) {
! 101: int list;
! 102: HTList *cur;
! 103: BOOL first=YES;
! 104: for (list=0; list<2; list++) {
! 105: if ((!list && ((cur = HTFormat_conversion()) != NULL)) ||
! 106: (list && ((cur = HTRequest_conversion(request))!=NULL))) {
! 107: HTPresentation * pres;
! 108: while ((pres=(HTPresentation *) HTList_nextObject(cur))) {
! 109: if (pres->rep_out==WWW_PRESENT && pres->quality<=1.0) {
! 110: if (first) {
! 111: PUTS("Accept: ");
! 112: first=NO;
! 113: } else
! 114: PUTC(',');
! 115: PUTS(HTAtom_name(pres->rep));
! 116: if (pres->quality != 1.0) {
! 117: sprintf(qstr, ";q=%1.1f", pres->quality);
! 118: PUTS(qstr);
! 119: }
2.1 frystyk 120: }
121: }
122: }
123: }
2.37 ! frystyk 124: if (!first) PUTBLOCK(crlf, 2);
! 125: } else {
! 126: PUTS("Accept: ");
! 127: PUTS(HTAtom_name(HTRequest_outputFormat(request)));
! 128: PUTBLOCK(crlf, 2);
! 129: }
2.1 frystyk 130: }
2.34 frystyk 131: if (request_mask & HT_C_ACCEPT_CHAR) {
2.4 frystyk 132: int list;
133: HTList *cur;
2.24 frystyk 134: BOOL first=YES;
2.4 frystyk 135: for (list=0; list<2; list++) {
2.14 frystyk 136: if ((!list && ((cur = HTFormat_charset()) != NULL)) ||
137: (list && ((cur = HTRequest_charset(request)) != NULL))) {
2.4 frystyk 138: HTAcceptNode *pres;
139: while ((pres = (HTAcceptNode *) HTList_nextObject(cur))) {
2.5 frystyk 140: if (first) {
2.24 frystyk 141: PUTS("Accept-Charset: ");
2.5 frystyk 142: first=NO;
2.24 frystyk 143: } else
144: PUTC(',');
145: PUTS(HTAtom_name(pres->atom));
2.4 frystyk 146: }
147: }
148: }
2.31 frystyk 149: if (!first) PUTBLOCK(crlf, 2);
2.4 frystyk 150: }
2.34 frystyk 151: if (request_mask & HT_C_ACCEPT_ENC) {
2.4 frystyk 152: int list;
153: HTList *cur;
2.24 frystyk 154: BOOL first=YES;
2.4 frystyk 155: for (list=0; list<2; list++) {
2.33 frystyk 156: if ((!list && ((cur = HTFormat_contentCoding()) != NULL)) ||
2.14 frystyk 157: (list && ((cur = HTRequest_encoding(request)) != NULL))) {
2.33 frystyk 158: HTCoding * pres;
159: while ((pres = (HTCoding *) HTList_nextObject(cur))) {
2.5 frystyk 160: if (first) {
2.24 frystyk 161: PUTS("Accept-Encoding: ");
2.32 frystyk 162: first = NO;
2.24 frystyk 163: } else
164: PUTC(',');
2.33 frystyk 165: PUTS(HTCoding_name(pres));
2.4 frystyk 166: }
167: }
168: }
2.31 frystyk 169: if (!first) PUTBLOCK(crlf, 2);
2.4 frystyk 170: }
2.34 frystyk 171: if (request_mask & HT_C_ACCEPT_LAN) {
2.4 frystyk 172: int list;
173: HTList *cur;
2.24 frystyk 174: BOOL first=YES;
2.4 frystyk 175: for (list=0; list<2; list++) {
2.14 frystyk 176: if ((!list && ((cur = HTFormat_language()) != NULL)) ||
177: (list && ((cur = HTRequest_language(request)) != NULL))) {
2.4 frystyk 178: HTAcceptNode *pres;
179: while ((pres = (HTAcceptNode *) HTList_nextObject(cur))) {
2.5 frystyk 180: if (first) {
2.24 frystyk 181: PUTS("Accept-Language: ");
2.5 frystyk 182: first=NO;
2.24 frystyk 183: } else
184: PUTC(',');
185: PUTS(HTAtom_name(pres->atom));
186: if (pres->quality != 1.0) {
187: sprintf(qstr, ";q=%1.1f", pres->quality);
188: PUTS(qstr);
2.5 frystyk 189: }
2.4 frystyk 190: }
191: }
192: }
2.31 frystyk 193: if (!first) PUTBLOCK(crlf, 2);
2.4 frystyk 194: }
2.36 frystyk 195: if (request_mask & HT_C_AUTH) {
2.34 frystyk 196: HTAssocList * cur = HTRequest_credentials(request);
197: if (cur) { /* Access authentication */
198: HTAssoc * pres;
199: while ((pres = (HTAssoc *) HTAssocList_nextObject(cur))) {
200: PUTS(HTAssoc_name(pres));
201: PUTS(": ");
202: PUTS(HTAssoc_value(pres));
203: PUTBLOCK(crlf, 2);
204: }
2.28 frystyk 205: }
2.1 frystyk 206: }
2.34 frystyk 207: if (request_mask & HT_C_FROM) {
208: HTUserProfile * up = HTRequest_userProfile(request);
209: const char * mailaddress = HTUserProfile_email(up);
2.1 frystyk 210: if (mailaddress) {
2.24 frystyk 211: PUTS("From: ");
212: PUTS(mailaddress);
213: PUTBLOCK(crlf, 2);
2.1 frystyk 214: }
215: }
2.34 frystyk 216: if (request_mask & HT_C_IMS) {
2.21 frystyk 217: time_t lm = HTAnchor_lastModified(anchor);
2.24 frystyk 218: if (lm > 0) {
219: PUTS("If-Modified-Since: ");
220: PUTS(HTDateTimeStr(&lm, NO));
221: PUTBLOCK(crlf, 2);
2.8 frystyk 222: }
223: }
2.34 frystyk 224: if (request_mask & HT_C_HOST) {
2.13 frystyk 225: char *orig = HTAnchor_address((HTAnchor *) anchor);
2.12 frystyk 226: char *host = HTParse(orig, "", PARSE_HOST);
2.34 frystyk 227: #if 0
228: /* Keep the port number for HTTP/1.1 compliance */
2.12 frystyk 229: char *ptr = strchr(host, ':'); /* Chop off port number */
230: if (ptr) *ptr = '\0';
2.34 frystyk 231: #endif
2.24 frystyk 232: PUTS("Host: ");
233: PUTS(host);
234: PUTBLOCK(crlf, 2);
2.26 frystyk 235: HT_FREE(orig);
236: HT_FREE(host);
2.1 frystyk 237: }
2.34 frystyk 238: if (request_mask & HT_C_REFERER) {
239: HTParentAnchor * parent_anchor = HTRequest_parent(request);
240: if (parent_anchor) {
241: char * act = HTAnchor_address((HTAnchor *) anchor);
242: char * parent = HTAnchor_address((HTAnchor *) parent_anchor);
243: char * relative = HTParse(parent, act,
244: PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
245: if (relative && *relative) {
246: PUTS("Referer: ");
247: PUTS(parent);
248: PUTBLOCK(crlf, 2);
249: }
250: HT_FREE(act);
251: HT_FREE(parent);
252: HT_FREE(relative);
2.1 frystyk 253: }
254: }
2.34 frystyk 255: if (request_mask & HT_C_USER_AGENT) {
2.24 frystyk 256: PUTS("User-Agent: ");
257: PUTS(HTLib_appName());
258: PUTC('/');
259: PUTS(HTLib_appVersion());
260: PUTC(' ');
261: PUTS(HTLib_name());
262: PUTC('/');
263: PUTS(HTLib_version());
264: PUTBLOCK(crlf, 2);
2.1 frystyk 265: }
2.27 eric 266: if (PROT_TRACE)HTTrace("HTTP........ Generating Request Headers\n");
2.1 frystyk 267: }
268:
2.29 frystyk 269: PRIVATE int HTTPRequest_put_block (HTStream * me, const char * b, int l)
2.1 frystyk 270: {
2.7 frystyk 271: if (!me->target) {
2.1 frystyk 272: return HT_WOULD_BLOCK;
2.7 frystyk 273: } else if (me->transparent)
2.11 frystyk 274: return b ? PUTBLOCK(b, l) : HT_OK;
2.1 frystyk 275: else {
276: int status;
2.11 frystyk 277: if (me->version == HTTP_09)
278: HTTP09Request(me, me->request);
2.24 frystyk 279: else {
2.11 frystyk 280: HTTPMakeRequest(me, me->request); /* Generate header */
2.1 frystyk 281: me->transparent = YES;
2.11 frystyk 282: return b ? PUTBLOCK(b, l) : HT_OK;
2.1 frystyk 283: }
284: return status;
285: }
286: }
287:
2.16 frystyk 288: PRIVATE int HTTPRequest_put_character (HTStream * me, char c)
2.1 frystyk 289: {
2.11 frystyk 290: return HTTPRequest_put_block(me, &c, 1);
2.1 frystyk 291: }
292:
2.29 frystyk 293: PRIVATE int HTTPRequest_put_string (HTStream * me, const char * s)
2.1 frystyk 294: {
2.11 frystyk 295: return HTTPRequest_put_block(me, s, strlen(s));
2.1 frystyk 296: }
297:
298: /*
299: ** Flushes data but doesn't free stream object
300: */
2.16 frystyk 301: PRIVATE int HTTPRequest_flush (HTStream * me)
2.1 frystyk 302: {
2.13 frystyk 303: int status = HTTPRequest_put_block(me, NULL, 0);
304: return status==HT_OK ? (*me->target->isa->flush)(me->target) : status;
2.1 frystyk 305: }
306:
307: /*
308: ** Flushes data and frees stream object
309: */
2.16 frystyk 310: PRIVATE int HTTPRequest_free (HTStream * me)
2.1 frystyk 311: {
2.11 frystyk 312: int status = HTTPRequest_flush(me);
313: if (status != HT_WOULD_BLOCK) {
314: if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
315: return HT_WOULD_BLOCK;
2.26 frystyk 316: HT_FREE(me);
2.1 frystyk 317: }
2.7 frystyk 318: return status;
2.1 frystyk 319: }
320:
2.16 frystyk 321: PRIVATE int HTTPRequest_abort (HTStream * me, HTList * e)
2.1 frystyk 322: {
2.13 frystyk 323: if (me->target) (*me->target->isa->abort)(me->target, e);
2.26 frystyk 324: HT_FREE(me);
2.27 eric 325: if (PROT_TRACE) HTTrace("HTTPRequest. ABORTING...\n");
2.1 frystyk 326: return HT_ERROR;
327: }
328:
329: /* HTTPRequest Stream
330: ** -----------------
331: */
2.29 frystyk 332: PRIVATE const HTStreamClass HTTPRequestClass =
2.1 frystyk 333: {
334: "HTTPRequest",
335: HTTPRequest_flush,
336: HTTPRequest_free,
337: HTTPRequest_abort,
338: HTTPRequest_put_character,
339: HTTPRequest_put_string,
340: HTTPRequest_put_block
341: };
342:
2.23 frystyk 343: PUBLIC HTStream * HTTPRequest_new (HTRequest * request, HTStream * target,
344: BOOL endHeader)
2.1 frystyk 345: {
2.34 frystyk 346: HTNet * net = HTRequest_net(request);
347: HTHost * host = HTNet_host(net);
2.26 frystyk 348: HTStream * me;
349: if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
350: HT_OUTOFMEM("HTTPRequest_new");
2.1 frystyk 351: me->isa = &HTTPRequestClass;
352: me->target = target;
353: me->request = request;
2.32 frystyk 354: me->version = HTHost_version(host);
2.1 frystyk 355: me->transparent = NO;
2.23 frystyk 356:
357: /* Return general HTTP header stream */
358: return HTTPGen_new(request, me, endHeader);
2.1 frystyk 359: }
Webmaster