pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
Create PurpleProtocolWhiteboard and remove PurpleProtocolFactory
21 months ago, Gary Kramlich
affc85fd4f3a
Create PurpleProtocolWhiteboard and remove PurpleProtocolFactory
Testing Done:
Compiled
Reviewed at https://reviews.imfreedom.org/r/1809/
/* 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
<glib/gi18n-lib.h>
#include
"accounts.h"
#include
"core.h"
#include
"debug.h"
#include
"network.h"
#include
"notify.h"
#include
"prefs.h"
#include
"purpleaccountmanager.h"
#include
"purpleaccountpresence.h"
#include
"purpleaddcontactrequest.h"
#include
"purpleconversationmanager.h"
#include
"purplecredentialmanager.h"
#include
"purplenotification.h"
#include
"purplenotificationmanager.h"
#include
"purpleprivate.h"
#include
"purpleprotocolclient.h"
#include
"purpleprotocolmanager.h"
#include
"purpleprotocolserver.h"
#include
"request.h"
#include
"server.h"
#include
"signals.h"
#include
"util.h"
struct
_PurpleAccount
{
GObject
gparent
;
gchar
*
id
;
char
*
username
;
/* The username. */
char
*
alias
;
/* How you appear to yourself. */
char
*
user_info
;
/* User information. */
char
*
buddy_icon_path
;
/* The buddy icon's non-cached path. */
gboolean
enabled
;
gboolean
remember_pass
;
/* Remember the password. */
/*
* TODO: After a GObject representing a protocol is ready, use it
* here instead of the protocol ID.
*/
char
*
protocol_id
;
/* The ID of the protocol. */
PurpleConnection
*
gc
;
/* The connection handle. */
gboolean
disconnecting
;
/* The account is currently disconnecting */
GHashTable
*
settings
;
/* Protocol-specific settings. */
PurpleProxyInfo
*
proxy_info
;
/* Proxy information. This will be set */
/* to NULL when the account inherits */
/* proxy settings from global prefs. */
/*
* TODO: Instead of linked lists for permit and deny, use a data
* structure that allows fast lookups AND decent performance when
* iterating through all items. Fast lookups should help performance
* for protocols like MSN, where all your buddies exist in your permit
* list therefore the permit list is large. Possibly GTree or
* GHashTable.
*/
GSList
*
permit
;
/* Permit list. */
GSList
*
deny
;
/* Deny list. */
PurpleAccountPrivacyType
privacy_type
;
/* The permit/deny setting. */
GList
*
status_types
;
/* Status types. */
PurplePresence
*
presence
;
/* Presence. */
PurpleAccountRegistrationCb
registration_cb
;
void
*
registration_cb_user_data
;
PurpleConnectionErrorInfo
*
current_error
;
/* Errors */
PurpleNotification
*
error_notification
;
}
PurpleAccountPrivate
;
typedef
struct
{
char
*
ui
;
GValue
value
;
}
PurpleAccountSetting
;
typedef
struct
{
PurpleAccount
*
account
;
GCallback
cb
;
gpointer
data
;
}
PurpleCallbackBundle
;
/* GObject Property enums */
enum
{
PROP_0
,
PROP_ID
,
PROP_USERNAME
,
PROP_PRIVATE_ALIAS
,
PROP_ENABLED
,
PROP_CONNECTION
,
PROP_PROTOCOL_ID
,
PROP_USER_INFO
,
PROP_BUDDY_ICON_PATH
,
PROP_REMEMBER_PASSWORD
,
PROP_PROXY_INFO
,
PROP_LAST
};
static
GParamSpec
*
properties
[
PROP_LAST
];
G_DEFINE_TYPE
(
PurpleAccount
,
purple_account
,
G_TYPE_OBJECT
);
/******************************************************************************
* Helpers
*****************************************************************************/
static
void
purple_account_register_got_password_cb
(
GObject
*
obj
,
GAsyncResult
*
res
,
gpointer
data
)
{
PurpleCredentialManager
*
manager
=
PURPLE_CREDENTIAL_MANAGER
(
obj
);
PurpleAccount
*
account
=
PURPLE_ACCOUNT
(
data
);
GError
*
error
=
NULL
;
gchar
*
password
=
NULL
;
password
=
purple_credential_manager_read_password_finish
(
manager
,
res
,
&
error
);
if
(
error
!=
NULL
)
{
purple_debug_warning
(
"account"
,
"failed to read password: %s"
,
error
->
message
);
g_error_free
(
error
);
}
_purple_connection_new
(
account
,
TRUE
,
password
);
g_free
(
password
);
}
void
purple_account_register
(
PurpleAccount
*
account
)
{
PurpleCredentialManager
*
manager
=
NULL
;
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
purple_debug_info
(
"account"
,
"Registering account %s
\n
"
,
purple_account_get_username
(
account
));
manager
=
purple_credential_manager_get_default
();
purple_credential_manager_read_password_async
(
manager
,
account
,
NULL
,
purple_account_register_got_password_cb
,
account
);
}
static
void
purple_account_unregister_got_password_cb
(
GObject
*
obj
,
GAsyncResult
*
res
,
gpointer
data
)
{
PurpleCredentialManager
*
manager
=
PURPLE_CREDENTIAL_MANAGER
(
obj
);
PurpleCallbackBundle
*
cbb
=
data
;
PurpleAccountUnregistrationCb
cb
;
GError
*
error
=
NULL
;
gchar
*
password
=
NULL
;
cb
=
(
PurpleAccountUnregistrationCb
)
cbb
->
cb
;
password
=
purple_credential_manager_read_password_finish
(
manager
,
res
,
&
error
);
if
(
error
!=
NULL
)
{
purple_debug_warning
(
"account"
,
"failed to read password: %s"
,
error
->
message
);
g_error_free
(
error
);
}
_purple_connection_new_unregister
(
cbb
->
account
,
password
,
cb
,
cbb
->
data
);
g_free
(
password
);
g_free
(
cbb
);
}
struct
register_completed_closure
{
PurpleAccount
*
account
;
gboolean
succeeded
;
};
static
gboolean
purple_account_register_completed_cb
(
gpointer
data
)
{
PurpleAccount
*
account
=
NULL
;
struct
register_completed_closure
*
closure
=
data
;
account
=
closure
->
account
;
if
(
account
->
registration_cb
)
{
(
account
->
registration_cb
)(
closure
->
account
,
closure
->
succeeded
,
account
->
registration_cb_user_data
);
}
g_object_unref
(
closure
->
account
);
g_free
(
closure
);
return
FALSE
;
}
static
void
request_password_write_cb
(
GObject
*
obj
,
GAsyncResult
*
res
,
gpointer
data
)
{
PurpleCredentialManager
*
manager
=
PURPLE_CREDENTIAL_MANAGER
(
obj
);
PurpleAccount
*
account
=
PURPLE_ACCOUNT
(
data
);
GError
*
error
=
NULL
;
gchar
*
password
=
NULL
;
/* We stash the password on the account to get it to this call back... It's
* kind of gross but shouldn't be a big deal because any plugin has access
* to the credential store, so it's not really a security leak.
*/
password
=
(
gchar
*
)
g_object_get_data
(
G_OBJECT
(
account
),
"_tmp_password"
);
g_object_set_data
(
G_OBJECT
(
account
),
"_tmp_password"
,
NULL
);
if
(
!
purple_credential_manager_write_password_finish
(
manager
,
res
,
&
error
))
{
const
gchar
*
name
=
purple_account_get_name_for_display
(
account
);
/* we can't error an account without a connection, so we just drop a
* debug message for now and continue to connect the account.
*/
purple_debug_info
(
"account"
,
"failed to save password for account
\"
%s
\"
: %s"
,
name
,
error
!=
NULL
?
error
->
message
:
"unknown error"
);
}
_purple_connection_new
(
account
,
FALSE
,
password
);
g_free
(
password
);
}
static
void
request_password_ok_cb
(
PurpleAccount
*
account
,
PurpleRequestFields
*
fields
)
{
const
char
*
entry
;
gboolean
remember
;
entry
=
purple_request_fields_get_string
(
fields
,
"password"
);
remember
=
purple_request_fields_get_bool
(
fields
,
"remember"
);
if
(
!
entry
||
!*
entry
)
{
purple_notify_error
(
account
,
NULL
,
_
(
"Password is required to sign on."
),
NULL
,
purple_request_cpar_from_account
(
account
));
return
;
}
purple_account_set_remember_password
(
account
,
remember
);
if
(
remember
)
{
PurpleCredentialManager
*
manager
=
NULL
;
manager
=
purple_credential_manager_get_default
();
/* The requests field can be invalidated by the time we write the
* password and we want to use it in the write callback, so we need to
* duplicate it for that callback.
*/
g_object_set_data
(
G_OBJECT
(
account
),
"_tmp_password"
,
g_strdup
(
entry
));
purple_credential_manager_write_password_async
(
manager
,
account
,
entry
,
NULL
,
request_password_write_cb
,
account
);
}
else
{
_purple_connection_new
(
account
,
FALSE
,
entry
);
}
}
static
void
request_password_cancel_cb
(
PurpleAccount
*
account
,
PurpleRequestFields
*
fields
)
{
/* Disable the account as the user has cancelled connecting */
purple_account_set_enabled
(
account
,
FALSE
);
}
static
void
purple_account_connect_got_password_cb
(
GObject
*
obj
,
GAsyncResult
*
res
,
gpointer
data
)
{
PurpleCredentialManager
*
manager
=
PURPLE_CREDENTIAL_MANAGER
(
obj
);
PurpleAccount
*
account
=
PURPLE_ACCOUNT
(
data
);
PurpleProtocol
*
protocol
=
NULL
;
GError
*
error
=
NULL
;
gchar
*
password
=
NULL
;
password
=
purple_credential_manager_read_password_finish
(
manager
,
res
,
&
error
);
if
(
error
!=
NULL
)
{
purple_debug_warning
(
"account"
,
"failed to read password %s"
,
error
->
message
);
g_error_free
(
error
);
}
protocol
=
purple_account_get_protocol
(
account
);
if
((
password
==
NULL
||
*
password
==
'\0'
)
&&
!
(
purple_protocol_get_options
(
protocol
)
&
OPT_PROTO_NO_PASSWORD
)
&&
!
(
purple_protocol_get_options
(
protocol
)
&
OPT_PROTO_PASSWORD_OPTIONAL
))
{
purple_account_request_password
(
account
,
G_CALLBACK
(
request_password_ok_cb
),
G_CALLBACK
(
request_password_cancel_cb
),
account
);
}
else
{
_purple_connection_new
(
account
,
FALSE
,
password
);
}
g_free
(
password
);
}
static
void
change_password_cb
(
PurpleAccount
*
account
,
PurpleRequestFields
*
fields
)
{
const
char
*
orig_pass
,
*
new_pass_1
,
*
new_pass_2
;
orig_pass
=
purple_request_fields_get_string
(
fields
,
"password"
);
new_pass_1
=
purple_request_fields_get_string
(
fields
,
"new_password_1"
);
new_pass_2
=
purple_request_fields_get_string
(
fields
,
"new_password_2"
);
if
(
g_utf8_collate
(
new_pass_1
,
new_pass_2
))
{
purple_notify_error
(
account
,
NULL
,
_
(
"New passwords do not match."
),
NULL
,
purple_request_cpar_from_account
(
account
));
return
;
}
if
((
purple_request_fields_is_field_required
(
fields
,
"password"
)
&&
(
orig_pass
==
NULL
||
*
orig_pass
==
'\0'
))
||
(
purple_request_fields_is_field_required
(
fields
,
"new_password_1"
)
&&
(
new_pass_1
==
NULL
||
*
new_pass_1
==
'\0'
))
||
(
purple_request_fields_is_field_required
(
fields
,
"new_password_2"
)
&&
(
new_pass_2
==
NULL
||
*
new_pass_2
==
'\0'
)))
{
purple_notify_error
(
account
,
NULL
,
_
(
"Fill out all fields completely."
),
NULL
,
purple_request_cpar_from_account
(
account
));
return
;
}
purple_account_change_password
(
account
,
orig_pass
,
new_pass_1
);
}
static
void
set_user_info_cb
(
PurpleAccount
*
account
,
const
char
*
user_info
)
{
PurpleConnection
*
gc
;
purple_account_set_user_info
(
account
,
user_info
);
gc
=
purple_account_get_connection
(
account
);
purple_serv_set_info
(
gc
,
user_info
);
}
static
void
delete_setting
(
void
*
data
)
{
PurpleAccountSetting
*
setting
=
(
PurpleAccountSetting
*
)
data
;
g_free
(
setting
->
ui
);
g_value_unset
(
&
setting
->
value
);
g_free
(
setting
);
}
static
PurpleConnectionState
purple_account_get_state
(
PurpleAccount
*
account
)
{
PurpleConnection
*
gc
;
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
PURPLE_CONNECTION_DISCONNECTED
);
gc
=
purple_account_get_connection
(
account
);
if
(
!
gc
)
return
PURPLE_CONNECTION_DISCONNECTED
;
return
purple_connection_get_state
(
gc
);
}
/*
* This makes sure your permit list contains all buddies from your
* buddy list and ONLY buddies from your buddy list.
*/
static
void
add_all_buddies_to_permit_list
(
PurpleAccount
*
account
,
gboolean
local
)
{
GSList
*
list
;
/* Remove anyone in the permit list who is not in the buddylist */
for
(
list
=
account
->
permit
;
list
!=
NULL
;
)
{
char
*
person
=
list
->
data
;
list
=
list
->
next
;
if
(
!
purple_blist_find_buddy
(
account
,
person
))
purple_account_privacy_permit_remove
(
account
,
person
,
local
);
}
/* Now make sure everyone in the buddylist is in the permit list */
list
=
purple_blist_find_buddies
(
account
,
NULL
);
while
(
list
!=
NULL
)
{
PurpleBuddy
*
buddy
=
list
->
data
;
const
gchar
*
name
=
purple_buddy_get_name
(
buddy
);
if
(
!
g_slist_find_custom
(
account
->
permit
,
name
,
(
GCompareFunc
)
g_utf8_collate
))
{
purple_account_privacy_permit_add
(
account
,
name
,
local
);
}
list
=
g_slist_delete_link
(
list
,
list
);
}
}
void
_purple_account_set_current_error
(
PurpleAccount
*
account
,
PurpleConnectionErrorInfo
*
new_err
)
{
PurpleConnectionErrorInfo
*
old_err
;
PurpleNotificationManager
*
manager
=
NULL
;
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
old_err
=
account
->
current_error
;
if
(
new_err
==
old_err
)
return
;
account
->
current_error
=
new_err
;
manager
=
purple_notification_manager_get_default
();
if
(
PURPLE_IS_NOTIFICATION
(
account
->
error_notification
))
{
purple_notification_manager_remove
(
manager
,
account
->
error_notification
);
g_clear_object
(
&
account
->
error_notification
);
}
if
(
new_err
!=
NULL
)
{
PurpleProtocol
*
protocol
=
NULL
;
gchar
*
title
=
NULL
;
account
->
error_notification
=
purple_notification_new
(
PURPLE_NOTIFICATION_TYPE_CONNECTION_ERROR
,
account
,
new_err
,
NULL
);
if
(
account
->
enabled
)
{
title
=
g_strdup_printf
(
_
(
"%s disconnected"
),
account
->
username
);
}
else
{
title
=
g_strdup_printf
(
_
(
"%s disabled"
),
account
->
username
);
}
purple_notification_set_title
(
account
->
error_notification
,
title
);
g_free
(
title
);
protocol
=
purple_account_get_protocol
(
account
);
if
(
PURPLE_IS_PROTOCOL
(
protocol
))
{
const
gchar
*
icon_name
=
purple_protocol_get_icon_name
(
protocol
);
if
(
icon_name
!=
NULL
)
{
purple_notification_set_icon_name
(
account
->
error_notification
,
icon_name
);
}
}
purple_notification_manager_add
(
manager
,
account
->
error_notification
);
}
purple_signal_emit
(
purple_accounts_get_handle
(),
"account-error-changed"
,
account
,
old_err
,
new_err
);
purple_accounts_schedule_save
();
g_clear_pointer
(
&
old_err
,
purple_connection_error_info_free
);
}
/******************************************************************************
* XmlNode Helpers
*****************************************************************************/
static
PurpleXmlNode
*
proxy_settings_to_xmlnode
(
PurpleProxyInfo
*
proxy_info
)
{
PurpleXmlNode
*
node
,
*
child
;
PurpleProxyType
proxy_type
;
const
char
*
value
;
int
int_value
;
char
buf
[
21
];
proxy_type
=
purple_proxy_info_get_proxy_type
(
proxy_info
);
node
=
purple_xmlnode_new
(
"proxy"
);
child
=
purple_xmlnode_new_child
(
node
,
"type"
);
purple_xmlnode_insert_data
(
child
,
(
proxy_type
==
PURPLE_PROXY_TYPE_USE_GLOBAL
?
"global"
:
proxy_type
==
PURPLE_PROXY_TYPE_NONE
?
"none"
:
proxy_type
==
PURPLE_PROXY_TYPE_HTTP
?
"http"
:
proxy_type
==
PURPLE_PROXY_TYPE_SOCKS4
?
"socks4"
:
proxy_type
==
PURPLE_PROXY_TYPE_SOCKS5
?
"socks5"
:
proxy_type
==
PURPLE_PROXY_TYPE_TOR
?
"tor"
:
proxy_type
==
PURPLE_PROXY_TYPE_USE_ENVVAR
?
"envvar"
:
"unknown"
),
-1
);
if
((
value
=
purple_proxy_info_get_hostname
(
proxy_info
))
!=
NULL
)
{
child
=
purple_xmlnode_new_child
(
node
,
"host"
);
purple_xmlnode_insert_data
(
child
,
value
,
-1
);
}
if
((
int_value
=
purple_proxy_info_get_port
(
proxy_info
))
!=
0
)
{
g_snprintf
(
buf
,
sizeof
(
buf
),
"%d"
,
int_value
);
child
=
purple_xmlnode_new_child
(
node
,
"port"
);
purple_xmlnode_insert_data
(
child
,
buf
,
-1
);
}
if
((
value
=
purple_proxy_info_get_username
(
proxy_info
))
!=
NULL
)
{
child
=
purple_xmlnode_new_child
(
node
,
"username"
);
purple_xmlnode_insert_data
(
child
,
value
,
-1
);
}
if
((
value
=
purple_proxy_info_get_password
(
proxy_info
))
!=
NULL
)
{
child
=
purple_xmlnode_new_child
(
node
,
"password"
);
purple_xmlnode_insert_data
(
child
,
value
,
-1
);
}
return
node
;
}
static
PurpleXmlNode
*
current_error_to_xmlnode
(
PurpleConnectionErrorInfo
*
err
)
{
PurpleXmlNode
*
node
,
*
child
;
char
type_str
[
3
];
node
=
purple_xmlnode_new
(
"current_error"
);
if
(
err
==
NULL
)
return
node
;
/* It doesn't make sense to have transient errors persist across a
* restart.
*/
if
(
!
purple_connection_error_is_fatal
(
err
->
type
))
return
node
;
child
=
purple_xmlnode_new_child
(
node
,
"type"
);
g_snprintf
(
type_str
,
sizeof
(
type_str
),
"%u"
,
err
->
type
);
purple_xmlnode_insert_data
(
child
,
type_str
,
-1
);
child
=
purple_xmlnode_new_child
(
node
,
"description"
);
if
(
err
->
description
)
{
char
*
utf8ized
=
purple_utf8_try_convert
(
err
->
description
);
if
(
utf8ized
==
NULL
)
{
utf8ized
=
g_utf8_make_valid
(
err
->
description
,
-1
);
}
purple_xmlnode_insert_data
(
child
,
utf8ized
,
-1
);
g_free
(
utf8ized
);
}
return
node
;
}
static
void
setting_to_xmlnode
(
gpointer
key
,
gpointer
value
,
gpointer
user_data
)
{
const
char
*
name
;
PurpleAccountSetting
*
setting
;
PurpleXmlNode
*
node
,
*
child
;
char
buf
[
21
];
name
=
(
const
char
*
)
key
;
setting
=
(
PurpleAccountSetting
*
)
value
;
node
=
(
PurpleXmlNode
*
)
user_data
;
child
=
purple_xmlnode_new_child
(
node
,
"setting"
);
purple_xmlnode_set_attrib
(
child
,
"name"
,
name
);
if
(
G_VALUE_HOLDS_INT
(
&
setting
->
value
))
{
purple_xmlnode_set_attrib
(
child
,
"type"
,
"int"
);
g_snprintf
(
buf
,
sizeof
(
buf
),
"%d"
,
g_value_get_int
(
&
setting
->
value
));
purple_xmlnode_insert_data
(
child
,
buf
,
-1
);
}
else
if
(
G_VALUE_HOLDS_STRING
(
&
setting
->
value
)
&&
g_value_get_string
(
&
setting
->
value
)
!=
NULL
)
{
purple_xmlnode_set_attrib
(
child
,
"type"
,
"string"
);
purple_xmlnode_insert_data
(
child
,
g_value_get_string
(
&
setting
->
value
),
-1
);
}
else
if
(
G_VALUE_HOLDS_BOOLEAN
(
&
setting
->
value
))
{
purple_xmlnode_set_attrib
(
child
,
"type"
,
"bool"
);
g_snprintf
(
buf
,
sizeof
(
buf
),
"%d"
,
g_value_get_boolean
(
&
setting
->
value
));
purple_xmlnode_insert_data
(
child
,
buf
,
-1
);
}
}
PurpleXmlNode
*
_purple_account_to_xmlnode
(
PurpleAccount
*
account
)
{
PurpleXmlNode
*
node
,
*
child
;
gchar
*
data
=
NULL
;
const
char
*
tmp
;
PurpleProxyInfo
*
proxy_info
;
node
=
purple_xmlnode_new
(
"account"
);
if
(
account
->
id
!=
NULL
)
{
child
=
purple_xmlnode_new_child
(
node
,
"id"
);
purple_xmlnode_insert_data
(
child
,
account
->
id
,
-1
);
}
child
=
purple_xmlnode_new_child
(
node
,
"protocol"
);
purple_xmlnode_insert_data
(
child
,
purple_account_get_protocol_id
(
account
),
-1
);
child
=
purple_xmlnode_new_child
(
node
,
"name"
);
purple_xmlnode_insert_data
(
child
,
purple_account_get_username
(
account
),
-1
);
child
=
purple_xmlnode_new_child
(
node
,
"enabled"
);
data
=
g_strdup_printf
(
"%d"
,
account
->
enabled
);
purple_xmlnode_insert_data
(
child
,
data
,
-1
);
g_clear_pointer
(
&
data
,
g_free
);
if
((
tmp
=
purple_account_get_private_alias
(
account
))
!=
NULL
)
{
child
=
purple_xmlnode_new_child
(
node
,
"alias"
);
purple_xmlnode_insert_data
(
child
,
tmp
,
-1
);
}
if
((
tmp
=
purple_account_get_user_info
(
account
))
!=
NULL
)
{
/* TODO: Do we need to call purple_str_strip_char(tmp, '\r') here? */
child
=
purple_xmlnode_new_child
(
node
,
"user-info"
);
purple_xmlnode_insert_data
(
child
,
tmp
,
-1
);
}
if
(
g_hash_table_size
(
account
->
settings
)
>
0
)
{
child
=
purple_xmlnode_new_child
(
node
,
"settings"
);
g_hash_table_foreach
(
account
->
settings
,
setting_to_xmlnode
,
child
);
}
if
((
proxy_info
=
purple_account_get_proxy_info
(
account
))
!=
NULL
)
{
child
=
proxy_settings_to_xmlnode
(
proxy_info
);
purple_xmlnode_insert_child
(
node
,
child
);
}
child
=
current_error_to_xmlnode
(
account
->
current_error
);
purple_xmlnode_insert_child
(
node
,
child
);
return
node
;
}
/******************************************************************************
* Helpers
*****************************************************************************/
static
void
purple_account_set_id
(
PurpleAccount
*
account
,
const
gchar
*
id
)
{
g_free
(
account
->
id
);
account
->
id
=
g_strdup
(
id
);
g_object_notify_by_pspec
(
G_OBJECT
(
account
),
properties
[
PROP_ID
]);
}
/******************************************************************************
* GObject Implementation
*****************************************************************************/
static
void
purple_account_set_property
(
GObject
*
obj
,
guint
param_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
)
{
PurpleAccount
*
account
=
PURPLE_ACCOUNT
(
obj
);
switch
(
param_id
)
{
case
PROP_ID
:
purple_account_set_id
(
account
,
g_value_get_string
(
value
));
break
;
case
PROP_USERNAME
:
purple_account_set_username
(
account
,
g_value_get_string
(
value
));
break
;
case
PROP_PRIVATE_ALIAS
:
purple_account_set_private_alias
(
account
,
g_value_get_string
(
value
));
break
;
case
PROP_ENABLED
:
purple_account_set_enabled
(
account
,
g_value_get_boolean
(
value
));
break
;
case
PROP_CONNECTION
:
purple_account_set_connection
(
account
,
g_value_get_object
(
value
));
break
;
case
PROP_PROTOCOL_ID
:
purple_account_set_protocol_id
(
account
,
g_value_get_string
(
value
));
break
;
case
PROP_USER_INFO
:
purple_account_set_user_info
(
account
,
g_value_get_string
(
value
));
break
;
case
PROP_BUDDY_ICON_PATH
:
purple_account_set_buddy_icon_path
(
account
,
g_value_get_string
(
value
));
break
;
case
PROP_REMEMBER_PASSWORD
:
purple_account_set_remember_password
(
account
,
g_value_get_boolean
(
value
));
break
;
case
PROP_PROXY_INFO
:
purple_account_set_proxy_info
(
account
,
g_value_get_object
(
value
));
break
;
default
:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
obj
,
param_id
,
pspec
);
break
;
}
}
static
void
purple_account_get_property
(
GObject
*
obj
,
guint
param_id
,
GValue
*
value
,
GParamSpec
*
pspec
)
{
PurpleAccount
*
account
=
PURPLE_ACCOUNT
(
obj
);
switch
(
param_id
)
{
case
PROP_ID
:
g_value_set_string
(
value
,
purple_account_get_id
(
account
));
break
;
case
PROP_USERNAME
:
g_value_set_string
(
value
,
purple_account_get_username
(
account
));
break
;
case
PROP_PRIVATE_ALIAS
:
g_value_set_string
(
value
,
purple_account_get_private_alias
(
account
));
break
;
case
PROP_ENABLED
:
g_value_set_boolean
(
value
,
purple_account_get_enabled
(
account
));
break
;
case
PROP_CONNECTION
:
g_value_set_object
(
value
,
purple_account_get_connection
(
account
));
break
;
case
PROP_PROTOCOL_ID
:
g_value_set_string
(
value
,
purple_account_get_protocol_id
(
account
));
break
;
case
PROP_USER_INFO
:
g_value_set_string
(
value
,
purple_account_get_user_info
(
account
));
break
;
case
PROP_BUDDY_ICON_PATH
:
g_value_set_string
(
value
,
purple_account_get_buddy_icon_path
(
account
));
break
;
case
PROP_REMEMBER_PASSWORD
:
g_value_set_boolean
(
value
,
purple_account_get_remember_password
(
account
));
break
;
case
PROP_PROXY_INFO
:
g_value_set_object
(
value
,
purple_account_get_proxy_info
(
account
));
break
;
default
:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
obj
,
param_id
,
pspec
);
break
;
}
}
static
void
purple_account_init
(
PurpleAccount
*
account
)
{
account
->
settings
=
g_hash_table_new_full
(
g_str_hash
,
g_str_equal
,
g_free
,
delete_setting
);
account
->
privacy_type
=
PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL
;
}
static
void
purple_account_constructed
(
GObject
*
object
)
{
PurpleAccount
*
account
=
PURPLE_ACCOUNT
(
object
);
gchar
*
username
,
*
protocol_id
;
PurpleProtocol
*
protocol
=
NULL
;
PurpleProtocolManager
*
manager
=
NULL
;
PurpleStatusType
*
status_type
;
G_OBJECT_CLASS
(
purple_account_parent_class
)
->
constructed
(
object
);
/* If we didn't get an id, just generate a random one. */
if
(
account
->
id
==
NULL
)
{
gchar
*
uuid
=
g_uuid_string_random
();
purple_account_set_id
(
account
,
uuid
);
g_free
(
uuid
);
}
g_object_get
(
object
,
"username"
,
&
username
,
"protocol-id"
,
&
protocol_id
,
NULL
);
purple_signal_emit
(
purple_accounts_get_handle
(),
"account-created"
,
account
);
manager
=
purple_protocol_manager_get_default
();
protocol
=
purple_protocol_manager_find
(
manager
,
protocol_id
);
if
(
protocol
==
NULL
)
{
g_free
(
username
);
g_free
(
protocol_id
);
return
;
}
purple_account_set_status_types
(
account
,
purple_protocol_get_status_types
(
protocol
,
account
));
account
->
presence
=
PURPLE_PRESENCE
(
purple_account_presence_new
(
account
));
status_type
=
purple_account_get_status_type_with_primitive
(
account
,
PURPLE_STATUS_AVAILABLE
);
if
(
status_type
!=
NULL
)
purple_presence_set_status_active
(
account
->
presence
,
purple_status_type_get_id
(
status_type
),
TRUE
);
else
purple_presence_set_status_active
(
account
->
presence
,
"offline"
,
TRUE
);
g_free
(
username
);
g_free
(
protocol_id
);
}
static
void
purple_account_dispose
(
GObject
*
object
)
{
PurpleAccount
*
account
=
PURPLE_ACCOUNT
(
object
);
if
(
!
purple_account_is_disconnected
(
account
))
{
purple_account_disconnect
(
account
);
}
g_clear_object
(
&
account
->
presence
);
G_OBJECT_CLASS
(
purple_account_parent_class
)
->
dispose
(
object
);
}
static
void
purple_account_finalize
(
GObject
*
object
)
{
GList
*
l
;
PurpleAccount
*
account
=
PURPLE_ACCOUNT
(
object
);
PurpleConversationManager
*
manager
=
NULL
;
purple_debug_info
(
"account"
,
"Destroying account %p"
,
account
);
purple_signal_emit
(
purple_accounts_get_handle
(),
"account-destroying"
,
account
);
manager
=
purple_conversation_manager_get_default
();
l
=
purple_conversation_manager_get_all
(
manager
);
while
(
l
!=
NULL
)
{
PurpleConversation
*
conv
=
PURPLE_CONVERSATION
(
l
->
data
);
if
(
purple_conversation_get_account
(
conv
)
==
account
)
{
purple_conversation_set_account
(
conv
,
NULL
);
}
l
=
g_list_delete_link
(
l
,
l
);
}
purple_account_set_status_types
(
account
,
NULL
);
g_clear_object
(
&
account
->
proxy_info
);
g_clear_pointer
(
&
account
->
current_error
,
purple_connection_error_info_free
);
g_clear_object
(
&
account
->
error_notification
);
g_free
(
account
->
id
);
g_free
(
account
->
username
);
g_free
(
account
->
alias
);
g_free
(
account
->
user_info
);
g_free
(
account
->
buddy_icon_path
);
g_free
(
account
->
protocol_id
);
g_hash_table_destroy
(
account
->
settings
);
g_slist_free_full
(
account
->
deny
,
g_free
);
g_slist_free_full
(
account
->
permit
,
g_free
);
G_OBJECT_CLASS
(
purple_account_parent_class
)
->
finalize
(
object
);
}
static
void
purple_account_class_init
(
PurpleAccountClass
*
klass
)
{
GObjectClass
*
obj_class
=
G_OBJECT_CLASS
(
klass
);
obj_class
->
dispose
=
purple_account_dispose
;
obj_class
->
finalize
=
purple_account_finalize
;
obj_class
->
constructed
=
purple_account_constructed
;
/* Setup properties */
obj_class
->
get_property
=
purple_account_get_property
;
obj_class
->
set_property
=
purple_account_set_property
;
/**
* PurpleAccount::id
*
* An identifier for the account.
*
* Since: 3.0.0
*/
properties
[
PROP_ID
]
=
g_param_spec_string
(
"id"
,
"id"
,
"The identifier of the account"
,
NULL
,
G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT_ONLY
|
G_PARAM_STATIC_STRINGS
);
properties
[
PROP_USERNAME
]
=
g_param_spec_string
(
"username"
,
"Username"
,
"The username for the account."
,
NULL
,
G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT
|
G_PARAM_STATIC_STRINGS
);
properties
[
PROP_PRIVATE_ALIAS
]
=
g_param_spec_string
(
"private-alias"
,
"Private Alias"
,
"The private alias for the account."
,
NULL
,
G_PARAM_READWRITE
|
G_PARAM_STATIC_STRINGS
);
properties
[
PROP_USER_INFO
]
=
g_param_spec_string
(
"user-info"
,
"User information"
,
"Detailed user information for the account."
,
NULL
,
G_PARAM_READWRITE
|
G_PARAM_STATIC_STRINGS
);
properties
[
PROP_BUDDY_ICON_PATH
]
=
g_param_spec_string
(
"buddy-icon-path"
,
"Buddy icon path"
,
"Path to the buddyicon for the account."
,
NULL
,
G_PARAM_READWRITE
|
G_PARAM_STATIC_STRINGS
);
properties
[
PROP_ENABLED
]
=
g_param_spec_boolean
(
"enabled"
,
"Enabled"
,
"Whether the account is enabled or not."
,
FALSE
,
G_PARAM_READWRITE
|
G_PARAM_STATIC_STRINGS
);
properties
[
PROP_REMEMBER_PASSWORD
]
=
g_param_spec_boolean
(
"remember-password"
,
"Remember password"
,
"Whether to remember and store the password for this account."
,
FALSE
,
G_PARAM_READWRITE
|
G_PARAM_STATIC_STRINGS
);
properties
[
PROP_CONNECTION
]
=
g_param_spec_object
(
"connection"
,
"Connection"
,
"The connection for the account."
,
PURPLE_TYPE_CONNECTION
,
G_PARAM_READWRITE
|
G_PARAM_STATIC_STRINGS
);
properties
[
PROP_PROTOCOL_ID
]
=
g_param_spec_string
(
"protocol-id"
,
"Protocol ID"
,
"ID of the protocol that is responsible for the account."
,
NULL
,
G_PARAM_READWRITE
|
G_PARAM_CONSTRUCT_ONLY
|
G_PARAM_STATIC_STRINGS
);
properties
[
PROP_PROXY_INFO
]
=
g_param_spec_object
(
"proxy-info"
,
"proxy-info"
,
"The PurpleProxyInfo for this account."
,
PURPLE_TYPE_PROXY_INFO
,
G_PARAM_READWRITE
|
G_PARAM_STATIC_STRINGS
);
g_object_class_install_properties
(
obj_class
,
PROP_LAST
,
properties
);
}
/******************************************************************************
* Public API
*****************************************************************************/
PurpleAccount
*
purple_account_new
(
const
gchar
*
username
,
const
gchar
*
protocol_id
)
{
PurpleAccount
*
account
;
PurpleAccountManager
*
manager
=
NULL
;
g_return_val_if_fail
(
username
!=
NULL
,
NULL
);
g_return_val_if_fail
(
protocol_id
!=
NULL
,
NULL
);
manager
=
purple_account_manager_get_default
();
account
=
purple_account_manager_find
(
manager
,
username
,
protocol_id
);
if
(
account
!=
NULL
)
{
return
account
;
}
account
=
g_object_new
(
PURPLE_TYPE_ACCOUNT
,
"username"
,
username
,
"protocol-id"
,
protocol_id
,
"enabled"
,
FALSE
,
NULL
);
return
account
;
}
const
gchar
*
purple_account_get_id
(
PurpleAccount
*
account
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
return
account
->
id
;
}
void
purple_account_connect
(
PurpleAccount
*
account
)
{
PurpleCredentialManager
*
manager
=
NULL
;
PurpleProtocol
*
protocol
=
NULL
;
const
char
*
username
=
NULL
;
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
purple_account_clear_current_error
(
account
);
username
=
purple_account_get_username
(
account
);
if
(
!
purple_account_get_enabled
(
account
))
{
purple_debug_info
(
"account"
,
"Account %s not enabled, not connecting.
\n
"
,
username
);
return
;
}
protocol
=
purple_account_get_protocol
(
account
);
if
(
protocol
==
NULL
)
{
gchar
*
message
;
message
=
g_strdup_printf
(
_
(
"Missing protocol for %s"
),
username
);
purple_notify_error
(
account
,
_
(
"Connection Error"
),
message
,
NULL
,
purple_request_cpar_from_account
(
account
));
g_free
(
message
);
return
;
}
purple_debug_info
(
"account"
,
"Connecting to account %s.
\n
"
,
username
);
manager
=
purple_credential_manager_get_default
();
purple_credential_manager_read_password_async
(
manager
,
account
,
NULL
,
purple_account_connect_got_password_cb
,
account
);
}
void
purple_account_set_register_callback
(
PurpleAccount
*
account
,
PurpleAccountRegistrationCb
cb
,
void
*
user_data
)
{
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
account
->
registration_cb
=
cb
;
account
->
registration_cb_user_data
=
user_data
;
}
void
purple_account_register_completed
(
PurpleAccount
*
account
,
gboolean
succeeded
)
{
struct
register_completed_closure
*
closure
;
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
closure
=
g_new0
(
struct
register_completed_closure
,
1
);
closure
->
account
=
g_object_ref
(
account
);
closure
->
succeeded
=
succeeded
;
g_timeout_add
(
0
,
purple_account_register_completed_cb
,
closure
);
}
void
purple_account_unregister
(
PurpleAccount
*
account
,
PurpleAccountUnregistrationCb
cb
,
gpointer
user_data
)
{
PurpleCallbackBundle
*
cbb
;
PurpleCredentialManager
*
manager
=
NULL
;
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
purple_debug_info
(
"account"
,
"Unregistering account %s
\n
"
,
purple_account_get_username
(
account
));
cbb
=
g_new0
(
PurpleCallbackBundle
,
1
);
cbb
->
account
=
account
;
cbb
->
cb
=
G_CALLBACK
(
cb
);
cbb
->
data
=
user_data
;
manager
=
purple_credential_manager_get_default
();
purple_credential_manager_read_password_async
(
manager
,
account
,
NULL
,
purple_account_unregister_got_password_cb
,
cbb
);
}
void
purple_account_disconnect
(
PurpleAccount
*
account
)
{
const
char
*
username
;
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
g_return_if_fail
(
!
purple_account_is_disconnecting
(
account
));
g_return_if_fail
(
!
purple_account_is_disconnected
(
account
));
username
=
purple_account_get_username
(
account
);
purple_debug_info
(
"account"
,
"Disconnecting account %s (%p)
\n
"
,
username
?
username
:
"(null)"
,
account
);
account
->
disconnecting
=
TRUE
;
purple_account_set_connection
(
account
,
NULL
);
account
->
disconnecting
=
FALSE
;
}
gboolean
purple_account_is_disconnecting
(
PurpleAccount
*
account
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
TRUE
);
return
account
->
disconnecting
;
}
void
purple_account_request_add
(
PurpleAccount
*
account
,
const
char
*
remote_user
,
const
char
*
alias
,
const
char
*
message
)
{
PurpleAddContactRequest
*
request
=
NULL
;
PurpleNotification
*
notification
=
NULL
;
PurpleNotificationManager
*
manager
=
NULL
;
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
g_return_if_fail
(
remote_user
!=
NULL
);
request
=
purple_add_contact_request_new
(
account
,
remote_user
);
if
(
alias
!=
NULL
&&
*
alias
!=
'\0'
)
{
purple_add_contact_request_set_alias
(
request
,
alias
);
}
if
(
message
!=
NULL
&&
*
message
!=
'\0'
)
{
purple_add_contact_request_set_message
(
request
,
message
);
}
notification
=
purple_notification_new_from_add_contact_request
(
request
);
manager
=
purple_notification_manager_get_default
();
purple_notification_manager_add
(
manager
,
notification
);
}
void
purple_account_request_close_with_account
(
PurpleAccount
*
account
)
{
PurpleNotificationManager
*
manager
=
NULL
;
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
manager
=
purple_notification_manager_get_default
();
purple_notification_manager_remove_with_account
(
manager
,
account
);
}
void
purple_account_request_password
(
PurpleAccount
*
account
,
GCallback
ok_cb
,
GCallback
cancel_cb
,
void
*
user_data
)
{
gchar
*
primary
;
const
gchar
*
username
;
PurpleRequestFieldGroup
*
group
;
PurpleRequestField
*
field
;
PurpleRequestFields
*
fields
;
/* Close any previous password request windows */
purple_request_close_with_handle
(
account
);
username
=
purple_account_get_username
(
account
);
primary
=
g_strdup_printf
(
_
(
"Enter password for %s (%s)"
),
username
,
purple_account_get_protocol_name
(
account
));
fields
=
purple_request_fields_new
();
group
=
purple_request_field_group_new
(
NULL
);
purple_request_fields_add_group
(
fields
,
group
);
field
=
purple_request_field_string_new
(
"password"
,
_
(
"Enter Password"
),
NULL
,
FALSE
);
purple_request_field_string_set_masked
(
field
,
TRUE
);
purple_request_field_set_required
(
field
,
TRUE
);
purple_request_field_group_add_field
(
group
,
field
);
field
=
purple_request_field_bool_new
(
"remember"
,
_
(
"Save password"
),
FALSE
);
purple_request_field_group_add_field
(
group
,
field
);
purple_request_fields
(
account
,
NULL
,
primary
,
NULL
,
fields
,
_
(
"OK"
),
ok_cb
,
_
(
"Cancel"
),
cancel_cb
,
purple_request_cpar_from_account
(
account
),
user_data
);
g_free
(
primary
);
}
void
purple_account_request_change_password
(
PurpleAccount
*
account
)
{
PurpleRequestFields
*
fields
;
PurpleRequestFieldGroup
*
group
;
PurpleRequestField
*
field
;
PurpleConnection
*
gc
;
PurpleProtocol
*
protocol
=
NULL
;
char
primary
[
256
];
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
g_return_if_fail
(
purple_account_is_connected
(
account
));
gc
=
purple_account_get_connection
(
account
);
if
(
gc
!=
NULL
)
protocol
=
purple_connection_get_protocol
(
gc
);
fields
=
purple_request_fields_new
();
group
=
purple_request_field_group_new
(
NULL
);
purple_request_fields_add_group
(
fields
,
group
);
field
=
purple_request_field_string_new
(
"password"
,
_
(
"Original password"
),
NULL
,
FALSE
);
purple_request_field_string_set_masked
(
field
,
TRUE
);
if
(
!
protocol
||
!
(
purple_protocol_get_options
(
protocol
)
&
OPT_PROTO_PASSWORD_OPTIONAL
))
purple_request_field_set_required
(
field
,
TRUE
);
purple_request_field_group_add_field
(
group
,
field
);
field
=
purple_request_field_string_new
(
"new_password_1"
,
_
(
"New password"
),
NULL
,
FALSE
);
purple_request_field_string_set_masked
(
field
,
TRUE
);
if
(
!
protocol
||
!
(
purple_protocol_get_options
(
protocol
)
&
OPT_PROTO_PASSWORD_OPTIONAL
))
purple_request_field_set_required
(
field
,
TRUE
);
purple_request_field_group_add_field
(
group
,
field
);
field
=
purple_request_field_string_new
(
"new_password_2"
,
_
(
"New password (again)"
),
NULL
,
FALSE
);
purple_request_field_string_set_masked
(
field
,
TRUE
);
if
(
!
protocol
||
!
(
purple_protocol_get_options
(
protocol
)
&
OPT_PROTO_PASSWORD_OPTIONAL
))
purple_request_field_set_required
(
field
,
TRUE
);
purple_request_field_group_add_field
(
group
,
field
);
g_snprintf
(
primary
,
sizeof
(
primary
),
_
(
"Change password for %s"
),
purple_account_get_username
(
account
));
/* I'm sticking this somewhere in the code: bologna */
purple_request_fields
(
purple_account_get_connection
(
account
),
NULL
,
primary
,
_
(
"Please enter your current password and your new "
"password."
),
fields
,
_
(
"OK"
),
G_CALLBACK
(
change_password_cb
),
_
(
"Cancel"
),
NULL
,
purple_request_cpar_from_account
(
account
),
account
);
}
void
purple_account_request_change_user_info
(
PurpleAccount
*
account
)
{
PurpleConnection
*
gc
;
char
primary
[
256
];
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
g_return_if_fail
(
purple_account_is_connected
(
account
));
gc
=
purple_account_get_connection
(
account
);
g_snprintf
(
primary
,
sizeof
(
primary
),
_
(
"Change user information for %s"
),
purple_account_get_username
(
account
));
purple_request_input
(
gc
,
_
(
"Set User Info"
),
primary
,
NULL
,
purple_account_get_user_info
(
account
),
TRUE
,
FALSE
,
((
gc
!=
NULL
)
&&
(
purple_connection_get_flags
(
gc
)
&
PURPLE_CONNECTION_FLAG_HTML
)
?
"html"
:
NULL
),
_
(
"Save"
),
G_CALLBACK
(
set_user_info_cb
),
_
(
"Cancel"
),
NULL
,
purple_request_cpar_from_account
(
account
),
account
);
}
void
purple_account_set_username
(
PurpleAccount
*
account
,
const
char
*
username
)
{
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
g_free
(
account
->
username
);
account
->
username
=
g_strdup
(
username
);
g_object_notify_by_pspec
(
G_OBJECT
(
account
),
properties
[
PROP_USERNAME
]);
purple_accounts_schedule_save
();
/* if the name changes, we should re-write the buddy list
* to disk with the new name */
purple_blist_save_account
(
purple_blist_get_default
(),
account
);
}
void
purple_account_set_private_alias
(
PurpleAccount
*
account
,
const
char
*
alias
)
{
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
/*
* Do nothing if alias and account->alias are both NULL. Or if
* they're the exact same string.
*/
if
(
alias
==
account
->
alias
)
return
;
if
((
!
alias
&&
account
->
alias
)
||
(
alias
&&
!
account
->
alias
)
||
g_utf8_collate
(
account
->
alias
,
alias
))
{
char
*
old
=
account
->
alias
;
account
->
alias
=
g_strdup
(
alias
);
g_object_notify_by_pspec
(
G_OBJECT
(
account
),
properties
[
PROP_PRIVATE_ALIAS
]);
purple_signal_emit
(
purple_accounts_get_handle
(),
"account-alias-changed"
,
account
,
old
);
g_free
(
old
);
purple_accounts_schedule_save
();
}
}
void
purple_account_set_user_info
(
PurpleAccount
*
account
,
const
char
*
user_info
)
{
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
g_free
(
account
->
user_info
);
account
->
user_info
=
g_strdup
(
user_info
);
g_object_notify_by_pspec
(
G_OBJECT
(
account
),
properties
[
PROP_USER_INFO
]);
purple_accounts_schedule_save
();
}
void
purple_account_set_buddy_icon_path
(
PurpleAccount
*
account
,
const
char
*
path
)
{
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
g_free
(
account
->
buddy_icon_path
);
account
->
buddy_icon_path
=
g_strdup
(
path
);
g_object_notify_by_pspec
(
G_OBJECT
(
account
),
properties
[
PROP_BUDDY_ICON_PATH
]);
purple_accounts_schedule_save
();
}
void
purple_account_set_protocol_id
(
PurpleAccount
*
account
,
const
char
*
protocol_id
)
{
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
g_return_if_fail
(
protocol_id
!=
NULL
);
g_free
(
account
->
protocol_id
);
account
->
protocol_id
=
g_strdup
(
protocol_id
);
g_object_notify_by_pspec
(
G_OBJECT
(
account
),
properties
[
PROP_PROTOCOL_ID
]);
purple_accounts_schedule_save
();
}
void
purple_account_set_connection
(
PurpleAccount
*
account
,
PurpleConnection
*
gc
)
{
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
g_clear_object
(
&
account
->
gc
);
account
->
gc
=
gc
;
g_object_notify_by_pspec
(
G_OBJECT
(
account
),
properties
[
PROP_CONNECTION
]);
}
void
purple_account_set_remember_password
(
PurpleAccount
*
account
,
gboolean
value
)
{
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
account
->
remember_pass
=
value
;
g_object_notify_by_pspec
(
G_OBJECT
(
account
),
properties
[
PROP_REMEMBER_PASSWORD
]);
purple_accounts_schedule_save
();
}
void
purple_account_set_enabled
(
PurpleAccount
*
account
,
gboolean
value
)
{
PurpleConnection
*
gc
;
gboolean
was_enabled
=
FALSE
;
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
was_enabled
=
account
->
enabled
;
account
->
enabled
=
value
;
gc
=
purple_account_get_connection
(
account
);
if
(
was_enabled
&&
!
value
)
purple_signal_emit
(
purple_accounts_get_handle
(),
"account-disabled"
,
account
);
else
if
(
!
was_enabled
&&
value
)
purple_signal_emit
(
purple_accounts_get_handle
(),
"account-enabled"
,
account
);
g_object_notify_by_pspec
(
G_OBJECT
(
account
),
properties
[
PROP_ENABLED
]);
if
((
gc
!=
NULL
)
&&
(
_purple_connection_wants_to_die
(
gc
)))
return
;
if
(
value
&&
purple_presence_is_online
(
account
->
presence
))
purple_account_connect
(
account
);
else
if
(
!
value
&&
!
purple_account_is_disconnected
(
account
))
purple_account_disconnect
(
account
);
purple_accounts_schedule_save
();
}
void
purple_account_set_proxy_info
(
PurpleAccount
*
account
,
PurpleProxyInfo
*
info
)
{
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
if
(
g_set_object
(
&
account
->
proxy_info
,
info
))
{
g_object_notify_by_pspec
(
G_OBJECT
(
account
),
properties
[
PROP_PROXY_INFO
]);
purple_accounts_schedule_save
();
}
}
void
purple_account_set_privacy_type
(
PurpleAccount
*
account
,
PurpleAccountPrivacyType
privacy_type
)
{
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
account
->
privacy_type
=
privacy_type
;
}
void
purple_account_set_status_types
(
PurpleAccount
*
account
,
GList
*
status_types
)
{
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
/* Out with the old... */
g_list_free_full
(
account
->
status_types
,
(
GDestroyNotify
)
purple_status_type_destroy
);
/* In with the new... */
account
->
status_types
=
status_types
;
}
void
purple_account_set_status
(
PurpleAccount
*
account
,
const
char
*
status_id
,
gboolean
active
,
...)
{
GHashTable
*
attrs
;
va_list
args
;
va_start
(
args
,
active
);
attrs
=
purple_attrs_from_vargs
(
args
);
purple_account_set_status_attrs
(
account
,
status_id
,
active
,
attrs
);
g_hash_table_destroy
(
attrs
);
va_end
(
args
);
}
void
purple_account_set_status_attrs
(
PurpleAccount
*
account
,
const
char
*
status_id
,
gboolean
active
,
GHashTable
*
attrs
)
{
PurpleStatus
*
status
;
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
g_return_if_fail
(
status_id
!=
NULL
);
status
=
purple_account_get_status
(
account
,
status_id
);
if
(
status
==
NULL
)
{
purple_debug_error
(
"account"
,
"Invalid status ID '%s' for account %s (%s)
\n
"
,
status_id
,
purple_account_get_username
(
account
),
purple_account_get_protocol_id
(
account
));
return
;
}
if
(
active
||
purple_status_is_independent
(
status
))
purple_status_set_active_with_attrs_dict
(
status
,
active
,
attrs
);
/*
* Our current statuses are saved to accounts.xml (so that when we
* reconnect, we go back to the previous status).
*/
purple_accounts_schedule_save
();
}
gboolean
purple_account_get_silence_suppression
(
PurpleAccount
*
account
)
{
return
purple_account_get_bool
(
account
,
"silence-suppression"
,
FALSE
);
}
void
purple_account_set_silence_suppression
(
PurpleAccount
*
account
,
gboolean
value
)
{
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
purple_account_set_bool
(
account
,
"silence-suppression"
,
value
);
}
void
purple_account_clear_settings
(
PurpleAccount
*
account
)
{
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
g_hash_table_destroy
(
account
->
settings
);
account
->
settings
=
g_hash_table_new_full
(
g_str_hash
,
g_str_equal
,
g_free
,
delete_setting
);
}
void
purple_account_remove_setting
(
PurpleAccount
*
account
,
const
char
*
setting
)
{
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
g_return_if_fail
(
setting
!=
NULL
);
g_hash_table_remove
(
account
->
settings
,
setting
);
}
void
purple_account_set_int
(
PurpleAccount
*
account
,
const
char
*
name
,
int
value
)
{
PurpleAccountSetting
*
setting
;
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
g_return_if_fail
(
name
!=
NULL
);
setting
=
g_new0
(
PurpleAccountSetting
,
1
);
g_value_init
(
&
setting
->
value
,
G_TYPE_INT
);
g_value_set_int
(
&
setting
->
value
,
value
);
g_hash_table_insert
(
account
->
settings
,
g_strdup
(
name
),
setting
);
purple_accounts_schedule_save
();
}
void
purple_account_set_string
(
PurpleAccount
*
account
,
const
char
*
name
,
const
char
*
value
)
{
PurpleAccountSetting
*
setting
;
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
g_return_if_fail
(
name
!=
NULL
);
setting
=
g_new0
(
PurpleAccountSetting
,
1
);
g_value_init
(
&
setting
->
value
,
G_TYPE_STRING
);
g_value_set_string
(
&
setting
->
value
,
value
);
g_hash_table_insert
(
account
->
settings
,
g_strdup
(
name
),
setting
);
purple_accounts_schedule_save
();
}
void
purple_account_set_bool
(
PurpleAccount
*
account
,
const
char
*
name
,
gboolean
value
)
{
PurpleAccountSetting
*
setting
;
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
g_return_if_fail
(
name
!=
NULL
);
setting
=
g_new0
(
PurpleAccountSetting
,
1
);
g_value_init
(
&
setting
->
value
,
G_TYPE_BOOLEAN
);
g_value_set_boolean
(
&
setting
->
value
,
value
);
g_hash_table_insert
(
account
->
settings
,
g_strdup
(
name
),
setting
);
purple_accounts_schedule_save
();
}
gboolean
purple_account_is_connected
(
PurpleAccount
*
account
)
{
return
(
purple_account_get_state
(
account
)
==
PURPLE_CONNECTION_CONNECTED
);
}
gboolean
purple_account_is_connecting
(
PurpleAccount
*
account
)
{
return
(
purple_account_get_state
(
account
)
==
PURPLE_CONNECTION_CONNECTING
);
}
gboolean
purple_account_is_disconnected
(
PurpleAccount
*
account
)
{
return
(
purple_account_get_state
(
account
)
==
PURPLE_CONNECTION_DISCONNECTED
);
}
const
char
*
purple_account_get_username
(
PurpleAccount
*
account
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
return
account
->
username
;
}
const
char
*
purple_account_get_private_alias
(
PurpleAccount
*
account
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
return
account
->
alias
;
}
const
char
*
purple_account_get_user_info
(
PurpleAccount
*
account
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
return
account
->
user_info
;
}
const
char
*
purple_account_get_buddy_icon_path
(
PurpleAccount
*
account
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
return
account
->
buddy_icon_path
;
}
const
char
*
purple_account_get_protocol_id
(
PurpleAccount
*
account
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
return
account
->
protocol_id
;
}
PurpleProtocol
*
purple_account_get_protocol
(
PurpleAccount
*
account
)
{
PurpleProtocolManager
*
manager
=
NULL
;
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
manager
=
purple_protocol_manager_get_default
();
return
purple_protocol_manager_find
(
manager
,
account
->
protocol_id
);
}
const
char
*
purple_account_get_protocol_name
(
PurpleAccount
*
account
)
{
PurpleProtocol
*
p
;
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
p
=
purple_account_get_protocol
(
account
);
return
(
p
&&
purple_protocol_get_name
(
p
)
?
_
(
purple_protocol_get_name
(
p
))
:
_
(
"Unknown"
));
}
PurpleConnection
*
purple_account_get_connection
(
PurpleAccount
*
account
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
return
account
->
gc
;
}
const
gchar
*
purple_account_get_name_for_display
(
PurpleAccount
*
account
)
{
PurpleBuddy
*
self
=
NULL
;
PurpleConnection
*
gc
=
NULL
;
const
gchar
*
name
=
NULL
,
*
username
=
NULL
,
*
displayname
=
NULL
;
name
=
purple_account_get_private_alias
(
account
);
if
(
name
)
{
return
name
;
}
username
=
purple_account_get_username
(
account
);
self
=
purple_blist_find_buddy
((
PurpleAccount
*
)
account
,
username
);
if
(
self
)
{
const
gchar
*
calias
=
purple_buddy_get_contact_alias
(
self
);
/* We don't want to return the buddy name if the buddy/contact
* doesn't have an alias set. */
if
(
!
purple_strequal
(
username
,
calias
))
{
return
calias
;
}
}
gc
=
purple_account_get_connection
(
account
);
displayname
=
purple_connection_get_display_name
(
gc
);
if
(
displayname
)
{
return
displayname
;
}
return
username
;
}
gboolean
purple_account_get_remember_password
(
PurpleAccount
*
account
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
FALSE
);
return
account
->
remember_pass
;
}
gboolean
purple_account_get_enabled
(
PurpleAccount
*
account
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
FALSE
);
return
account
->
enabled
;
}
PurpleProxyInfo
*
purple_account_get_proxy_info
(
PurpleAccount
*
account
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
return
account
->
proxy_info
;
}
PurpleAccountPrivacyType
purple_account_get_privacy_type
(
PurpleAccount
*
account
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL
);
return
account
->
privacy_type
;
}
gboolean
purple_account_privacy_permit_add
(
PurpleAccount
*
account
,
const
char
*
who
,
gboolean
local_only
)
{
char
*
name
;
PurpleBuddy
*
buddy
;
PurpleAccountUiOps
*
ui_ops
=
purple_accounts_get_ui_ops
();
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
FALSE
);
g_return_val_if_fail
(
who
!=
NULL
,
FALSE
);
name
=
g_strdup
(
purple_normalize
(
account
,
who
));
if
(
g_slist_find_custom
(
account
->
permit
,
name
,
(
GCompareFunc
)
g_strcmp0
)
!=
NULL
)
{
/* This buddy already exists, so bail out */
g_free
(
name
);
return
FALSE
;
}
account
->
permit
=
g_slist_append
(
account
->
permit
,
name
);
if
(
!
local_only
&&
purple_account_is_connected
(
account
))
purple_serv_add_permit
(
purple_account_get_connection
(
account
),
who
);
if
(
ui_ops
!=
NULL
&&
ui_ops
->
permit_added
!=
NULL
)
ui_ops
->
permit_added
(
account
,
who
);
purple_blist_save_account
(
purple_blist_get_default
(),
account
);
/* This lets the UI know a buddy has had its privacy setting changed */
buddy
=
purple_blist_find_buddy
(
account
,
name
);
if
(
buddy
!=
NULL
)
{
purple_signal_emit
(
purple_blist_get_handle
(),
"buddy-privacy-changed"
,
buddy
);
}
return
TRUE
;
}
gboolean
purple_account_privacy_permit_remove
(
PurpleAccount
*
account
,
const
char
*
who
,
gboolean
local_only
)
{
GSList
*
l
;
const
char
*
name
;
PurpleBuddy
*
buddy
;
char
*
del
;
PurpleAccountUiOps
*
ui_ops
=
purple_accounts_get_ui_ops
();
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
FALSE
);
g_return_val_if_fail
(
who
!=
NULL
,
FALSE
);
name
=
purple_normalize
(
account
,
who
);
l
=
g_slist_find_custom
(
account
->
permit
,
name
,
(
GCompareFunc
)
g_strcmp0
);
if
(
l
==
NULL
)
{
/* We didn't find the buddy we were looking for, so bail out */
return
FALSE
;
}
/* We should not free l->data just yet. There can be occasions where
* l->data == who. In such cases, freeing l->data here can cause crashes
* later when who is used. */
del
=
l
->
data
;
account
->
permit
=
g_slist_delete_link
(
account
->
permit
,
l
);
if
(
!
local_only
&&
purple_account_is_connected
(
account
))
{
purple_serv_remove_permit
(
purple_account_get_connection
(
account
),
who
);
}
if
(
ui_ops
!=
NULL
&&
ui_ops
->
permit_removed
!=
NULL
)
{
ui_ops
->
permit_removed
(
account
,
who
);
}
purple_blist_save_account
(
purple_blist_get_default
(),
account
);
buddy
=
purple_blist_find_buddy
(
account
,
name
);
if
(
buddy
!=
NULL
)
{
purple_signal_emit
(
purple_blist_get_handle
(),
"buddy-privacy-changed"
,
buddy
);
}
g_free
(
del
);
return
TRUE
;
}
gboolean
purple_account_privacy_deny_add
(
PurpleAccount
*
account
,
const
char
*
who
,
gboolean
local_only
)
{
char
*
name
;
PurpleBuddy
*
buddy
;
PurpleAccountUiOps
*
ui_ops
=
purple_accounts_get_ui_ops
();
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
FALSE
);
g_return_val_if_fail
(
who
!=
NULL
,
FALSE
);
name
=
g_strdup
(
purple_normalize
(
account
,
who
));
if
(
g_slist_find_custom
(
account
->
deny
,
name
,
(
GCompareFunc
)
g_strcmp0
)
!=
NULL
)
{
/* This buddy already exists, so bail out */
g_free
(
name
);
return
FALSE
;
}
account
->
deny
=
g_slist_append
(
account
->
deny
,
name
);
if
(
!
local_only
&&
purple_account_is_connected
(
account
))
purple_serv_add_deny
(
purple_account_get_connection
(
account
),
who
);
if
(
ui_ops
!=
NULL
&&
ui_ops
->
deny_added
!=
NULL
)
ui_ops
->
deny_added
(
account
,
who
);
purple_blist_save_account
(
purple_blist_get_default
(),
account
);
buddy
=
purple_blist_find_buddy
(
account
,
name
);
if
(
buddy
!=
NULL
)
{
purple_signal_emit
(
purple_blist_get_handle
(),
"buddy-privacy-changed"
,
buddy
);
}
return
TRUE
;
}
gboolean
purple_account_privacy_deny_remove
(
PurpleAccount
*
account
,
const
char
*
who
,
gboolean
local_only
)
{
GSList
*
l
;
const
char
*
normalized
;
char
*
name
;
PurpleBuddy
*
buddy
;
PurpleAccountUiOps
*
ui_ops
=
purple_accounts_get_ui_ops
();
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
FALSE
);
g_return_val_if_fail
(
who
!=
NULL
,
FALSE
);
normalized
=
purple_normalize
(
account
,
who
);
l
=
g_slist_find_custom
(
account
->
deny
,
normalized
,
(
GCompareFunc
)
g_strcmp0
);
if
(
l
==
NULL
)
{
/* We didn't find the buddy we were looking for, so bail out */
return
FALSE
;
}
buddy
=
purple_blist_find_buddy
(
account
,
normalized
);
name
=
l
->
data
;
account
->
deny
=
g_slist_delete_link
(
account
->
deny
,
l
);
if
(
!
local_only
&&
purple_account_is_connected
(
account
))
{
purple_serv_remove_deny
(
purple_account_get_connection
(
account
),
name
);
}
if
(
ui_ops
!=
NULL
&&
ui_ops
->
deny_removed
!=
NULL
)
{
ui_ops
->
deny_removed
(
account
,
who
);
}
if
(
buddy
!=
NULL
)
{
purple_signal_emit
(
purple_blist_get_handle
(),
"buddy-privacy-changed"
,
buddy
);
}
g_free
(
name
);
purple_blist_save_account
(
purple_blist_get_default
(),
account
);
return
TRUE
;
}
void
purple_account_privacy_allow
(
PurpleAccount
*
account
,
const
char
*
who
)
{
GSList
*
list
;
PurpleAccountPrivacyType
type
=
purple_account_get_privacy_type
(
account
);
switch
(
type
)
{
case
PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL
:
return
;
case
PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
:
purple_account_privacy_permit_add
(
account
,
who
,
FALSE
);
break
;
case
PURPLE_ACCOUNT_PRIVACY_DENY_USERS
:
purple_account_privacy_deny_remove
(
account
,
who
,
FALSE
);
break
;
case
PURPLE_ACCOUNT_PRIVACY_DENY_ALL
:
{
/* Empty the allow-list. */
const
char
*
norm
=
purple_normalize
(
account
,
who
);
for
(
list
=
account
->
permit
;
list
!=
NULL
;)
{
char
*
person
=
list
->
data
;
list
=
list
->
next
;
if
(
!
purple_strequal
(
norm
,
person
))
purple_account_privacy_permit_remove
(
account
,
person
,
FALSE
);
}
purple_account_privacy_permit_add
(
account
,
who
,
FALSE
);
purple_account_set_privacy_type
(
account
,
PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
);
}
break
;
case
PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST
:
if
(
!
purple_blist_find_buddy
(
account
,
who
))
{
add_all_buddies_to_permit_list
(
account
,
FALSE
);
purple_account_privacy_permit_add
(
account
,
who
,
FALSE
);
purple_account_set_privacy_type
(
account
,
PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
);
}
break
;
default
:
g_return_if_reached
();
}
/* Notify the server if the privacy setting was changed */
if
(
type
!=
purple_account_get_privacy_type
(
account
)
&&
purple_account_is_connected
(
account
))
purple_serv_set_permit_deny
(
purple_account_get_connection
(
account
));
}
void
purple_account_privacy_deny
(
PurpleAccount
*
account
,
const
char
*
who
)
{
GSList
*
list
;
PurpleAccountPrivacyType
type
=
purple_account_get_privacy_type
(
account
);
switch
(
type
)
{
case
PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL
:
{
/* Empty the deny-list. */
const
char
*
norm
=
purple_normalize
(
account
,
who
);
for
(
list
=
account
->
deny
;
list
!=
NULL
;
)
{
char
*
person
=
list
->
data
;
list
=
list
->
next
;
if
(
!
purple_strequal
(
norm
,
person
))
purple_account_privacy_deny_remove
(
account
,
person
,
FALSE
);
}
purple_account_privacy_deny_add
(
account
,
who
,
FALSE
);
purple_account_set_privacy_type
(
account
,
PURPLE_ACCOUNT_PRIVACY_DENY_USERS
);
}
break
;
case
PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
:
purple_account_privacy_permit_remove
(
account
,
who
,
FALSE
);
break
;
case
PURPLE_ACCOUNT_PRIVACY_DENY_USERS
:
purple_account_privacy_deny_add
(
account
,
who
,
FALSE
);
break
;
case
PURPLE_ACCOUNT_PRIVACY_DENY_ALL
:
break
;
case
PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST
:
if
(
purple_blist_find_buddy
(
account
,
who
))
{
add_all_buddies_to_permit_list
(
account
,
FALSE
);
purple_account_privacy_permit_remove
(
account
,
who
,
FALSE
);
purple_account_set_privacy_type
(
account
,
PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
);
}
break
;
default
:
g_return_if_reached
();
}
/* Notify the server if the privacy setting was changed */
if
(
type
!=
purple_account_get_privacy_type
(
account
)
&&
purple_account_is_connected
(
account
))
purple_serv_set_permit_deny
(
purple_account_get_connection
(
account
));
}
GSList
*
purple_account_privacy_get_permitted
(
PurpleAccount
*
account
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
return
account
->
permit
;
}
GSList
*
purple_account_privacy_get_denied
(
PurpleAccount
*
account
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
return
account
->
deny
;
}
gboolean
purple_account_privacy_check
(
PurpleAccount
*
account
,
const
char
*
who
)
{
switch
(
purple_account_get_privacy_type
(
account
))
{
case
PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL
:
return
TRUE
;
case
PURPLE_ACCOUNT_PRIVACY_DENY_ALL
:
return
FALSE
;
case
PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
:
who
=
purple_normalize
(
account
,
who
);
return
(
g_slist_find_custom
(
account
->
permit
,
who
,
(
GCompareFunc
)
g_strcmp0
)
!=
NULL
);
case
PURPLE_ACCOUNT_PRIVACY_DENY_USERS
:
who
=
purple_normalize
(
account
,
who
);
return
(
g_slist_find_custom
(
account
->
deny
,
who
,
(
GCompareFunc
)
g_strcmp0
)
==
NULL
);
case
PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST
:
return
(
purple_blist_find_buddy
(
account
,
who
)
!=
NULL
);
default
:
g_return_val_if_reached
(
TRUE
);
}
}
PurpleStatus
*
purple_account_get_active_status
(
PurpleAccount
*
account
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
return
purple_presence_get_active_status
(
account
->
presence
);
}
PurpleStatus
*
purple_account_get_status
(
PurpleAccount
*
account
,
const
char
*
status_id
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
g_return_val_if_fail
(
status_id
!=
NULL
,
NULL
);
return
purple_presence_get_status
(
account
->
presence
,
status_id
);
}
PurpleStatusType
*
purple_account_get_status_type
(
PurpleAccount
*
account
,
const
char
*
id
)
{
GList
*
l
;
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
g_return_val_if_fail
(
id
!=
NULL
,
NULL
);
for
(
l
=
purple_account_get_status_types
(
account
);
l
!=
NULL
;
l
=
l
->
next
)
{
PurpleStatusType
*
status_type
=
(
PurpleStatusType
*
)
l
->
data
;
if
(
purple_strequal
(
purple_status_type_get_id
(
status_type
),
id
))
return
status_type
;
}
return
NULL
;
}
PurpleStatusType
*
purple_account_get_status_type_with_primitive
(
PurpleAccount
*
account
,
PurpleStatusPrimitive
primitive
)
{
GList
*
l
;
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
for
(
l
=
purple_account_get_status_types
(
account
);
l
!=
NULL
;
l
=
l
->
next
)
{
PurpleStatusType
*
status_type
=
(
PurpleStatusType
*
)
l
->
data
;
if
(
purple_status_type_get_primitive
(
status_type
)
==
primitive
)
return
status_type
;
}
return
NULL
;
}
PurplePresence
*
purple_account_get_presence
(
PurpleAccount
*
account
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
return
account
->
presence
;
}
gboolean
purple_account_is_status_active
(
PurpleAccount
*
account
,
const
char
*
status_id
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
FALSE
);
g_return_val_if_fail
(
status_id
!=
NULL
,
FALSE
);
return
purple_presence_is_status_active
(
account
->
presence
,
status_id
);
}
GList
*
purple_account_get_status_types
(
PurpleAccount
*
account
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
return
account
->
status_types
;
}
int
purple_account_get_int
(
PurpleAccount
*
account
,
const
char
*
name
,
int
default_value
)
{
PurpleAccountSetting
*
setting
;
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
default_value
);
g_return_val_if_fail
(
name
!=
NULL
,
default_value
);
setting
=
g_hash_table_lookup
(
account
->
settings
,
name
);
if
(
setting
==
NULL
)
return
default_value
;
g_return_val_if_fail
(
G_VALUE_HOLDS_INT
(
&
setting
->
value
),
default_value
);
return
g_value_get_int
(
&
setting
->
value
);
}
const
char
*
purple_account_get_string
(
PurpleAccount
*
account
,
const
char
*
name
,
const
char
*
default_value
)
{
PurpleAccountSetting
*
setting
;
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
default_value
);
g_return_val_if_fail
(
name
!=
NULL
,
default_value
);
setting
=
g_hash_table_lookup
(
account
->
settings
,
name
);
if
(
setting
==
NULL
)
return
default_value
;
g_return_val_if_fail
(
G_VALUE_HOLDS_STRING
(
&
setting
->
value
),
default_value
);
return
g_value_get_string
(
&
setting
->
value
);
}
gboolean
purple_account_get_bool
(
PurpleAccount
*
account
,
const
char
*
name
,
gboolean
default_value
)
{
PurpleAccountSetting
*
setting
;
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
default_value
);
g_return_val_if_fail
(
name
!=
NULL
,
default_value
);
setting
=
g_hash_table_lookup
(
account
->
settings
,
name
);
if
(
setting
==
NULL
)
return
default_value
;
g_return_val_if_fail
(
G_VALUE_HOLDS_BOOLEAN
(
&
setting
->
value
),
default_value
);
return
g_value_get_boolean
(
&
setting
->
value
);
}
void
purple_account_add_buddy
(
PurpleAccount
*
account
,
PurpleBuddy
*
buddy
,
const
char
*
message
)
{
PurpleProtocol
*
protocol
=
NULL
;
PurpleConnection
*
gc
;
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
g_return_if_fail
(
PURPLE_IS_BUDDY
(
buddy
));
gc
=
purple_account_get_connection
(
account
);
if
(
gc
!=
NULL
)
protocol
=
purple_connection_get_protocol
(
gc
);
if
(
PURPLE_IS_PROTOCOL_SERVER
(
protocol
))
{
PurpleGroup
*
group
=
purple_buddy_get_group
(
buddy
);
purple_protocol_server_add_buddy
(
PURPLE_PROTOCOL_SERVER
(
protocol
),
gc
,
buddy
,
group
,
message
);
}
}
void
purple_account_add_buddies
(
PurpleAccount
*
account
,
GList
*
buddies
,
const
char
*
message
)
{
PurpleProtocol
*
protocol
=
NULL
;
PurpleConnection
*
gc
=
purple_account_get_connection
(
account
);
if
(
gc
!=
NULL
)
protocol
=
purple_connection_get_protocol
(
gc
);
if
(
protocol
)
{
GList
*
groups
;
/* Make a list of what group each buddy is in */
groups
=
g_list_copy_deep
(
buddies
,
(
GCopyFunc
)
purple_buddy_get_group
,
NULL
);
if
(
PURPLE_IS_PROTOCOL_SERVER
(
protocol
))
{
purple_protocol_server_add_buddies
(
PURPLE_PROTOCOL_SERVER
(
protocol
),
gc
,
buddies
,
groups
,
message
);
}
g_list_free
(
groups
);
}
}
void
purple_account_remove_buddy
(
PurpleAccount
*
account
,
PurpleBuddy
*
buddy
,
PurpleGroup
*
group
)
{
PurpleProtocol
*
protocol
=
NULL
;
PurpleConnection
*
gc
=
purple_account_get_connection
(
account
);
if
(
gc
!=
NULL
)
protocol
=
purple_connection_get_protocol
(
gc
);
if
(
PURPLE_IS_PROTOCOL_SERVER
(
protocol
))
{
purple_protocol_server_remove_buddy
(
PURPLE_PROTOCOL_SERVER
(
protocol
),
gc
,
buddy
,
group
);
}
}
void
purple_account_remove_buddies
(
PurpleAccount
*
account
,
GList
*
buddies
,
GList
*
groups
)
{
PurpleProtocol
*
protocol
=
NULL
;
PurpleConnection
*
gc
=
purple_account_get_connection
(
account
);
if
(
gc
!=
NULL
)
protocol
=
purple_connection_get_protocol
(
gc
);
if
(
PURPLE_IS_PROTOCOL_SERVER
(
protocol
))
{
purple_protocol_server_remove_buddies
(
PURPLE_PROTOCOL_SERVER
(
protocol
),
gc
,
buddies
,
groups
);
}
}
void
purple_account_remove_group
(
PurpleAccount
*
account
,
PurpleGroup
*
group
)
{
PurpleProtocol
*
protocol
=
NULL
;
PurpleConnection
*
gc
=
purple_account_get_connection
(
account
);
if
(
gc
!=
NULL
)
protocol
=
purple_connection_get_protocol
(
gc
);
if
(
PURPLE_IS_PROTOCOL_SERVER
(
protocol
))
{
purple_protocol_server_remove_group
(
PURPLE_PROTOCOL_SERVER
(
protocol
),
gc
,
group
);
}
}
void
purple_account_change_password
(
PurpleAccount
*
account
,
const
char
*
orig_pw
,
const
char
*
new_pw
)
{
PurpleCredentialManager
*
manager
=
NULL
;
PurpleProtocol
*
protocol
=
NULL
;
PurpleConnection
*
gc
=
purple_account_get_connection
(
account
);
/* just going to fire and forget this for now as not many protocols even
* implement the change password stuff.
*/
manager
=
purple_credential_manager_get_default
();
purple_credential_manager_write_password_async
(
manager
,
account
,
new_pw
,
NULL
,
NULL
,
NULL
);
if
(
gc
!=
NULL
)
protocol
=
purple_connection_get_protocol
(
gc
);
if
(
PURPLE_IS_PROTOCOL_SERVER
(
protocol
))
{
purple_protocol_server_change_passwd
(
PURPLE_PROTOCOL_SERVER
(
protocol
),
gc
,
orig_pw
,
new_pw
);
}
}
gboolean
purple_account_supports_offline_message
(
PurpleAccount
*
account
,
PurpleBuddy
*
buddy
)
{
PurpleConnection
*
gc
;
PurpleProtocol
*
protocol
=
NULL
;
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
FALSE
);
g_return_val_if_fail
(
PURPLE_IS_BUDDY
(
buddy
),
FALSE
);
gc
=
purple_account_get_connection
(
account
);
if
(
gc
==
NULL
)
{
return
FALSE
;
}
protocol
=
purple_connection_get_protocol
(
gc
);
if
(
!
protocol
)
{
return
FALSE
;
}
return
purple_protocol_client_offline_message
(
PURPLE_PROTOCOL_CLIENT
(
protocol
),
buddy
);
}
const
PurpleConnectionErrorInfo
*
purple_account_get_current_error
(
PurpleAccount
*
account
)
{
g_return_val_if_fail
(
PURPLE_IS_ACCOUNT
(
account
),
NULL
);
return
account
->
current_error
;
}
void
purple_account_clear_current_error
(
PurpleAccount
*
account
)
{
_purple_account_set_current_error
(
account
,
NULL
);
}