6 * Copyright (C) 2010-2017 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
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
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>
58 * Thanks to Google's Summer of Code Program and the helpful mentors
60 *------------------- Copyright notices from "sipe.c" ---------------
72 #include "sipe-common.h"
75 #include "sip-transport.h"
76 #include "sipe-backend.h"
77 #include "sipe-buddy.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-ews-autodiscover.h"
86 #include "sipe-group.h"
87 #include "sipe-groupchat.h"
88 #include "sipe-http.h"
89 #include "sipe-lync-autodiscover.h"
90 #include "sipe-media.h"
91 #include "sipe-mime.h"
93 #include "sipe-ocs2007.h"
94 #include "sipe-schedule.h"
95 #include "sipe-session.h"
96 #include "sipe-status.h"
97 #include "sipe-subscriptions.h"
100 #include "sipe-utils.h"
101 #include "sipe-webticket.h"
103 #ifdef PACKAGE_GIT_COMMIT
104 #define SIPE_CORE_VERSION PACKAGE_VERSION " (git commit " PACKAGE_GIT_COMMIT " / "
106 #define SIPE_CORE_VERSION PACKAGE_VERSION " ("
109 /* translate config.h options to strings */
110 static const gchar
* const sipe_core_build_options
[] = {
115 #elif defined(HAVE_GSSAPI_ONLY)
117 #ifndef HAVE_GSSAPI_PASSWORD_SUPPORT
121 #ifdef HAVE_GSSAPI_GSSAPI_H
138 "Application Sharing",
151 /* locale_dir is unused if ENABLE_NLS is not defined */
152 void sipe_core_init(SIPE_UNUSED_PARAMETER
const char *locale_dir
)
158 SIPE_DEBUG_INFO("bindtextdomain = %s",
159 bindtextdomain(PACKAGE_NAME
, locale_dir
));
160 SIPE_DEBUG_INFO("bind_textdomain_codeset = %s",
161 bind_textdomain_codeset(PACKAGE_NAME
, "UTF-8"));
162 textdomain(PACKAGE_NAME
);
164 /* Initialization for crypto backend (production mode) */
165 sipe_crypto_init(TRUE
);
170 void sipe_core_destroy(void)
173 sipe_status_shutdown();
174 sipe_mime_shutdown();
175 sipe_crypto_shutdown();
179 gchar
*sipe_core_about(void)
181 gchar
*options
= g_strjoinv(" / ", (gchar
**) sipe_core_build_options
);
182 gchar
*about
= g_strdup_printf(
184 * Non-translatable parts, like markup, are hard-coded
185 * into the format string. This requires more translatable
186 * texts but it makes the translations less error prone.
188 "<b><font size=\"+1\">SIPE " SIPE_CORE_VERSION
"%s) </font></b><br/>"
191 " - Skype for Business<br/>"
192 " - Microsoft Office 365<br/>"
193 " - Microsoft Business Productivity Online Suite (BPOS)<br/>"
194 " - Microsoft Lync Server<br/>"
195 " - Microsoft Office Communications Server 2007 R2<br/>"
196 " - Microsoft Office Communications Server 2007<br/>"
197 " - Microsoft Live Communications Server 2005<br/>"
198 " - Microsoft Live Communications Server 2003<br/>"
199 " - Reuters Messaging<br/>"
201 /* 2 */ "%s: <a href=\"" PACKAGE_URL
"\">" PACKAGE_URL
"</a><br/>"
202 /* 3,4 */ "%s: <a href=\"http://sourceforge.net/p/sipe/discussion/688534/\">%s</a><br/>"
203 /* 5,6 */ "%s: <a href=\"" PACKAGE_BUGREPORT
"\">%s</a><br/>"
204 /* 7 */ "%s: <a href=\"" SIPE_TRANSLATIONS_URL
"\">Transifex.com</a><br/>"
205 /* 8 */ "%s: GPLv2+<br/>"
208 /* 10,11 */ "%s<a href=\"" SIPE_TRANSLATIONS_URL
"\">Transifex.com</a>%s.<br/>"
210 /* 12 */ "<b>%s:</b><br/>"
211 " - Stefan Becker<br/>"
213 " - Jochen De Smet (retired, Miranda port)<br/>"
214 " - Michael Lamb (retired, Adium port)<br/>"
215 " - Anibal Avelar (retired)<br/>"
216 " - Gabriel Burt (retired)<br/>"
217 " - pier11 (retired)<br/>"
218 " - Tomáš Hrabčík (retired)<br/>"
222 /* The next 13 texts make up the SIPE about note text */
223 /* About note, part 1/13: introduction */
224 _("A third-party plugin implementing extended version of SIP/SIMPLE used by various products"),
225 /* About note, part 2/13: home page URL (label) */
227 /* About note, part 3/13: support forum URL (label) */
229 /* About note, part 4/13: support forum name (hyperlink text) */
231 /* About note, part 5/13: bug tracker URL (label) */
232 _("Report Problems"),
233 /* About note, part 6/13: bug tracker URL (hyperlink text) */
235 /* About note, part 7/13: translation service URL (label) */
237 /* About note, part 8/13: license type (label) */
239 /* About note, part 9/13: (REMOVED) */
240 /* About note, part 10/13: translation request, text before Transifex.com URL */
241 /* append a space if text is not empty */
242 _("Please help us to translate SIPE to your native language here at "),
243 /* About note, part 11/13: translation request, text after Transifex.com URL */
244 /* start with a space if text is not empty */
245 _(" using convenient web interface"),
246 /* About note, part 12/13: author list (header) */
248 /* About note, part 13/13: Localization credit */
249 /* PLEASE NOTE: do *NOT* simply translate the english original */
250 /* but write something similar to the following sentence: */
251 /* "Localization for <language name> (<language code>): <name>" */
252 _("Original texts in English (en): SIPE developers")
258 struct sipe_core_public
*sipe_core_allocate(const gchar
*signin_name
,
260 const gchar
*login_account
,
261 const gchar
*password
,
263 const gchar
*email_url
,
264 const gchar
**errmsg
)
266 struct sipe_core_private
*sipe_private
;
268 gchar
*options
= g_strjoinv(" / ", (gchar
**) sipe_core_build_options
);
270 SIPE_LOG_INFO("sipe_core_allocate: SIPE version " SIPE_CORE_VERSION
"%s)", options
);
272 SIPE_DEBUG_INFO("sipe_core_allocate: signin_name '%s'", signin_name
);
274 /* ensure that sign-in name doesn't contain invalid characters */
275 if (strpbrk(signin_name
, "\t\v\r\n") != NULL
) {
276 *errmsg
= _("SIP Exchange user name contains invalid characters");
280 /* ensure that sign-in name format is name@domain */
281 if (!strchr(signin_name
, '@') ||
282 g_str_has_prefix(signin_name
, "@") ||
283 g_str_has_suffix(signin_name
, "@")) {
284 *errmsg
= _("User name should be a valid SIP URI\nExample: user@company.com");
289 /* ensure that Password is valid when SSO is not selected */
290 if (!sso
&& is_empty(password
)) {
291 *errmsg
= _("Password is required when Single Sign-On is not enabled");
295 /* ensure that email format is name@domain (if provided) */
296 if (!is_empty(email
) &&
297 (!strchr(email
, '@') ||
298 g_str_has_prefix(email
, "@") ||
299 g_str_has_suffix(email
, "@")))
301 *errmsg
= _("Email address should be valid if provided\nExample: user@company.com");
305 /* ensure that user name doesn't contain spaces */
306 user_domain
= g_strsplit(signin_name
, "@", 2);
307 SIPE_DEBUG_INFO("sipe_core_allocate: user '%s' domain '%s'", user_domain
[0], user_domain
[1]);
308 if (strchr(user_domain
[0], ' ') != NULL
) {
309 g_strfreev(user_domain
);
310 *errmsg
= _("SIP Exchange user name contains whitespace");
314 /* ensure that email_url is in proper format if enabled (if provided).
315 * Example (Exchange): https://server.company.com/EWS/Exchange.asmx
316 * Example (Domino) : https://[domino_server]/[mail_database_name].nsf
318 if (!is_empty(email_url
)) {
319 char *tmp
= g_ascii_strdown(email_url
, -1);
320 if (!g_str_has_prefix(tmp
, "https://"))
323 g_strfreev(user_domain
);
324 *errmsg
= _("Email services URL should be valid if provided\n"
325 "Example: https://exchange.corp.com/EWS/Exchange.asmx\n"
326 "Example: https://domino.corp.com/maildatabase.nsf");
332 /* re-use sign-in name if login is empty */
333 if (is_empty(login_account
))
334 login_account
= signin_name
;
336 sipe_private
= g_new0(struct sipe_core_private
, 1);
337 SIPE_CORE_PRIVATE_FLAG_UNSET(SUBSCRIBED_BUDDIES
);
338 SIPE_CORE_PRIVATE_FLAG_UNSET(INITIAL_PUBLISH
);
339 SIPE_CORE_PRIVATE_FLAG_UNSET(SSO
);
341 SIPE_CORE_PRIVATE_FLAG_SET(SSO
);
342 sipe_private
->username
= g_strdup(signin_name
);
343 sipe_private
->email
= is_empty(email
) ? g_strdup(signin_name
) : g_strdup(email
);
344 sipe_private
->authuser
= sso
? NULL
: g_strdup(login_account
);
345 sipe_private
->password
= sso
? NULL
: g_strdup(password
);
346 sipe_private
->public.sip_name
= g_strdup(user_domain
[0]);
347 sipe_private
->public.sip_domain
= g_strdup(user_domain
[1]);
348 g_strfreev(user_domain
);
350 sipe_group_init(sipe_private
);
351 sipe_buddy_init(sipe_private
);
352 sipe_private
->our_publications
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
353 g_free
, (GDestroyNotify
)g_hash_table_destroy
);
354 sipe_subscriptions_init(sipe_private
);
355 sipe_lync_autodiscover_init(sipe_private
);
356 sipe_ews_autodiscover_init(sipe_private
);
357 sipe_status_set_activity(sipe_private
, SIPE_ACTIVITY_UNSET
);
359 sipe_private
->media_calls
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
361 sipe_private
->access_numbers
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
364 return((struct sipe_core_public
*)sipe_private
);
367 void sipe_core_backend_initialized(struct sipe_core_private
*sipe_private
,
368 guint authentication
)
372 sipe_private
->authentication_type
= authentication
;
374 /* user specified email login? */
375 value
= sipe_backend_setting(SIPE_CORE_PUBLIC
, SIPE_SETTING_EMAIL_LOGIN
);
376 if (!is_empty(value
)) {
377 sipe_private
->email_authuser
= g_strdup(value
);
378 sipe_private
->email_password
= g_strdup(sipe_backend_setting(SIPE_CORE_PUBLIC
,
379 SIPE_SETTING_EMAIL_PASSWORD
));
383 void sipe_core_connection_cleanup(struct sipe_core_private
*sipe_private
)
385 sipe_http_free(sipe_private
);
386 sip_transport_disconnect(sipe_private
);
388 sipe_schedule_cancel_all(sipe_private
);
390 if (sipe_private
->allowed_events
)
391 sipe_utils_slist_free_full(sipe_private
->allowed_events
, g_free
);
393 sipe_ocs2007_free(sipe_private
);
395 sipe_core_buddy_menu_free(SIPE_CORE_PUBLIC
);
397 if (sipe_private
->contact
)
398 g_free(sipe_private
->contact
);
399 sipe_private
->contact
= NULL
;
400 if (sipe_private
->register_callid
)
401 g_free(sipe_private
->register_callid
);
402 sipe_private
->register_callid
= NULL
;
404 if (sipe_private
->focus_factory_uri
)
405 g_free(sipe_private
->focus_factory_uri
);
406 sipe_private
->focus_factory_uri
= NULL
;
408 sipe_groupchat_free(sipe_private
);
410 while (sipe_private
->lync_autodiscover_servers
)
411 sipe_private
->lync_autodiscover_servers
=
412 sipe_lync_autodiscover_pop(sipe_private
->lync_autodiscover_servers
);
415 void sipe_core_deallocate(struct sipe_core_public
*sipe_public
)
417 struct sipe_core_private
*sipe_private
= SIPE_CORE_PRIVATE
;
420 sipe_media_handle_going_offline(sipe_private
);
423 /* leave all conversations */
424 if (sipe_private
->sessions
) {
426 while ((entry
= sipe_private
->sessions
) != NULL
) {
427 sipe_session_close(sipe_private
, entry
->data
);
431 sipe_conf_cancel_unaccepted(sipe_private
, NULL
);
433 if (sipe_private
->csta
) {
434 sip_csta_close(sipe_private
);
437 /* pending service requests must be cancelled first */
438 sipe_svc_free(sipe_private
);
439 sipe_webticket_free(sipe_private
);
440 sipe_ucs_free(sipe_private
);
441 sipe_lync_autodiscover_free(sipe_private
);
443 if (sipe_backend_connection_is_valid(SIPE_CORE_PUBLIC
)) {
444 sipe_subscriptions_unsubscribe(sipe_private
);
445 sip_transport_deregister(sipe_private
);
448 sipe_core_connection_cleanup(sipe_private
);
449 sipe_ews_autodiscover_free(sipe_private
);
450 sipe_cal_calendar_free(sipe_private
->calendar
);
451 sipe_certificate_free(sipe_private
);
453 g_free(sipe_private
->public.sip_name
);
454 g_free(sipe_private
->public.sip_domain
);
455 g_free(sipe_private
->username
);
456 g_free(sipe_private
->email_password
);
457 g_free(sipe_private
->email_authuser
);
458 g_free(sipe_private
->email
);
459 g_free(sipe_private
->password
);
460 g_free(sipe_private
->authuser
);
461 g_free(sipe_private
->status
);
462 g_free(sipe_private
->note
);
463 g_free(sipe_private
->ocs2005_user_states
);
465 sipe_buddy_free(sipe_private
);
466 g_hash_table_destroy(sipe_private
->our_publications
);
467 g_hash_table_destroy(sipe_private
->user_state_publications
);
468 g_hash_table_destroy(sipe_private
->media_calls
);
469 sipe_subscriptions_destroy(sipe_private
);
470 sipe_group_free(sipe_private
);
472 if (sipe_private
->our_publication_keys
)
473 sipe_utils_slist_free_full(sipe_private
->our_publication_keys
, g_free
);
476 g_free(sipe_private
->test_call_bot_uri
);
477 g_free(sipe_private
->uc_line_uri
);
478 g_free(sipe_private
->mras_uri
);
479 g_free(sipe_private
->media_relay_username
);
480 g_free(sipe_private
->media_relay_password
);
481 sipe_media_relay_list_free(sipe_private
->media_relays
);
484 g_free(sipe_private
->persistentChatPool_uri
);
485 g_free(sipe_private
->addressbook_uri
);
486 g_free(sipe_private
->dlx_uri
);
487 sipe_utils_slist_free_full(sipe_private
->conf_mcu_types
, g_free
);
488 g_hash_table_destroy(sipe_private
->access_numbers
);
489 g_free(sipe_private
);
492 void sipe_core_email_authentication(struct sipe_core_private
*sipe_private
,
493 struct sipe_http_request
*request
)
495 if (sipe_private
->email_authuser
) {
496 sipe_http_request_authentication(request
,
497 sipe_private
->email_authuser
,
498 sipe_private
->email_password
);