6 * Copyright (C) 2010-11 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
32 #include "sipe-common.h"
35 #include "sip-transport.h"
36 #include "sipe-backend.h"
37 #include "sipe-certificate.h"
38 #include "sipe-chat.h"
39 #include "sipe-conf.h"
40 #include "sipe-core.h"
41 #include "sipe-core-private.h"
42 #include "sipe-crypt.h"
43 #include "sipe-group.h"
44 #include "sipe-media.h"
45 #include "sipe-mime.h"
47 #include "sipe-session.h"
48 #include "sipe-subscriptions.h"
50 #include "sipe-utils.h"
53 /* locale_dir is unused if ENABLE_NLS is not defined */
54 void sipe_core_init(SIPE_UNUSED_PARAMETER
const char *locale_dir
)
60 SIPE_DEBUG_INFO("bindtextdomain = %s",
61 bindtextdomain(PACKAGE_NAME
, locale_dir
));
62 SIPE_DEBUG_INFO("bind_textdomain_codeset = %s",
63 bind_textdomain_codeset(PACKAGE_NAME
, "UTF-8"));
64 textdomain(PACKAGE_NAME
);
66 /* Initialization for crypto backend (production mode) */
67 sipe_crypto_init(TRUE
);
71 void sipe_core_destroy(void)
75 sipe_crypto_shutdown();
79 gchar
*sipe_core_about(void)
81 return g_strdup_printf(
83 * Non-translatable parts, like markup, are hard-coded
84 * into the format string. This requires more translatable
85 * texts but it makes the translations less error prone.
87 "<b><font size=\"+1\">SIPE " PACKAGE_VERSION
" </font></b><br/>"
90 "<li> - MS Office Communications Server 2007 R2</li><br/>"
91 "<li> - MS Office Communications Server 2007</li><br/>"
92 "<li> - MS Live Communications Server 2005</li><br/>"
93 "<li> - MS Live Communications Server 2003</li><br/>"
94 "<li> - Reuters Messaging</li><br/>"
96 /* 2 */ "%s: <a href=\"" PACKAGE_URL
"\">" PACKAGE_URL
"</a><br/>"
97 /* 3,4 */ "%s: <a href=\"http://sourceforge.net/projects/sipe/forums/forum/688534\">%s</a><br/>"
98 /* 5,6 */ "%s: <a href=\"" PACKAGE_BUGREPORT
"\">%s</a><br/>"
99 /* 7 */ "%s: <a href=\"" SIPE_TRANSLATIONS_URL
"\">Transifex.net</a><br/>"
100 /* 8 */ "%s: GPLv2+<br/>"
104 " - Reuters Messaging network<br/>"
105 " - Deutsche Bank<br/>"
106 " - Merrill Lynch<br/>"
115 " - Alcatel-Lucent<br/>"
118 /* 10,11 */ "%s<a href=\"" SIPE_TRANSLATIONS_URL
"\">Transifex.net</a>%s.<br/>"
120 /* 12 */ "<b>%s:</b><br/>"
121 " - Anibal Avelar<br/>"
122 " - Gabriel Burt<br/>"
123 " - Stefan Becker<br/>"
126 " - Tomáš Hrabčík<br/>"
130 /* The next 13 texts make up the SIPE about note text */
131 /* About note, part 1/13: introduction */
132 _("A third-party plugin implementing extended version of SIP/SIMPLE used by various products"),
133 /* About note, part 2/13: home page URL (label) */
135 /* About note, part 3/13: support forum URL (label) */
137 /* About note, part 4/13: support forum name (hyperlink text) */
139 /* About note, part 5/13: bug tracker URL (label) */
140 _("Report Problems"),
141 /* About note, part 6/13: bug tracker URL (hyperlink text) */
143 /* About note, part 7/13: translation service URL (label) */
145 /* About note, part 8/13: license type (label) */
147 /* About note, part 9/13: known users */
148 _("We support users in such organizations as"),
149 /* About note, part 10/13: translation request, text before Transifex.net URL */
150 /* append a space if text is not empty */
151 _("Please help us to translate SIPE to your native language here at "),
152 /* About note, part 11/13: translation request, text after Transifex.net URL */
153 /* start with a space if text is not empty */
154 _(" using convenient web interface"),
155 /* About note, part 12/13: author list (header) */
157 /* About note, part 13/13: Localization credit */
158 /* PLEASE NOTE: do *NOT* simply translate the english original */
159 /* but write something similar to the following sentence: */
160 /* "Localization for <language name> (<language code>): <name>" */
161 _("Original texts in English (en): SIPE developers")
165 static guint
sipe_ht_hash_nick(const char *nick
)
167 char *lc
= g_utf8_strdown(nick
, -1);
168 guint bucket
= g_str_hash(lc
);
174 static gboolean
sipe_ht_equals_nick(const char *nick1
, const char *nick2
)
176 char *nick1_norm
= NULL
;
177 char *nick2_norm
= NULL
;
180 if (nick1
== NULL
&& nick2
== NULL
) return TRUE
;
181 if (nick1
== NULL
|| nick2
== NULL
||
182 !g_utf8_validate(nick1
, -1, NULL
) ||
183 !g_utf8_validate(nick2
, -1, NULL
)) return FALSE
;
185 nick1_norm
= g_utf8_casefold(nick1
, -1);
186 nick2_norm
= g_utf8_casefold(nick2
, -1);
187 equal
= g_utf8_collate(nick1_norm
, nick2_norm
) == 0;
194 struct sipe_core_public
*sipe_core_allocate(const gchar
*signin_name
,
195 const gchar
*login_domain
,
196 const gchar
*login_account
,
197 const gchar
*password
,
199 const gchar
*email_url
,
200 const gchar
**errmsg
)
202 struct sipe_core_private
*sipe_private
;
203 struct sipe_account_data
*sip
;
206 SIPE_DEBUG_INFO("sipe_core_allocate: signin_name '%s'", signin_name
);
208 /* ensure that sign-in name doesn't contain invalid characters */
209 if (strpbrk(signin_name
, "\t\v\r\n") != NULL
) {
210 *errmsg
= _("SIP Exchange user name contains invalid characters");
214 /* ensure that sign-in name format is name@domain */
215 if (!strchr(signin_name
, '@') ||
216 g_str_has_prefix(signin_name
, "@") ||
217 g_str_has_suffix(signin_name
, "@")) {
218 *errmsg
= _("User name should be a valid SIP URI\nExample: user@company.com");
222 /* ensure that email format is name@domain (if provided) */
223 if (!is_empty(email
) &&
224 (!strchr(email
, '@') ||
225 g_str_has_prefix(email
, "@") ||
226 g_str_has_suffix(email
, "@")))
228 *errmsg
= _("Email address should be valid if provided\nExample: user@company.com");
232 /* ensure that user name doesn't contain spaces */
233 user_domain
= g_strsplit(signin_name
, "@", 2);
234 SIPE_DEBUG_INFO("sipe_core_allocate: user '%s' domain '%s'", user_domain
[0], user_domain
[1]);
235 if (strchr(user_domain
[0], ' ') != NULL
) {
236 g_strfreev(user_domain
);
237 *errmsg
= _("SIP Exchange user name contains whitespace");
241 /* ensure that email_url is in proper format if enabled (if provided).
242 * Example (Exchange): https://server.company.com/EWS/Exchange.asmx
243 * Example (Domino) : https://[domino_server]/[mail_database_name].nsf
245 if (!is_empty(email_url
)) {
246 char *tmp
= g_ascii_strdown(email_url
, -1);
247 if (!g_str_has_prefix(tmp
, "https://"))
250 g_strfreev(user_domain
);
251 *errmsg
= _("Email services URL should be valid if provided\n"
252 "Example: https://exchange.corp.com/EWS/Exchange.asmx\n"
253 "Example: https://domino.corp.com/maildatabase.nsf");
259 sipe_private
= g_new0(struct sipe_core_private
, 1);
260 sipe_private
->temporary
= sip
= g_new0(struct sipe_account_data
, 1);
261 sip
->subscribed_buddies
= FALSE
;
262 sip
->initial_state_published
= FALSE
;
263 sipe_private
->username
= g_strdup(signin_name
);
264 sip
->email
= is_empty(email
) ? g_strdup(signin_name
) : g_strdup(email
);
265 sip
->authdomain
= is_empty(login_domain
) ? NULL
: g_strdup(login_domain
);
266 sip
->authuser
= is_empty(login_account
) ? NULL
: g_strdup(login_account
);
267 sip
->password
= g_strdup(password
);
268 sipe_private
->public.sip_name
= g_strdup(user_domain
[0]);
269 sipe_private
->public.sip_domain
= g_strdup(user_domain
[1]);
270 g_strfreev(user_domain
);
272 sipe_private
->buddies
= g_hash_table_new((GHashFunc
)sipe_ht_hash_nick
, (GEqualFunc
)sipe_ht_equals_nick
);
273 sip
->our_publications
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
274 g_free
, (GDestroyNotify
)g_hash_table_destroy
);
275 sipe_subscriptions_init(sipe_private
);
276 sipe_set_unknown_status(sipe_private
);
278 return((struct sipe_core_public
*)sipe_private
);
281 void sipe_core_deallocate(struct sipe_core_public
*sipe_public
)
283 struct sipe_core_private
*sipe_private
= SIPE_CORE_PRIVATE
;
284 struct sipe_account_data
*sip
= SIPE_ACCOUNT_DATA_PRIVATE
;
287 if (sipe_private
->media_call
) {
288 sipe_media_handle_going_offline(sipe_private
->media_call
);
292 /* leave all conversations */
293 if (sipe_private
->sessions
) {
295 while ((entry
= sipe_private
->sessions
) != NULL
) {
296 sipe_session_close(sipe_private
, entry
->data
);
300 sipe_conf_cancel_unaccepted(sipe_private
, NULL
);
303 sip_csta_close(sipe_private
);
306 sipe_certificate_free(sipe_private
);
307 sipe_svc_free(sipe_private
);
309 if (sipe_backend_connection_is_valid(SIPE_CORE_PUBLIC
)) {
310 sipe_subscriptions_unsubscribe(sipe_private
);
311 sip_transport_deregister(sipe_private
);
314 sipe_connection_cleanup(sipe_private
);
315 g_free(sipe_private
->public.sip_name
);
316 g_free(sipe_private
->public.sip_domain
);
317 g_free(sipe_private
->username
);
319 g_free(sip
->password
);
320 g_free(sip
->authdomain
);
321 g_free(sip
->authuser
);
324 g_free(sip
->user_states
);
326 sipe_buddy_free_all(sipe_private
);
327 g_hash_table_destroy(sipe_private
->buddies
);
328 g_hash_table_destroy(sip
->our_publications
);
329 g_hash_table_destroy(sip
->user_state_publications
);
330 sipe_subscriptions_destroy(sipe_private
);
332 if (sipe_private
->groups
) {
333 GSList
*entry
= sipe_private
->groups
;
335 struct sipe_group
*group
= entry
->data
;
341 g_slist_free(sipe_private
->groups
);
343 if (sip
->our_publication_keys
) {
344 GSList
*entry
= sip
->our_publication_keys
;
350 g_slist_free(sip
->our_publication_keys
);
353 g_free(sipe_private
->mras_uri
);
354 g_free(sipe_private
->media_relay_username
);
355 g_free(sipe_private
->media_relay_password
);
356 sipe_media_relay_list_free(sipe_private
->media_relays
);
360 g_free(sipe_private
);