1 /*
2     GSK - a library to write servers
3     Copyright (C) 1999-2000 Dave Benson
4 
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Lesser General Public
7     License as published by the Free Software Foundation; either
8     version 2 of the License, or (at your option) any later version.
9 
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Lesser General Public License for more details.
14 
15     You should have received a copy of the GNU Lesser General Public
16     License along with this library; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
18 
19     Contact:
20         daveb@ffem.org <Dave Benson>
21 */
22 
23 /*
24  * As per the HTTP 1.1 Specification, RFC 2616.
25  *
26  * TODO:  Compliance notes.
27  */
28 
29 #ifndef __GSK_HTTP_HEADER_H_
30 #define __GSK_HTTP_HEADER_H_
31 
32 #include <glib-object.h>
33 #include "../gskbuffer.h"
34 
35 G_BEGIN_DECLS
36 
37 typedef struct _GskHttpHeaderClass GskHttpHeaderClass;
38 typedef struct _GskHttpHeader GskHttpHeader;
39 typedef struct _GskHttpAuthorization GskHttpAuthorization;
40 typedef struct _GskHttpAuthenticate GskHttpAuthenticate;
41 typedef struct _GskHttpCharSet GskHttpCharSet;
42 typedef struct _GskHttpResponseCacheDirective GskHttpResponseCacheDirective;
43 typedef struct _GskHttpRequestCacheDirective GskHttpRequestCacheDirective;
44 typedef struct _GskHttpCookie GskHttpCookie;
45 typedef struct _GskHttpLanguageSet GskHttpLanguageSet;
46 typedef struct _GskHttpMediaTypeSet GskHttpMediaTypeSet;
47 typedef struct _GskHttpContentEncodingSet GskHttpContentEncodingSet;
48 typedef struct _GskHttpTransferEncodingSet GskHttpTransferEncodingSet;
49 typedef struct _GskHttpRangeSet GskHttpRangeSet;
50 
51 /* enums */
52 GType gsk_http_status_get_type (void) G_GNUC_CONST;
53 GType gsk_http_verb_get_type (void) G_GNUC_CONST;
54 GType gsk_http_content_encoding_get_type (void) G_GNUC_CONST;
55 GType gsk_http_transfer_encoding_get_type (void) G_GNUC_CONST;
56 GType gsk_http_range_get_type (void) G_GNUC_CONST;
57 GType gsk_http_connection_get_type (void) G_GNUC_CONST;
58 
59 /* boxed types */
60 GType gsk_http_cookie_get_type (void) G_GNUC_CONST;
61 GType gsk_http_authorization_get_type (void) G_GNUC_CONST;
62 GType gsk_http_authenticate_get_type (void) G_GNUC_CONST;
63 GType gsk_http_char_set_get_type (void) G_GNUC_CONST;
64 GType gsk_http_cache_directive_get_type (void) G_GNUC_CONST;
65 GType gsk_http_language_set_get_type (void) G_GNUC_CONST;
66 GType gsk_http_media_type_set_get_type (void) G_GNUC_CONST;
67 GType gsk_http_content_encoding_set_get_type (void) G_GNUC_CONST;
68 GType gsk_http_transfer_encoding_set_get_type (void) G_GNUC_CONST;
69 GType gsk_http_range_set_get_type (void) G_GNUC_CONST;
70 
71 /* object types */
72 GType gsk_http_header_get_type (void) G_GNUC_CONST;
73 GType gsk_http_request_get_type (void) G_GNUC_CONST;
74 GType gsk_http_response_get_type (void) G_GNUC_CONST;
75 
76 /* type macros */
77 #define GSK_TYPE_HTTP_STATUS       (gsk_http_status_get_type ())
78 #define GSK_TYPE_HTTP_VERB         (gsk_http_verb_get_type ())
79 #define GSK_TYPE_HTTP_TRANSFER_ENCODING     (gsk_http_transfer_encoding_get_type ())
80 #define GSK_TYPE_HTTP_CONTENT_ENCODING     (gsk_http_content_encoding_get_type ())
81 #define GSK_TYPE_HTTP_RANGE        (gsk_http_range_get_type ())
82 #define GSK_TYPE_HTTP_CONNECTION   (gsk_http_connection_get_type ())
83 #define GSK_TYPE_HTTP_MEDIA_SET    (gsk_http_media_set_get_type ())
84 
85 /* type-casting macros */
86 #define GSK_TYPE_HTTP_HEADER               (gsk_http_header_get_type ())
87 #define GSK_HTTP_HEADER(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_HTTP_HEADER, GskHttpHeader))
88 #define GSK_HTTP_HEADER_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_HTTP_HEADER, GskHttpHeaderClass))
89 #define GSK_HTTP_HEADER_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_HTTP_HEADER, GskHttpHeaderClass))
90 #define GSK_IS_HTTP_HEADER(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_HTTP_HEADER))
91 #define GSK_IS_HTTP_HEADER_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_HTTP_HEADER))
92 
93 
94 typedef enum
95 {
96   GSK_HTTP_STATUS_CONTINUE                      = 100,
97   GSK_HTTP_STATUS_SWITCHING_PROTOCOLS           = 101,
98   GSK_HTTP_STATUS_OK                            = 200,
99   GSK_HTTP_STATUS_CREATED                       = 201,
100   GSK_HTTP_STATUS_ACCEPTED                      = 202,
101   GSK_HTTP_STATUS_NONAUTHORITATIVE_INFO         = 203,
102   GSK_HTTP_STATUS_NO_CONTENT                    = 204,
103   GSK_HTTP_STATUS_RESET_CONTENT                 = 205,
104   GSK_HTTP_STATUS_PARTIAL_CONTENT               = 206,
105   GSK_HTTP_STATUS_MULTIPLE_CHOICES              = 300,
106   GSK_HTTP_STATUS_MOVED_PERMANENTLY             = 301,
107   GSK_HTTP_STATUS_FOUND                         = 302,
108   GSK_HTTP_STATUS_SEE_OTHER                     = 303,
109   GSK_HTTP_STATUS_NOT_MODIFIED                  = 304,
110   GSK_HTTP_STATUS_USE_PROXY                     = 305,
111   GSK_HTTP_STATUS_TEMPORARY_REDIRECT            = 306,
112   GSK_HTTP_STATUS_BAD_REQUEST                   = 400,
113   GSK_HTTP_STATUS_UNAUTHORIZED                  = 401,
114   GSK_HTTP_STATUS_PAYMENT_REQUIRED              = 402,
115   GSK_HTTP_STATUS_FORBIDDEN                     = 403,
116   GSK_HTTP_STATUS_NOT_FOUND                     = 404,
117   GSK_HTTP_STATUS_METHOD_NOT_ALLOWED            = 405,
118   GSK_HTTP_STATUS_NOT_ACCEPTABLE                = 406,
119   GSK_HTTP_STATUS_PROXY_AUTH_REQUIRED           = 407,
120   GSK_HTTP_STATUS_REQUEST_TIMEOUT               = 408,
121   GSK_HTTP_STATUS_CONFLICT                      = 409,
122   GSK_HTTP_STATUS_GONE                          = 410,
123   GSK_HTTP_STATUS_LENGTH_REQUIRED               = 411,
124   GSK_HTTP_STATUS_PRECONDITION_FAILED           = 412,
125   GSK_HTTP_STATUS_ENTITY_TOO_LARGE              = 413,
126   GSK_HTTP_STATUS_URI_TOO_LARGE                 = 414,
127   GSK_HTTP_STATUS_UNSUPPORTED_MEDIA             = 415,
128   GSK_HTTP_STATUS_BAD_RANGE                     = 416,
129   GSK_HTTP_STATUS_EXPECTATION_FAILED            = 417,
130   GSK_HTTP_STATUS_INTERNAL_SERVER_ERROR         = 500,
131   GSK_HTTP_STATUS_NOT_IMPLEMENTED               = 501,
132   GSK_HTTP_STATUS_BAD_GATEWAY                   = 502,
133   GSK_HTTP_STATUS_SERVICE_UNAVAILABLE           = 503,
134   GSK_HTTP_STATUS_GATEWAY_TIMEOUT               = 504,
135   GSK_HTTP_STATUS_UNSUPPORTED_VERSION           = 505
136 } GskHttpStatus;
137 
138 /*
139  * The Verb is the first text transmitted
140  * (from the user-agent to the server).
141  */
142 typedef enum
143 {
144   GSK_HTTP_VERB_GET,
145   GSK_HTTP_VERB_POST,
146   GSK_HTTP_VERB_PUT,
147   GSK_HTTP_VERB_HEAD,
148   GSK_HTTP_VERB_OPTIONS,
149   GSK_HTTP_VERB_DELETE,
150   GSK_HTTP_VERB_TRACE,
151   GSK_HTTP_VERB_CONNECT
152 } GskHttpVerb;
153 
154 /* A GskHttpRange is a unit in which partial content ranges
155  * may be specified and transferred.
156  */
157 typedef enum
158 {
159   GSK_HTTP_RANGE_BYTES
160 } GskHttpRange;
161 
162 typedef enum {
163   GSK_HTTP_CONTENT_ENCODING_IDENTITY,
164   GSK_HTTP_CONTENT_ENCODING_GZIP,
165   GSK_HTTP_CONTENT_ENCODING_COMPRESS,
166   GSK_HTTP_CONTENT_ENCODING_UNRECOGNIZED = 0x100
167 } GskHttpContentEncoding;
168 
169 /*
170  * The Transfer-Encoding field of HTTP/1.1.
171  *
172  * In particular, HTTP/1.1 compliant clients and proxies
173  * MUST support `chunked'.  The compressed Transfer-Encodings
174  * are rarely (if ever) used.
175  *
176  * Note that:
177  *   - we interpret this field, even for HTTP/1.0 clients.
178  */
179 typedef enum {
180   GSK_HTTP_TRANSFER_ENCODING_NONE    = 0,
181   GSK_HTTP_TRANSFER_ENCODING_CHUNKED = 1,
182   GSK_HTTP_TRANSFER_ENCODING_UNRECOGNIZED = 0x100
183 } GskHttpTransferEncoding;
184 
185 /*
186  * The Connection: header enables or disables http-keepalive.
187  *
188  * For HTTP/1.0, NONE should be treated like CLOSE.
189  * For HTTP/1.1, NONE should be treated like KEEPALIVE.
190  *
191  * Use gsk_http_header_get_connection () to do this automatically -- it
192  * always returns GSK_HTTP_CONNECTION_CLOSE or GSK_HTTP_CONNECTION_KEEPALIVE.
193  *
194  * See RFC 2616, Section 14.10.
195  */
196 typedef enum
197 {
198   GSK_HTTP_CONNECTION_NONE       = 0,
199   GSK_HTTP_CONNECTION_CLOSE      = 1,
200   GSK_HTTP_CONNECTION_KEEPALIVE  = 2,
201 } GskHttpConnection;
202 
203 /*
204  * The Cache-Control response directive.
205  * See RFC 2616, Section 14.9 (cache-response-directive)
206  */
207 struct _GskHttpResponseCacheDirective
208 {
209   /*< public (read/write) >*/
210   /* the http is `public' and `private'; is_ is added
211    * for C++ users.
212    */
213   guint   is_public : 1;
214   guint   is_private : 1;
215 
216   guint   no_cache : 1;
217   guint   no_store : 1;
218   guint   no_transform : 1;
219 
220   guint   must_revalidate : 1;
221   guint   proxy_revalidate : 1;
222   guint   max_age;
223   guint   s_max_age;
224 
225   /*< public (read-only) >*/
226   char   *private_name;
227   char   *no_cache_name;
228 
229   /* TODO: what about cache-extensions? */
230 };
231 
232 /*
233  * The Cache-Control request directive.
234  * See RFC 2616, Section 14.9 (cache-request-directive)
235  */
236 struct _GskHttpRequestCacheDirective
237 {
238   guint no_cache : 1;
239   guint no_store : 1;
240   guint no_transform : 1;
241   guint only_if_cached : 1;
242 
243   guint max_age;
244   guint min_fresh;
245 
246  /*
247   * We need to be able to indicate that max_stale is set without the
248   * optional argument. So:
249   *		      0 not set
250   *		     -1 set no arg
251   *		     >0 set with arg.
252   */
253   gint  max_stale;
254 
255   /* TODO: what about cache-extensions? */
256 };
257 
258 
259 GskHttpResponseCacheDirective *gsk_http_response_cache_directive_new (void);
260 void gsk_http_response_cache_directive_set_private_name (
261 				     GskHttpResponseCacheDirective *directive,
262 				     const char            *name,
263 				     gsize                  name_len);
264 void gsk_http_response_cache_directive_set_no_cache_name (
265 				     GskHttpResponseCacheDirective *directive,
266 				     const char            *name,
267 				     gsize                  name_len);
268 void gsk_http_response_cache_directive_free(
269 				    GskHttpResponseCacheDirective *directive);
270 
271 
272 GskHttpRequestCacheDirective *gsk_http_request_cache_directive_new (void);
273 void gsk_http_request_cache_directive_free(
274 				     GskHttpRequestCacheDirective *directive);
275 
276 
277 /*
278  * The Accept: request-header.
279  *
280  * See RFC 2616, Section 14.1.
281  *
282  * TODO: support level= accept-extension.
283  */
284 struct _GskHttpMediaTypeSet
285 {
286   /*< public: read-only >*/
287   char                 *type;
288   char                 *subtype;
289   gfloat                quality;                /* -1 if not present */
290 
291   /*< private >*/
292   GskHttpMediaTypeSet  *next;
293 };
294 GskHttpMediaTypeSet *gsk_http_media_type_set_new (const char *type,
295                                                   const char *subtype,
296                                                   gfloat      quality);
297 void                 gsk_http_media_type_set_free(GskHttpMediaTypeSet *set);
298 
299 
300 /*
301  * The Accept-Charset: request-header.
302  *
303  * See RFC 2616, Section 14.2.
304  */
305 struct _GskHttpCharSet
306 {
307   /*< public: read-only >*/
308   char                 *charset_name;
309   gfloat                quality;                /* -1 if not present */
310 
311   /*< private >*/
312   GskHttpCharSet       *next;
313 };
314 GskHttpCharSet       *gsk_http_char_set_new (const char *charset_name,
315                                              gfloat      quality);
316 void                  gsk_http_char_set_free(GskHttpCharSet *char_set);
317 
318 /*
319  * The Accept-Encoding: request-header.
320  *
321  * See RFC 2616, Section 14.3.
322  */
323 struct _GskHttpContentEncodingSet
324 {
325   /*< public: read-only >*/
326   GskHttpContentEncoding       encoding;
327   gfloat                       quality;       /* -1 if not present */
328 
329   /*< private >*/
330   GskHttpContentEncodingSet   *next;
331 };
332 GskHttpContentEncodingSet *
333 gsk_http_content_encoding_set_new (GskHttpContentEncoding encoding,
334 				   gfloat                 quality);
335 void
336 gsk_http_content_encoding_set_free(GskHttpContentEncodingSet *encoding_set);
337 
338 /*
339  * for the TE: request-header.
340  *
341  * See RFC 2616, Section 14.39.
342  */
343 struct _GskHttpTransferEncodingSet
344 {
345   /*< public: read-only >*/
346   GskHttpTransferEncoding      encoding;
347   gfloat                       quality;       /* -1 if not present */
348 
349   /*< private >*/
350   GskHttpTransferEncodingSet   *next;
351 };
352 GskHttpTransferEncodingSet *
353 gsk_http_transfer_encoding_set_new (GskHttpTransferEncoding     encoding,
354 				    gfloat                      quality);
355 void
356 gsk_http_transfer_encoding_set_free(GskHttpTransferEncodingSet *encoding_set);
357 
358 struct _GskHttpRangeSet
359 {
360   /*< public: read-only >*/
361   GskHttpRange          range_type;
362 
363   /*< private >*/
364   GskHttpRangeSet   *next;
365 };
366 GskHttpRangeSet *gsk_http_range_set_new (GskHttpRange range_type);
367 void             gsk_http_range_set_free(GskHttpRangeSet *set);
368 
369 
370 /*
371  * The Accept-Language: request-header.
372  *
373  * See RFC 2616, Section 14.4.
374  */
375 struct _GskHttpLanguageSet
376 {
377   /*< public: read-only >*/
378 
379   /* these give a language (with optional dialect specifier) */
380   char                 *language;
381   gfloat                quality;                /* -1 if not present */
382 
383   /*< private >*/
384   GskHttpLanguageSet   *next;
385 };
386 GskHttpLanguageSet *gsk_http_language_set_new (const char *language,
387                                                gfloat      quality);
388 void                gsk_http_language_set_free(GskHttpLanguageSet *set);
389 
390 typedef enum
391 {
392   GSK_HTTP_AUTH_MODE_UNKNOWN,
393   GSK_HTTP_AUTH_MODE_BASIC,
394   GSK_HTTP_AUTH_MODE_DIGEST
395 } GskHttpAuthMode;
396 
397 /* HTTP Authentication.
398 
399    These structures give map to the WWW-Authenticate/Authorization headers,
400    see RFC 2617.
401 
402    The outline is:
403      If you get a 401 (Unauthorized) header, the server will
404      accompany that with information about how to authenticate,
405      in the WWW-Authenticate header.
406 
407      The user-agent should prompt the user for a username/password.
408 
409      Then the client tries again: but this time with an appropriate Authorization.
410      If the server is satified, it will presumably give you the content.
411  */
412 struct _GskHttpAuthenticate
413 {
414   GskHttpAuthMode mode;
415   char           *auth_scheme_name;
416   char           *realm;
417   union
418   {
419     struct {
420       char                   *options;
421     } unknown;
422     /* no members:
423     struct {
424     } basic;
425     */
426     struct {
427       char                   *domain;
428       char                   *nonce;
429       char                   *opaque;
430       gboolean                is_stale;
431       char                   *algorithm;
432     } digest;
433   } info;
434   guint           ref_count;            /*< private >*/
435 };
436 GskHttpAuthenticate *gsk_http_authenticate_new_unknown (const char          *auth_scheme_name,
437                                                         const char          *realm,
438                                                         const char          *options);
439 GskHttpAuthenticate *gsk_http_authenticate_new_basic   (const char          *realm);
440 GskHttpAuthenticate *gsk_http_authenticate_new_digest  (const char          *realm,
441                                                         const char          *domain,
442                                                         const char          *nonce,
443                                                         const char          *opaque,
444                                                         const char          *algorithm);
445 GskHttpAuthenticate  *gsk_http_authenticate_ref        (GskHttpAuthenticate *auth);
446 void                  gsk_http_authenticate_unref      (GskHttpAuthenticate *auth);
447 
448 struct _GskHttpAuthorization
449 {
450   GskHttpAuthMode mode;
451   char           *auth_scheme_name;
452   union
453   {
454     struct {
455       char                   *response;
456     } unknown;
457     struct {
458       char                   *user;
459       char                   *password;
460     } basic;
461     struct {
462       char                   *realm;
463       char                   *domain;
464       char                   *nonce;
465       char                   *opaque;
466       char                   *algorithm;
467       char                   *user;
468       char                   *password;
469       char                   *response_digest;
470       char                   *entity_digest;
471     } digest;
472   } info;
473   guint           ref_count;            /*< private >*/
474 };
475 GskHttpAuthorization *gsk_http_authorization_new_unknown (const char *auth_scheme_name,
476                                                           const char *response);
477 GskHttpAuthorization *gsk_http_authorization_new_basic   (const char *user,
478                                                           const char *password);
479 GskHttpAuthorization *gsk_http_authorization_new_digest  (const char *realm,
480                                                           const char *domain,
481                                                           const char *nonce,
482                                                           const char *opaque,
483                                                           const char *algorithm,
484                                                           const char *user,
485                                                           const char *password,
486                                                           const char *response_digest,
487                                                           const char *entity_digest);
488 GskHttpAuthorization *gsk_http_authorization_new_respond (const GskHttpAuthenticate *,
489                                                           const char *user,
490                                                           const char *password,
491                                                           GError    **error);
492 GskHttpAuthorization *gsk_http_authorization_new_respond_post(const GskHttpAuthenticate *,
493                                                           const char *user,
494                                                           const char *password,
495                                                           guint       post_data_len,
496                                                           gconstpointer post_data,
497                                                           GError    **error);
498 const char           *gsk_http_authorization_peek_response_digest (GskHttpAuthorization *);
499 GskHttpAuthorization *gsk_http_authorization_copy        (const GskHttpAuthorization *);
500 void                  gsk_http_authorization_set_nonce   (GskHttpAuthorization *,
501                                                           const char *nonce);
502 GskHttpAuthorization *gsk_http_authorization_ref         (GskHttpAuthorization *);
503 void                  gsk_http_authorization_unref       (GskHttpAuthorization *);
504 
505 /* an update to an existing authentication,
506    to verify that we're talking to the same host. */
507 struct _GskHttpAuthenticateInfo
508 {
509   char *next_nonce;
510   char *response_digest;
511   char *cnonce;
512   guint has_nonce_count;
513   guint32 nonce_count;
514 };
515 
516 /* A single `Cookie' or `Set-Cookie' header.
517  *
518  * See RFC 2109, HTTP State Management Mechanism
519  */
520 struct _GskHttpCookie
521 {
522   /*< public: read-only >*/
523   char                   *key;
524   char                   *value;
525   char                   *domain;
526   char                   *path;
527   char                   *expire_date;
528   char                   *comment;
529   int                     max_age;
530   gboolean                secure;               /* default is FALSE */
531   guint                   version;              /* default is 0, unspecified */
532 };
533 GskHttpCookie  *gsk_http_cookie_new              (const char     *key,
534                                                   const char     *value,
535                                                   const char     *path,
536                                                   const char     *domain,
537                                                   const char     *expire_date,
538                                                   const char     *comment,
539                                                   int             max_age);
540 GskHttpCookie  *gsk_http_cookie_copy             (const GskHttpCookie *orig);
541 void            gsk_http_cookie_free             (GskHttpCookie *orig);
542 
543 
544 /*
545  *                 GskHttpHeader
546  *
547  * A structure embodying an http header
548  * (as in a request or a response).
549  */
550 struct _GskHttpHeaderClass
551 {
552   GObjectClass                  base_class;
553 };
554 
555 struct _GskHttpHeader
556 {
557   GObject                       base_instance;
558 
559   /*< public >*/  /* read-write */
560   guint16                       http_major_version;             /* always 1 */
561   guint16                       http_minor_version;
562 
563   GskHttpConnection             connection_type;
564 
565   GskHttpTransferEncoding       transfer_encoding_type;
566   GskHttpContentEncoding        content_encoding_type;
567   GskHttpRangeSet              *accepted_range_units;  /* Accept-Ranges */
568 
569   /*< public >*/
570   char                         *unrecognized_transfer_encoding;
571   char                         *unrecognized_content_encoding;
572 
573   char                     *content_encoding;     /* Content-Encoding */
574 
575   unsigned                  has_content_type : 1;
576 
577   char                     *content_type;             /* Content-Type */
578   char                     *content_subtype;
579   char                     *content_charset;
580   GSList                   *content_additional;
581 
582   /* NULL-terminated array of language tags from the Content-Language
583    * header, or NULL if header not present. */
584   char                    **content_languages;
585 
586   /* Bytes ranges. Both with be == -1 if there is no Range tag. */
587   int                           range_start;
588   int                           range_end;
589 
590   /* may be set to ((time_t) -1) to omit them. */
591   glong                         date;
592 
593   /* From the Content-Length header. */
594   gint64                        content_length;
595 
596   /*< public >*/
597 
598   /* Key/value searchable header lines. */
599   GHashTable                   *header_lines;
600 
601   /* Error messages.  */
602   GSList                       *errors;		      /* list of char* Error: directives */
603 
604   /* General headers.  */
605   GSList                       *pragmas;
606 
607   /* and actual accumulated parse error (a bit of a hack) */
608   GError                       *g_error;
609 };
610 
611 
612 /* Public methods to parse/write a header. */
613 typedef enum
614 {
615   GSK_HTTP_PARSE_STRICT = (1 << 0),
616 
617   /* instead of giving up on unknown headers, just
618    * add them as misc-headers */
619   GSK_HTTP_PARSE_SAVE_ERRORS = (1 << 1)
620 } GskHttpParseFlags;
621 
622 GskHttpHeader  *gsk_http_header_from_buffer      (GskBuffer     *input,
623 						  gboolean       is_request,
624                                                   GskHttpParseFlags flags,
625                                                   GError        **error);
626 void            gsk_http_header_to_buffer        (GskHttpHeader *header,
627                                                   GskBuffer     *output);
628 
629 
630 /* response specific functions */
631 /* unhandled: content-type and friends */
632 void             gsk_http_header_set_content_encoding(GskHttpHeader *header,
633                                                      const char      *encoding);
634 
635 /*content_type; content_subtype; content_charset; content_additional;*/
636 
637 typedef struct _GskHttpContentTypeInfo GskHttpContentTypeInfo;
638 struct _GskHttpContentTypeInfo
639 {
640   const char *type_start;
641   guint type_len;
642   const char *subtype_start;
643   guint subtype_len;
644   const char *charset_start;
645   guint charset_len;
646   guint max_additional;         /* unimplemented */
647   guint n_additional;           /* unimplemented */
648   const char **additional_starts; /* unimplemented */
649   guint *additional_lens;         /* unimplemented */
650 };
651 typedef enum
652 {
653   GSK_HTTP_CONTENT_TYPE_PARSE_ADDL = (1<<0) /* unimplemented */
654 } GskHttpContentTypeParseFlags;
655 
656 gboolean gsk_http_content_type_parse (const char *content_type_header,
657                                       GskHttpContentTypeParseFlags flags,
658                                       GskHttpContentTypeInfo *out,
659                                       GError                **error);
660 
661 
662 
663 /* --- miscellaneous key/value pairs --- */
664 void             gsk_http_header_add_misc     (GskHttpHeader *header,
665                                                const char    *key,
666                                                const char    *value);
667 void             gsk_http_header_remove_misc  (GskHttpHeader *header,
668                                                const char    *key);
669 const char      *gsk_http_header_lookup_misc  (GskHttpHeader *header,
670                                                const char    *key);
671 
672 /* XXX: need to figure out the clean way to replace this one
673  * (probably some generic gsk_make_randomness (CHAR-SET, LENGTH) trick)
674  */
675 /*char                *gsk_http_header_gen_random_cookie();*/
676 
677 
678 typedef struct _GskHttpHeaderLineParser GskHttpHeaderLineParser;
679 typedef gboolean (*GskHttpHeaderLineParserFunc) (GskHttpHeader *header,
680 						 const char    *text,
681 						 gpointer       data);
682 struct _GskHttpHeaderLineParser
683 {
684   const char *name;
685   GskHttpHeaderLineParserFunc func;
686   gpointer data;
687 };
688 
689 /* The returned table is a map from g_str_hash(lowercase(header)) to
690    GskHttpHeaderLineParser. */
691 GHashTable        *gsk_http_header_get_parser_table(gboolean       is_request);
692 
693 /* Standard header constructions... */
694 
695 
696 /* --- outputting an http header --- */
697 typedef void (*GskHttpHeaderPrintFunc) (const char       *text,
698 					gpointer          data);
699 void              gsk_http_header_print (GskHttpHeader          *http_header,
700 		                         GskHttpHeaderPrintFunc  print_func,
701 		                         gpointer                print_data);
702 
703 
704 GskHttpConnection    gsk_http_header_get_connection (GskHttpHeader *header);
705 void                 gsk_http_header_set_version    (GskHttpHeader *header,
706 						     gint           major,
707 						     gint           minor);
708 void                 gsk_http_header_add_pragma     (GskHttpHeader *header,
709                                                      const char    *pragma);
710 void             gsk_http_header_add_accepted_range (GskHttpHeader *header,
711                                                      GskHttpRange   range);
712 
713 
714 #define gsk_http_header_set_connection_type(header, connection_type)	      \
715   g_object_set (GSK_HTTP_HEADER(header), "connection", (GskHttpConnection) (connection_type), NULL)
716 #define gsk_http_header_get_connection_type(header)			      \
717   (GSK_HTTP_HEADER(header)->connection_type)
718 #define gsk_http_header_set_transfer_encoding(header, enc)		      \
719   g_object_set (GSK_HTTP_HEADER(header), "transfer-encoding", (GskHttpTransferEncoding) (enc), NULL)
720 #define gsk_http_header_get_transfer_encoding(header)			      \
721   (GSK_HTTP_HEADER(header)->transfer_encoding_type)
722 #define gsk_http_header_set_content_encoding(header, enc)		      \
723   g_object_set (GSK_HTTP_HEADER(header), "content-encoding", (GskHttpContentEncoding) (enc), NULL)
724 #define gsk_http_header_get_content_encoding(header)			      \
725   (GSK_HTTP_HEADER(header)->content_encoding_type)
726 #define gsk_http_header_set_content_length(header, len)		              \
727   g_object_set (GSK_HTTP_HEADER(header), "content-length", (gint64) (len), NULL)
728 #define gsk_http_header_get_content_length(header)			      \
729   (GSK_HTTP_HEADER(header)->content_length)
730 #define gsk_http_header_set_range(header, start, end)		              \
731   g_object_set (GSK_HTTP_HEADER(header), "range-start", (gint) (start), "range-end", (gint) (end), NULL)
732 #define gsk_http_header_get_range_start(header)			              \
733   (GSK_HTTP_HEADER(header)->range_start)
734 #define gsk_http_header_get_range_end(header)			              \
735   (GSK_HTTP_HEADER(header)->range_end)
736 #define gsk_http_header_set_date(header, date)			      	      \
737   g_object_set (GSK_HTTP_HEADER(header), "date", (long) (date), NULL)
738 #define gsk_http_header_get_date(header)				      \
739   (GSK_HTTP_HEADER(header)->date)
740 
741 /*< private >*/
742 void gsk_http_header_set_string (gpointer         http_header,
743                                  char           **p_str,
744                                  const char      *str);
745 void gsk_http_header_set_string_len (gpointer         http_header,
746                                      char           **p_str,
747                                      const char      *str,
748                                      guint            len);
749 
750 void gsk_http_header_set_string_val (gpointer         http_header,
751                                      char           **p_str,
752                                      const GValue    *value);
753 
754 char * gsk_http_header_cut_string (gpointer    http_header,
755                                    const char *start,
756                                    const char *end);
757 
758 void gsk_http_header_free_string (gpointer http_header,
759 			          char    *str);
760 void gsk_http_header_set_connection_string (GskHttpHeader *header,
761                                             const char    *str);
762 void gsk_http_header_set_content_encoding_string  (GskHttpHeader *header,
763                                                    const char    *str);
764 void gsk_http_header_set_transfer_encoding_string (GskHttpHeader *header,
765                                                    const char    *str);
766 
767 #define gsk_http_header_set_content_type(header, content_type)	      \
768   g_object_set (GSK_HTTP_HEADER(header), "content-type", (const char *)(content_type), NULL)
769 #define gsk_http_header_get_content_type(header)			      \
770   (GSK_HTTP_HEADER(header)->content_type)
771 #define gsk_http_header_set_content_subtype(header, content_type)	      \
772   g_object_set (GSK_HTTP_HEADER(header), "content-subtype", (const char *)(content_type), NULL)
773 #define gsk_http_header_get_content_subtype(header)			      \
774   (GSK_HTTP_HEADER(header)->content_subtype)
775 #define gsk_http_header_set_content_charset(header, content_type)	      \
776   g_object_set (GSK_HTTP_HEADER(header), "content-charset", (const char *)(content_type), NULL)
777 #define gsk_http_header_get_content_charset(header)			      \
778   (GSK_HTTP_HEADER(header)->content_charset)
779 
780 G_END_DECLS
781 
782 #endif
783