telepathy: remove trailing white space in password hack
[siplcs.git] / src / telepathy / telepathy-connection.c
blob20d80e78ecb80685c297c9a63c1e02874a9a7761
1 /**
2 * @file telepathy-connection.c
4 * pidgin-sipe
6 * Copyright (C) 2012 SIPE Project <http://sipe.sourceforge.net/>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include <string.h>
25 #include <glib-object.h>
26 #include <telepathy-glib/base-connection.h>
27 #include <telepathy-glib/base-protocol.h>
28 #include <telepathy-glib/handle-repo-dynamic.h>
29 #include <telepathy-glib/simple-password-manager.h>
30 #include <telepathy-glib/telepathy-glib.h>
32 #include "sipe-backend.h"
33 #include "sipe-common.h"
34 #include "sipe-core.h"
36 #include "telepathy-private.h"
38 G_BEGIN_DECLS
40 * Connection class - data structures
42 typedef struct _SipeConnectionClass {
43 TpBaseConnectionClass parent_class;
44 } SipeConnectionClass;
46 typedef struct _SipeConnection {
47 TpBaseConnection parent;
49 TpSimplePasswordManager *password_manager;
51 struct sipe_backend_private private;
52 gchar *account;
53 gchar *login;
54 gchar *password;
55 gchar *server;
56 gchar *port;
57 guint transport;
58 } SipeConnection;
61 * Connection class - type macros
63 static GType sipe_connection_get_type(void) G_GNUC_CONST;
64 #define SIPE_TYPE_CONNECTION \
65 (sipe_connection_get_type())
66 #define SIPE_CONNECTION(obj) \
67 (G_TYPE_CHECK_INSTANCE_CAST((obj), SIPE_TYPE_CONNECTION, \
68 SipeConnection))
69 G_END_DECLS
72 * Connection class - type definition
74 G_DEFINE_TYPE(SipeConnection,
75 sipe_connection,
76 TP_TYPE_BASE_CONNECTION)
79 * Connection class - instance methods
81 static gchar *normalize_contact(SIPE_UNUSED_PARAMETER TpHandleRepoIface *repo,
82 const gchar *id,
83 SIPE_UNUSED_PARAMETER gpointer context,
84 GError **error)
86 return(sipe_telepathy_protocol_normalize_contact(NULL, id, error));
89 static void create_handle_repos(SIPE_UNUSED_PARAMETER TpBaseConnection *conn,
90 TpHandleRepoIface *repos[NUM_TP_HANDLE_TYPES])
92 repos[TP_HANDLE_TYPE_CONTACT] = tp_dynamic_handle_repo_new(TP_HANDLE_TYPE_CONTACT,
93 normalize_contact,
94 NULL);
97 static gboolean connect_to_core(SipeConnection *self,
98 GError **error)
100 gchar *login_domain = NULL;
101 gchar *login_account = NULL;
102 struct sipe_core_public *sipe_public;
103 const gchar *errmsg;
105 /* login name specified? */
106 if (self->login && strlen(self->login)) {
107 /* Allowed domain-account separators are / or \ */
108 gchar **domain_user = g_strsplit_set(self->login, "/\\", 2);
109 gboolean has_domain = domain_user[1] != NULL;
110 SIPE_DEBUG_INFO("connect_to_core: login '%s'", self->login);
111 login_domain = has_domain ? g_strdup(domain_user[0]) : NULL;
112 login_account = g_strdup(domain_user[has_domain ? 1 : 0]);
113 SIPE_DEBUG_INFO("connect_to_core: auth domain '%s' user '%s'",
114 login_domain ? login_domain : "",
115 login_account);
116 g_strfreev(domain_user);
119 sipe_public = sipe_core_allocate(self->account,
120 login_domain, login_account,
121 self->password,
122 NULL, /* @TODO: email */
123 NULL, /* @TODO: email_url */
124 &errmsg);
125 g_free(login_domain);
126 g_free(login_account);
128 SIPE_DEBUG_INFO("connect_to_core: created %p", sipe_public);
130 if (sipe_public) {
131 struct sipe_backend_private *telepathy_private = &self->private;
133 /* initialize backend private data */
134 sipe_public->backend_private = telepathy_private;
135 telepathy_private->public = sipe_public;
136 telepathy_private->connection = self;
137 telepathy_private->transport = NULL;
138 telepathy_private->ipaddress = NULL;
140 /* map option list to flags - default is NTLM */
141 SIPE_CORE_FLAG_UNSET(KRB5);
142 SIPE_CORE_FLAG_UNSET(TLS_DSK);
143 SIPE_CORE_FLAG_UNSET(SSO);
144 /* @TODO: add parameters for these */
146 sipe_core_transport_sip_connect(sipe_public,
147 self->transport,
148 self->server,
149 self->port);
151 return(TRUE);
152 } else {
153 g_set_error_literal(error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
154 errmsg);
155 return(FALSE);
159 static void password_manager_cb(GObject *source,
160 GAsyncResult *result,
161 gpointer data)
163 SipeConnection *self = data;
164 TpBaseConnection *base = TP_BASE_CONNECTION(self);
165 GError *error = NULL;
166 const GString *password = tp_simple_password_manager_prompt_finish(
167 TP_SIMPLE_PASSWORD_MANAGER(source),
168 result,
169 &error);
171 if (error) {
172 SIPE_DEBUG_ERROR("password_manager_cb: failed: %s",
173 error->message);
175 if (base->status != TP_CONNECTION_STATUS_DISCONNECTED) {
176 tp_base_connection_disconnect_with_dbus_error(base,
177 tp_error_get_dbus_name(error->code),
178 NULL,
179 TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED);
181 g_error_free(error);
182 } else {
184 g_free(self->password);
185 self->password = g_strdup(password->str);
187 if (!connect_to_core(self, &error)) {
188 if (base->status != TP_CONNECTION_STATUS_DISCONNECTED) {
189 tp_base_connection_disconnect_with_dbus_error(base,
190 tp_error_get_dbus_name(error->code),
191 NULL,
192 TP_CONNECTION_STATUS_REASON_AUTHENTICATION_FAILED);
194 g_error_free(error);
199 static gboolean start_connecting(TpBaseConnection *base,
200 GError **error)
202 SipeConnection *self = SIPE_CONNECTION(base);
203 gboolean rc = TRUE;
205 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::start_connecting");
207 tp_base_connection_change_status(base, TP_CONNECTION_STATUS_CONNECTING,
208 TP_CONNECTION_STATUS_REASON_REQUESTED);
210 /* we need a password */
211 if (self->password)
212 rc = connect_to_core(self, error);
213 else {
214 #if 0
215 /* this doesn't work. Nobody has a clue why */
216 SIPE_DEBUG_INFO("SipeConnection::start_connecting: requesting password from user: %p",
217 self->password_manager);
218 tp_simple_password_manager_prompt_async(self->password_manager,
219 password_manager_cb,
220 self);
221 #else
222 /* MAJOR HACK */
223 gchar *password_file = g_strdup_printf("%s/.sipe-password",
224 g_getenv("HOME"));
225 SIPE_DEBUG_INFO("SipeConnection::start_connecting - password file %s",
226 password_file);
227 rc = FALSE;
228 if (g_file_get_contents(password_file,
229 &self->password,
230 NULL, error)) {
231 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::start_connecting - got password");
232 g_strchomp(self->password);
233 rc = connect_to_core(self, error);
234 } else {
235 SIPE_DEBUG_ERROR("SipeConnection::start_connecting: %s",
236 (*error)->message);
238 g_free(password_file);
240 /* to make compiler happy */
241 (void)password_manager_cb;
242 #endif
245 return(rc);
248 static void shut_down(TpBaseConnection *base)
250 SipeConnection *self = SIPE_CONNECTION(base);
251 struct sipe_backend_private *telepathy_private = &self->private;
252 struct sipe_core_public *sipe_public = telepathy_private->public;
254 SIPE_DEBUG_INFO("SipeConnection::shut_down: closing %p", sipe_public);
256 if (sipe_public)
257 sipe_core_deallocate(sipe_public);
258 telepathy_private->public = NULL;
259 telepathy_private->transport = NULL;
261 g_free(telepathy_private->ipaddress);
262 telepathy_private->ipaddress = NULL;
264 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::shut_down: core deallocated");
267 static GPtrArray *create_channel_managers(TpBaseConnection *base)
269 SipeConnection *self = SIPE_CONNECTION(base);
270 GPtrArray *channel_managers = g_ptr_array_new();
272 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::create_channel_managers");
274 self->password_manager = tp_simple_password_manager_new(base);
275 g_ptr_array_add(channel_managers, self->password_manager);
276 SIPE_DEBUG_INFO("SipeConnection::create_channel_managers: password %p",
277 self->password_manager);
279 return(channel_managers);
282 static void sipe_connection_finalize(GObject *object)
284 SipeConnection *self = SIPE_CONNECTION(object);
286 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::finalize");
288 g_free(self->port);
289 g_free(self->server);
290 g_free(self->password);
291 g_free(self->login);
292 g_free(self->account);
294 G_OBJECT_CLASS(sipe_connection_parent_class)->finalize(object);
298 * Connection class - type implementation
300 static void sipe_connection_class_init(SipeConnectionClass *klass)
302 GObjectClass *object_class = G_OBJECT_CLASS(klass);
303 TpBaseConnectionClass *base_class = TP_BASE_CONNECTION_CLASS(klass);
305 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::class_init");
307 object_class->finalize = sipe_connection_finalize;
309 base_class->create_handle_repos = create_handle_repos;
310 base_class->start_connecting = start_connecting;
311 base_class->shut_down = shut_down;
312 base_class->create_channel_managers = create_channel_managers;
315 static void sipe_connection_init(SIPE_UNUSED_PARAMETER SipeConnection *self)
317 SIPE_DEBUG_INFO_NOFORMAT("SipeConnection::init");
320 /* create new connection object */
321 TpBaseConnection *sipe_telepathy_connection_new(TpBaseProtocol *protocol,
322 GHashTable *params,
323 SIPE_UNUSED_PARAMETER GError **error)
325 const gchar *password = tp_asv_get_string(params, "password");
326 const gchar *server = tp_asv_get_string(params, "server");
327 const gchar *transport = tp_asv_get_string(params, "transport");
328 SipeConnection *conn = g_object_new(SIPE_TYPE_CONNECTION,
329 "protocol", tp_base_protocol_get_name(protocol),
330 NULL);
331 guint port;
332 gboolean valid;
334 SIPE_DEBUG_INFO_NOFORMAT("sipe_telepathy_connection_new");
336 /* account & login are required fields */
337 conn->account = g_strdup(tp_asv_get_string(params, "account"));
338 conn->login = g_strdup(tp_asv_get_string(params, "login"));
340 /* password */
341 if (password && strlen(password))
342 conn->password = g_strdup(password);
343 else
344 conn->password = NULL;
346 /* server name */
347 if (server && strlen(server))
348 conn->server = g_strdup(server);
349 else
350 conn->server = NULL;
352 /* server port: core expects a string */
353 port = tp_asv_get_uint32(params, "port", &valid);
354 if (valid)
355 conn->port = g_strdup_printf("%d", port);
356 else
357 conn->port = NULL;
359 /* transport type */
360 if (sipe_strequal(transport, "auto")) {
361 conn->transport = conn->server ?
362 SIPE_TRANSPORT_TLS : SIPE_TRANSPORT_AUTO;
363 } else if (sipe_strequal(transport, "tls")) {
364 conn->transport = SIPE_TRANSPORT_TLS;
365 } else {
366 conn->transport = SIPE_TRANSPORT_TCP;
369 return(TP_BASE_CONNECTION(conn));
374 * Backend adaptor functions
376 gboolean sipe_backend_connection_is_valid(struct sipe_core_public *sipe_public) {
377 return(sipe_public->backend_private->transport != NULL);
381 Local Variables:
382 mode: c
383 c-file-style: "bsd"
384 indent-tabs-mode: t
385 tab-width: 8
386 End: