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
35 #include "sipe-backend.h"
36 #include "sipe-utils.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
);
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
)
72 const gchar
*tmp
, *tmp2
= hdr
;
74 if (!hdr
) return NULL
;
75 SIPE_DEBUG_INFO("parsing address out of %s", hdr
);
76 tmp
= strchr(hdr
, '<');
78 /* i hate the different SIP UA behaviours... */
79 if (tmp
) { /* sip address in <...> */
81 tmp
= strchr(tmp2
, '>');
83 from
= g_strndup(tmp2
, tmp
- tmp2
);
85 SIPE_DEBUG_INFO_NOFORMAT("found < without > in From");
89 tmp
= strchr(tmp2
, ';');
91 from
= g_strndup(tmp2
, tmp
- tmp2
);
93 from
= g_strdup(tmp2
);
96 SIPE_DEBUG_INFO("got %s", from
);
100 int parse_cseq(const gchar
*hdr
)
104 items
= g_strsplit(hdr
, " ", 1);
106 res
= atoi(items
[0]);
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
, ...)
125 xmlnode
*node
= NULL
;
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;
139 gint
xmlnode_get_int_attrib(xmlnode
*node
,
143 const char *value
= xmlnode_get_attrib(node
, attr
);
144 return(value
? atoi(value
) : fallback
);
149 get_epid(struct sipe_account_data
*sip
)
152 gchar
*self_sip_uri
= sip_uri_self(sip
);
153 sip
->epid
= sipe_get_epid(self_sip_uri
,
155 purple_network_get_my_ip(-1));
156 g_free(self_sip_uri
);
158 return g_strdup(sip
->epid
);
162 sipe_get_pub_instance(struct sipe_account_data
*sip
,
166 gchar
*epid
= get_epid(sip
);
168 sscanf(epid
, "%08x", &res
);
171 if (publication_key
== SIPE_PUB_DEVICE
) {
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
);
189 res
= (calendar_id
>> 4) | 0x40000000;
196 sipe_get_pub_instance_(struct sipe_account_data *sip,
197 const char *publication_key)
201 gchar *epid = get_epid(sip);
202 sscanf(epid, "%08x", &part_1);
204 sscanf(publication_key, "%uh", &part_2);
205 return part_1 + part_2;
209 sipe_is_bad_alias(const char *uri
,
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
)) {
231 is_empty(const char *st
)
233 if (!st
|| strlen(st
) == 0)
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) {
252 /** Returns newly allocated string. Must be g_free()'d */
254 replace(const char *st
,
261 if (!st
) return NULL
;
263 res
= g_strjoinv(replace
, tmp
= g_strsplit(st
, search
, -1));
269 fix_newlines(const char *st
)
271 return replace(st
, "\r\n", "\n");
275 sipe_strequal(const gchar
*left
, const gchar
*right
)
277 #if GLIB_CHECK_VERSION(2,16,0)
278 return (g_strcmp0(left
, right
) == 0);
280 return ((left
== NULL
&& right
== NULL
) ||
281 (left
!= NULL
&& right
!= NULL
&& strcmp(left
, right
) == 0));
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));
293 sipe_utils_str_to_time(const gchar
*timestamp
)
296 g_time_val_from_iso8601(timestamp
, &time
);
301 sipe_utils_time_to_str(time_t timestamp
)
303 GTimeVal time
= { timestamp
, 0 };
304 return g_time_val_to_iso8601(&time
);
308 hex_str_to_buff(const char *hex_str
, guint8
**buff
)
315 if (!hex_str
) return 0;
317 length
= strlen(hex_str
)/2;
318 *buff
= (unsigned char *)g_malloc(length
);
319 for (i
= 0; i
< length
; i
++) {
320 two_digits
[0] = hex_str
[i
* 2];
321 two_digits
[1] = hex_str
[i
* 2 + 1];
322 two_digits
[2] = '\0';
323 (*buff
)[i
] = (unsigned char)strtoul(two_digits
, NULL
, 16);
330 buff_to_hex_str(const guint8
*buff
, const size_t buff_len
)
335 if (!buff
) return NULL
;
337 res
= g_malloc(buff_len
* 2 + 1);
338 for (i
= 0, j
= 0; i
< buff_len
; i
++, j
+=2) {
339 sprintf(&res
[j
], "%02X", buff
[i
]);
346 sipe_utils_parse_lines(GSList
**list
, gchar
**lines
)
354 for(i
= 0; lines
[i
] && strlen(lines
[i
]) > 2; i
++) {
355 parts
= g_strsplit(lines
[i
], ":", 2);
356 if(!parts
[0] || !parts
[1]) {
362 while(*dummy
==' ' || *dummy
=='\t') dummy
++;
363 dummy2
= g_strdup(dummy
);
364 while(lines
[i
+1] && (lines
[i
+1][0]==' ' || lines
[i
+1][0]=='\t')) {
367 while(*dummy
==' ' || *dummy
=='\t') dummy
++;
368 tmp
= g_strdup_printf("%s %s",dummy2
, dummy
);
372 *list
= sipe_utils_nameval_add(*list
, parts
[0], dummy2
);
381 sipe_utils_nameval_add(GSList
* list
, const gchar
*name
, const gchar
*value
)
383 struct sipnameval
*element
= g_new0(struct sipnameval
,1);
385 /* SANITY CHECK: the calling code must be fixed if this happens! */
387 SIPE_DEBUG_ERROR("sipe_utils_nameval_add: NULL value for %s",
392 element
->name
= g_strdup(name
);
393 element
->value
= g_strdup(value
);
394 return g_slist_append(list
, element
);
398 sipe_utils_nameval_free(GSList
*list
) {
399 struct sipnameval
*elem
;
402 list
= g_slist_remove(list
,elem
);
410 sipe_utils_nameval_find(const GSList
*list
, const gchar
*name
)
412 return sipe_utils_nameval_find_instance (list
, name
, 0);
416 sipe_utils_nameval_find_instance(const GSList
*list
, const gchar
*name
, int which
)
419 struct sipnameval
*elem
;
424 // OCS2005 can send the same header in either all caps or mixed case
425 if (sipe_strcase_equal(elem
->name
, name
)) {
431 tmp
= g_slist_next(tmp
);