Fix FSF address (Tobias Mueller, #470445)
[platform/upstream/evolution-data-server.git] / servers / exchange / lib / test-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 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 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 <string.h>
25 #include <termios.h>
26 #include <unistd.h>
27
28 #include <libedataserverui/e-passwords.h>
29 #include <libgnome/gnome-util.h>
30
31 #include "e2k-context.h"
32 #include "e2k-global-catalog.h"
33 #include "e2k-uri.h"
34
35 #include "test-utils.h"
36
37 extern const char *test_program_name;
38
39 /**
40  * test_ask_password:
41  * @prompt: prompt string
42  *
43  * Prints @prompt followed by ": " and waits for the user to type
44  * a password (with echoing disabled).
45  *
46  * Return value: the password (or %NULL if stdin is not a tty).
47  **/
48 char *
49 test_ask_password (const char *prompt)
50 {
51         char *password;
52         struct termios t;
53         int old_lflag;
54         char buf[80];
55
56         if (tcgetattr (STDIN_FILENO, &t) != 0)
57                 return NULL;
58
59         old_lflag = t.c_lflag;
60         t.c_lflag = (t.c_lflag | ICANON | ECHONL) & ~ECHO;
61         tcsetattr (STDIN_FILENO, TCSANOW, &t);
62
63         fprintf (stderr, "%s: ", prompt);
64         fflush (stdout);
65
66         /* For some reason, fgets can return EINTR on
67          * Linux if ECHO is false...
68          */
69         do
70                 password = fgets (buf, sizeof (buf), stdin);
71         while (password == NULL && errno == EINTR);
72
73         t.c_lflag = old_lflag;
74         tcsetattr (STDIN_FILENO, TCSANOW, &t);
75
76         if (!password)
77                 exit (1);
78         return g_strndup (password, strcspn (password, "\n"));
79 }
80
81 /**
82  * test_get_password:
83  * @user: username to get the password for
84  * @host: Exchange (or global catalog) server name
85  *
86  * Tries to get a password for @user on @host, by looking it up in
87  * the Evolution password database or by prompting the user.
88  *
89  * Return value: the password, or %NULL if it could not be determined.
90  **/
91 const char *
92 test_get_password (const char *user, const char *host)
93 {
94         static char *password = NULL;
95         char *prompt;
96
97         if (password)
98                 return password;
99
100         if (host) {
101                 char *key;
102
103                 key = g_strdup_printf ("exchange://%s@%s", user, host);
104                 password = e_passwords_get_password ("Exchange", key);
105                 g_free (key);
106         }
107
108         if (!password) {
109                 if (host) {
110                         prompt = g_strdup_printf ("Password for %s@%s",
111                                                   user, host);
112                 } else
113                         prompt = g_strdup_printf ("Password for %s", user);
114
115                 password = test_ask_password (prompt);
116                 g_free (prompt);
117         }
118
119         return password;
120 }
121
122 /**
123  * test_get_context:
124  * @uri: an Exchange HTTP/HTTPS URI
125  *
126  * Creates an %E2kContext based on @uri. If @uri does not contain a
127  * username, the user's local username will be used. If it does not
128  * contain a password, test_get_password() will be called to get one.
129  *
130  * Return value: the new %E2kContext (always; if an error occurs,
131  * test_get_context() will exit the program).
132  **/
133 E2kContext *
134 test_get_context (const char *uri)
135 {
136         E2kContext *ctx;
137         E2kUri *euri;
138
139         ctx = e2k_context_new (uri);
140         if (!ctx) {
141                 fprintf (stderr, "Could not parse %s as URI\n", uri);
142                 exit (1);
143         }
144
145         euri = e2k_uri_new (uri);
146         if (!euri->user)
147                 euri->user = g_strdup (g_get_user_name ());
148         if (!euri->passwd)
149                 euri->passwd = g_strdup (test_get_password (euri->user, euri->host));
150
151         e2k_context_set_auth (ctx, euri->user, euri->domain,
152                               euri->authmech, euri->passwd);
153
154         e2k_uri_free (euri);
155         return ctx;
156 }
157
158 /**
159  * test_get_gc:
160  * @server: the global catalog server to contact
161  *
162  * Creates an %E2kGlobalCatalog for the server @server.
163  * test_get_password() will be called to get a password.
164  *
165  * Return value: the new %E2kGlobalCatalog (always; if an error occurs,
166  * test_get_gc() will exit the program).
167  **/
168 E2kGlobalCatalog *
169 test_get_gc (const char *server)
170 {
171         E2kGlobalCatalog *gc;
172         const char *password;
173         char *user, *p;
174
175         if (strchr (server, '@')) {
176                 user = g_strdup (server);
177                 p = strchr (user, '@');
178                 *p = '\0';
179                 server = p + 1;
180         } else
181                 user = g_strdup (g_get_user_name ());
182
183         password = test_get_password (user, server);
184         gc = e2k_global_catalog_new (server, -1, user, NULL, password);
185         if (!gc) {
186                 fprintf (stderr, "Could not create GC\n");
187                 exit (1);
188         }
189         g_free (user);
190
191         return gc;
192 }
193
194 static char **global_argv;
195 static int global_argc;
196 static GMainLoop *loop;
197
198 /**
199  * test_main:
200  * @argc: argc
201  * @argv: argv
202  *
203  * test-utils.o includes a main() function that calls various
204  * initialization routines, starts the main loop, and then calls
205  * test_main(). So test_main() is the entry point for a
206  * test-utils-using program.
207  **/
208
209 /**
210  * test_quit:
211  *
212  * Cleanly quits a test program.
213  **/
214 void
215 test_quit (void)
216 {
217         g_main_loop_quit (loop);
218 }
219
220 /**
221  * test_abort_if_http_error:
222  * @status: an HTTP status code
223  *
224  * Checks if @status is an HTTP or libsoup error, and if so, prints
225  * the error message and exits.
226  **/
227 void
228 test_abort_if_http_error (E2kHTTPStatus status)
229 {
230         if (E2K_HTTP_STATUS_IS_TRANSPORT_ERROR (status)) {
231                 fprintf (stderr, "\n%s\n", soup_status_get_phrase (status));
232                 exit (1);
233         } else if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
234                 fprintf (stderr, "\n%d\n", status);
235                 exit (1);
236         }
237 }
238
239 static gboolean
240 idle_run (gpointer data)
241 {
242         test_main (global_argc, global_argv);
243         return FALSE;
244 }
245
246 int
247 main (int argc, char **argv)
248 {
249         gnome_program_init (test_program_name, VERSION, LIBGNOME_MODULE,
250                             argc, argv, NULL);
251
252         global_argc = argc;
253         global_argv = argv;
254
255         loop = g_main_loop_new (NULL, TRUE);
256         g_idle_add (idle_run, NULL);
257         g_main_loop_run (loop);
258
259         return 0;
260 }