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)
122 /* TODO: Use GetSystemDefaultLangID or similar */
126 locale = setlocale (LC_MESSAGES, NULL);
131 if (strcmp (locale, "C") == 0)
134 lang = g_strdup (locale);
136 dash_index = http_language_from_locale (lang);
138 tmp = g_string_new (lang);
139 g_string_append (tmp, ";q=1");
141 /* Append preference for basic (non-country specific) language version
143 if (dash_index > 0) {
144 g_string_append (tmp, ", ");
146 lang[dash_index] = '\0';
147 g_string_append (tmp, lang);
148 g_string_append (tmp, ";q=0.5");
153 soup_message_headers_append (message->request_headers,
157 g_string_free (tmp, TRUE);
162 get_quality (const char *val)
164 val = strstr (val, ";q=");
168 val += strlen (";q=");
173 sort_locales_by_quality (const char *a,
176 const double diff = get_quality (a) - get_quality (b);
186 /* Parses the Accept-Language header in @message, and returns its values
187 * in an ordered list in UNIX locale format */
189 http_request_get_accept_locales (SoupMessage *message)
196 header = soup_message_headers_get_one (message->request_headers,
203 bits = g_strsplit (header, ",", -1);
205 /* Transform to list */
206 for (i = 0; bits[i] != NULL; i++) {
207 bits[i] = g_strstrip (bits[i]);
209 switch (bits[i][0]) {
213 /* Wildcard: ignore */
218 locale_from_http_language (bits[i]);
220 /* Because bits is sorted in ascending order */
221 locales = g_list_prepend (locales, bits[i]);
229 locales = g_list_sort (locales, (GCompareFunc) sort_locales_by_quality);
234 /* Set Accept-Language header according to @locale. */
236 http_response_set_content_locale (SoupMessage *msg,
241 lang = g_strdup (locale);
242 http_language_from_locale (lang);
244 soup_message_headers_append (msg->response_headers,
251 /* Set Content-Type header guessed from @path, @data and @data_size using
252 * g_content_type_guess(). */
254 http_response_set_content_type (SoupMessage *msg,
259 char *content_type, *mime;
261 content_type = g_content_type_guess
266 mime = g_content_type_get_mime_type (content_type);
268 mime = g_strdup ("application/octet-stream");
269 else if (strcmp (mime, "application/xml") == 0) {
271 mime = g_strdup ("text/xml; charset=\"utf-8\"");
274 soup_message_headers_append (msg->response_headers,
279 g_free (content_type);
282 /* Set Content-Encoding header to gzip and append compressed body */
284 http_response_set_body_gzip (SoupMessage *msg,
288 GZlibCompressor *compressor;
289 gboolean finished = FALSE;
292 soup_message_headers_append (msg->response_headers,
293 "Content-Encoding", "gzip");
295 compressor = g_zlib_compressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP, -1);
298 GError *error = NULL;
300 gsize bytes_read = 0;
301 gsize bytes_written = 0;
303 switch (g_converter_convert (G_CONVERTER (compressor),
307 G_CONVERTER_INPUT_AT_END,
308 &bytes_read, &bytes_written,
310 case G_CONVERTER_ERROR:
311 g_warning ("Error compressing response: %s",
313 g_error_free (error);
314 g_object_unref (compressor);
316 case G_CONVERTER_CONVERTED:
317 converted += bytes_read;
319 case G_CONVERTER_FINISHED:
322 case G_CONVERTER_FLUSHED:
327 soup_message_body_append (msg->response_body,
332 g_object_unref (compressor);