1 /*
2  * "$Id: http.h 148 2006-04-25 16:54:17Z njacobs $"
3  *
4  *   Hyper-Text Transport Protocol definitions for the Common UNIX Printing
5  *   System (CUPS).
6  *
7  *   Copyright 1997-2005 by Easy Software Products, all rights reserved.
8  *
9  *   These coded instructions, statements, and computer programs are the
10  *   property of Easy Software Products and are protected by Federal
11  *   copyright law.  Distribution and use rights are outlined in the file
12  *   "LICENSE.txt" which should have been included with this file.  If this
13  *   file is missing or damaged please contact Easy Software Products
14  *   at:
15  *
16  *       Attn: CUPS Licensing Information
17  *       Easy Software Products
18  *       44141 Airport View Drive, Suite 204
19  *       Hollywood, Maryland 20636 USA
20  *
21  *       Voice: (301) 373-9600
22  *       EMail: cups-info@cups.org
23  *         WWW: http://www.cups.org
24  *
25  *   This file is subject to the Apple OS-Developed Software exception.
26  */
27 
28 #ifndef _CUPS_HTTP_H_
29 #define _CUPS_HTTP_H_
30 
31 /*
32  * Include necessary headers...
33  */
34 
35 #  include <string.h>
36 #  include <time.h>
37 #  ifdef WIN32
38 #    include <winsock.h>
39 #  else
40 #    include <unistd.h>
41 #    include <sys/time.h>
42 #    include <sys/types.h>
43 #    include <sys/socket.h>
44 #    include <netdb.h>
45 #    include <netinet/in.h>
46 #    include <arpa/inet.h>
47 #    include <netinet/in_systm.h>
48 #    include <netinet/ip.h>
49 #    if !defined(__APPLE__) || !defined(TCP_NODELAY)
50 #      include <netinet/tcp.h>
51 #    endif /* !__APPLE__ || !TCP_NODELAY */
52 #    ifdef AF_LOCAL
53 #      include <sys/un.h>
54 #    endif /* AF_LOCAL */
55 #  endif /* WIN32 */
56 
57 
58 /*
59  * C++ magic...
60  */
61 
62 #ifdef __cplusplus
63 extern "C" {
64 #endif
65 
66 
67 /*
68  * Oh, the wonderful world of IPv6 compatibility.  Apparently some
69  * implementations expose the (more logical) 32-bit address parts
70  * to everyone, while others only expose it to kernel code...  To
71  * make supporting IPv6 even easier, each vendor chose different
72  * core structure and union names, so the same defines or code
73  * can't be used on all platforms.
74  *
75  * The following will likely need tweeking on new platforms that
76  * support IPv6 - the "s6_addr32" define maps to the 32-bit integer
77  * array in the in6_addr union, which is named differently on various
78  * platforms.
79  */
80 
81 #if defined(AF_INET6) && !defined(s6_addr32)
82 #  if defined(__sun)
83 #    define s6_addr32	_S6_un._S6_u32
84 #  elif defined(__FreeBSD__) || defined(__APPLE__)
85 #    define s6_addr32	__u6_addr.__u6_addr32
86 #  endif /* __sun */
87 #endif /* AF_INET6 && !s6_addr32 */
88 
89 
90 /*
91  * Limits...
92  */
93 
94 #  define HTTP_MAX_URI		1024	/* Max length of URI string */
95 #  define HTTP_MAX_HOST		256	/* Max length of hostname string */
96 #  define HTTP_MAX_BUFFER	2048	/* Max length of data buffer */
97 #  define HTTP_MAX_VALUE	256	/* Max header field value length */
98 
99 
100 /*
101  * HTTP state values...
102  */
103 
104 typedef enum			/* States are server-oriented */
105 {
106   HTTP_WAITING,			/* Waiting for command */
107   HTTP_OPTIONS,			/* OPTIONS command, waiting for blank line */
108   HTTP_GET,			/* GET command, waiting for blank line */
109   HTTP_GET_SEND,		/* GET command, sending data */
110   HTTP_HEAD,			/* HEAD command, waiting for blank line */
111   HTTP_POST,			/* POST command, waiting for blank line */
112   HTTP_POST_RECV,		/* POST command, receiving data */
113   HTTP_POST_SEND,		/* POST command, sending data */
114   HTTP_PUT,			/* PUT command, waiting for blank line */
115   HTTP_PUT_RECV,		/* PUT command, receiving data */
116   HTTP_DELETE,			/* DELETE command, waiting for blank line */
117   HTTP_TRACE,			/* TRACE command, waiting for blank line */
118   HTTP_CLOSE,			/* CLOSE command, waiting for blank line */
119   HTTP_STATUS			/* Command complete, sending status */
120 } http_state_t;
121 
122 
123 /*
124  * HTTP version numbers...
125  */
126 
127 typedef enum
128 {
129   HTTP_0_9 = 9,			/* HTTP/0.9 */
130   HTTP_1_0 = 100,		/* HTTP/1.0 */
131   HTTP_1_1 = 101		/* HTTP/1.1 */
132 } http_version_t;
133 
134 
135 /*
136  * HTTP keep-alive values...
137  */
138 
139 typedef enum
140 {
141   HTTP_KEEPALIVE_OFF = 0,
142   HTTP_KEEPALIVE_ON
143 } http_keepalive_t;
144 
145 
146 /*
147  * HTTP transfer encoding values...
148  */
149 
150 typedef enum
151 {
152   HTTP_ENCODE_LENGTH,		/* Data is sent with Content-Length */
153   HTTP_ENCODE_CHUNKED		/* Data is chunked */
154 } http_encoding_t;
155 
156 
157 /*
158  * HTTP encryption values...
159  */
160 
161 typedef enum
162 {
163   HTTP_ENCRYPT_IF_REQUESTED,	/* Encrypt if requested (TLS upgrade) */
164   HTTP_ENCRYPT_NEVER,		/* Never encrypt */
165   HTTP_ENCRYPT_REQUIRED,	/* Encryption is required (TLS upgrade) */
166   HTTP_ENCRYPT_ALWAYS		/* Always encrypt (SSL) */
167 } http_encryption_t;
168 
169 
170 /*
171  * HTTP authentication types...
172  */
173 
174 typedef enum
175 {
176   HTTP_AUTH_NONE,		/* No authentication in use */
177   HTTP_AUTH_BASIC,		/* Basic authentication in use */
178   HTTP_AUTH_MD5,		/* Digest authentication in use */
179   HTTP_AUTH_MD5_SESS,		/* MD5-session authentication in use */
180   HTTP_AUTH_MD5_INT,		/* Digest authentication in use for body */
181   HTTP_AUTH_MD5_SESS_INT	/* MD5-session authentication in use for body */
182 } http_auth_t;
183 
184 
185 /*
186  * HTTP status codes...
187  */
188 
189 typedef enum
190 {
191   HTTP_ERROR = -1,		/* An error response from httpXxxx() */
192 
193   HTTP_CONTINUE = 100,		/* Everything OK, keep going... */
194   HTTP_SWITCHING_PROTOCOLS,	/* HTTP upgrade to TLS/SSL */
195 
196   HTTP_OK = 200,		/* OPTIONS/GET/HEAD/POST/TRACE command was successful */
197   HTTP_CREATED,			/* PUT command was successful */
198   HTTP_ACCEPTED,		/* DELETE command was successful */
199   HTTP_NOT_AUTHORITATIVE,	/* Information isn't authoritative */
200   HTTP_NO_CONTENT,		/* Successful command, no new data */
201   HTTP_RESET_CONTENT,		/* Content was reset/recreated */
202   HTTP_PARTIAL_CONTENT,		/* Only a partial file was recieved/sent */
203 
204   HTTP_MULTIPLE_CHOICES = 300,	/* Multiple files match request */
205   HTTP_MOVED_PERMANENTLY,	/* Document has moved permanently */
206   HTTP_MOVED_TEMPORARILY,	/* Document has moved temporarily */
207   HTTP_SEE_OTHER,		/* See this other link... */
208   HTTP_NOT_MODIFIED,		/* File not modified */
209   HTTP_USE_PROXY,		/* Must use a proxy to access this URI */
210 
211   HTTP_BAD_REQUEST = 400,	/* Bad request */
212   HTTP_UNAUTHORIZED,		/* Unauthorized to access host */
213   HTTP_PAYMENT_REQUIRED,	/* Payment required */
214   HTTP_FORBIDDEN,		/* Forbidden to access this URI */
215   HTTP_NOT_FOUND,		/* URI was not found */
216   HTTP_METHOD_NOT_ALLOWED,	/* Method is not allowed */
217   HTTP_NOT_ACCEPTABLE,		/* Not Acceptable */
218   HTTP_PROXY_AUTHENTICATION,	/* Proxy Authentication is Required */
219   HTTP_REQUEST_TIMEOUT,		/* Request timed out */
220   HTTP_CONFLICT,		/* Request is self-conflicting */
221   HTTP_GONE,			/* Server has gone away */
222   HTTP_LENGTH_REQUIRED,		/* A content length or encoding is required */
223   HTTP_PRECONDITION,		/* Precondition failed */
224   HTTP_REQUEST_TOO_LARGE,	/* Request entity too large */
225   HTTP_URI_TOO_LONG,		/* URI too long */
226   HTTP_UNSUPPORTED_MEDIATYPE,	/* The requested media type is unsupported */
227   HTTP_UPGRADE_REQUIRED = 426,	/* Upgrade to SSL/TLS required */
228 
229   HTTP_SERVER_ERROR = 500,	/* Internal server error */
230   HTTP_NOT_IMPLEMENTED,		/* Feature not implemented */
231   HTTP_BAD_GATEWAY,		/* Bad gateway */
232   HTTP_SERVICE_UNAVAILABLE,	/* Service is unavailable */
233   HTTP_GATEWAY_TIMEOUT,		/* Gateway connection timed out */
234   HTTP_NOT_SUPPORTED		/* HTTP version not supported */
235 } http_status_t;
236 
237 
238 /*
239  * HTTP field names...
240  */
241 
242 typedef enum
243 {
244   HTTP_FIELD_UNKNOWN = -1,
245   HTTP_FIELD_ACCEPT_LANGUAGE,
246   HTTP_FIELD_ACCEPT_RANGES,
247   HTTP_FIELD_AUTHORIZATION,
248   HTTP_FIELD_CONNECTION,
249   HTTP_FIELD_CONTENT_ENCODING,
250   HTTP_FIELD_CONTENT_LANGUAGE,
251   HTTP_FIELD_CONTENT_LENGTH,
252   HTTP_FIELD_CONTENT_LOCATION,
253   HTTP_FIELD_CONTENT_MD5,
254   HTTP_FIELD_CONTENT_RANGE,
255   HTTP_FIELD_CONTENT_TYPE,
256   HTTP_FIELD_CONTENT_VERSION,
257   HTTP_FIELD_DATE,
258   HTTP_FIELD_HOST,
259   HTTP_FIELD_IF_MODIFIED_SINCE,
260   HTTP_FIELD_IF_UNMODIFIED_SINCE,
261   HTTP_FIELD_KEEP_ALIVE,
262   HTTP_FIELD_LAST_MODIFIED,
263   HTTP_FIELD_LINK,
264   HTTP_FIELD_LOCATION,
265   HTTP_FIELD_RANGE,
266   HTTP_FIELD_REFERER,
267   HTTP_FIELD_RETRY_AFTER,
268   HTTP_FIELD_TRANSFER_ENCODING,
269   HTTP_FIELD_UPGRADE,
270   HTTP_FIELD_USER_AGENT,
271   HTTP_FIELD_WWW_AUTHENTICATE,
272   HTTP_FIELD_MAX
273 } http_field_t;
274 
275 
276 /*
277  * HTTP address structure (makes using IPv6 a little easier and more portable.)
278  */
279 
280 typedef union
281 {
282   struct sockaddr	addr;		/* Base structure for family value */
283   struct sockaddr_in	ipv4;		/* IPv4 address */
284 #ifdef AF_INET6
285   struct sockaddr_in6	ipv6;		/* IPv6 address */
286 #endif /* AF_INET6 */
287 #ifdef AF_LOCAL
288   struct sockaddr_un	un;		/* Domain socket file */
289 #endif /* AF_LOCAL */
290   char			pad[128];	/* Pad to ensure binary compatibility */
291 } http_addr_t;
292 
293 /*
294  * HTTP connection structure...
295  */
296 
297 typedef struct
298 {
299   int			fd;		/* File descriptor for this socket */
300   int			blocking;	/* To block or not to block */
301   int			error;		/* Last error on read */
302   time_t		activity;	/* Time since last read/write */
303   http_state_t		state;		/* State of client */
304   http_status_t		status;		/* Status of last request */
305   http_version_t	version;	/* Protocol version */
306   http_keepalive_t	keep_alive;	/* Keep-alive supported? */
307   struct sockaddr_in	oldaddr;	/* Address of connected host */
308   char			hostname[HTTP_MAX_HOST],
309   					/* Name of connected host */
310 			fields[HTTP_FIELD_MAX][HTTP_MAX_VALUE];
311 					/* Field values */
312   char			*data;		/* Pointer to data buffer */
313   http_encoding_t	data_encoding;	/* Chunked or not */
314   int			data_remaining;	/* Number of bytes left */
315   int			used;		/* Number of bytes used in buffer */
316   char			buffer[HTTP_MAX_BUFFER];
317 					/* Buffer for messages */
318   int			auth_type;	/* Authentication in use */
319   char			nonce[HTTP_MAX_VALUE];
320 					/* Nonce value */
321   int			nonce_count;	/* Nonce count */
322   void			*tls;		/* TLS state information */
323   http_encryption_t	encryption;	/* Encryption requirements */
324   /**** New in CUPS 1.1.19 ****/
325   fd_set		*input_set;	/* select() set for httpWait() */
326   http_status_t		expect;		/* Expect: header */
327   char			*cookie;	/* Cookie value(s) */
328   /**** New in CUPS 1.1.20 ****/
329   char			authstring[HTTP_MAX_VALUE],
330 					/* Current Authentication value */
331 			userpass[HTTP_MAX_VALUE];
332 					/* Username:password string */
333   int			digest_tries;	/* Number of tries for digest auth */
334   /**** New in CUPS 1.2 ****/
335   http_addr_t		hostaddr;	/* Host address and port */
336 } http_t;
337 
338 
339 /*
340  * Prototypes...
341  */
342 
343 #  define		httpBlocking(http,b)	(http)->blocking = (b)
344 extern int		httpCheck(http_t *http);
345 #  define		httpClearFields(http)	memset((http)->fields, 0, sizeof((http)->fields)),\
346 						httpSetField((http), HTTP_FIELD_HOST, (http)->hostname)
347 extern void		httpClose(http_t *http);
348 extern http_t		*httpConnect(const char *host, int port);
349 extern http_t		*httpConnectEncrypt(const char *host, int port,
350 			                    http_encryption_t encrypt);
351 extern int		httpDelete(http_t *http, const char *uri);
352 extern int		httpEncryption(http_t *http, http_encryption_t e);
353 #  define		httpError(http) ((http)->error)
354 extern void		httpFlush(http_t *http);
355 extern int		httpGet(http_t *http, const char *uri);
356 extern char		*httpGets(char *line, int length, http_t *http);
357 extern const char	*httpGetDateString(time_t t);
358 extern time_t		httpGetDateTime(const char *s);
359 #  define		httpGetField(http,field)	(http)->fields[field]
360 extern struct hostent	*httpGetHostByName(const char *name);
361 extern char		*httpGetSubField(http_t *http, http_field_t field,
362 			                 const char *name, char *value);
363 extern int		httpHead(http_t *http, const char *uri);
364 extern void		httpInitialize(void);
365 extern int		httpOptions(http_t *http, const char *uri);
366 extern int		httpPost(http_t *http, const char *uri);
367 extern int		httpPrintf(http_t *http, const char *format, ...)
368 #  ifdef __GNUC__
369 __attribute__ ((__format__ (__printf__, 2, 3)))
370 #  endif /* __GNUC__ */
371 ;
372 extern int		httpPut(http_t *http, const char *uri);
373 extern int		httpRead(http_t *http, char *buffer, int length);
374 extern int		httpReconnect(http_t *http);
375 extern void		httpSeparate(const char *uri, char *method,
376 			             char *username, char *host, int *port,
377 				     char *resource);
378 extern void		httpSetField(http_t *http, http_field_t field,
379 			             const char *value);
380 extern const char	*httpStatus(http_status_t status);
381 extern int		httpTrace(http_t *http, const char *uri);
382 extern http_status_t	httpUpdate(http_t *http);
383 extern int		httpWrite(http_t *http, const char *buffer, int length);
384 extern char		*httpEncode64(char *out, const char *in);
385 extern char		*httpDecode64(char *out, const char *in);
386 extern int		httpGetLength(http_t *http);
387 extern char		*httpMD5(const char *, const char *, const char *,
388 			         char [33]);
389 extern char		*httpMD5Final(const char *, const char *, const char *,
390 			              char [33]);
391 extern char		*httpMD5String(const unsigned char *, char [33]);
392 
393 /**** New in CUPS 1.1.19 ****/
394 extern void		httpClearCookie(http_t *http);
395 #define httpGetCookie(http) ((http)->cookie)
396 extern void		httpSetCookie(http_t *http, const char *cookie);
397 extern int		httpWait(http_t *http, int msec);
398 
399 /**** New in CUPS 1.1.21 ****/
400 extern char		*httpDecode64_2(char *out, int *outlen, const char *in);
401 extern char		*httpEncode64_2(char *out, int outlen, const char *in,
402 			                int inlen);
403 extern void		httpSeparate2(const char *uri,
404 			              char *method, int methodlen,
405 			              char *username, int usernamelen,
406 				      char *host, int hostlen, int *port,
407 				      char *resource, int resourcelen);
408 
409 /**** New in CUPS 1.2 ****/
410 extern int		httpAddrAny(const http_addr_t *addr);
411 extern int		httpAddrEqual(const http_addr_t *addr1,
412 			              const http_addr_t *addr2);
413 extern void		httpAddrLoad(const struct hostent *host, int port,
414 			             int n, http_addr_t *addr);
415 extern int		httpAddrLocalhost(const http_addr_t *addr);
416 extern char		*httpAddrLookup(const http_addr_t *addr,
417                                         char *name, int namelen);
418 extern char		*httpAddrString(const http_addr_t *addr,
419 			                char *s, int slen);
420 
421 #include <stdio.h>
422 extern void httpDumpData(FILE *, const char *, const char *, int);
423 
424 
425 /*
426  * C++ magic...
427  */
428 
429 #ifdef __cplusplus
430 }
431 #endif
432 
433 #endif /* !_CUPS_HTTP_H_ */
434 
435 /*
436  * End of "$Id: http.h 148 2006-04-25 16:54:17Z njacobs $"
437  */
438