2 * Copyright (C) 2007, 2008 OpenedHand Ltd.
4 * Author: Jorn Baayen <jorn@openedhand.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
29 #include "http-headers.h"
31 /* Converts @lang from HTTP language tag format into locale format.
32 * Return value: The index of the '-' character. */
34 http_language_from_locale (char *lang)
42 for (i = 0; lang[i] != '\0'; i++) {
45 /* Underscores to dashes */
48 /* Lowercase country bit */
57 /* Terminate our string here */
63 lang[i] = g_ascii_tolower (lang[i]);
72 /* Converts @lang from locale format into HTTP language tag format.
73 * Return value: The index of the '_' character. */
75 locale_from_http_language (char *lang)
78 int i, underscore_index;
81 underscore_index = -1;
83 for (i = 0; lang[i] != '\0'; i++) {
86 /* Dashes to underscores */
89 /* Uppercase country bit */
92 /* Save underscore index */
97 /* Terminate our string here */
100 return underscore_index;
103 lang[i] = g_ascii_toupper (lang[i]);
109 return underscore_index;
112 /* Parses the HTTP Range header on @message and sets:
114 * @have_range to %TRUE if a range was specified,
115 * @offset to the requested offset (left unchanged if none specified),
116 * @length to the requested length (left unchanged if none specified).
118 * Both @offset and @length are expected to be initialised to their default
121 * Returns %TRUE on success. */
123 http_request_get_range (SoupMessage *message,
124 gboolean *have_range,
131 header = soup_message_headers_get_one (message->request_headers,
133 if (header == NULL) {
139 /* We have a Range header. Parse. */
140 if (strncmp (header, "bytes=", 6) != 0)
145 v = g_strsplit (header, "-", 2);
147 /* Get first byte position */
148 if (v[0] != NULL && *v[0] != 0)
149 *offset = atoll (v[0]);
152 /* We don't support ranges without first byte position */
158 /* Get last byte position if specified */
159 if (v[1] != NULL && *v[1] != 0)
160 *length = atoll (v[1]) - *offset;
162 *length = *length - *offset;
172 /* Sets the Accept-Language on @message with the language taken from the
175 http_request_set_accept_language (SoupMessage *message)
181 locale = setlocale (LC_ALL, NULL);
185 if (strcmp (locale, "C") == 0)
188 lang = g_strdup (locale);
190 dash_index = http_language_from_locale (lang);
192 tmp = g_string_new (lang);
193 g_string_append (tmp, ";q=1");
195 /* Append preference for basic (non-country specific) language version
197 if (dash_index > 0) {
198 g_string_append (tmp, ", ");
200 lang[dash_index] = '\0';
201 g_string_append (tmp, lang);
202 g_string_append (tmp, ";q=0.5");
207 soup_message_headers_append (message->request_headers,
211 g_string_free (tmp, TRUE);
215 get_quality (const char *val)
217 val = strstr (val, ";q=");
221 val += strlen (";q=");
226 sort_locales_by_quality (const char *a,
229 const double diff = get_quality (a) - get_quality (b);
239 /* Parses the Accept-Language header in @message, and returns its values
240 * in an ordered list in UNIX locale format */
242 http_request_get_accept_locales (SoupMessage *message)
249 header = soup_message_headers_get_one (message->request_headers,
256 bits = g_strsplit (header, ",", -1);
258 /* Transform to list */
259 for (i = 0; bits[i] != NULL; i++) {
260 bits[i] = g_strstrip (bits[i]);
262 switch (bits[i][0]) {
266 /* Wildcard: ignore */
271 locale_from_http_language (bits[i]);
273 /* Because bits is sorted in ascending order */
274 locales = g_list_prepend (locales, bits[i]);
282 locales = g_list_sort (locales, (GCompareFunc) sort_locales_by_quality);
287 /* Set Accept-Language header according to @locale. */
289 http_response_set_content_locale (SoupMessage *msg,
294 lang = g_strdup (locale);
295 http_language_from_locale (lang);
297 soup_message_headers_append (msg->response_headers,
304 /* Set Content-Type header guessed from @path, @data and @data_size using
305 * g_content_type_guess(). */
307 http_response_set_content_type (SoupMessage *msg,
312 char *content_type, *mime;
314 content_type = g_content_type_guess
319 mime = g_content_type_get_mime_type (content_type);
321 mime = g_strdup ("application/octet-stream");
322 else if (strcmp (mime, "application/xml") == 0) {
324 mime = g_strdup ("text/xml; charset=\"utf-8\"");
327 soup_message_headers_append (msg->response_headers,
332 g_free (content_type);
335 /* Set Content-Range header */
337 http_response_set_content_range (SoupMessage *msg,
344 content_range = g_strdup_printf
345 ("bytes %" G_GSIZE_FORMAT "-%"
346 G_GSIZE_FORMAT "/%" G_GSIZE_FORMAT,
351 soup_message_headers_append (msg->response_headers,
355 g_free (content_range);