Fix FSF address (Tobias Mueller, #470445)
[platform/upstream/evolution-data-server.git] / servers / exchange / storage / exchange-oof.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 /* Copyright (C) 2002-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 /* exchange-oof: Out of Office code */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include "exchange-oof.h"
27 #include "exchange-account.h"
28 #include "e2k-propnames.h"
29 #include "e2k-utils.h"
30 #include "e2k-uri.h"
31
32 #include <string.h>
33
34 /* Taken from gal/util/e-util.c */
35 static char *
36 find_str_case (const char *haystack, const char *needle)
37 {
38         /* find the needle in the haystack neglecting case */
39         const char *ptr;
40         int len;
41
42         g_return_val_if_fail (haystack != NULL, NULL);
43         g_return_val_if_fail (needle != NULL, NULL);
44
45         len = strlen(needle);
46         if (len > strlen(haystack))
47                 return NULL;
48
49         if (len == 0)
50                 return (char *) haystack;
51
52         for (ptr = haystack; *(ptr + len - 1) != '\0'; ptr++)
53                 if (!g_ascii_strncasecmp (ptr, needle, len))
54                         return (char *) ptr;
55
56         return NULL;
57
58 }
59 /**
60  * exchange_oof_get:
61  * @account: an #ExchangeAccount
62  * @oof: pointer to variable to pass back OOF state in
63  * @message: pointer to variable to pass back OOF message in
64  *
65  * Checks if Out-of-Office is enabled for @account and returns the
66  * state in *@oof and the message in *@message (which the caller
67  * must free).
68  *
69  * Return value: %TRUE if the OOF state was read, %FALSE if an error
70  * occurred.
71  **/
72 gboolean
73 exchange_oof_get (ExchangeAccount *account, gboolean *oof, char **message)
74 {
75         E2kContext *ctx;
76         E2kHTTPStatus status;
77         char *url, *body = NULL, *p = NULL, *checked, *ta_start, *ta_end;
78         int len;
79
80         ctx = exchange_account_get_context (account);
81         if (!ctx)
82                 return FALSE;
83
84         if (!message) {
85                 /* Do this the easy way */
86                 const char *prop = E2K_PR_EXCHANGE_OOF_STATE;
87                 E2kResult *results;
88                 int nresults = 0;
89
90                 url = e2k_uri_concat (account->home_uri, "NON_IPM_SUBTREE/");
91                 status = e2k_context_propfind (ctx, NULL, url, &prop, 1,
92                                                &results, &nresults);
93                 g_free (url);
94                 if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status) || nresults == 0)
95                         return FALSE;
96
97                 prop = e2k_properties_get_prop (results[0].props, E2K_PR_EXCHANGE_OOF_STATE);
98                 *oof = prop && atoi (prop);
99
100                 e2k_results_free (results, nresults);
101                 return TRUE;
102         }
103
104         url = e2k_uri_concat (account->home_uri, "?Cmd=options");
105         status = e2k_context_get_owa (ctx, NULL, url, FALSE, &body, &len);
106         g_free (url);
107         if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status))
108                 return FALSE;
109
110         p = find_str_case (body, "<!--End OOF Assist-->");
111         if (p)
112                 *p = '\0';
113         else
114                 body[len - 1] = '\0';
115
116         p = find_str_case (body, "name=\"OofState\"");
117         if (p)
118                 p = find_str_case (body, "value=\"1\"");
119         if (!p) {
120                 g_warning ("Could not find OofState in options page");
121                 g_free (body);
122                 return FALSE;
123         }
124
125         checked = find_str_case (p, "checked");
126         *oof = (checked && checked < strchr (p, '>'));
127
128         if (message) {
129                 ta_end = find_str_case (p, "</textarea>");
130                 if (!ta_end) {
131                         g_warning ("Could not find OOF text in options page");
132                         g_free (body);
133                         *message = g_strdup ("");
134                         return TRUE;
135                 }
136                 for (ta_start = ta_end - 1; ta_start > p; ta_start--) {
137                         if (*ta_start == '>')
138                                 break;
139                 }
140                 if (*ta_start++ != '>') {
141                         g_warning ("Could not find OOF text in options page");
142                         g_free (body);
143                         *message = g_strdup ("");
144                         return TRUE;
145                 }
146
147                 *message = g_strndup (ta_start, ta_end - ta_start);
148                 /* FIXME: HTML decode */
149                 
150         }
151
152         return TRUE;
153 }
154
155 /**
156  * exchange_oof_set:
157  * @account: an #ExchangeAccount
158  * @oof: new OOF state
159  * @message: new OOF message, or %NULL
160  *
161  * Sets the OOF state for @account to @oof.
162  *
163  * Return value: %TRUE if the OOF state was updated, %FALSE if an
164  * error occurred.
165  **/
166 gboolean
167 exchange_oof_set (ExchangeAccount *account, gboolean oof, const char *message)
168 {
169         E2kContext *ctx;
170         E2kHTTPStatus status;
171
172         ctx = exchange_account_get_context (account);
173         if (!ctx)
174                 return FALSE;
175
176         if (message) {
177                 char *body, *message_enc;
178
179                 message_enc = e2k_uri_encode (message, FALSE, NULL);
180                 body = g_strdup_printf ("Cmd=options&OofState=%d&"
181                                         "OofReply=%s",
182                                         oof ? 1 : 0, message_enc);
183                 status = e2k_context_post (ctx, NULL, account->home_uri,
184                                            "application/x-www-form-urlencoded",
185                                            body, strlen (body), NULL, NULL);
186                 g_free (message_enc);
187                 g_free (body);
188         } else {
189                 E2kProperties *props;
190                 char *url;
191
192                 props = e2k_properties_new ();
193                 e2k_properties_set_bool (props, E2K_PR_EXCHANGE_OOF_STATE, oof);
194                 url = e2k_uri_concat (account->home_uri, "NON_IPM_SUBTREE/");
195                 /* Need to pass TRUE for "create" here or it won't work */
196                 status = e2k_context_proppatch (ctx, NULL, url, props,
197                                                 TRUE, NULL);
198                 g_free (url);
199                 e2k_properties_free (props);
200         }
201
202         return E2K_HTTP_STATUS_IS_SUCCESSFUL (status) ||
203                 E2K_HTTP_STATUS_IS_REDIRECTION (status);
204 }