3 * Purple is the legal property of its developers, whose names are too numerous
4 * to list here. Please refer to the COPYRIGHT file distributed with this
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
28 #include "buddylist.h"
29 #include "conversations.h"
30 #include "glibcompat.h"
38 fb_util_error_quark(void)
42 if (G_UNLIKELY(q
== 0)) {
43 q
= g_quark_from_static_string("fb-util-error-quark");
50 fb_util_account_find_buddy(PurpleAccount
*acct
, PurpleChatConversation
*chat
,
51 const gchar
*search
, GError
**error
)
58 PurpleBuddy
*ret
= NULL
;
60 g_return_val_if_fail(PURPLE_IS_ACCOUNT(acct
), NULL
);
61 g_return_val_if_fail(search
!= NULL
, NULL
);
63 buddies
= purple_blist_find_buddies(acct
, NULL
);
65 for (retc
= 0, l
= buddies
; l
!= NULL
; l
= l
->next
) {
66 name
= purple_buddy_get_name(l
->data
);
67 alias
= purple_buddy_get_alias(l
->data
);
70 !purple_chat_conversation_has_user(chat
, name
))
75 if (g_ascii_strcasecmp(name
, search
) == 0) {
80 if (g_ascii_strcasecmp(alias
, search
) == 0) {
87 g_set_error(error
, FB_UTIL_ERROR
, FB_UTIL_ERROR_GENERAL
,
88 _("Buddy %s not found"), search
);
89 } else if (retc
> 1) {
90 g_set_error(error
, FB_UTIL_ERROR
, FB_UTIL_ERROR_GENERAL
,
91 _("Buddy name %s is ambiguous"), search
);
95 g_slist_free(buddies
);
100 fb_util_debug(PurpleDebugLevel level
, const gchar
*format
, ...)
104 va_start(ap
, format
);
105 fb_util_vdebug(level
, format
, ap
);
110 fb_util_vdebug(PurpleDebugLevel level
, const gchar
*format
, va_list ap
)
116 g_return_if_fail(format
!= NULL
);
118 unsafe
= (level
& FB_UTIL_DEBUG_FLAG_UNSAFE
) != 0;
119 verbose
= (level
& FB_UTIL_DEBUG_FLAG_VERBOSE
) != 0;
121 if ((unsafe
&& !purple_debug_is_unsafe()) ||
122 (verbose
&& !purple_debug_is_verbose()))
127 /* Ensure all local flags are removed */
128 level
&= ~FB_UTIL_DEBUG_FLAG_ALL
;
130 str
= g_strdup_vprintf(format
, ap
);
131 purple_debug(level
, "facebook", "%s\n", str
);
136 fb_util_debug_misc(const gchar
*format
, ...)
140 va_start(ap
, format
);
141 fb_util_vdebug(PURPLE_DEBUG_MISC
, format
, ap
);
146 fb_util_debug_info(const gchar
*format
, ...)
150 va_start(ap
, format
);
151 fb_util_vdebug(PURPLE_DEBUG_INFO
, format
, ap
);
156 fb_util_debug_warning(const gchar
*format
, ...)
160 va_start(ap
, format
);
161 fb_util_vdebug(PURPLE_DEBUG_WARNING
, format
, ap
);
166 fb_util_debug_error(const gchar
*format
, ...)
170 va_start(ap
, format
);
171 fb_util_vdebug(PURPLE_DEBUG_ERROR
, format
, ap
);
176 fb_util_debug_fatal(const gchar
*format
, ...)
180 va_start(ap
, format
);
181 fb_util_vdebug(PURPLE_DEBUG_FATAL
, format
, ap
);
186 fb_util_debug_hexdump(PurpleDebugLevel level
, const GByteArray
*bytes
,
187 const gchar
*format
, ...)
195 static const gchar
*indent
= " ";
197 g_return_if_fail(bytes
!= NULL
);
199 if (format
!= NULL
) {
200 va_start(ap
, format
);
201 fb_util_vdebug(level
, format
, ap
);
205 gstr
= g_string_sized_new(80);
207 for (i
= 0; i
< bytes
->len
; i
+= 16) {
208 g_string_append_printf(gstr
, "%s%08x ", indent
, i
);
210 for (j
= 0; j
< 16; j
++) {
211 if ((i
+ j
) < bytes
->len
) {
212 g_string_append_printf(gstr
, "%02x ",
215 g_string_append(gstr
, " ");
219 g_string_append_c(gstr
, ' ');
223 g_string_append(gstr
, " |");
225 for (j
= 0; (j
< 16) && ((i
+ j
) < bytes
->len
); j
++) {
226 c
= bytes
->data
[i
+ j
];
228 if (!g_ascii_isprint(c
) || g_ascii_isspace(c
)) {
232 g_string_append_c(gstr
, c
);
235 g_string_append_c(gstr
, '|');
236 fb_util_debug(level
, "%s", gstr
->str
);
237 g_string_erase(gstr
, 0, -1);
240 g_string_append_printf(gstr
, "%s%08x", indent
, i
);
241 fb_util_debug(level
, "%s", gstr
->str
);
242 g_string_free(gstr
, TRUE
);
246 fb_util_get_locale(void)
248 const gchar
* const *langs
;
253 static const gchar chrs
[] = {'.', '@'};
255 langs
= g_get_language_names();
258 if (purple_strequal(lang
, "C")) {
259 return g_strdup("en_US");
262 for (i
= 0; i
< G_N_ELEMENTS(chrs
); i
++) {
263 chr
= strchr(lang
, chrs
[i
]);
266 return g_strndup(lang
, chr
- lang
);
270 return g_strdup(lang
);
274 fb_util_rand_alnum(guint len
)
281 static const gchar chars
[] =
282 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
283 "abcdefghijklmnopqrstuvwxyz"
285 static const gsize charc
= G_N_ELEMENTS(chars
) - 1;
287 g_return_val_if_fail(len
> 0, NULL
);
289 ret
= g_new(gchar
, len
+ 1);
291 for (i
= 0; i
< len
; i
++) {
292 j
= g_rand_int_range(rand
, 0, charc
);
302 fb_util_request_buddy_ok(gpointer
*mata
, PurpleRequestFields
*fields
)
304 FbUtilRequestBuddyFunc func
= mata
[0];
307 gpointer data
= mata
[2];
310 PurpleRequestField
*field
;
317 field
= purple_request_fields_get_field(fields
, "buddy");
318 select
= purple_request_field_list_get_selected(field
);
320 for (l
= select
; l
!= NULL
; l
= l
->next
) {
321 bdy
= purple_request_field_list_get_data(field
, l
->data
);
322 ret
= g_slist_prepend(ret
, bdy
);
325 ret
= g_slist_reverse(ret
);
333 fb_util_request_buddy_cancel(gpointer
*mata
, PurpleRequestFields
*fields
)
335 FbUtilRequestBuddyFunc func
= mata
[1];
336 gpointer data
= mata
[2];
346 fb_util_request_buddy(PurpleConnection
*gc
, const gchar
*title
,
347 const gchar
*primary
, const gchar
*secondary
,
348 GSList
*select
, gboolean multi
, GCallback ok_cb
,
349 GCallback cancel_cb
, gpointer data
)
359 PurpleRequestCommonParameters
*cpar
;
360 PurpleRequestField
*field
;
361 PurpleRequestFieldGroup
*group
;
362 PurpleRequestFields
*fields
;
364 mata
= g_new0(gpointer
, 3);
369 acct
= purple_connection_get_account(gc
);
370 buddies
= purple_blist_find_buddies(acct
, NULL
);
371 buddies
= g_slist_sort(buddies
, (GCompareFunc
) g_ascii_strcasecmp
);
373 fields
= purple_request_fields_new();
374 group
= purple_request_field_group_new(NULL
);
375 purple_request_fields_add_group(fields
, group
);
377 field
= purple_request_field_list_new("buddy", NULL
);
378 purple_request_field_list_set_multi_select(field
, multi
);
379 purple_request_field_set_required(field
, TRUE
);
380 purple_request_field_group_add_field(group
, field
);
382 for (l
= buddies
; l
!= NULL
; l
= l
->next
) {
383 name
= purple_buddy_get_name(l
->data
);
384 alias
= purple_buddy_get_alias(l
->data
);
385 str
= g_strdup_printf("%s (%s)", alias
, name
);
386 purple_request_field_list_add_icon(field
, str
, NULL
, l
->data
);
390 for (l
= select
; l
!= NULL
; l
= l
->next
) {
391 name
= purple_buddy_get_name(l
->data
);
392 alias
= purple_buddy_get_alias(l
->data
);
393 str
= g_strdup_printf("%s (%s)", alias
, name
);
394 items
= g_list_append(items
, str
);
397 purple_request_field_list_set_selected(field
, items
);
398 g_slist_free(buddies
);
399 g_list_free_full(items
, g_free
);
401 cpar
= purple_request_cpar_from_connection(gc
);
402 return purple_request_fields(gc
, title
, primary
, secondary
, fields
,
404 G_CALLBACK(fb_util_request_buddy_ok
),
406 G_CALLBACK(fb_util_request_buddy_cancel
),
411 fb_util_serv_got_im(PurpleConnection
*gc
, const gchar
*who
, const gchar
*text
,
412 PurpleMessageFlags flags
, guint64 timestamp
)
416 PurpleIMConversation
*conv
;
419 if (!(flags
& PURPLE_MESSAGE_SEND
)) {
420 purple_serv_got_im(gc
, who
, text
, flags
, timestamp
);
424 acct
= purple_connection_get_account(gc
);
425 conv
= purple_conversations_find_im_with_account(who
, acct
);
428 conv
= purple_im_conversation_new(acct
, who
);
431 name
= purple_account_get_username(acct
);
432 msg
= purple_message_new_outgoing(name
, text
, flags
);
433 purple_message_set_time(msg
, timestamp
);
434 purple_conversation_write_message(PURPLE_CONVERSATION(conv
), msg
);
438 fb_util_serv_got_chat_in(PurpleConnection
*gc
, gint id
, const gchar
*who
,
439 const gchar
*text
, PurpleMessageFlags flags
,
444 PurpleChatConversation
*conv
;
447 if (!(flags
& PURPLE_MESSAGE_SEND
)) {
448 purple_serv_got_chat_in(gc
, id
, who
, flags
, text
, timestamp
);
452 acct
= purple_connection_get_account(gc
);
453 conv
= purple_conversations_find_chat(gc
, id
);
455 name
= purple_account_get_username(acct
);
456 msg
= purple_message_new_outgoing(name
, text
, flags
);
457 purple_message_set_time(msg
, timestamp
);
458 purple_conversation_write_message(PURPLE_CONVERSATION(conv
), msg
);
462 fb_util_strtest(const gchar
*str
, GAsciiType type
)
468 g_return_val_if_fail(str
!= NULL
, FALSE
);
471 for (i
= 0; i
< size
; i
++) {
474 if ((g_ascii_table
[c
] & type
) == 0) {
483 fb_util_zlib_test(const GByteArray
*bytes
)
488 g_return_val_if_fail(bytes
!= NULL
, FALSE
);
490 if (bytes
->len
< 2) {
494 b0
= *(bytes
->data
+ 0);
495 b1
= *(bytes
->data
+ 1);
497 return ((((b0
<< 8) | b1
) % 31) == 0) && /* Check the header */
498 ((b0
& 0x0F) == 8 /* Z_DEFLATED */); /* Check the method */
502 fb_util_zlib_conv(GConverter
*conv
, const GByteArray
*bytes
, GError
**error
)
505 GConverterResult res
;
511 ret
= g_byte_array_new();
517 res
= g_converter_convert(conv
,
521 G_CONVERTER_INPUT_AT_END
,
522 &rize
, &wize
, error
);
525 case G_CONVERTER_CONVERTED
:
526 g_byte_array_append(ret
, data
, wize
);
530 case G_CONVERTER_ERROR
:
531 g_byte_array_free(ret
, TRUE
);
534 case G_CONVERTER_FINISHED
:
535 g_byte_array_append(ret
, data
, wize
);
545 fb_util_zlib_deflate(const GByteArray
*bytes
, GError
**error
)
548 GZlibCompressor
*conv
;
550 conv
= g_zlib_compressor_new(G_ZLIB_COMPRESSOR_FORMAT_ZLIB
, -1);
551 ret
= fb_util_zlib_conv(G_CONVERTER(conv
), bytes
, error
);
552 g_object_unref(conv
);
557 fb_util_zlib_inflate(const GByteArray
*bytes
, GError
**error
)
560 GZlibDecompressor
*conv
;
562 conv
= g_zlib_decompressor_new(G_ZLIB_COMPRESSOR_FORMAT_ZLIB
);
563 ret
= fb_util_zlib_conv(G_CONVERTER(conv
), bytes
, error
);
564 g_object_unref(conv
);