pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
Remove all if 0'd code from gtkconv.c
2021-04-21, Gary Kramlich
1f54363a79f2
Remove all if 0'd code from gtkconv.c
This also help expose the bug that caused the pidgin user's nick to be black
in XMPP MUCs.
Testing Done:
Joined a MUC made sure it worked.
Reviewed at https://reviews.imfreedom.org/r/623/
/* purple
*
* Purple is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
* source distribution.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#include
<libsoup/soup.h>
#include
<string.h>
#include
<purple.h>
#include
"libpurple/glibcompat.h"
#include
"api.h"
#include
"data.h"
typedef
struct
{
FbApi
*
api
;
SoupSession
*
cons
;
PurpleConnection
*
gc
;
PurpleRoomlist
*
roomlist
;
GQueue
*
msgs
;
GHashTable
*
imgs
;
GHashTable
*
unread
;
GHashTable
*
evs
;
}
FbDataPrivate
;
/**
* FbData:
*
* Represents the connection data used by #FacebookProtocol.
*/
struct
_FbData
{
GObject
parent
;
FbDataPrivate
*
priv
;
};
typedef
struct
{
FbData
*
fata
;
gchar
*
url
;
FbDataImageFunc
func
;
gpointer
data
;
GDestroyNotify
dunc
;
gboolean
active
;
const
guint8
*
image
;
gsize
size
;
}
FbDataImagePrivate
;
/**
* FbDataImage:
*
* Represents the data used for fetching images.
*/
struct
_FbDataImage
{
GObject
parent
;
FbDataImagePrivate
*
priv
;
};
static
const
gchar
*
fb_props_strs
[]
=
{
"cid"
,
"did"
,
"stoken"
,
"token"
};
G_DEFINE_TYPE_WITH_PRIVATE
(
FbData
,
fb_data
,
G_TYPE_OBJECT
);
G_DEFINE_TYPE_WITH_PRIVATE
(
FbDataImage
,
fb_data_image
,
G_TYPE_OBJECT
);
static
void
fb_data_dispose
(
GObject
*
obj
)
{
FbDataPrivate
*
priv
=
FB_DATA
(
obj
)
->
priv
;
GHashTableIter
iter
;
gpointer
ptr
;
soup_session_abort
(
priv
->
cons
);
g_hash_table_iter_init
(
&
iter
,
priv
->
evs
);
while
(
g_hash_table_iter_next
(
&
iter
,
NULL
,
&
ptr
))
{
g_source_remove
(
GPOINTER_TO_UINT
(
ptr
));
}
if
(
G_LIKELY
(
priv
->
api
!=
NULL
))
{
g_object_unref
(
priv
->
api
);
}
g_object_unref
(
priv
->
cons
);
g_queue_free_full
(
priv
->
msgs
,
(
GDestroyNotify
)
fb_api_message_free
);
g_hash_table_destroy
(
priv
->
imgs
);
g_hash_table_destroy
(
priv
->
unread
);
g_hash_table_destroy
(
priv
->
evs
);
}
static
void
fb_data_class_init
(
FbDataClass
*
klass
)
{
GObjectClass
*
gklass
=
G_OBJECT_CLASS
(
klass
);
gklass
->
dispose
=
fb_data_dispose
;
}
static
void
fb_data_init
(
FbData
*
fata
)
{
FbDataPrivate
*
priv
=
fb_data_get_instance_private
(
fata
);
fata
->
priv
=
priv
;
priv
->
msgs
=
g_queue_new
();
priv
->
imgs
=
g_hash_table_new_full
(
g_direct_hash
,
g_direct_equal
,
g_object_unref
,
NULL
);
priv
->
unread
=
g_hash_table_new_full
(
fb_id_hash
,
fb_id_equal
,
g_free
,
NULL
);
priv
->
evs
=
g_hash_table_new_full
(
g_str_hash
,
g_str_equal
,
g_free
,
NULL
);
}
static
void
fb_data_image_dispose
(
GObject
*
obj
)
{
FbDataImage
*
img
=
FB_DATA_IMAGE
(
obj
);
FbDataImagePrivate
*
priv
=
img
->
priv
;
FbData
*
fata
=
priv
->
fata
;
if
((
priv
->
dunc
!=
NULL
)
&&
(
priv
->
data
!=
NULL
))
{
priv
->
dunc
(
priv
->
data
);
}
g_free
(
priv
->
url
);
g_hash_table_steal
(
fata
->
priv
->
imgs
,
img
);
}
static
void
fb_data_image_class_init
(
FbDataImageClass
*
klass
)
{
GObjectClass
*
gklass
=
G_OBJECT_CLASS
(
klass
);
gklass
->
dispose
=
fb_data_image_dispose
;
}
static
void
fb_data_image_init
(
FbDataImage
*
img
)
{
FbDataImagePrivate
*
priv
=
fb_data_image_get_instance_private
(
img
);
img
->
priv
=
priv
;
}
FbData
*
fb_data_new
(
PurpleConnection
*
gc
,
GProxyResolver
*
resolver
)
{
FbData
*
fata
;
FbDataPrivate
*
priv
;
fata
=
g_object_new
(
FB_TYPE_DATA
,
NULL
);
priv
=
fata
->
priv
;
priv
->
cons
=
soup_session_new_with_options
(
"proxy-resolver"
,
resolver
,
NULL
);
priv
->
api
=
fb_api_new
(
gc
,
resolver
);
priv
->
gc
=
gc
;
return
fata
;
}
gboolean
fb_data_load
(
FbData
*
fata
)
{
const
gchar
*
str
;
FbDataPrivate
*
priv
;
FbId
id
;
gboolean
ret
=
TRUE
;
guint
i
;
guint64
uint
;
GValue
val
=
G_VALUE_INIT
;
PurpleAccount
*
acct
;
g_return_val_if_fail
(
FB_IS_DATA
(
fata
),
FALSE
);
priv
=
fata
->
priv
;
acct
=
purple_connection_get_account
(
priv
->
gc
);
for
(
i
=
0
;
i
<
G_N_ELEMENTS
(
fb_props_strs
);
i
++
)
{
str
=
purple_account_get_string
(
acct
,
fb_props_strs
[
i
],
NULL
);
if
(
str
==
NULL
)
{
ret
=
FALSE
;
}
g_value_init
(
&
val
,
G_TYPE_STRING
);
g_value_set_string
(
&
val
,
str
);
g_object_set_property
(
G_OBJECT
(
priv
->
api
),
fb_props_strs
[
i
],
&
val
);
g_value_unset
(
&
val
);
}
str
=
purple_account_get_string
(
acct
,
"mid"
,
NULL
);
if
(
str
!=
NULL
)
{
uint
=
g_ascii_strtoull
(
str
,
NULL
,
10
);
g_value_init
(
&
val
,
G_TYPE_UINT64
);
g_value_set_uint64
(
&
val
,
uint
);
g_object_set_property
(
G_OBJECT
(
priv
->
api
),
"mid"
,
&
val
);
g_value_unset
(
&
val
);
}
else
{
ret
=
FALSE
;
}
str
=
purple_account_get_string
(
acct
,
"uid"
,
NULL
);
if
(
str
!=
NULL
)
{
id
=
FB_ID_FROM_STR
(
str
);
g_value_init
(
&
val
,
FB_TYPE_ID
);
g_value_set_int64
(
&
val
,
id
);
g_object_set_property
(
G_OBJECT
(
priv
->
api
),
"uid"
,
&
val
);
g_value_unset
(
&
val
);
}
else
{
ret
=
FALSE
;
}
fb_api_rehash
(
priv
->
api
);
return
ret
;
}
void
fb_data_save
(
FbData
*
fata
)
{
const
gchar
*
str
;
FbDataPrivate
*
priv
;
gchar
*
dup
;
guint
i
;
guint64
uint
;
GValue
val
=
G_VALUE_INIT
;
PurpleAccount
*
acct
;
g_return_if_fail
(
FB_IS_DATA
(
fata
));
priv
=
fata
->
priv
;
acct
=
purple_connection_get_account
(
priv
->
gc
);
for
(
i
=
0
;
i
<
G_N_ELEMENTS
(
fb_props_strs
);
i
++
)
{
g_value_init
(
&
val
,
G_TYPE_STRING
);
g_object_get_property
(
G_OBJECT
(
priv
->
api
),
fb_props_strs
[
i
],
&
val
);
str
=
g_value_get_string
(
&
val
);
if
(
purple_strequal
(
fb_props_strs
[
i
],
"token"
)
&&
!
purple_account_get_remember_password
(
acct
))
{
str
=
""
;
}
purple_account_set_string
(
acct
,
fb_props_strs
[
i
],
str
);
g_value_unset
(
&
val
);
}
g_value_init
(
&
val
,
G_TYPE_UINT64
);
g_object_get_property
(
G_OBJECT
(
priv
->
api
),
"mid"
,
&
val
);
uint
=
g_value_get_uint64
(
&
val
);
g_value_unset
(
&
val
);
dup
=
g_strdup_printf
(
"%"
G_GINT64_FORMAT
,
uint
);
purple_account_set_string
(
acct
,
"mid"
,
dup
);
g_free
(
dup
);
g_value_init
(
&
val
,
G_TYPE_INT64
);
g_object_get_property
(
G_OBJECT
(
priv
->
api
),
"uid"
,
&
val
);
uint
=
g_value_get_int64
(
&
val
);
g_value_unset
(
&
val
);
dup
=
g_strdup_printf
(
"%"
FB_ID_FORMAT
,
uint
);
purple_account_set_string
(
acct
,
"uid"
,
dup
);
g_free
(
dup
);
}
void
fb_data_add_timeout
(
FbData
*
fata
,
const
gchar
*
name
,
guint
interval
,
GSourceFunc
func
,
gpointer
data
)
{
FbDataPrivate
*
priv
;
gchar
*
key
;
guint
id
;
g_return_if_fail
(
FB_IS_DATA
(
fata
));
priv
=
fata
->
priv
;
fb_data_clear_timeout
(
fata
,
name
,
TRUE
);
key
=
g_strdup
(
name
);
id
=
g_timeout_add_seconds
(
interval
,
func
,
data
);
g_hash_table_replace
(
priv
->
evs
,
key
,
GUINT_TO_POINTER
(
id
));
}
void
fb_data_clear_timeout
(
FbData
*
fata
,
const
gchar
*
name
,
gboolean
remove
)
{
FbDataPrivate
*
priv
;
gpointer
ptr
;
guint
id
;
g_return_if_fail
(
FB_IS_DATA
(
fata
));
priv
=
fata
->
priv
;
ptr
=
g_hash_table_lookup
(
priv
->
evs
,
name
);
id
=
GPOINTER_TO_UINT
(
ptr
);
if
((
id
>
0
)
&&
remove
)
{
g_source_remove
(
id
);
}
g_hash_table_remove
(
priv
->
evs
,
name
);
}
FbApi
*
fb_data_get_api
(
FbData
*
fata
)
{
FbDataPrivate
*
priv
;
g_return_val_if_fail
(
FB_IS_DATA
(
fata
),
NULL
);
priv
=
fata
->
priv
;
return
priv
->
api
;
}
PurpleConnection
*
fb_data_get_connection
(
FbData
*
fata
)
{
FbDataPrivate
*
priv
;
g_return_val_if_fail
(
FB_IS_DATA
(
fata
),
NULL
);
priv
=
fata
->
priv
;
return
priv
->
gc
;
}
PurpleRoomlist
*
fb_data_get_roomlist
(
FbData
*
fata
)
{
FbDataPrivate
*
priv
;
g_return_val_if_fail
(
FB_IS_DATA
(
fata
),
NULL
);
priv
=
fata
->
priv
;
return
priv
->
roomlist
;
}
gboolean
fb_data_get_unread
(
FbData
*
fata
,
FbId
id
)
{
FbDataPrivate
*
priv
;
gpointer
*
ptr
;
g_return_val_if_fail
(
FB_IS_DATA
(
fata
),
FALSE
);
g_return_val_if_fail
(
id
!=
0
,
FALSE
);
priv
=
fata
->
priv
;
ptr
=
g_hash_table_lookup
(
priv
->
unread
,
&
id
);
return
GPOINTER_TO_INT
(
ptr
);
}
void
fb_data_set_roomlist
(
FbData
*
fata
,
PurpleRoomlist
*
list
)
{
FbDataPrivate
*
priv
;
g_return_if_fail
(
FB_IS_DATA
(
fata
));
priv
=
fata
->
priv
;
priv
->
roomlist
=
list
;
}
void
fb_data_set_unread
(
FbData
*
fata
,
FbId
id
,
gboolean
unread
)
{
FbDataPrivate
*
priv
;
gpointer
key
;
g_return_if_fail
(
FB_IS_DATA
(
fata
));
g_return_if_fail
(
id
!=
0
);
priv
=
fata
->
priv
;
if
(
!
unread
)
{
g_hash_table_remove
(
priv
->
unread
,
&
id
);
return
;
}
key
=
g_memdup2
(
&
id
,
sizeof
id
);
g_hash_table_replace
(
priv
->
unread
,
key
,
GINT_TO_POINTER
(
unread
));
}
void
fb_data_add_message
(
FbData
*
fata
,
FbApiMessage
*
msg
)
{
FbDataPrivate
*
priv
;
g_return_if_fail
(
FB_IS_DATA
(
fata
));
priv
=
fata
->
priv
;
g_queue_push_tail
(
priv
->
msgs
,
msg
);
}
void
fb_data_remove_message
(
FbData
*
fata
,
FbApiMessage
*
msg
)
{
FbDataPrivate
*
priv
;
g_return_if_fail
(
FB_IS_DATA
(
fata
));
priv
=
fata
->
priv
;
g_queue_remove
(
priv
->
msgs
,
msg
);
}
GSList
*
fb_data_take_messages
(
FbData
*
fata
,
FbId
uid
)
{
FbApiMessage
*
msg
;
FbDataPrivate
*
priv
;
GList
*
l
;
GList
*
prev
;
GSList
*
msgs
=
NULL
;
g_return_val_if_fail
(
FB_IS_DATA
(
fata
),
NULL
);
priv
=
fata
->
priv
;
l
=
priv
->
msgs
->
tail
;
while
(
l
!=
NULL
)
{
msg
=
l
->
data
;
prev
=
l
->
prev
;
if
(
msg
->
uid
==
uid
)
{
msgs
=
g_slist_prepend
(
msgs
,
msg
);
g_queue_delete_link
(
priv
->
msgs
,
l
);
}
l
=
prev
;
}
return
msgs
;
}
FbDataImage
*
fb_data_image_add
(
FbData
*
fata
,
const
gchar
*
url
,
FbDataImageFunc
func
,
gpointer
data
,
GDestroyNotify
dunc
)
{
FbDataImage
*
img
;
FbDataImagePrivate
*
priv
;
g_return_val_if_fail
(
FB_IS_DATA
(
fata
),
NULL
);
g_return_val_if_fail
(
url
!=
NULL
,
NULL
);
g_return_val_if_fail
(
func
!=
NULL
,
NULL
);
img
=
g_object_new
(
FB_TYPE_DATA_IMAGE
,
NULL
);
priv
=
img
->
priv
;
priv
->
fata
=
fata
;
priv
->
url
=
g_strdup
(
url
);
priv
->
func
=
func
;
priv
->
data
=
data
;
priv
->
dunc
=
dunc
;
g_hash_table_insert
(
fata
->
priv
->
imgs
,
img
,
img
);
return
img
;
}
gboolean
fb_data_image_get_active
(
FbDataImage
*
img
)
{
FbDataImagePrivate
*
priv
;
g_return_val_if_fail
(
FB_IS_DATA_IMAGE
(
img
),
FALSE
);
priv
=
img
->
priv
;
return
priv
->
active
;
}
gpointer
fb_data_image_get_data
(
FbDataImage
*
img
)
{
FbDataImagePrivate
*
priv
;
g_return_val_if_fail
(
FB_IS_DATA_IMAGE
(
img
),
NULL
);
priv
=
img
->
priv
;
return
priv
->
data
;
}
FbData
*
fb_data_image_get_fata
(
FbDataImage
*
img
)
{
FbDataImagePrivate
*
priv
;
g_return_val_if_fail
(
FB_IS_DATA_IMAGE
(
img
),
NULL
);
priv
=
img
->
priv
;
return
priv
->
fata
;
}
const
guint8
*
fb_data_image_get_image
(
FbDataImage
*
img
,
gsize
*
size
)
{
FbDataImagePrivate
*
priv
;
g_return_val_if_fail
(
FB_IS_DATA_IMAGE
(
img
),
NULL
);
priv
=
img
->
priv
;
if
(
size
!=
NULL
)
{
*
size
=
priv
->
size
;
}
return
priv
->
image
;
}
guint8
*
fb_data_image_dup_image
(
FbDataImage
*
img
,
gsize
*
size
)
{
FbDataImagePrivate
*
priv
;
g_return_val_if_fail
(
FB_IS_DATA_IMAGE
(
img
),
NULL
);
priv
=
img
->
priv
;
if
(
size
!=
NULL
)
{
*
size
=
priv
->
size
;
}
if
(
priv
->
size
<
1
)
{
return
NULL
;
}
return
g_memdup2
(
priv
->
image
,
priv
->
size
);
}
const
gchar
*
fb_data_image_get_url
(
FbDataImage
*
img
)
{
FbDataImagePrivate
*
priv
;
g_return_val_if_fail
(
FB_IS_DATA_IMAGE
(
img
),
NULL
);
priv
=
img
->
priv
;
return
priv
->
url
;
}
static
void
fb_data_image_cb
(
G_GNUC_UNUSED
SoupSession
*
session
,
SoupMessage
*
res
,
gpointer
data
)
{
FbDataImage
*
img
=
data
;
FbDataImagePrivate
*
priv
=
img
->
priv
;
GError
*
err
=
NULL
;
fb_http_error_chk
(
res
,
&
err
);
priv
->
image
=
(
guint8
*
)
res
->
response_body
->
data
;
priv
->
size
=
res
->
response_body
->
length
;
priv
->
func
(
img
,
err
);
if
(
G_LIKELY
(
err
==
NULL
))
{
fb_data_image_queue
(
priv
->
fata
);
}
else
{
g_error_free
(
err
);
}
g_object_unref
(
img
);
}
void
fb_data_image_queue
(
FbData
*
fata
)
{
const
gchar
*
url
;
FbDataImage
*
img
;
FbDataPrivate
*
priv
;
GHashTableIter
iter
;
guint
active
=
0
;
g_return_if_fail
(
FB_IS_DATA
(
fata
));
priv
=
fata
->
priv
;
g_hash_table_iter_init
(
&
iter
,
priv
->
imgs
);
while
(
g_hash_table_iter_next
(
&
iter
,
(
gpointer
*
)
&
img
,
NULL
))
{
if
(
fb_data_image_get_active
(
img
))
{
active
++
;
}
}
if
(
active
>=
FB_DATA_ICON_MAX
)
{
return
;
}
g_hash_table_iter_init
(
&
iter
,
priv
->
imgs
);
while
(
g_hash_table_iter_next
(
&
iter
,
(
gpointer
*
)
&
img
,
NULL
))
{
SoupMessage
*
msg
;
if
(
fb_data_image_get_active
(
img
))
{
continue
;
}
img
->
priv
->
active
=
TRUE
;
url
=
fb_data_image_get_url
(
img
);
msg
=
soup_message_new
(
"GET"
,
url
);
// purple_http_request_set_max_len(req, FB_DATA_ICON_SIZE_MAX);
soup_session_queue_message
(
priv
->
cons
,
msg
,
fb_data_image_cb
,
img
);
if
(
++
active
>=
FB_DATA_ICON_MAX
)
{
break
;
}
}
}