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., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, 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 /* Sets the Accept-Language on @message with the language taken from the
115 http_request_set_accept_language (SoupMessage *message)
121 locale = setlocale (LC_ALL, NULL);
125 if (strcmp (locale, "C") == 0)
128 lang = g_strdup (locale);
130 dash_index = http_language_from_locale (lang);
132 tmp = g_string_new (lang);
133 g_string_append (tmp, ";q=1");
135 /* Append preference for basic (non-country specific) language version
137 if (dash_index > 0) {
138 g_string_append (tmp, ", ");
140 lang[dash_index] = '\0';
141 g_string_append (tmp, lang);
142 g_string_append (tmp, ";q=0.5");
147 soup_message_headers_append (message->request_headers,
151 g_string_free (tmp, TRUE);
155 get_quality (const char *val)
157 val = strstr (val, ";q=");
161 val += strlen (";q=");
166 sort_locales_by_quality (const char *a,
169 const double diff = get_quality (a) - get_quality (b);
179 /* Parses the Accept-Language header in @message, and returns its values
180 * in an ordered list in UNIX locale format */
182 http_request_get_accept_locales (SoupMessage *message)
189 header = soup_message_headers_get_one (message->request_headers,
196 bits = g_strsplit (header, ",", -1);
198 /* Transform to list */
199 for (i = 0; bits[i] != NULL; i++) {
200 bits[i] = g_strstrip (bits[i]);
202 switch (bits[i][0]) {
206 /* Wildcard: ignore */
211 locale_from_http_language (bits[i]);
213 /* Because bits is sorted in ascending order */
214 locales = g_list_prepend (locales, bits[i]);
222 locales = g_list_sort (locales, (GCompareFunc) sort_locales_by_quality);
227 /* Set Accept-Language header according to @locale. */
229 http_response_set_content_locale (SoupMessage *msg,
234 lang = g_strdup (locale);
235 http_language_from_locale (lang);
237 soup_message_headers_append (msg->response_headers,
244 /* Set Content-Type header guessed from @path, @data and @data_size using
245 * g_content_type_guess(). */
247 http_response_set_content_type (SoupMessage *msg,
252 char *content_type, *mime;
254 content_type = g_content_type_guess
259 mime = g_content_type_get_mime_type (content_type);
261 mime = g_strdup ("application/octet-stream");
262 else if (strcmp (mime, "application/xml") == 0) {
264 mime = g_strdup ("text/xml; charset=\"utf-8\"");
267 soup_message_headers_append (msg->response_headers,
272 g_free (content_type);
275 /* Set Content-Encoding header to gzip and append compressed body */
277 http_response_set_body_gzip (SoupMessage *msg,
281 GZlibCompressor *compressor;
282 gboolean finished = FALSE;
285 soup_message_headers_append (msg->response_headers,
286 "Content-Encoding", "gzip");
288 compressor = g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP, -1);
291 GError *error = NULL;
293 gsize bytes_read = 0;
294 gsize bytes_written = 0;
296 switch (g_converter_convert (G_CONVERTER (compressor),
300 G_CONVERTER_INPUT_AT_END,
301 &bytes_read, &bytes_written,
303 case G_CONVERTER_ERROR:
304 g_warning ("Error compressing response: %s",
306 g_error_free (error);
307 g_object_unref (compressor);
309 case G_CONVERTER_CONVERTED:
310 converted += bytes_read;
312 case G_CONVERTER_FINISHED:
315 case G_CONVERTER_FLUSHED:
320 soup_message_body_append (msg->response_body,
325 g_object_unref (compressor);