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
25 #include "glibcompat.h"
35 PurpleRoomlist
*roomlist
;
45 * Represents the connection data used by #FacebookProtocol.
69 * Represents the data used for fetching images.
74 FbDataImagePrivate
*priv
;
77 static const gchar
*fb_props_strs
[] = {
84 G_DEFINE_TYPE_WITH_PRIVATE(FbData
, fb_data
, G_TYPE_OBJECT
);
85 G_DEFINE_TYPE_WITH_PRIVATE(FbDataImage
, fb_data_image
, G_TYPE_OBJECT
);
88 fb_data_dispose(GObject
*obj
)
90 FbDataPrivate
*priv
= FB_DATA(obj
)->priv
;
94 fb_http_conns_cancel_all(priv
->cons
);
95 g_hash_table_iter_init(&iter
, priv
->evs
);
97 while (g_hash_table_iter_next(&iter
, NULL
, &ptr
)) {
98 g_source_remove(GPOINTER_TO_UINT(ptr
));
101 if (G_LIKELY(priv
->api
!= NULL
)) {
102 g_object_unref(priv
->api
);
105 fb_http_conns_free(priv
->cons
);
106 g_queue_free_full(priv
->msgs
, (GDestroyNotify
) fb_api_message_free
);
108 g_hash_table_destroy(priv
->imgs
);
109 g_hash_table_destroy(priv
->unread
);
110 g_hash_table_destroy(priv
->evs
);
114 fb_data_class_init(FbDataClass
*klass
)
116 GObjectClass
*gklass
= G_OBJECT_CLASS(klass
);
118 gklass
->dispose
= fb_data_dispose
;
122 fb_data_init(FbData
*fata
)
124 FbDataPrivate
*priv
= fb_data_get_instance_private(fata
);
127 priv
->cons
= fb_http_conns_new();
128 priv
->msgs
= g_queue_new();
130 priv
->imgs
= g_hash_table_new_full(g_direct_hash
, g_direct_equal
,
131 g_object_unref
, NULL
);
132 priv
->unread
= g_hash_table_new_full(fb_id_hash
, fb_id_equal
,
134 priv
->evs
= g_hash_table_new_full(g_str_hash
, g_str_equal
,
139 fb_data_image_dispose(GObject
*obj
)
141 FbDataImage
*img
= FB_DATA_IMAGE(obj
);
142 FbDataImagePrivate
*priv
= img
->priv
;
143 FbData
*fata
= priv
->fata
;
145 if ((priv
->dunc
!= NULL
) && (priv
->data
!= NULL
)) {
146 priv
->dunc(priv
->data
);
150 g_hash_table_steal(fata
->priv
->imgs
, img
);
154 fb_data_image_class_init(FbDataImageClass
*klass
)
156 GObjectClass
*gklass
= G_OBJECT_CLASS(klass
);
158 gklass
->dispose
= fb_data_image_dispose
;
162 fb_data_image_init(FbDataImage
*img
)
164 FbDataImagePrivate
*priv
= fb_data_image_get_instance_private(img
);
169 fb_data_new(PurpleConnection
*gc
)
174 fata
= g_object_new(FB_TYPE_DATA
, NULL
);
177 priv
->api
= fb_api_new(gc
);
184 fb_data_load(FbData
*fata
)
192 GValue val
= G_VALUE_INIT
;
195 g_return_val_if_fail(FB_IS_DATA(fata
), FALSE
);
197 acct
= purple_connection_get_account(priv
->gc
);
199 for (i
= 0; i
< G_N_ELEMENTS(fb_props_strs
); i
++) {
200 str
= purple_account_get_string(acct
, fb_props_strs
[i
], NULL
);
206 g_value_init(&val
, G_TYPE_STRING
);
207 g_value_set_string(&val
, str
);
208 g_object_set_property(G_OBJECT(priv
->api
), fb_props_strs
[i
],
213 str
= purple_account_get_string(acct
, "mid", NULL
);
216 uint
= g_ascii_strtoull(str
, NULL
, 10);
217 g_value_init(&val
, G_TYPE_UINT64
);
218 g_value_set_uint64(&val
, uint
);
219 g_object_set_property(G_OBJECT(priv
->api
), "mid", &val
);
225 str
= purple_account_get_string(acct
, "uid", NULL
);
228 id
= FB_ID_FROM_STR(str
);
229 g_value_init(&val
, FB_TYPE_ID
);
230 g_value_set_int64(&val
, id
);
231 g_object_set_property(G_OBJECT(priv
->api
), "uid", &val
);
237 fb_api_rehash(priv
->api
);
242 fb_data_save(FbData
*fata
)
249 GValue val
= G_VALUE_INIT
;
252 g_return_if_fail(FB_IS_DATA(fata
));
254 acct
= purple_connection_get_account(priv
->gc
);
256 for (i
= 0; i
< G_N_ELEMENTS(fb_props_strs
); i
++) {
257 g_value_init(&val
, G_TYPE_STRING
);
258 g_object_get_property(G_OBJECT(priv
->api
), fb_props_strs
[i
],
260 str
= g_value_get_string(&val
);
262 if (purple_strequal(fb_props_strs
[i
], "token") && !purple_account_get_remember_password(acct
)) {
265 purple_account_set_string(acct
, fb_props_strs
[i
], str
);
269 g_value_init(&val
, G_TYPE_UINT64
);
270 g_object_get_property(G_OBJECT(priv
->api
), "mid", &val
);
271 uint
= g_value_get_uint64(&val
);
274 dup
= g_strdup_printf("%" G_GINT64_FORMAT
, uint
);
275 purple_account_set_string(acct
, "mid", dup
);
278 g_value_init(&val
, G_TYPE_INT64
);
279 g_object_get_property(G_OBJECT(priv
->api
), "uid", &val
);
280 uint
= g_value_get_int64(&val
);
283 dup
= g_strdup_printf("%" FB_ID_FORMAT
, uint
);
284 purple_account_set_string(acct
, "uid", dup
);
289 fb_data_add_timeout(FbData
*fata
, const gchar
*name
, guint interval
,
290 GSourceFunc func
, gpointer data
)
296 g_return_if_fail(FB_IS_DATA(fata
));
299 fb_data_clear_timeout(fata
, name
, TRUE
);
301 key
= g_strdup(name
);
302 id
= g_timeout_add(interval
, func
, data
);
303 g_hash_table_replace(priv
->evs
, key
, GUINT_TO_POINTER(id
));
307 fb_data_clear_timeout(FbData
*fata
, const gchar
*name
, gboolean remove
)
313 g_return_if_fail(FB_IS_DATA(fata
));
316 ptr
= g_hash_table_lookup(priv
->evs
, name
);
317 id
= GPOINTER_TO_UINT(ptr
);
319 if ((id
> 0) && remove
) {
323 g_hash_table_remove(priv
->evs
, name
);
327 fb_data_get_api(FbData
*fata
)
331 g_return_val_if_fail(FB_IS_DATA(fata
), NULL
);
338 fb_data_get_connection(FbData
*fata
)
342 g_return_val_if_fail(FB_IS_DATA(fata
), NULL
);
349 fb_data_get_roomlist(FbData
*fata
)
353 g_return_val_if_fail(FB_IS_DATA(fata
), NULL
);
356 return priv
->roomlist
;
360 fb_data_get_unread(FbData
*fata
, FbId id
)
365 g_return_val_if_fail(FB_IS_DATA(fata
), FALSE
);
366 g_return_val_if_fail(id
!= 0, FALSE
);
369 ptr
= g_hash_table_lookup(priv
->unread
, &id
);
370 return GPOINTER_TO_INT(ptr
);
374 fb_data_set_roomlist(FbData
*fata
, PurpleRoomlist
*list
)
378 g_return_if_fail(FB_IS_DATA(fata
));
381 priv
->roomlist
= list
;
385 fb_data_set_unread(FbData
*fata
, FbId id
, gboolean unread
)
390 g_return_if_fail(FB_IS_DATA(fata
));
391 g_return_if_fail(id
!= 0);
395 g_hash_table_remove(priv
->unread
, &id
);
399 key
= g_memdup(&id
, sizeof id
);
400 g_hash_table_replace(priv
->unread
, key
, GINT_TO_POINTER(unread
));
404 fb_data_add_message(FbData
*fata
, FbApiMessage
*msg
)
408 g_return_if_fail(FB_IS_DATA(fata
));
411 g_queue_push_tail(priv
->msgs
, msg
);
415 fb_data_remove_message(FbData
*fata
, FbApiMessage
*msg
)
419 g_return_if_fail(FB_IS_DATA(fata
));
422 g_queue_remove(priv
->msgs
, msg
);
426 fb_data_take_messages(FbData
*fata
, FbId uid
)
434 g_return_val_if_fail(FB_IS_DATA(fata
), NULL
);
436 l
= priv
->msgs
->tail
;
442 if (msg
->uid
== uid
) {
443 msgs
= g_slist_prepend(msgs
, msg
);
444 g_queue_delete_link(priv
->msgs
, l
);
454 fb_data_image_add(FbData
*fata
, const gchar
*url
, FbDataImageFunc func
,
455 gpointer data
, GDestroyNotify dunc
)
458 FbDataImagePrivate
*priv
;
460 g_return_val_if_fail(FB_IS_DATA(fata
), NULL
);
461 g_return_val_if_fail(url
!= NULL
, NULL
);
462 g_return_val_if_fail(func
!= NULL
, NULL
);
464 img
= g_object_new(FB_TYPE_DATA_IMAGE
, NULL
);
468 priv
->url
= g_strdup(url
);
473 g_hash_table_insert(fata
->priv
->imgs
, img
, img
);
478 fb_data_image_get_active(FbDataImage
*img
)
480 FbDataImagePrivate
*priv
;
482 g_return_val_if_fail(FB_IS_DATA_IMAGE(img
), FALSE
);
489 fb_data_image_get_data(FbDataImage
*img
)
491 FbDataImagePrivate
*priv
;
493 g_return_val_if_fail(FB_IS_DATA_IMAGE(img
), NULL
);
500 fb_data_image_get_fata(FbDataImage
*img
)
502 FbDataImagePrivate
*priv
;
504 g_return_val_if_fail(FB_IS_DATA_IMAGE(img
), NULL
);
511 fb_data_image_get_image(FbDataImage
*img
, gsize
*size
)
513 FbDataImagePrivate
*priv
;
515 g_return_val_if_fail(FB_IS_DATA_IMAGE(img
), NULL
);
526 fb_data_image_dup_image(FbDataImage
*img
, gsize
*size
)
528 FbDataImagePrivate
*priv
;
530 g_return_val_if_fail(FB_IS_DATA_IMAGE(img
), NULL
);
537 if (priv
->size
< 1) {
541 return g_memdup(priv
->image
, priv
->size
);
545 fb_data_image_get_url(FbDataImage
*img
)
547 FbDataImagePrivate
*priv
;
549 g_return_val_if_fail(FB_IS_DATA_IMAGE(img
), NULL
);
556 fb_data_image_cb(PurpleHttpConnection
*con
, PurpleHttpResponse
*res
,
559 FbDataImage
*img
= data
;
560 FbDataImagePrivate
*priv
= img
->priv
;
561 FbDataPrivate
*driv
= priv
->fata
->priv
;
564 if (fb_http_conns_is_canceled(driv
->cons
)) {
568 fb_http_conns_remove(driv
->cons
, con
);
569 fb_http_error_chk(res
, &err
);
571 priv
->image
= (guint8
*) purple_http_response_get_data(res
, &priv
->size
);
572 priv
->func(img
, err
);
574 if (G_LIKELY(err
== NULL
)) {
575 fb_data_image_queue(priv
->fata
);
584 fb_data_image_queue(FbData
*fata
)
591 PurpleHttpConnection
*con
;
593 g_return_if_fail(FB_IS_DATA(fata
));
595 g_hash_table_iter_init(&iter
, priv
->imgs
);
597 while (g_hash_table_iter_next(&iter
, (gpointer
*) &img
, NULL
)) {
598 if (fb_data_image_get_active(img
)) {
603 if (active
>= FB_DATA_ICON_MAX
) {
607 g_hash_table_iter_init(&iter
, priv
->imgs
);
609 while (g_hash_table_iter_next(&iter
, (gpointer
*) &img
, NULL
)) {
610 PurpleHttpRequest
*req
;
612 if (fb_data_image_get_active(img
)) {
616 img
->priv
->active
= TRUE
;
617 url
= fb_data_image_get_url(img
);
619 req
= purple_http_request_new(url
);
620 purple_http_request_set_max_len(req
, FB_DATA_ICON_SIZE_MAX
);
621 con
= purple_http_request(priv
->gc
, req
,
622 fb_data_image_cb
, img
);
623 fb_http_conns_add(priv
->cons
, con
);
624 purple_http_request_unref(req
);
626 if (++active
>= FB_DATA_ICON_MAX
) {