Fix FSF address (Tobias Mueller, #470445)
[platform/upstream/evolution-data-server.git] / servers / exchange / lib / e2k-http-utils.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 /* Copyright (C) 2001-2004 Novell, Inc.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of version 2 of the GNU Lesser General Public
7  * License as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "e2k-http-utils.h"
25
26 #include <libedataserver/e-time-utils.h>
27
28 #include <ctype.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 extern const char *e2k_rfc822_months [];
33
34 /**
35  * e2k_http_parse_date:
36  * @date: an HTTP Date header, returned from Exchange
37  *
38  * Converts an HTTP Date header into a time_t value. Doesn't
39  * do much sanity checking on the format since we know IIS always
40  * returns the date in RFC 1123 format, not either of the other two
41  * allowable formats.
42  *
43  * Return value: a %time_t corresponding to @date.
44  **/
45 time_t
46 e2k_http_parse_date (const char *date)
47 {
48         struct tm tm;
49         char *p;
50
51         if (strlen (date) < 29 || date[3] != ',' || date[4] != ' ')
52                 return -1;
53
54         memset (&tm, 0, sizeof (tm));
55         p = (char *)date + 5;
56
57         tm.tm_mday = strtol (p, &p, 10);
58         p++;
59         for (tm.tm_mon = 0; tm.tm_mon < 12; tm.tm_mon++) {
60                 if (!strncmp (p, e2k_rfc822_months[tm.tm_mon], 3))
61                         break;
62         }
63         p += 3;
64
65         tm.tm_year = strtol (p, &p, 10) - 1900;
66
67         tm.tm_hour = strtol (p, &p, 10);
68         p++;
69         tm.tm_min  = strtol (p, &p, 10);
70         p++;
71         tm.tm_sec  = strtol (p, &p, 10);
72
73         return e_mktime_utc (&tm);
74 }
75
76 /**
77  * e2k_http_parse_status:
78  * @status_line: an HTTP Status-Line
79  *
80  * Parses an HTTP Status-Line and returns the Status-Code
81  *
82  * Return value: the Status-Code portion of @status_line
83  **/
84 E2kHTTPStatus
85 e2k_http_parse_status (const char *status_line)
86 {
87         if (strncmp (status_line, "HTTP/1.", 7) != 0 ||
88             !isdigit (status_line[7]) ||
89             status_line[8] != ' ')
90                 return E2K_HTTP_MALFORMED;
91
92         return atoi (status_line + 9);
93 }
94
95 /**
96  * e2k_http_accept_language:
97  *
98  * Generates an Accept-Language value to send to the Exchange server.
99  * The user's default folders (Inbox, Calendar, etc) are not created
100  * until the user connects to Exchange for the first time, and in that
101  * case, it needs to know what language to name the folders in.
102  * libexchange users are responsible for setting the Accept-Language
103  * header on any request that could be the first-ever request to a
104  * mailbox. (Exchange will return 401 Unauthorized if it receives a
105  * request with no Accept-Language header for an uninitialized
106  * mailbox.)
107  *
108  * Return value: an Accept-Language string.
109  **/
110 const char *
111 e2k_http_accept_language (void)
112 {
113         static char *accept = NULL;
114
115         if (!accept) {
116                 GString *buf;
117                 const char *lang, *sub;
118                 int baselen;
119
120                 buf = g_string_new (NULL);
121
122                 lang = getenv ("LANG");
123                 if (!lang || !strcmp (lang, "C") || !strcmp (lang, "POSIX"))
124                         lang = "en";
125
126                 /* lang is "language[_territory][.codeset][@modifier]",
127                  * eg "fr" or "de_AT.utf8@euro". The Accept-Language
128                  * header should be a comma-separated list of
129                  * "language[-territory]". For the above cases we'd
130                  * generate "fr, en" and "de-AT, de, en". (We always
131                  * include "en" in case the server doesn't support the
132                  * user's preferred locale.)
133                  */
134
135                 baselen = strcspn (lang, "_.@");
136                 g_string_append_len (buf, lang, baselen);
137                 if (lang[baselen] == '_') {
138                         sub = lang + baselen + 1;
139                         g_string_append_c   (buf, '-');
140                         g_string_append_len (buf, sub, strcspn (sub, ".@"));
141
142                         g_string_append     (buf, ", ");
143                         g_string_append_len (buf, lang, baselen);
144                 }
145
146                 if (baselen != 2 || strncmp (lang, "en", 2) != 0)
147                         g_string_append (buf, ", en");
148
149                 accept = buf->str;
150                 g_string_free (buf, FALSE);
151         }
152
153         return accept;
154 }
155