i18n: update bug tracker URL in script
[siplcs.git] / src / core / sipe-core.c
blob539e0d30863faa3f375de1853d934eda415c704c
1 /**
2 * @file sipe-core.c
4 * pidgin-sipe
6 * Copyright (C) 2010-2013 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 * Some notes on the history of this project/code/copyrights:
25 * - the project is called SIPE, but originally the code was only written
26 * for the libpurple framework, i.e. Pidgin. Hence the package name is
27 * "pidgin-sipe".
29 * - in the beginning almost all of the code was located in a module
30 * called "sipe.c". During the effort to remove the libpurple
31 * dependencies from the SIPE core, thousands of lines of code got
32 * shifted out of sipe.c, mostly to newly created modules and sipe.c
33 * ceased to exist.
35 * - it would have been tedious to track down the original author or
36 * copyright and preserve them for each line of code that was moved.
37 * Therefore the new modules started with a fresh copyright notice
38 * (like the one above).
40 * - the original copyright notices from sipe.c have been moved to this
41 * file (see below) and *MUST* be preserved!
43 * - if necessary the author of a line of code in question can still be
44 * reconstructed from the git repository information.
45 * See also "man git-blame"
47 * - if you think your copyright should be restored for a piece of code,
48 * then please contact the SIPE project to fix the source files ASAP.
50 *------------------- Copyright notices from "sipe.c" ---------------
51 * Copyright (C) 2010-11 SIPE Project <http://sipe.sourceforge.net/>
52 * Copyright (C) 2009-10 pier11 <pier11@operamail.com>
53 * Copyright (C) 2008 Novell, Inc.
54 * Copyright (C) 2007-09 Anibal Avelar <debianmx@gmail.com>
55 * Copyright (C) 2005 Thomas Butter <butter@uni-mannheim.de>
57 * ***
58 * Thanks to Google's Summer of Code Program and the helpful mentors
59 * ***
60 *------------------- Copyright notices from "sipe.c" ---------------
63 #ifdef HAVE_CONFIG_H
64 #include "config.h"
65 #endif
67 #include <stdlib.h>
68 #include <string.h>
70 #include <glib.h>
72 #include "sipe-common.h"
73 #include "sip-csta.h"
74 #include "sip-sec.h"
75 #include "sip-transport.h"
76 #include "sipe-backend.h"
77 #include "sipe-buddy.h"
78 #include "sipe-cal.h"
79 #include "sipe-certificate.h"
80 #include "sipe-chat.h"
81 #include "sipe-conf.h"
82 #include "sipe-core.h"
83 #include "sipe-core-private.h"
84 #include "sipe-crypt.h"
85 #include "sipe-group.h"
86 #include "sipe-groupchat.h"
87 #include "sipe-media.h"
88 #include "sipe-mime.h"
89 #include "sipe-nls.h"
90 #include "sipe-ocs2007.h"
91 #include "sipe-schedule.h"
92 #include "sipe-session.h"
93 #include "sipe-status.h"
94 #include "sipe-subscriptions.h"
95 #include "sipe-svc.h"
96 #include "sipe-utils.h"
97 #include "sipe-webticket.h"
99 #ifdef PACKAGE_GIT_COMMIT
100 #define SIPE_CORE_VERSION PACKAGE_VERSION " (git commit " PACKAGE_GIT_COMMIT ")"
101 #else
102 #define SIPE_CORE_VERSION PACKAGE_VERSION
103 #endif
105 /* locale_dir is unused if ENABLE_NLS is not defined */
106 void sipe_core_init(SIPE_UNUSED_PARAMETER const char *locale_dir)
108 srand(time(NULL));
109 sip_sec_init();
111 #ifdef ENABLE_NLS
112 SIPE_DEBUG_INFO("bindtextdomain = %s",
113 bindtextdomain(PACKAGE_NAME, locale_dir));
114 SIPE_DEBUG_INFO("bind_textdomain_codeset = %s",
115 bind_textdomain_codeset(PACKAGE_NAME, "UTF-8"));
116 textdomain(PACKAGE_NAME);
117 #endif
118 /* Initialization for crypto backend (production mode) */
119 sipe_crypto_init(TRUE);
120 sipe_mime_init();
121 sipe_status_init();
124 void sipe_core_destroy(void)
126 sipe_chat_destroy();
127 sipe_status_shutdown();
128 sipe_mime_shutdown();
129 sipe_crypto_shutdown();
130 sip_sec_destroy();
133 gchar *sipe_core_about(void)
135 return g_strdup_printf(
137 * Non-translatable parts, like markup, are hard-coded
138 * into the format string. This requires more translatable
139 * texts but it makes the translations less error prone.
141 "<b><font size=\"+1\">SIPE " SIPE_CORE_VERSION " </font></b><br/>"
142 "<br/>"
143 /* 1 */ "%s:<br/>"
144 "<li> - Microsoft Lync Server 2010</li><br/>"
145 "<li> - Microsoft Office Communications Server 2007 R2</li><br/>"
146 "<li> - Microsoft Office Communications Server 2007</li><br/>"
147 "<li> - Microsoft Live Communications Server 2005</li><br/>"
148 "<li> - Microsoft Live Communications Server 2003</li><br/>"
149 "<li> - Reuters Messaging</li><br/>"
150 "<br/>"
151 /* 2 */ "%s: <a href=\"" PACKAGE_URL "\">" PACKAGE_URL "</a><br/>"
152 /* 3,4 */ "%s: <a href=\"http://sourceforge.net/p/sipe/discussion/688534/\">%s</a><br/>"
153 /* 5,6 */ "%s: <a href=\"" PACKAGE_BUGREPORT "\">%s</a><br/>"
154 /* 7 */ "%s: <a href=\"" SIPE_TRANSLATIONS_URL "\">Transifex.net</a><br/>"
155 /* 8 */ "%s: GPLv2+<br/>"
156 "<br/>"
157 /* 9 */ "%s:<br/>"
158 " - CERN<br/>"
159 " - Reuters Messaging network<br/>"
160 " - Deutsche Bank<br/>"
161 " - Merrill Lynch<br/>"
162 " - Wachovia<br/>"
163 " - Intel<br/>"
164 " - Nokia<br/>"
165 " - HP<br/>"
166 " - Symantec<br/>"
167 " - Accenture<br/>"
168 " - Capgemini<br/>"
169 " - Siemens<br/>"
170 " - Alcatel-Lucent<br/>"
171 " - BT<br/>"
172 "<br/>"
173 /* 10,11 */ "%s<a href=\"" SIPE_TRANSLATIONS_URL "\">Transifex.net</a>%s.<br/>"
174 "<br/>"
175 /* 12 */ "<b>%s:</b><br/>"
176 " - Anibal Avelar<br/>"
177 " - Gabriel Burt<br/>"
178 " - Stefan Becker<br/>"
179 " - pier11<br/>"
180 " - Jakub Adam<br/>"
181 " - Tomáš Hrabčík<br/>"
182 "<br/>"
183 /* 13 */ "%s<br/>"
185 /* The next 13 texts make up the SIPE about note text */
186 /* About note, part 1/13: introduction */
187 _("A third-party plugin implementing extended version of SIP/SIMPLE used by various products"),
188 /* About note, part 2/13: home page URL (label) */
189 _("Home Page"),
190 /* About note, part 3/13: support forum URL (label) */
191 _("Support"),
192 /* About note, part 4/13: support forum name (hyperlink text) */
193 _("Help Forum"),
194 /* About note, part 5/13: bug tracker URL (label) */
195 _("Report Problems"),
196 /* About note, part 6/13: bug tracker URL (hyperlink text) */
197 _("Bug Tracker"),
198 /* About note, part 7/13: translation service URL (label) */
199 _("Translations"),
200 /* About note, part 8/13: license type (label) */
201 _("License"),
202 /* About note, part 9/13: known users */
203 _("We support users in such organizations as"),
204 /* About note, part 10/13: translation request, text before Transifex.net URL */
205 /* append a space if text is not empty */
206 _("Please help us to translate SIPE to your native language here at "),
207 /* About note, part 11/13: translation request, text after Transifex.net URL */
208 /* start with a space if text is not empty */
209 _(" using convenient web interface"),
210 /* About note, part 12/13: author list (header) */
211 _("Authors"),
212 /* About note, part 13/13: Localization credit */
213 /* PLEASE NOTE: do *NOT* simply translate the english original */
214 /* but write something similar to the following sentence: */
215 /* "Localization for <language name> (<language code>): <name>" */
216 _("Original texts in English (en): SIPE developers")
220 static guint sipe_ht_hash_nick(const char *nick)
222 char *lc = g_utf8_strdown(nick, -1);
223 guint bucket = g_str_hash(lc);
224 g_free(lc);
226 return bucket;
229 static gboolean sipe_ht_equals_nick(const char *nick1, const char *nick2)
231 char *nick1_norm = NULL;
232 char *nick2_norm = NULL;
233 gboolean equal;
235 if (nick1 == NULL && nick2 == NULL) return TRUE;
236 if (nick1 == NULL || nick2 == NULL ||
237 !g_utf8_validate(nick1, -1, NULL) ||
238 !g_utf8_validate(nick2, -1, NULL)) return FALSE;
240 nick1_norm = g_utf8_casefold(nick1, -1);
241 nick2_norm = g_utf8_casefold(nick2, -1);
242 equal = g_utf8_collate(nick1_norm, nick2_norm) == 0;
243 g_free(nick2_norm);
244 g_free(nick1_norm);
246 return equal;
249 struct sipe_core_public *sipe_core_allocate(const gchar *signin_name,
250 gboolean sso,
251 const gchar *login_domain,
252 const gchar *login_account,
253 const gchar *password,
254 const gchar *email,
255 const gchar *email_url,
256 const gchar **errmsg)
258 struct sipe_core_private *sipe_private;
259 gchar **user_domain;
261 SIPE_DEBUG_INFO("sipe_core_allocate: SIPE version " SIPE_CORE_VERSION " signin_name '%s'", signin_name);
263 /* ensure that sign-in name doesn't contain invalid characters */
264 if (strpbrk(signin_name, "\t\v\r\n") != NULL) {
265 *errmsg = _("SIP Exchange user name contains invalid characters");
266 return NULL;
269 /* ensure that sign-in name format is name@domain */
270 if (!strchr(signin_name, '@') ||
271 g_str_has_prefix(signin_name, "@") ||
272 g_str_has_suffix(signin_name, "@")) {
273 *errmsg = _("User name should be a valid SIP URI\nExample: user@company.com");
274 return NULL;
277 /* ensure that Login & Password are valid when SSO is not selected */
278 if (!sso && (is_empty(login_account) || is_empty(password))) {
279 *errmsg = _("Login and password are required when Single Sign-On is not enabled");
280 return NULL;
283 /* ensure that email format is name@domain (if provided) */
284 if (!is_empty(email) &&
285 (!strchr(email, '@') ||
286 g_str_has_prefix(email, "@") ||
287 g_str_has_suffix(email, "@")))
289 *errmsg = _("Email address should be valid if provided\nExample: user@company.com");
290 return NULL;
293 /* ensure that user name doesn't contain spaces */
294 user_domain = g_strsplit(signin_name, "@", 2);
295 SIPE_DEBUG_INFO("sipe_core_allocate: user '%s' domain '%s'", user_domain[0], user_domain[1]);
296 if (strchr(user_domain[0], ' ') != NULL) {
297 g_strfreev(user_domain);
298 *errmsg = _("SIP Exchange user name contains whitespace");
299 return NULL;
302 /* ensure that email_url is in proper format if enabled (if provided).
303 * Example (Exchange): https://server.company.com/EWS/Exchange.asmx
304 * Example (Domino) : https://[domino_server]/[mail_database_name].nsf
306 if (!is_empty(email_url)) {
307 char *tmp = g_ascii_strdown(email_url, -1);
308 if (!g_str_has_prefix(tmp, "https://"))
310 g_free(tmp);
311 g_strfreev(user_domain);
312 *errmsg = _("Email services URL should be valid if provided\n"
313 "Example: https://exchange.corp.com/EWS/Exchange.asmx\n"
314 "Example: https://domino.corp.com/maildatabase.nsf");
315 return NULL;
317 g_free(tmp);
320 sipe_private = g_new0(struct sipe_core_private, 1);
321 SIPE_CORE_PRIVATE_FLAG_UNSET(SUBSCRIBED_BUDDIES);
322 SIPE_CORE_PRIVATE_FLAG_UNSET(INITIAL_PUBLISH);
323 SIPE_CORE_PRIVATE_FLAG_UNSET(SSO);
324 if (sso)
325 SIPE_CORE_PRIVATE_FLAG_SET(SSO);
326 sipe_private->username = g_strdup(signin_name);
327 sipe_private->email = is_empty(email) ? g_strdup(signin_name) : g_strdup(email);
328 sipe_private->authdomain = sso ? NULL : g_strdup(login_domain);
329 sipe_private->authuser = sso ? NULL : g_strdup(login_account);
330 sipe_private->password = sso ? NULL : g_strdup(password);
331 sipe_private->public.sip_name = g_strdup(user_domain[0]);
332 sipe_private->public.sip_domain = g_strdup(user_domain[1]);
333 g_strfreev(user_domain);
335 sipe_private->buddies = g_hash_table_new((GHashFunc)sipe_ht_hash_nick, (GEqualFunc)sipe_ht_equals_nick);
336 sipe_private->our_publications = g_hash_table_new_full(g_str_hash, g_str_equal,
337 g_free, (GDestroyNotify)g_hash_table_destroy);
338 sipe_subscriptions_init(sipe_private);
339 sipe_status_set_activity(sipe_private, SIPE_ACTIVITY_UNSET);
341 return((struct sipe_core_public *)sipe_private);
344 void sipe_core_connection_cleanup(struct sipe_core_private *sipe_private)
346 g_free(sipe_private->epid);
347 sipe_private->epid = NULL;
349 sip_transport_disconnect(sipe_private);
351 sipe_schedule_cancel_all(sipe_private);
353 if (sipe_private->allowed_events) {
354 GSList *entry = sipe_private->allowed_events;
355 while (entry) {
356 g_free(entry->data);
357 entry = entry->next;
360 g_slist_free(sipe_private->allowed_events);
362 sipe_ocs2007_free(sipe_private);
364 sipe_core_buddy_menu_free(SIPE_CORE_PUBLIC);
366 if (sipe_private->contact)
367 g_free(sipe_private->contact);
368 sipe_private->contact = NULL;
369 if (sipe_private->register_callid)
370 g_free(sipe_private->register_callid);
371 sipe_private->register_callid = NULL;
373 if (sipe_private->focus_factory_uri)
374 g_free(sipe_private->focus_factory_uri);
375 sipe_private->focus_factory_uri = NULL;
377 if (sipe_private->calendar) {
378 sipe_cal_calendar_free(sipe_private->calendar);
380 sipe_private->calendar = NULL;
382 sipe_groupchat_free(sipe_private);
385 void sipe_core_deallocate(struct sipe_core_public *sipe_public)
387 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
389 #ifdef HAVE_VV
390 if (sipe_private->media_call) {
391 sipe_media_handle_going_offline(sipe_private->media_call);
393 #endif
395 /* leave all conversations */
396 if (sipe_private->sessions) {
397 GSList *entry;
398 while ((entry = sipe_private->sessions) != NULL) {
399 sipe_session_close(sipe_private, entry->data);
403 sipe_conf_cancel_unaccepted(sipe_private, NULL);
405 if (sipe_private->csta) {
406 sip_csta_close(sipe_private);
409 /* pending service requests must be cancelled first */
410 sipe_svc_free(sipe_private);
411 sipe_webticket_free(sipe_private);
413 if (sipe_backend_connection_is_valid(SIPE_CORE_PUBLIC)) {
414 sipe_subscriptions_unsubscribe(sipe_private);
415 sip_transport_deregister(sipe_private);
418 sipe_core_connection_cleanup(sipe_private);
419 sipe_certificate_free(sipe_private);
421 g_free(sipe_private->public.sip_name);
422 g_free(sipe_private->public.sip_domain);
423 g_free(sipe_private->username);
424 g_free(sipe_private->email);
425 g_free(sipe_private->password);
426 g_free(sipe_private->authdomain);
427 g_free(sipe_private->authuser);
428 g_free(sipe_private->status);
429 g_free(sipe_private->note);
430 g_free(sipe_private->ocs2005_user_states);
432 sipe_buddy_free_all(sipe_private);
433 g_hash_table_destroy(sipe_private->buddies);
434 g_hash_table_destroy(sipe_private->our_publications);
435 g_hash_table_destroy(sipe_private->user_state_publications);
436 sipe_subscriptions_destroy(sipe_private);
438 if (sipe_private->groups) {
439 GSList *entry;
440 while ((entry = sipe_private->groups) != NULL)
441 sipe_group_free(sipe_private, entry->data);
444 if (sipe_private->our_publication_keys) {
445 GSList *entry = sipe_private->our_publication_keys;
446 while (entry) {
447 g_free(entry->data);
448 entry = entry->next;
451 g_slist_free(sipe_private->our_publication_keys);
453 #ifdef HAVE_VV
454 g_free(sipe_private->test_call_bot_uri);
455 g_free(sipe_private->mras_uri);
456 g_free(sipe_private->media_relay_username);
457 g_free(sipe_private->media_relay_password);
458 sipe_media_relay_list_free(sipe_private->media_relays);
459 #endif
461 g_free(sipe_private->addressbook_uri);
462 g_free(sipe_private->dlx_uri);
463 g_free(sipe_private);
467 Local Variables:
468 mode: c
469 c-file-style: "bsd"
470 indent-tabs-mode: t
471 tab-width: 8
472 End: