core cleanup: 6 more modules are purple free
[siplcs.git] / src / core / sipe-utils.c
blob5643adc6c1a84980f4f255aa1f68962678116c4f
1 /**
2 * @file sipe-utils.c
4 * pidgin-sipe
6 * Copyright (C) 2009 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 <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <time.h>
28 #include <glib.h>
30 #include "debug.h"
31 #include "network.h"
32 #include "util.h"
33 #include "xmlnode.h"
35 #include "sip-sec.h"
36 #include "sipe-utils.h"
37 #include "uuid.h"
38 #include "sipe.h"
40 /* Generate 32 random bits */
41 #define RANDOM32BITS (rand() & 0xFFFF)
43 gchar *gencallid(void)
45 return g_strdup_printf("%04Xg%04Xa%04Xi%04Xm%04Xt%04Xb%04Xx%04Xx",
46 RANDOM32BITS, RANDOM32BITS, RANDOM32BITS,
47 RANDOM32BITS, RANDOM32BITS, RANDOM32BITS,
48 RANDOM32BITS, RANDOM32BITS);
51 gchar *gentag(void)
53 return g_strdup_printf("%04d%04d", RANDOM32BITS, RANDOM32BITS);
56 gchar *genconfid(void)
58 return g_strdup_printf("%04X%04X%04X%04X%04X%04X%04X%04X",
59 RANDOM32BITS, RANDOM32BITS, RANDOM32BITS,
60 RANDOM32BITS, RANDOM32BITS, RANDOM32BITS,
61 RANDOM32BITS, RANDOM32BITS);
64 gchar *get_contact(const struct sipe_account_data *sip)
66 return g_strdup(sip->contact);
69 gchar *parse_from(const gchar *hdr)
71 gchar *from;
72 const gchar *tmp, *tmp2 = hdr;
74 if (!hdr) return NULL;
75 purple_debug_info("sipe", "parsing address out of %s\n", hdr);
76 tmp = strchr(hdr, '<');
78 /* i hate the different SIP UA behaviours... */
79 if (tmp) { /* sip address in <...> */
80 tmp2 = tmp + 1;
81 tmp = strchr(tmp2, '>');
82 if (tmp) {
83 from = g_strndup(tmp2, tmp - tmp2);
84 } else {
85 purple_debug_info("sipe", "found < without > in From\n");
86 return NULL;
88 } else {
89 tmp = strchr(tmp2, ';');
90 if (tmp) {
91 from = g_strndup(tmp2, tmp - tmp2);
92 } else {
93 from = g_strdup(tmp2);
96 purple_debug_info("sipe", "got %s\n", from);
97 return from;
100 int parse_cseq(const gchar *hdr)
102 int res = -1;
103 gchar **items;
104 items = g_strsplit(hdr, " ", 1);
105 if (items[0]) {
106 res = atoi(items[0]);
108 g_strfreev(items);
109 return res;
112 gchar *sip_uri_from_name(const gchar *name)
114 return(g_strdup_printf("sip:%s", name));
117 gchar *sip_uri(const gchar *string)
119 return(strstr(string, "sip:") ? g_strdup(string) : sip_uri_from_name(string));
122 xmlnode *xmlnode_get_descendant(const xmlnode *parent, ...)
124 va_list args;
125 xmlnode *node = NULL;
126 const gchar *name;
128 va_start(args, parent);
129 while ((name = va_arg(args, const char *)) != NULL) {
130 node = xmlnode_get_child(parent, name);
131 if (node == NULL) break;
132 parent = node;
134 va_end(args);
136 return node;
139 gint xmlnode_get_int_attrib(xmlnode *node,
140 const char *attr,
141 gint fallback)
143 const char *value = xmlnode_get_attrib(node, attr);
144 return(value ? atoi(value) : fallback);
148 gchar *
149 get_epid(struct sipe_account_data *sip)
151 if (!sip->epid) {
152 gchar *self_sip_uri = sip_uri_self(sip);
153 sip->epid = sipe_get_epid(self_sip_uri,
154 g_get_host_name(),
155 purple_network_get_my_ip(-1));
156 g_free(self_sip_uri);
158 return g_strdup(sip->epid);
161 guint
162 sipe_get_pub_instance(struct sipe_account_data *sip,
163 int publication_key)
165 unsigned res = 0;
166 gchar *epid = get_epid(sip);
168 sscanf(epid, "%08x", &res);
169 g_free(epid);
171 if (publication_key == SIPE_PUB_DEVICE) {
172 /* as is */
173 } else if (publication_key == SIPE_PUB_STATE_MACHINE) { /* First hexadecimal digit is 0x3 */
174 res = (res >> 4) | 0x30000000;
175 } else if (publication_key == SIPE_PUB_STATE_USER) {
176 res = 0x20000000; /* fixed */
177 } else if (publication_key == SIPE_PUB_STATE_CALENDAR) { /* First hexadecimal digit is 0x4 */
178 res = (res >> 4) | 0x40000000;
179 } else if (publication_key == SIPE_PUB_STATE_CALENDAR_OOF) { /* First hexadecimal digit is 0x5 */
180 res = (res >> 4) | 0x50000000;
181 } else if (publication_key == SIPE_PUB_CALENDAR_DATA ||
182 publication_key == SIPE_PUB_NOTE_OOF)
183 { /* First hexadecimal digit is 0x4 */
184 unsigned calendar_id = 0;
185 char *mail_hash = sipe_get_epid(sip->email, "", "");
187 sscanf(mail_hash, "%08x", &calendar_id);
188 g_free(mail_hash);
189 res = (calendar_id >> 4) | 0x40000000;
192 return res;
194 /* an old version
195 guint
196 sipe_get_pub_instance_(struct sipe_account_data *sip,
197 const char *publication_key)
199 unsigned part_1;
200 unsigned part_2;
201 gchar *epid = get_epid(sip);
202 sscanf(epid, "%08x", &part_1);
203 g_free(epid);
204 sscanf(publication_key, "%uh", &part_2);
205 return part_1 + part_2;
208 gboolean
209 sipe_is_bad_alias(const char *uri,
210 const char *alias)
212 char *uri_alias;
213 gboolean result = FALSE;
215 if (!uri) return FALSE;
216 if (!alias) return TRUE;
218 if (g_str_has_prefix(alias, "sip:") || g_str_has_prefix(alias, "sips:")) return TRUE;
220 /* check if alias is just SIP URI but without 'sip:' prefix */
221 uri_alias = sip_uri_from_name(alias);
222 if (sipe_strcase_equal(uri, uri_alias)) {
223 result = TRUE;
225 g_free(uri_alias);
227 return result;
230 gboolean
231 is_empty(const char *st)
233 if (!st || strlen(st) == 0)
235 return TRUE;
237 /* suspecious leading or trailing staces */
238 else if (isspace((unsigned char) *st) ||
239 isspace((unsigned char) *(st + strlen(st) - 1)))
241 /* to not modify original string */
242 char *dup = g_strdup(st);
243 if (strlen(g_strstrip(dup)) == 0) {
244 g_free(dup);
245 return TRUE;
247 g_free(dup);
249 return FALSE;
252 /** Returns newly allocated string. Must be g_free()'d */
253 char *
254 replace(const char *st,
255 const char *search,
256 const char *replace)
258 char **tmp;
259 char *res;
261 if (!st) return NULL;
263 res = g_strjoinv(replace, tmp = g_strsplit(st, search, -1));
264 g_strfreev(tmp);
265 return res;
268 char *
269 fix_newlines(const char *st)
271 return replace(st, "\r\n", "\n");
274 gboolean
275 sipe_strequal(const gchar *left, const gchar *right)
277 #if GLIB_CHECK_VERSION(2,16,0)
278 return (g_strcmp0(left, right) == 0);
279 #else
280 return ((left == NULL && right == NULL) ||
281 (left != NULL && right != NULL && strcmp(left, right) == 0));
282 #endif
285 gboolean
286 sipe_strcase_equal(const gchar *left, const gchar *right)
288 return ((left == NULL && right == NULL) ||
289 (left != NULL && right != NULL && g_ascii_strcasecmp(left, right) == 0));
292 time_t
293 sipe_utils_str_to_time(const char *timestamp)
295 return purple_str_to_time(timestamp, TRUE, NULL, NULL, NULL);
298 char *
299 sipe_utils_time_to_str(time_t timestamp)
301 #define SIPE_XML_DATE_PATTERN "%Y-%m-%dT%H:%M:%SZ"
302 return g_strdup(purple_utf8_strftime(SIPE_XML_DATE_PATTERN, gmtime(&timestamp)));
305 size_t
306 hex_str_to_buff(const char *hex_str, guint8 **buff)
308 char two_digits[3];
309 size_t length;
310 size_t i;
312 if (!buff) return 0;
313 if (!hex_str) return 0;
315 length = strlen(hex_str)/2;
316 *buff = (unsigned char *)g_malloc(length);
317 for (i = 0; i < length; i++) {
318 two_digits[0] = hex_str[i * 2];
319 two_digits[1] = hex_str[i * 2 + 1];
320 two_digits[2] = '\0';
321 (*buff)[i] = (unsigned char)strtoul(two_digits, NULL, 16);
324 return length;
327 char *
328 buff_to_hex_str(const guint8 *buff, const size_t buff_len)
330 char *res;
331 size_t i, j;
333 if (!buff) return NULL;
335 res = g_malloc(buff_len * 2 + 1);
336 for (i = 0, j = 0; i < buff_len; i++, j+=2) {
337 sprintf(&res[j], "%02X", buff[i]);
339 res[j] = '\0';
340 return res;
343 gboolean
344 sipe_utils_parse_lines(GSList **list, gchar **lines)
346 int i;
347 gchar **parts;
348 gchar *dummy;
349 gchar *dummy2;
350 gchar *tmp;
352 for(i = 0; lines[i] && strlen(lines[i]) > 2; i++) {
353 parts = g_strsplit(lines[i], ":", 2);
354 if(!parts[0] || !parts[1]) {
355 g_strfreev(parts);
356 return FALSE;
358 dummy = parts[1];
359 dummy2 = 0;
360 while(*dummy==' ' || *dummy=='\t') dummy++;
361 dummy2 = g_strdup(dummy);
362 while(lines[i+1] && (lines[i+1][0]==' ' || lines[i+1][0]=='\t')) {
363 i++;
364 dummy = lines[i];
365 while(*dummy==' ' || *dummy=='\t') dummy++;
366 tmp = g_strdup_printf("%s %s",dummy2, dummy);
367 g_free(dummy2);
368 dummy2 = tmp;
370 *list = sipe_utils_nameval_add(*list, parts[0], dummy2);
371 g_free(dummy2);
372 g_strfreev(parts);
375 return TRUE;
378 GSList*
379 sipe_utils_nameval_add(GSList* list, const gchar *name, const gchar *value)
381 struct sipnameval *element = g_new0(struct sipnameval,1);
383 /* SANITY CHECK: the calling code must be fixed if this happens! */
384 if (!value) {
385 purple_debug(PURPLE_DEBUG_ERROR, "sipe", "sipe_utils_nameval_add: NULL value for %s\n",
386 name);
387 value = "";
390 element->name = g_strdup(name);
391 element->value = g_strdup(value);
392 return g_slist_append(list, element);
395 void
396 sipe_utils_nameval_free(GSList *list) {
397 struct sipnameval *elem;
398 while(list) {
399 elem = list->data;
400 list = g_slist_remove(list,elem);
401 g_free(elem->name);
402 g_free(elem->value);
403 g_free(elem);
407 const gchar *
408 sipe_utils_nameval_find(const GSList *list, const gchar *name)
410 return sipe_utils_nameval_find_instance (list, name, 0);
413 const gchar *
414 sipe_utils_nameval_find_instance(const GSList *list, const gchar *name, int which)
416 const GSList *tmp;
417 struct sipnameval *elem;
418 int i = 0;
419 tmp = list;
420 while(tmp) {
421 elem = tmp->data;
422 // OCS2005 can send the same header in either all caps or mixed case
423 if (sipe_strcase_equal(elem->name, name)) {
424 if (i == which) {
425 return elem->value;
427 i++;
429 tmp = g_slist_next(tmp);
431 return NULL;
435 Local Variables:
436 mode: c
437 c-file-style: "bsd"
438 indent-tabs-mode: t
439 tab-width: 8
440 End: