1 /*****
2 * HTTP.h : Public header file for HTTP.c, a simple HTTP/1.0 implementation.
3 *
4 * This file Version	$Revision: 1.1 $
5 *
6 * Creation date:		Tue Oct 21 01:56:19 GMT+0100 1997
7 * Last modification: 	$Date: 1997/10/23 00:28:26 $
8 * By:					$Author: newt $
9 * Current State:		$State: Exp $
10 *
11 * Author:				Richard Offer
12 *
13 * Copyright (C) 1994-1997 by Richard Offer <offer@sgi.com>
14 * All Rights Reserved
15 *
16 * This library is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Library General Public
18 * License as published by the Free Software Foundation; either
19 * version 2 of the License, or (at your option) any later version.
20 *
21 * This library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24 * Library General Public License for more details.
25 *
26 * You should have received a copy of the GNU Library General Public
27 * License along with this library; if not, write to the Free
28 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 *
30 *****/
31 /*****
32 * $Source: /usr/local/rcs/Newt/XmHTML/RCS/HTTP.h,v $
33 *****/
34 /*****
35 * ChangeLog
36 * $Log: HTTP.h,v $
37 * Revision 1.1  1997/10/23 00:28:26  newt
38 * Initial Revision
39 *
40 *****/
41 
42 #ifndef _HTTP_h_
43 #define _HTTP_h_
44 
45 #define HTTPVERSION	0
46 #define HTTPREVISION	1
47 #define HTTPUPDATE_LEVEL 1
48 #define HTTPVersion \
49 	(HTTPVERSION * 1000 + HTTPREVISION * 100 + HTTPUPDATE_LEVEL)
50 
51 /* used by Imake to get Shared library version numbering */
52 #ifndef _LIBRARY
53 
54 #define LIBHTTPVERSION_STRING \
55 	"Client/HTTP Version 0.1.1 (C)Richard Offer and Ripley Software Development"
56 
57 /*****
58 * Feel free to re-define the following, this is passed to every web-server
59 * during all requests.
60 * If you do change this, be careful (bad editing may lead to failed requests)
61 * the format is
62 * User-Agent: <space> (manditory)
63 * <client identifier,most significant parts first> / <version number>
64 * <space>
65 * <extra fields, for development software, a point of contact is reccommended
66 * \r\n terminator
67 *
68 * wrapped in a #ifdef so an application can define it before #include'ing
69 * this file
70 *****/
71 #ifndef USER_AGENT
72 #define USER_AGENT "User-Agent: XmHTML-HTTP/0.1.x ripley@xs4all.nl\r\n"
73 #endif /* USER_AGENT */
74 
75 typedef enum {
76 	HTTPLoadToFile,
77 	HTTPLoadToString
78 } HTTPLoadType;
79 
80 typedef enum {
81 	HTTPGET,
82 	HTTPPOST,
83 	HTTPHEAD
84 } HTTPLoadMethod;
85 
86 /* possible HTTP return values */
87 typedef enum {
88 	/* our own error values */
89 	HTTPInvalid					= 0,
90 	HTTPBadProtocol				= 1,
91 	HTTPBadHost					= 2,
92 	HTTPBadURL					= 3,
93 	HTTPBadLoadType				= 4,
94 	HTTPMethodUnsupported		= 5,
95 	HTTPNoSocket				= 6,
96 	HTTPNoConnection			= 7,
97 	HTTPBadHttp10				= 8,
98 	HTTPCannotCreateFile		= 9,
99 	HTTPConnectTimeout			= 10,
100 	HTTPTimeout					= 11,
101 
102 	/* Now 'Real' HTTP return codes */
103 	HTTPContinue				= 100,
104 	HTTPSwitchProtocols			= 101,
105 
106 	HTTPSuccess					= 200,
107 	HTTPCreated					= 201,
108 	HTTPAccepted				= 202,
109 	HTTPNonAuthoritativeInfo	= 203,
110 	HTTPNoContent				= 204,
111 	HTTPResetContent			= 205,
112 	HTTPPartialContent			= 206,
113 
114 	HTTPMultipleChoices			= 300,
115 	HTTPPermMoved				= 301,
116 	HTTPTempMoved				= 302,
117 	HTTPSeeOther				= 303,
118 	HTTPNotModified				= 304,
119 	HTTPUseProxy				= 305,
120 
121 	HTTPBadRequest				= 400,
122 	HTTPUnauthorised			= 401,
123 	HTTPPaymentReq				= 402,
124 	HTTPForbidden				= 403,
125 	HTTPNotFound				= 404,
126 	HTTPMethodNotAllowed		= 405,
127 	HTTPNotAcceptable			= 406,
128 	HTTPProxyAuthReq			= 407,
129 	HTTPRequestTimeOut			= 408,
130 	HTTPConflict				= 409,
131 	HTTPGone					= 410,
132 	HTTPLengthReq				= 411,
133 	HTTPPreCondFailed			= 412,
134 	HTTPReqEntityTooBig			= 413,
135 	HTTPURITooBig				= 414,
136 	HTTPUnsupportedMediaType	= 415,
137 
138 	HTTPInternalServerError		= 500,
139 	HTTPNotImplemented			= 501,
140 	HTTPBadGateway				= 502,
141 	HTTPServiceUnavailable		= 503,
142 	HTTPGatewayTimeOut			= 504,
143 	HTTPHTTPVersionNotSupported	= 505
144 
145 } HTTPRequestReturn;
146 
147 /* flags for parseURL */
148 typedef enum {
149 	PARSE_SCHEME	= 1,
150 	PARSE_USER		= 2,
151 	PARSE_PASSWORD	= 4,
152 	PARSE_HOSTNAME	= 8,
153 	PARSE_PORT		= 16,
154 	PARSE_FILENAME	= 32
155 }HTTPParseURL;
156 
157 #define PARSE_URL (PARSE_SCHEME|PARSE_HOSTNAME|PARSE_PORT|PARSE_FILENAME)
158 
159 /*****
160 * Used internally for HTTP headers and externally for the form data
161 * name/value pairs
162 *****/
163 typedef struct _HTTPNamedValues {
164 	char *name;
165 	char *value;
166 } HTTPNamedValues;
167 
168 /*****
169 * Definition of a requestor.
170 * *never* store static data in the ptr fields as deleteHTTPRequest explicitly
171 * frees any non-NULL fields.
172 *****/
173 typedef struct _HTTPRequest {
174 	HTTPLoadType type;			/* load to string or file			*/
175 	char *in_data;				/* filename for LoadToFile			*/
176 	HTTPNamedValues *form_data;	/* data for form processing			*/
177 	unsigned char *out_data;	/* response string					*/
178 	size_t length;				/* length of out_data, from
179 								 * Content-Length or strlen
180 								 */
181 	HTTPLoadMethod method;		/* get, post etc					*/
182 	char *url;					/* fully qualified location			*/
183 
184 	int timeout;				/* select() timeout in seconds		*/
185 	int retry;					/* retry count, zero based			*/
186 
187 	HTTPNamedValues *headers;	/* array of returned headers		*/
188 	int num_headers;			/* no of headers					*/
189 
190 	HTTPRequestReturn ret;		/* Server return value				*/
191 }HTTPRequest;
192 
193 /* type of cookies
194  *   Not a lot an application can do here, it all depends on what the
195  *   server sends.
196  *
197  *   SetCookie implies the server is using Netscape style cookies.
198  *   SetCookie means the server is using RFC2109 style cookies.
199  */
200 enum { SetCookie, SetCookie2 };
201 
202 /* type of cookie file
203  *   For safety I am only going to support the writting of CookieJar files
204  *   however, I will allow an application to read cookie files generated by
205  *   netscape.
206  *
207  *   CookieJar (a name I've just invented) files are much richer than Netscape
208  *   ones, they have to be they store the full SetCookie2 response.
209  */
210 enum { NetscapeCookieFile = 1, CookieJar = 2 } ;
211 
212 typedef struct _HTTPCookie {
213 
214 	HTTPNamedValues	cookie;
215 	char	type;
216 	char	*comment;	/* this and the url are not preserved between sessions*/
217 	char	*commentURL;
218 	int		discard;
219 	char	*domain;
220 	int		exactHostMatch;
221 	int		secure;		/* not supported in HTTP.c */
222 	char	*path;
223 	int		expires;
224 	char	*port;
225 	int		version;
226 
227 } HTTPCookie;
228 
229 typedef struct _HTTPCookieList {
230 
231 	HTTPCookie	*cookie;
232 	struct _HTTPCookieList *next;
233 
234 } HTTPCookieList;
235 
236 typedef struct _HTTPCookieRequest {
237 
238 	HTTPCookieList *cookieList;
239 	HTTPCookieList *setCookie;
240 
241 	int	sendCookie;
242 
243 } HTTPCookieRequest;
244 
245 
246 typedef struct _HTTPCookieCache {
247 
248 	HTTPCookie	**cookies;
249 	int			ncookies;
250 
251 	char		*filename;
252 	char		fileType;
253 
254 } HTTPCookieCache ;
255 
256 
257 /*****
258 * Create a new, empty, request instance. This is the only safe way to create
259 * a request.
260 *****/
261 extern HTTPRequest *newHTTPRequest(void);
262 
263 /* make a request for some URI */
264 extern void loadHTTPURL(void *unused, HTTPRequest * request, HTTPCookieRequest *cookieReq);
265 
266 /*****
267 * Clear a no longer needed request instance. Deletes any field that have
268 * been allocated.
269 *****/
270 extern void deleteHTTPRequest(HTTPRequest * req);
271 
272 /* split a full URI into separate fields */
273 extern void parseURL(char *url, long parseflag, char **scheme,
274 	char **username, char **password, char **hostname, int *port,
275 	char **filename);
276 
277 /* free fields allocated by parseURL */
278 extern void freeURL(long parseflag, char *scheme, char *username,
279 	char *password, char *hostname, int port, char *filename);
280 
281 /* Determine whether or not the given url should be retrieved via HTTP. */
282 extern int HTTPAbsoluteURL(char *url);
283 
284 /*****
285 * Compose a full URI from a (possibly local) url and the base url for this
286 * document. Return value should be freed by caller unless the return value
287 * is stored in a HTTPRequest in which case it will be freed when
288 * deleteHTTPRequest is called.
289 *****/
290 extern char *HTTPFindAbsoluteURL(char *url, char *baseUrl);
291 
292 /* display an error message for the given error code */
293 extern void HTTPError(char *msg, HTTPRequestReturn error);
294 
295 extern const char *HTTPErrorString(HTTPRequestReturn error);
296 
297 /* unescape a HTTP escaped string */
298 void HTTPUnescapeResponse(char *buf);
299 
300 /* load the cookie file into memory, a cookieCache is self-contained so
301  * multiple files can be read within an app.
302  */
303 extern HTTPCookieCache * loadCookieFileToCache(char * filename, char fileType);
304 
305 /* The procedure for using cookies
306  *
307  *  1) load the cookie cache.
308  *  2) for a given URL, call getCookieFromCache(), this returns a
309  *     CookieRequest, req->cookieList is a list of all the cookies that apply
310  *     to the the URL (it will be NULL if no cookies are wanted by the server).
311  *  3) at this point the application can step in and inform the user that a
312  *     cookie is wanted by the server, if the user doesn't want to send the
313  *     cookie, it should set cookieRequest->sendCookie to false _before_ calling
314  *     loadHTTPUrl() (this is better than simply passing NULL into
315  *     loadHTTPUrl() since it gives tha application chnace to recieve any new
316  *     cookies.
317  *  4) on return from loadHTTPUrl() cookieRequest->setCookie will be non-null
318  *     if the server sent a save cookie response. The application can then
319  *     decide to save this cookie for the rest of the session by calling
320  *     addCookieListToCache (passing in cookieRequest->setCookie).
321  *  5) for permanant saving of the cookies the application needs to call
322  *     writeCookieCache();
323  */
324 
325 /*
326  * Notes.
327  *
328  * url must be fully qualified, CookieList is a linked-list of Cookies, all
329  * that apply to the url.
330  *
331  * To save the cookies between sessions, use writeCookieCache(). This writes
332  * cache back out (including any new cookies set during the session). Note that
333  * for safety, I'm not going to allow for the writing of Netscape cookie files
334  * (but using mergeCookieCache() we can read the existing Netscape cookie file
335  * and merge it with a custom cookie file (makes it easier moving to a new
336  * browser from netscape.
337  * ---if pushed, this may change later.
338  */
339 
340 extern HTTPCookieRequest *getCookieFromCache(HTTPCookieCache *, char * url);
341 
342 extern void addCookieListToCache(HTTPCookieCache *, HTTPCookieList *);
343 
344 extern void writeCookieCache(HTTPCookieCache *cache);
345 
346 /* take the cookies from cache c2 and add them into c1.
347  *   The reason for this is so that you can open an empty CookieJar file _and_
348  *   a Netscape cookie file (in that order), then take the cookies from the
349  *   Netscape file and save them into the CookieJar file (since I don't
350  *   support the writing of Netscape cookie files
351  *
352  *   Do not free c2
353  */
354 extern void mergeCookieCache(HTTPCookieCache *c1, HTTPCookieCache *c2);
355 
356 void freeCookieCache(HTTPCookieCache * , int /* free cookies ? */);
357 void freeCookieRequest(HTTPCookieRequest *);
358 
359 /* convenience macros */
360 #define NewNString(STR,len) \
361 	((STR) != NULL ? (strncpy(calloc(len+1,sizeof(char)), STR,(len))) : NULL)
362 
363 #define NewString(STR) \
364 	((STR) != NULL ? (strcpy(malloc(strlen(STR)+1),STR)) : NULL)
365 
366 #define	stringToBoolean(str) \
367 	((str) != NULL && *(str) ? ( *(str) == 'T' || *(str) == 't' || *(str) == 'y' ? 1: 0 ) : 0)
368 
369 #endif /* _LIBRARY */
370 
371 /* Don't add anything after this endif! */
372 #endif /* _HTTP_h_ */
373