pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
Use Meson summary() function.
2021-07-27, Elliott Sales de Andrade
cb640ea0f315
Use Meson summary() function.
Now that we require at least 0.52, we can use Meson's builtin summary printing to display the results of configuration.
Testing Done:
Configured with defaults, and with pixmaps disabled to trigger the warning: https://asciinema.org/a/mV2oxOoVCJNdmrPwgqqUJ3mkU?t=17
Reviewed at https://reviews.imfreedom.org/r/848/
/*
* novell.c
*
* Copyright (c) 2004 Novell, Inc. All Rights Reserved.
*
* 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; version 2 of the License.
*
* 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>
#ifndef _WIN32
#
include
<sys/utsname.h>
#endif
#include
<gplugin.h>
#include
<gplugin-native.h>
#include
<purple.h>
#include
"nmuser.h"
#include
"novell.h"
#define DEFAULT_PORT 8300
#define NOVELL_CONNECT_STEPS 4
#define NM_ROOT_FOLDER_NAME "GroupWise Messenger"
#define NOVELL_STATUS_TYPE_AVAILABLE "available"
#define NOVELL_STATUS_TYPE_AWAY "away"
#define NOVELL_STATUS_TYPE_BUSY "busy"
#define NOVELL_STATUS_TYPE_OFFLINE "offline"
#define NOVELL_STATUS_TYPE_IDLE "idle"
#define NOVELL_STATUS_TYPE_APPEAR_OFFLINE "appearoffline"
struct
_NovellProtocol
{
PurpleProtocol
parent
;
};
static
PurpleProtocol
*
my_protocol
=
NULL
;
static
gboolean
_is_disconnect_error
(
NMERR_T
err
);
static
gboolean
_check_for_disconnect
(
NMUser
*
user
,
NMERR_T
err
);
static
void
_send_message
(
NMUser
*
user
,
NMMessage
*
message
);
static
void
_update_buddy_status
(
NMUser
*
user
,
PurpleBuddy
*
buddy
,
int
status
,
int
gmt
);
static
void
_remove_purple_buddies
(
NMUser
*
user
);
static
void
_add_contacts_to_purple_blist
(
NMUser
*
user
,
NMFolder
*
folder
);
static
void
_add_purple_buddies
(
NMUser
*
user
);
static
void
_sync_contact_list
(
NMUser
*
user
);
static
void
_sync_privacy_lists
(
NMUser
*
user
);
static
void
_show_info
(
PurpleConnection
*
gc
,
NMUserRecord
*
user_record
,
char
*
name
);
const
char
*
_get_conference_name
(
int
id
);
/*******************************************************************************
* Response callbacks
*******************************************************************************/
/* Handle login response */
static
void
_login_resp_cb
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
PurpleConnection
*
gc
;
const
char
*
alias
;
NMERR_T
rc
;
if
(
user
==
NULL
)
return
;
gc
=
purple_account_get_connection
(
user
->
client_data
);
if
(
gc
==
NULL
)
return
;
if
(
ret_code
==
NM_OK
)
{
/* Set alias for user if not set (use Full Name) */
alias
=
purple_account_get_private_alias
(
user
->
client_data
);
if
(
alias
==
NULL
||
*
alias
==
'\0'
)
{
alias
=
nm_user_record_get_full_name
(
user
->
user_record
);
if
(
alias
)
purple_account_set_private_alias
(
user
->
client_data
,
alias
);
}
/* Tell Purple that we are connected */
purple_connection_set_state
(
gc
,
PURPLE_CONNECTION_CONNECTED
);
_sync_contact_list
(
user
);
rc
=
nm_send_set_status
(
user
,
NM_STATUS_AVAILABLE
,
NULL
,
NULL
,
NULL
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
}
else
{
PurpleConnectionError
reason
;
char
*
err
=
g_strdup_printf
(
_
(
"Unable to login: %s"
),
nm_error_to_string
(
ret_code
));
switch
(
ret_code
)
{
case
NMERR_AUTHENTICATION_FAILED
:
case
NMERR_CREDENTIALS_MISSING
:
case
NMERR_PASSWORD_INVALID
:
/* Don't attempt to auto-reconnect if our
* password was invalid.
*/
if
(
!
purple_account_get_remember_password
(
purple_connection_get_account
(
gc
)))
{
PurpleAccount
*
account
=
NULL
;
PurpleCredentialManager
*
manager
=
NULL
;
account
=
purple_connection_get_account
(
gc
);
manager
=
purple_credential_manager_get_default
();
purple_credential_manager_clear_password_async
(
manager
,
account
,
NULL
,
NULL
,
NULL
);
}
reason
=
PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED
;
break
;
default
:
/* FIXME: There are other reasons login could fail */
reason
=
PURPLE_CONNECTION_ERROR_NETWORK_ERROR
;
}
purple_connection_error
(
gc
,
reason
,
err
);
g_free
(
err
);
}
}
/* Handle getstatus response*/
static
void
_get_status_resp_cb
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
PurpleBuddy
*
buddy
;
GSList
*
buddies
;
GSList
*
bnode
;
NMUserRecord
*
user_record
=
(
NMUserRecord
*
)
resp_data
;
int
status
;
if
(
user
==
NULL
||
user_record
==
NULL
)
return
;
if
(
ret_code
==
NM_OK
)
{
/* Find all Purple buddies and update their statuses */
const
char
*
name
=
nm_user_record_get_display_id
(
user_record
);
if
(
name
)
{
buddies
=
purple_blist_find_buddies
((
PurpleAccount
*
)
user
->
client_data
,
name
);
for
(
bnode
=
buddies
;
bnode
;
bnode
=
bnode
->
next
)
{
buddy
=
(
PurpleBuddy
*
)
bnode
->
data
;
if
(
buddy
)
{
status
=
nm_user_record_get_status
(
user_record
);
_update_buddy_status
(
user
,
buddy
,
status
,
time
(
0
));
}
}
g_slist_free
(
buddies
);
}
}
else
{
purple_debug_info
(
"novell"
,
"_get_status_resp_cb(): rc = 0x%X"
,
ret_code
);
}
}
/* Show an error if the rename failed */
static
void
_rename_contact_resp_cb
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
if
(
ret_code
!=
NM_OK
)
{
purple_debug_info
(
"novell"
,
"_rename_contact_resp_cb(): rc = 0x%X"
,
ret_code
);
}
}
/* Handle the getdetails response and send the message */
static
void
_get_details_resp_send_msg
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
PurpleConversation
*
gconv
;
PurpleConnection
*
gc
;
NMUserRecord
*
user_record
=
NULL
;
NMContact
*
cntct
=
NULL
;
NMConference
*
conf
;
NMMessage
*
msg
=
user_data
;
const
char
*
dn
=
NULL
;
const
char
*
name
;
if
(
user
==
NULL
||
msg
==
NULL
)
return
;
if
(
ret_code
==
NM_OK
)
{
user_record
=
(
NMUserRecord
*
)
resp_data
;
if
(
user_record
)
{
PurpleConversationManager
*
manager
=
NULL
;
manager
=
purple_conversation_manager_get_default
();
/* Set the title for the conversation */
/* XXX - Should this be find_im_with_account? */
gconv
=
purple_conversation_manager_find
(
manager
,
(
PurpleAccount
*
)
user
->
client_data
,
nm_user_record_get_display_id
(
user_record
));
if
(
gconv
)
{
dn
=
nm_user_record_get_dn
(
user_record
);
if
(
dn
)
{
cntct
=
nm_find_contact
(
user
,
dn
);
}
if
(
cntct
)
{
purple_conversation_set_title
(
gconv
,
nm_contact_get_display_name
(
cntct
));
}
else
{
/* Not in the contact list, try to user full name */
name
=
(
char
*
)
nm_user_record_get_full_name
(
user_record
);
if
(
name
)
purple_conversation_set_title
(
gconv
,
name
);
}
}
/* Add the user record to particpant list */
conf
=
nm_message_get_conference
(
msg
);
if
(
conf
)
{
nm_conference_add_participant
(
conf
,
user_record
);
_send_message
(
user
,
msg
);
}
}
}
else
{
gc
=
purple_account_get_connection
(
user
->
client_data
);
if
(
gc
!=
NULL
)
{
char
*
err
=
g_strdup_printf
(
_
(
"Unable to send message."
" Could not get details for user (%s)."
),
nm_error_to_string
(
ret_code
));
purple_notify_error
(
gc
,
NULL
,
err
,
NULL
,
purple_request_cpar_from_connection
(
gc
));
g_free
(
err
);
}
nm_release_message
(
msg
);
}
}
/* Set up the new PurpleBuddy based on the response from getdetails */
static
void
_get_details_resp_setup_buddy
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
NMUserRecord
*
user_record
;
NMContact
*
contact
;
PurpleBuddy
*
buddy
;
const
char
*
alias
;
NMERR_T
rc
=
NM_OK
;
if
(
user
==
NULL
||
resp_data
==
NULL
||
user_data
==
NULL
)
return
;
contact
=
user_data
;
if
(
ret_code
==
NM_OK
)
{
user_record
=
resp_data
;
buddy
=
nm_contact_get_data
(
contact
);
nm_contact_set_user_record
(
contact
,
user_record
);
/* Set the display id */
purple_buddy_set_name
(
buddy
,
nm_user_record_get_display_id
(
user_record
));
alias
=
purple_buddy_get_alias
(
buddy
);
if
(
alias
==
NULL
||
*
alias
==
'\0'
||
purple_strequal
(
alias
,
purple_buddy_get_name
(
buddy
)))
{
purple_buddy_set_local_alias
(
buddy
,
nm_user_record_get_full_name
(
user_record
));
/* Tell the server about the new display name */
rc
=
nm_send_rename_contact
(
user
,
contact
,
nm_user_record_get_full_name
(
user_record
),
NULL
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
}
/* Get initial status for the buddy */
rc
=
nm_send_get_status
(
user
,
resp_data
,
_get_status_resp_cb
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
/* nm_release_contact(contact);*/
}
nm_release_contact
(
contact
);
}
/* Add the new contact into the PurpleBuddy list */
static
void
_create_contact_resp_cb
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
NMContact
*
tmp_contact
=
(
NMContact
*
)
user_data
;
NMContact
*
new_contact
=
NULL
;
NMFolder
*
folder
=
NULL
;
PurpleGroup
*
group
;
PurpleBuddy
*
buddy
;
const
char
*
folder_name
=
NULL
;
NMERR_T
rc
=
NM_OK
;
if
(
user
==
NULL
)
return
;
if
(
ret_code
==
NM_OK
)
{
new_contact
=
(
NMContact
*
)
resp_data
;
if
(
new_contact
==
NULL
||
tmp_contact
==
NULL
)
return
;
/* Get the userid and folder name for the new contact */
folder
=
nm_find_folder_by_id
(
user
,
nm_contact_get_parent_id
(
new_contact
));
if
(
folder
)
{
folder_name
=
nm_folder_get_name
(
folder
);
}
if
(
folder_name
==
NULL
||
*
folder_name
==
'\0'
)
folder_name
=
NM_ROOT_FOLDER_NAME
;
/* Re-add the buddy now that we got the okay from the server */
group
=
purple_blist_find_group
(
folder_name
);
if
(
group
)
{
const
char
*
alias
=
nm_contact_get_display_name
(
tmp_contact
);
const
char
*
display_id
=
nm_contact_get_display_id
(
new_contact
);
if
(
display_id
==
NULL
)
display_id
=
nm_contact_get_dn
(
new_contact
);
if
(
alias
&&
!
purple_strequal
(
alias
,
display_id
))
{
/* The user requested an alias, tell the server about it. */
rc
=
nm_send_rename_contact
(
user
,
new_contact
,
alias
,
_rename_contact_resp_cb
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
}
else
{
alias
=
""
;
}
/* Add it to the purple buddy list if it is not there */
buddy
=
purple_blist_find_buddy_in_group
(
user
->
client_data
,
display_id
,
group
);
if
(
buddy
==
NULL
)
{
buddy
=
purple_buddy_new
(
user
->
client_data
,
display_id
,
alias
);
purple_blist_add_buddy
(
buddy
,
NULL
,
group
,
NULL
);
}
/* Save the new buddy as part of the contact object */
nm_contact_set_data
(
new_contact
,
(
gpointer
)
buddy
);
/* We need details for the user before we can setup the
* new Purple buddy. We always call this because the
* 'createcontact' response fields do not always contain
* everything that we need.
*/
nm_contact_add_ref
(
new_contact
);
rc
=
nm_send_get_details
(
user
,
nm_contact_get_dn
(
new_contact
),
_get_details_resp_setup_buddy
,
new_contact
);
_check_for_disconnect
(
user
,
rc
);
}
}
else
{
PurpleConnection
*
gc
=
purple_account_get_connection
(
user
->
client_data
);
const
char
*
name
=
nm_contact_get_dn
(
tmp_contact
);
char
*
err
;
err
=
g_strdup_printf
(
_
(
"Unable to add %s to your buddy list (%s)."
),
name
,
nm_error_to_string
(
ret_code
));
purple_notify_error
(
gc
,
NULL
,
err
,
NULL
,
purple_request_cpar_from_connection
(
gc
));
g_free
(
err
);
}
if
(
tmp_contact
)
nm_release_contact
(
tmp_contact
);
}
/* Show an error if we failed to send the message */
static
void
_send_message_resp_cb
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
PurpleConnection
*
gc
;
char
*
err
=
NULL
;
if
(
user
==
NULL
)
return
;
if
(
ret_code
!=
NM_OK
)
{
gc
=
purple_account_get_connection
(
user
->
client_data
);
/* TODO: Improve this! message to who or for what conference? */
err
=
g_strdup_printf
(
_
(
"Unable to send message (%s)."
),
nm_error_to_string
(
ret_code
));
purple_notify_error
(
gc
,
NULL
,
err
,
NULL
,
purple_request_cpar_from_connection
(
gc
));
g_free
(
err
);
}
}
/* Show an error if the remove failed */
static
void
_remove_contact_resp_cb
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
if
(
ret_code
!=
NM_OK
)
{
/* TODO: Display an error? */
purple_debug_info
(
"novell"
,
"_remove_contact_resp_cb(): rc = 0x%x"
,
ret_code
);
}
}
/* Show an error if the remove failed */
static
void
_remove_folder_resp_cb
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
if
(
ret_code
!=
NM_OK
)
{
/* TODO: Display an error? */
purple_debug_info
(
"novell"
,
"_remove_folder_resp_cb(): rc = 0x%x"
,
ret_code
);
}
}
/* Show an error if the move failed */
static
void
_move_contact_resp_cb
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
if
(
ret_code
!=
NM_OK
)
{
/* TODO: Display an error? */
purple_debug_info
(
"novell"
,
"_move_contact_resp_cb(): rc = 0x%x"
,
ret_code
);
}
}
/* Show an error if the rename failed */
static
void
_rename_folder_resp_cb
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
if
(
ret_code
!=
NM_OK
)
{
/* TODO: Display an error? */
purple_debug_info
(
"novell"
,
"_rename_folder_resp_cb(): rc = 0x%x"
,
ret_code
);
}
}
static
void
_sendinvite_resp_cb
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
char
*
err
;
PurpleConnection
*
gc
;
if
(
user
==
NULL
)
return
;
if
(
ret_code
!=
NM_OK
)
{
gc
=
purple_account_get_connection
(
user
->
client_data
);
err
=
g_strdup_printf
(
_
(
"Unable to invite user (%s)."
),
nm_error_to_string
(
ret_code
));
purple_notify_error
(
gc
,
NULL
,
err
,
NULL
,
purple_request_cpar_from_connection
(
gc
));
g_free
(
err
);
purple_debug_info
(
"novell"
,
"_sendinvite_resp_cb(): rc = 0x%x"
,
ret_code
);
}
}
/* If the createconf was successful attempt to send the message,
* otherwise display an error message to the user.
*/
static
void
_createconf_resp_send_msg
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
NMConference
*
conf
;
NMMessage
*
msg
=
user_data
;
if
(
user
==
NULL
||
msg
==
NULL
)
return
;
if
(
ret_code
==
NM_OK
)
{
_send_message
(
user
,
msg
);
}
else
{
if
((
conf
=
nm_message_get_conference
(
msg
)))
{
PurpleConnection
*
gc
=
purple_account_get_connection
(
user
->
client_data
);
const
char
*
name
=
NULL
;
char
*
err
;
NMUserRecord
*
ur
;
ur
=
nm_conference_get_participant
(
conf
,
0
);
if
(
ur
)
name
=
nm_user_record_get_userid
(
ur
);
if
(
name
)
err
=
g_strdup_printf
(
_
(
"Unable to send message to %s."
" Could not create the conference (%s)."
),
name
,
nm_error_to_string
(
ret_code
));
else
err
=
g_strdup_printf
(
_
(
"Unable to send message."
" Could not create the conference (%s)."
),
nm_error_to_string
(
ret_code
));
purple_notify_error
(
gc
,
NULL
,
err
,
NULL
,
purple_request_cpar_from_connection
(
gc
));
g_free
(
err
);
}
nm_release_message
(
msg
);
}
}
/* Move contact to newly created folder */
static
void
_create_folder_resp_move_contact
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
NMContact
*
contact
=
user_data
;
NMFolder
*
new_folder
;
char
*
folder_name
=
resp_data
;
NMERR_T
rc
=
NM_OK
;
if
(
user
==
NULL
||
folder_name
==
NULL
||
contact
==
NULL
)
{
g_free
(
folder_name
);
return
;
}
if
(
ret_code
==
NM_OK
||
ret_code
==
NMERR_DUPLICATE_FOLDER
)
{
new_folder
=
nm_find_folder
(
user
,
folder_name
);
if
(
new_folder
)
{
/* Tell the server to move the contact to the new folder */
/* rc = nm_send_move_contact(user, contact, new_folder,
_move_contact_resp_cb, NULL); */
rc
=
nm_send_create_contact
(
user
,
new_folder
,
contact
,
NULL
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
}
}
else
{
PurpleConnection
*
gc
=
purple_account_get_connection
(
user
->
client_data
);
char
*
err
=
g_strdup_printf
(
_
(
"Unable to move user %s"
" to folder %s in the server side list."
" Error while creating folder (%s)."
),
nm_contact_get_dn
(
contact
),
folder_name
,
nm_error_to_string
(
ret_code
));
purple_notify_error
(
gc
,
NULL
,
err
,
NULL
,
purple_request_cpar_from_connection
(
gc
));
g_free
(
err
);
}
g_free
(
folder_name
);
}
/* Add contact to newly create folder */
static
void
_create_folder_resp_add_contact
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
NMContact
*
contact
=
(
NMContact
*
)
user_data
;
NMFolder
*
folder
;
char
*
folder_name
=
(
char
*
)
resp_data
;
NMERR_T
rc
=
NM_OK
;
if
(
user
==
NULL
||
folder_name
==
NULL
||
contact
==
NULL
)
{
if
(
contact
)
nm_release_contact
(
contact
);
g_free
(
folder_name
);
return
;
}
if
(
ret_code
==
NM_OK
||
ret_code
==
NMERR_DUPLICATE_FOLDER
)
{
folder
=
nm_find_folder
(
user
,
folder_name
);
if
(
folder
)
{
rc
=
nm_send_create_contact
(
user
,
folder
,
contact
,
_create_contact_resp_cb
,
contact
);
_check_for_disconnect
(
user
,
rc
);
}
}
else
{
PurpleConnection
*
gc
=
purple_account_get_connection
(
user
->
client_data
);
const
char
*
name
=
nm_contact_get_dn
(
contact
);
char
*
err
=
g_strdup_printf
(
_
(
"Unable to add %s to your buddy list."
" Error creating folder in server side list (%s)."
),
name
,
nm_error_to_string
(
ret_code
));
purple_notify_error
(
gc
,
NULL
,
err
,
NULL
,
purple_request_cpar_from_connection
(
gc
));
nm_release_contact
(
contact
);
g_free
(
err
);
}
g_free
(
folder_name
);
}
static
void
_join_conf_resp_cb
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
PurpleConversation
*
chat
;
PurpleConnection
*
gc
;
NMUserRecord
*
ur
;
NMConference
*
conference
=
user_data
;
const
char
*
name
,
*
conf_name
;
int
i
,
count
;
if
(
user
==
NULL
||
conference
==
NULL
)
return
;
gc
=
purple_account_get_connection
(
user
->
client_data
);
if
(
ret_code
==
NM_OK
)
{
conf_name
=
_get_conference_name
(
++
user
->
conference_count
);
chat
=
purple_serv_got_joined_chat
(
gc
,
user
->
conference_count
,
conf_name
);
if
(
chat
)
{
nm_conference_set_data
(
conference
,
(
gpointer
)
chat
);
count
=
nm_conference_get_participant_count
(
conference
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
ur
=
nm_conference_get_participant
(
conference
,
i
);
if
(
ur
)
{
name
=
nm_user_record_get_display_id
(
ur
);
purple_chat_conversation_add_user
(
PURPLE_CHAT_CONVERSATION
(
chat
),
name
,
NULL
,
PURPLE_CHAT_USER_NONE
,
TRUE
);
}
}
}
}
}
/* Show info returned by getdetails */
static
void
_get_details_resp_show_info
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
PurpleConnection
*
gc
;
NMUserRecord
*
user_record
;
char
*
name
;
char
*
err
;
if
(
user
==
NULL
)
return
;
name
=
user_data
;
if
(
ret_code
==
NM_OK
)
{
user_record
=
(
NMUserRecord
*
)
resp_data
;
if
(
user_record
)
{
_show_info
(
purple_account_get_connection
(
user
->
client_data
),
user_record
,
g_strdup
(
name
));
}
}
else
{
gc
=
purple_account_get_connection
(
user
->
client_data
);
err
=
g_strdup_printf
(
_
(
"Could not get details for user %s (%s)."
),
name
,
nm_error_to_string
(
ret_code
));
purple_notify_error
(
gc
,
NULL
,
err
,
NULL
,
purple_request_cpar_from_connection
(
gc
));
g_free
(
err
);
}
g_free
(
name
);
}
/* Handle get details response add to privacy list */
static
void
_get_details_resp_add_privacy_item
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
PurpleConnection
*
gc
;
PurpleAccount
*
account
;
NMUserRecord
*
user_record
=
resp_data
;
char
*
err
;
gboolean
allowed
=
GPOINTER_TO_INT
(
user_data
);
const
char
*
display_id
;
if
(
user
==
NULL
)
return
;
gc
=
purple_account_get_connection
(
user
->
client_data
);
display_id
=
nm_user_record_get_display_id
(
user_record
);
account
=
purple_connection_get_account
(
gc
);
if
(
ret_code
==
NM_OK
)
{
if
(
allowed
)
{
if
(
!
g_slist_find_custom
(
purple_account_privacy_get_denied
(
account
),
display_id
,
(
GCompareFunc
)
purple_utf8_strcasecmp
))
{
purple_account_privacy_permit_add
(
account
,
display_id
,
TRUE
);
}
}
else
{
if
(
!
g_slist_find_custom
(
purple_account_privacy_get_denied
(
account
),
display_id
,
(
GCompareFunc
)
purple_utf8_strcasecmp
))
{
purple_account_privacy_deny_add
(
account
,
display_id
,
TRUE
);
}
}
}
else
{
err
=
g_strdup_printf
(
_
(
"Unable to add user to privacy list (%s)."
),
nm_error_to_string
(
ret_code
));
purple_notify_error
(
gc
,
NULL
,
err
,
NULL
,
purple_request_cpar_from_connection
(
gc
));
g_free
(
err
);
}
}
/* Handle response to create privacy item request */
static
void
_create_privacy_item_deny_resp_cb
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
PurpleConnection
*
gc
;
PurpleAccount
*
account
;
NMUserRecord
*
user_record
;
char
*
who
=
user_data
;
char
*
err
;
NMERR_T
rc
=
NM_OK
;
const
char
*
display_id
=
NULL
;
if
(
user
==
NULL
)
return
;
gc
=
purple_account_get_connection
(
user
->
client_data
);
account
=
purple_connection_get_account
(
gc
);
if
(
ret_code
==
NM_OK
)
{
user_record
=
nm_find_user_record
(
user
,
who
);
if
(
user_record
)
display_id
=
nm_user_record_get_display_id
(
user_record
);
if
(
display_id
)
{
if
(
!
g_slist_find_custom
(
purple_account_privacy_get_denied
(
account
),
display_id
,
(
GCompareFunc
)
purple_utf8_strcasecmp
))
{
purple_account_privacy_deny_add
(
account
,
display_id
,
TRUE
);
}
}
else
{
rc
=
nm_send_get_details
(
user
,
who
,
_get_details_resp_add_privacy_item
,
GINT_TO_POINTER
(
FALSE
));
_check_for_disconnect
(
user
,
rc
);
}
}
else
{
err
=
g_strdup_printf
(
_
(
"Unable to add %s to deny list (%s)."
),
who
,
nm_error_to_string
(
ret_code
));
purple_notify_error
(
gc
,
NULL
,
err
,
NULL
,
purple_request_cpar_from_connection
(
gc
));
g_free
(
err
);
}
g_free
(
who
);
}
/* Handle response to create privacy item request */
static
void
_create_privacy_item_permit_resp_cb
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
PurpleConnection
*
gc
;
PurpleAccount
*
account
;
NMUserRecord
*
user_record
;
char
*
who
=
user_data
;
char
*
err
;
NMERR_T
rc
=
NM_OK
;
const
char
*
display_id
=
NULL
;
if
(
user
==
NULL
)
return
;
gc
=
purple_account_get_connection
(
user
->
client_data
);
account
=
purple_connection_get_account
(
gc
);
if
(
ret_code
==
NM_OK
)
{
user_record
=
nm_find_user_record
(
user
,
who
);
if
(
user_record
)
display_id
=
nm_user_record_get_display_id
(
user_record
);
if
(
display_id
)
{
if
(
!
g_slist_find_custom
(
purple_account_privacy_get_permitted
(
account
),
display_id
,
(
GCompareFunc
)
purple_utf8_strcasecmp
))
{
purple_account_privacy_permit_add
(
account
,
display_id
,
TRUE
);
}
}
else
{
rc
=
nm_send_get_details
(
user
,
who
,
_get_details_resp_add_privacy_item
,
GINT_TO_POINTER
(
TRUE
));
_check_for_disconnect
(
user
,
rc
);
}
}
else
{
err
=
g_strdup_printf
(
_
(
"Unable to add %s to permit list (%s)."
),
who
,
nm_error_to_string
(
ret_code
));
purple_notify_error
(
gc
,
NULL
,
err
,
NULL
,
purple_request_cpar_from_connection
(
gc
));
g_free
(
err
);
}
g_free
(
who
);
}
static
void
_get_details_send_privacy_create
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
NMERR_T
rc
=
NM_OK
;
PurpleConnection
*
gc
;
NMUserRecord
*
user_record
=
resp_data
;
char
*
err
;
gboolean
allowed
=
GPOINTER_TO_INT
(
user_data
);
const
char
*
dn
,
*
display_id
;
if
(
user
==
NULL
)
return
;
gc
=
purple_account_get_connection
(
user
->
client_data
);
dn
=
nm_user_record_get_dn
(
user_record
);
display_id
=
nm_user_record_get_display_id
(
user_record
);
if
(
ret_code
==
NM_OK
)
{
if
(
allowed
)
{
rc
=
nm_send_create_privacy_item
(
user
,
dn
,
TRUE
,
_create_privacy_item_permit_resp_cb
,
g_strdup
(
display_id
));
_check_for_disconnect
(
user
,
rc
);
}
else
{
rc
=
nm_send_create_privacy_item
(
user
,
dn
,
FALSE
,
_create_privacy_item_deny_resp_cb
,
g_strdup
(
display_id
));
_check_for_disconnect
(
user
,
rc
);
}
}
else
{
err
=
g_strdup_printf
(
_
(
"Unable to add user to privacy list (%s)."
),
nm_error_to_string
(
ret_code
));
purple_notify_error
(
gc
,
NULL
,
err
,
NULL
,
purple_request_cpar_from_connection
(
gc
));
g_free
(
err
);
}
}
static
void
_remove_privacy_item_resp_cb
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
PurpleConnection
*
gc
;
char
*
who
=
user_data
;
char
*
err
;
if
(
user
==
NULL
)
return
;
if
(
ret_code
!=
NM_OK
)
{
gc
=
purple_account_get_connection
(
user
->
client_data
);
err
=
g_strdup_printf
(
_
(
"Unable to remove %s from privacy list (%s)."
),
who
,
nm_error_to_string
(
ret_code
));
purple_notify_error
(
gc
,
NULL
,
err
,
NULL
,
purple_request_cpar_from_connection
(
gc
));
g_free
(
err
);
}
g_free
(
who
);
}
static
void
_set_privacy_default_resp_cb
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
PurpleConnection
*
gc
;
char
*
err
;
if
(
user
==
NULL
)
return
;
if
(
ret_code
!=
NM_OK
)
{
gc
=
purple_account_get_connection
(
user
->
client_data
);
err
=
g_strdup_printf
(
_
(
"Unable to change server side privacy settings (%s)."
),
nm_error_to_string
(
ret_code
));
purple_notify_error
(
gc
,
NULL
,
err
,
NULL
,
purple_request_cpar_from_connection
(
gc
));
g_free
(
err
);
}
}
/* Handle get details response add to privacy list */
static
void
_get_details_resp_send_invite
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
NMERR_T
rc
=
NM_OK
;
PurpleConnection
*
gc
;
NMUserRecord
*
user_record
=
resp_data
;
char
*
err
;
GSList
*
cnode
;
NMConference
*
conference
;
gpointer
chat
;
int
id
=
GPOINTER_TO_INT
(
user_data
);
if
(
user
==
NULL
)
return
;
gc
=
purple_account_get_connection
(
user
->
client_data
);
if
(
ret_code
==
NM_OK
)
{
for
(
cnode
=
user
->
conferences
;
cnode
!=
NULL
;
cnode
=
cnode
->
next
)
{
conference
=
cnode
->
data
;
if
(
conference
&&
(
chat
=
nm_conference_get_data
(
conference
)))
{
if
(
purple_chat_conversation_get_id
(
PURPLE_CHAT_CONVERSATION
(
chat
))
==
id
)
{
rc
=
nm_send_conference_invite
(
user
,
conference
,
user_record
,
NULL
,
_sendinvite_resp_cb
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
break
;
}
}
}
}
else
{
err
=
g_strdup_printf
(
_
(
"Unable to invite user (%s)."
),
nm_error_to_string
(
ret_code
));
purple_notify_error
(
gc
,
NULL
,
err
,
NULL
,
purple_request_cpar_from_connection
(
gc
));
g_free
(
err
);
}
}
static
void
_createconf_resp_send_invite
(
NMUser
*
user
,
NMERR_T
ret_code
,
gpointer
resp_data
,
gpointer
user_data
)
{
NMERR_T
rc
=
NM_OK
;
NMConference
*
conference
=
resp_data
;
NMUserRecord
*
user_record
=
user_data
;
PurpleConnection
*
gc
;
char
*
err
;
if
(
user
==
NULL
)
return
;
if
(
ret_code
==
NM_OK
)
{
rc
=
nm_send_conference_invite
(
user
,
conference
,
user_record
,
NULL
,
_sendinvite_resp_cb
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
}
else
{
err
=
g_strdup_printf
(
_
(
"Unable to create conference (%s)."
),
nm_error_to_string
(
ret_code
));
gc
=
purple_account_get_connection
(
user
->
client_data
);
purple_notify_error
(
gc
,
NULL
,
err
,
NULL
,
purple_request_cpar_from_connection
(
gc
));
g_free
(
err
);
}
}
/*******************************************************************************
* Helper functions
******************************************************************************/
static
char
*
_user_agent_string
(
void
)
{
#if !defined(_WIN32)
const
char
*
sysname
=
""
;
const
char
*
release
=
""
;
struct
utsname
u
;
if
(
uname
(
&
u
)
==
0
)
{
sysname
=
u
.
sysname
;
release
=
u
.
release
;
}
else
{
sysname
=
"Linux"
;
release
=
"Unknown"
;
}
return
g_strdup_printf
(
"Purple/%s (%s; %s)"
,
VERSION
,
sysname
,
release
);
#else
const
char
*
sysname
=
""
;
OSVERSIONINFO
os_info
;
SYSTEM_INFO
sys_info
;
os_info
.
dwOSVersionInfoSize
=
sizeof
(
OSVERSIONINFO
);
GetVersionEx
(
&
os_info
);
GetSystemInfo
(
&
sys_info
);
if
(
os_info
.
dwPlatformId
==
VER_PLATFORM_WIN32_NT
)
{
switch
(
os_info
.
dwMajorVersion
)
{
case
3
:
case
4
:
sysname
=
"Windows NT"
;
break
;
case
5
:
switch
(
os_info
.
dwMinorVersion
)
{
case
0
:
sysname
=
"Windows 2000"
;
break
;
case
1
:
sysname
=
"Windows XP"
;
break
;
case
2
:
sysname
=
"Windows Server 2003"
;
break
;
default
:
sysname
=
"Windows"
;
break
;
}
break
;
default
:
sysname
=
"Windows"
;
break
;
}
}
else
if
(
os_info
.
dwPlatformId
==
VER_PLATFORM_WIN32_WINDOWS
)
{
switch
(
os_info
.
dwMinorVersion
)
{
case
0
:
sysname
=
"Windows 95"
;
break
;
case
10
:
sysname
=
"Windows 98"
;
break
;
case
90
:
sysname
=
"Windows ME"
;
break
;
default
:
sysname
=
"Windows"
;
break
;
}
}
else
{
sysname
=
"Windows"
;
}
return
g_strdup_printf
(
"Purple/%s (%s; %ld.%ld)"
,
VERSION
,
sysname
,
os_info
.
dwMajorVersion
,
os_info
.
dwMinorVersion
);
#endif
}
static
gboolean
_is_disconnect_error
(
NMERR_T
err
)
{
return
(
err
==
NMERR_TCP_WRITE
||
err
==
NMERR_TCP_READ
||
err
==
NMERR_PROTOCOL
);
}
static
gboolean
_check_for_disconnect
(
NMUser
*
user
,
NMERR_T
err
)
{
PurpleConnection
*
gc
=
purple_account_get_connection
(
user
->
client_data
);
if
(
_is_disconnect_error
(
err
))
{
purple_connection_error
(
gc
,
PURPLE_CONNECTION_ERROR_NETWORK_ERROR
,
_
(
"Error communicating with server. Closing connection."
));
return
TRUE
;
}
return
FALSE
;
}
/* Check to see if the conference is instantiated, if so send the message.
* If not send the create conference -- the response handler for the createconf
* will call this function again.
*/
static
void
_send_message
(
NMUser
*
user
,
NMMessage
*
message
)
{
NMConference
*
conf
;
NMERR_T
rc
=
NM_OK
;
conf
=
nm_message_get_conference
(
message
);
if
(
conf
)
{
/* We have a conference make sure that the
server knows about it already. */
if
(
nm_conference_is_instantiated
(
conf
))
{
/* We have everything that we need...finally! */
rc
=
nm_send_message
(
user
,
message
,
_send_message_resp_cb
);
_check_for_disconnect
(
user
,
rc
);
nm_release_message
(
message
);
}
else
{
rc
=
nm_send_create_conference
(
user
,
conf
,
_createconf_resp_send_msg
,
message
);
_check_for_disconnect
(
user
,
rc
);
}
}
}
/*
* Update the status of the given buddy in the Purple buddy list
*/
static
void
_update_buddy_status
(
NMUser
*
user
,
PurpleBuddy
*
buddy
,
int
novellstatus
,
int
gmt
)
{
PurpleAccount
*
account
;
const
char
*
status_id
;
const
char
*
text
=
NULL
;
const
char
*
dn
;
const
char
*
name
;
int
idle
=
0
;
account
=
purple_buddy_get_account
(
buddy
);
name
=
purple_buddy_get_name
(
buddy
);
switch
(
novellstatus
)
{
case
NM_STATUS_AVAILABLE
:
status_id
=
NOVELL_STATUS_TYPE_AVAILABLE
;
break
;
case
NM_STATUS_AWAY
:
status_id
=
NOVELL_STATUS_TYPE_AWAY
;
break
;
case
NM_STATUS_BUSY
:
status_id
=
NOVELL_STATUS_TYPE_BUSY
;
break
;
case
NM_STATUS_OFFLINE
:
status_id
=
NOVELL_STATUS_TYPE_OFFLINE
;
break
;
case
NM_STATUS_AWAY_IDLE
:
status_id
=
NOVELL_STATUS_TYPE_AWAY
;
idle
=
gmt
;
break
;
default
:
status_id
=
NOVELL_STATUS_TYPE_OFFLINE
;
break
;
}
/* Get status text for the user */
dn
=
nm_lookup_dn
(
user
,
name
);
if
(
dn
)
{
NMUserRecord
*
user_record
=
nm_find_user_record
(
user
,
dn
);
if
(
user_record
)
{
text
=
nm_user_record_get_status_text
(
user_record
);
}
}
purple_protocol_got_user_status
(
account
,
name
,
status_id
,
"message"
,
text
,
NULL
);
purple_protocol_got_user_idle
(
account
,
name
,
(
novellstatus
==
NM_STATUS_AWAY_IDLE
),
idle
);
}
/* Iterate through the cached Purple buddy list and remove buddies
* that are not in the server side list.
*/
static
void
_remove_purple_buddies
(
NMUser
*
user
)
{
PurpleBlistNode
*
gnode
;
PurpleBlistNode
*
cnode
;
PurpleBlistNode
*
bnode
;
PurpleGroup
*
group
;
PurpleBuddy
*
buddy
;
GSList
*
rem_list
=
NULL
;
NMFolder
*
folder
=
NULL
;
const
char
*
gname
=
NULL
;
for
(
gnode
=
purple_blist_get_default_root
();
gnode
;
gnode
=
purple_blist_node_get_sibling_next
(
gnode
))
{
if
(
!
PURPLE_IS_GROUP
(
gnode
))
continue
;
group
=
(
PurpleGroup
*
)
gnode
;
gname
=
purple_group_get_name
(
group
);
for
(
cnode
=
purple_blist_node_get_first_child
(
gnode
);
cnode
;
cnode
=
purple_blist_node_get_sibling_next
(
cnode
))
{
if
(
!
PURPLE_IS_CONTACT
(
cnode
))
continue
;
for
(
bnode
=
purple_blist_node_get_first_child
(
cnode
);
bnode
;
bnode
=
purple_blist_node_get_sibling_next
(
bnode
))
{
if
(
!
PURPLE_IS_BUDDY
(
bnode
))
continue
;
buddy
=
(
PurpleBuddy
*
)
bnode
;
if
(
purple_buddy_get_account
(
buddy
)
==
user
->
client_data
)
{
if
(
purple_strequal
(
gname
,
NM_ROOT_FOLDER_NAME
))
gname
=
""
;
folder
=
nm_find_folder
(
user
,
gname
);
if
(
folder
==
NULL
||
!
nm_folder_find_contact_by_display_id
(
folder
,
purple_buddy_get_name
(
buddy
)))
{
rem_list
=
g_slist_append
(
rem_list
,
buddy
);
}
}
}
}
}
g_slist_free_full
(
rem_list
,
(
GDestroyNotify
)
purple_blist_remove_buddy
);
}
/* Add all of the contacts in the given folder to the Purple buddy list */
static
void
_add_contacts_to_purple_blist
(
NMUser
*
user
,
NMFolder
*
folder
)
{
NMUserRecord
*
user_record
=
NULL
;
NMContact
*
contact
=
NULL
;
PurpleBuddy
*
buddy
=
NULL
;
PurpleGroup
*
group
;
NMERR_T
cnt
=
0
,
i
;
const
char
*
name
=
NULL
;
const
char
*
fname
=
NULL
;
int
status
=
0
;
/* If this is the root folder give it a name. Purple does not have the concept of
* a root folder.
*/
fname
=
nm_folder_get_name
(
folder
);
if
(
fname
==
NULL
||
*
fname
==
'\0'
)
{
fname
=
NM_ROOT_FOLDER_NAME
;
}
/* Does the Purple group exist already? */
group
=
purple_blist_find_group
(
fname
);
if
(
group
==
NULL
)
{
group
=
purple_group_new
(
fname
);
purple_blist_add_group
(
group
,
NULL
);
}
/* Get each contact for this folder */
cnt
=
nm_folder_get_contact_count
(
folder
);
for
(
i
=
0
;
i
<
cnt
;
i
++
)
{
contact
=
nm_folder_get_contact
(
folder
,
i
);
if
(
contact
)
{
name
=
nm_contact_get_display_id
(
contact
);
if
(
name
)
{
buddy
=
purple_blist_find_buddy_in_group
(
user
->
client_data
,
name
,
group
);
if
(
buddy
==
NULL
)
{
/* Add it to the purple buddy list */
buddy
=
purple_buddy_new
(
user
->
client_data
,
name
,
nm_contact_get_display_name
(
contact
));
purple_blist_add_buddy
(
buddy
,
NULL
,
group
,
NULL
);
}
/* Set the initial status for the buddy */
user_record
=
nm_contact_get_user_record
(
contact
);
if
(
user_record
)
{
status
=
nm_user_record_get_status
(
user_record
);
}
_update_buddy_status
(
user
,
buddy
,
status
,
time
(
0
));
/* Save the new buddy as part of the contact object */
nm_contact_set_data
(
contact
,
(
gpointer
)
buddy
);
}
}
else
{
/* NULL contact. This should not happen, but
* let's break out of the loop.
*/
break
;
}
}
}
/* Add all of the server side contacts to the Purple buddy list. */
static
void
_add_purple_buddies
(
NMUser
*
user
)
{
int
cnt
=
0
,
i
;
NMFolder
*
root_folder
=
NULL
;
NMFolder
*
folder
=
NULL
;
root_folder
=
nm_get_root_folder
(
user
);
if
(
root_folder
)
{
/* Add sub-folders and contacts to sub-folders...
* iterate throught the sub-folders in reverse order
* because Purple adds the folders to the front -- so we
* want to add the first folder last
*/
cnt
=
nm_folder_get_subfolder_count
(
root_folder
);
for
(
i
=
cnt
-1
;
i
>=
0
;
i
--
)
{
folder
=
nm_folder_get_subfolder
(
root_folder
,
i
);
if
(
folder
)
{
_add_contacts_to_purple_blist
(
user
,
folder
);
}
}
/* Add contacts for the root folder */
_add_contacts_to_purple_blist
(
user
,
root_folder
);
}
}
static
void
_sync_contact_list
(
NMUser
*
user
)
{
/* Remove all buddies from the local list that are
* not in the server side list and add all buddies
* from the server side list that are not in
* the local list
*/
_remove_purple_buddies
(
user
);
_add_purple_buddies
(
user
);
user
->
clist_synched
=
TRUE
;
}
static
void
_sync_privacy_lists
(
NMUser
*
user
)
{
GSList
*
node
=
NULL
,
*
rem_list
=
NULL
;
PurpleConnection
*
gc
;
PurpleAccount
*
account
;
const
char
*
name
,
*
dn
;
NMUserRecord
*
user_record
;
if
(
user
==
NULL
)
return
;
gc
=
purple_account_get_connection
(
user
->
client_data
);
if
(
gc
==
NULL
)
return
;
account
=
purple_connection_get_account
(
gc
);
/* Set the Purple privacy setting */
if
(
user
->
default_deny
)
{
if
(
user
->
allow_list
==
NULL
)
{
purple_account_set_privacy_type
(
account
,
PURPLE_ACCOUNT_PRIVACY_DENY_ALL
);
}
else
{
purple_account_set_privacy_type
(
account
,
PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
);
}
}
else
{
if
(
user
->
deny_list
==
NULL
)
{
purple_account_set_privacy_type
(
account
,
PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL
);
}
else
{
purple_account_set_privacy_type
(
account
,
PURPLE_ACCOUNT_PRIVACY_DENY_USERS
);
}
}
/* Add stuff */
for
(
node
=
user
->
allow_list
;
node
;
node
=
node
->
next
)
{
user_record
=
nm_find_user_record
(
user
,
(
char
*
)
node
->
data
);
if
(
user_record
)
name
=
nm_user_record_get_display_id
(
user_record
);
else
name
=
(
char
*
)
node
->
data
;
if
(
!
g_slist_find_custom
(
purple_account_privacy_get_permitted
(
account
),
name
,
(
GCompareFunc
)
purple_utf8_strcasecmp
))
{
purple_account_privacy_permit_add
(
account
,
name
,
TRUE
);
}
}
for
(
node
=
user
->
deny_list
;
node
;
node
=
node
->
next
)
{
user_record
=
nm_find_user_record
(
user
,
(
char
*
)
node
->
data
);
if
(
user_record
)
name
=
nm_user_record_get_display_id
(
user_record
);
else
name
=
(
char
*
)
node
->
data
;
if
(
!
g_slist_find_custom
(
purple_account_privacy_get_denied
(
account
),
name
,
(
GCompareFunc
)
purple_utf8_strcasecmp
))
{
purple_account_privacy_deny_add
(
account
,
name
,
TRUE
);
}
}
/* Remove stuff */
for
(
node
=
purple_account_privacy_get_permitted
(
account
);
node
;
node
=
node
->
next
)
{
dn
=
nm_lookup_dn
(
user
,
(
char
*
)
node
->
data
);
if
(
dn
!=
NULL
&&
!
g_slist_find_custom
(
user
->
allow_list
,
dn
,
(
GCompareFunc
)
purple_utf8_strcasecmp
))
{
rem_list
=
g_slist_append
(
rem_list
,
node
->
data
);
}
}
if
(
rem_list
)
{
for
(
node
=
rem_list
;
node
;
node
=
node
->
next
)
{
purple_account_privacy_permit_remove
(
account
,
(
char
*
)
node
->
data
,
TRUE
);
}
g_slist_free
(
rem_list
);
rem_list
=
NULL
;
}
for
(
node
=
purple_account_privacy_get_denied
(
account
);
node
;
node
=
node
->
next
)
{
dn
=
nm_lookup_dn
(
user
,
(
char
*
)
node
->
data
);
if
(
dn
!=
NULL
&&
!
g_slist_find_custom
(
user
->
deny_list
,
dn
,
(
GCompareFunc
)
purple_utf8_strcasecmp
))
{
rem_list
=
g_slist_append
(
rem_list
,
node
->
data
);
}
}
if
(
rem_list
)
{
for
(
node
=
rem_list
;
node
;
node
=
node
->
next
)
{
purple_account_privacy_deny_remove
(
account
,
(
char
*
)
node
->
data
,
TRUE
);
}
g_slist_free
(
rem_list
);
}
}
/* Map known property tags to user-friendly strings */
static
const
char
*
_map_property_tag
(
const
char
*
tag
)
{
if
(
tag
==
NULL
)
return
NULL
;
if
(
purple_strequal
(
tag
,
"telephoneNumber"
))
return
_
(
"Telephone Number"
);
else
if
(
purple_strequal
(
tag
,
"L"
))
return
_
(
"Location"
);
else
if
(
purple_strequal
(
tag
,
"OU"
))
return
_
(
"Department"
);
else
if
(
purple_strequal
(
tag
,
"personalTitle"
))
return
_
(
"Personal Title"
);
else
if
(
purple_strequal
(
tag
,
"Title"
))
return
_
(
"Job Title"
);
else
if
(
purple_strequal
(
tag
,
"mailstop"
))
return
_
(
"Mailstop"
);
else
if
(
purple_strequal
(
tag
,
"Internet EMail Address"
))
return
_
(
"Email Address"
);
else
return
tag
;
}
/* Display a dialog box showing the properties for the given user record */
static
void
_show_info
(
PurpleConnection
*
gc
,
NMUserRecord
*
user_record
,
char
*
name
)
{
PurpleNotifyUserInfo
*
user_info
=
purple_notify_user_info_new
();
int
count
,
i
;
const
char
*
tag
,
*
value
;
tag
=
_
(
"User ID"
);
value
=
nm_user_record_get_userid
(
user_record
);
if
(
value
)
{
/* TODO: Check whether it's correct to call add_pair_html,
or if we should be using add_pair_plaintext */
purple_notify_user_info_add_pair_html
(
user_info
,
tag
,
value
);
}
tag
=
_
(
"Full name"
);
value
=
nm_user_record_get_full_name
(
user_record
);
if
(
value
)
{
/* TODO: Check whether it's correct to call add_pair_html,
or if we should be using add_pair_plaintext */
purple_notify_user_info_add_pair_html
(
user_info
,
tag
,
value
);
}
count
=
nm_user_record_get_property_count
(
user_record
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
PurpleKeyValuePair
*
property
=
nm_user_record_get_property
(
user_record
,
i
);
if
(
property
)
{
tag
=
_map_property_tag
(
property
->
key
);
value
=
property
->
value
;
if
(
tag
&&
value
)
{
/* TODO: Check whether it's correct to call add_pair_html,
or if we should be using add_pair_plaintext */
purple_notify_user_info_add_pair_html
(
user_info
,
tag
,
value
);
}
purple_key_value_pair_free
(
property
);
}
}
purple_notify_userinfo
(
gc
,
name
,
user_info
,
NULL
,
NULL
);
purple_notify_user_info_destroy
(
user_info
);
g_free
(
name
);
}
/* Send a join conference, the first item in the parms list is the
* NMUser object and the second item is the conference to join.
* This callback is passed to purple_request_action when we ask the
* user if they want to join the conference.
*/
static
void
_join_conference_cb
(
GSList
*
parms
)
{
NMUser
*
user
;
NMConference
*
conference
;
NMERR_T
rc
=
NM_OK
;
if
(
parms
==
NULL
||
g_slist_length
(
parms
)
!=
2
)
return
;
user
=
g_slist_nth_data
(
parms
,
0
);
conference
=
g_slist_nth_data
(
parms
,
1
);
if
(
user
&&
conference
)
{
rc
=
nm_send_join_conference
(
user
,
conference
,
_join_conf_resp_cb
,
conference
);
_check_for_disconnect
(
user
,
rc
);
}
g_slist_free
(
parms
);
}
/* Send a reject conference, the first item in the parms list is the
* NMUser object and the second item is the conference to reject.
* This callback is passed to purple_request_action when we ask the
* user if they want to joing the conference.
*/
static
void
_reject_conference_cb
(
GSList
*
parms
)
{
NMUser
*
user
;
NMConference
*
conference
;
NMERR_T
rc
=
NM_OK
;
if
(
parms
==
NULL
||
g_slist_length
(
parms
)
!=
2
)
return
;
user
=
g_slist_nth_data
(
parms
,
0
);
conference
=
g_slist_nth_data
(
parms
,
1
);
if
(
user
&&
conference
)
{
rc
=
nm_send_reject_conference
(
user
,
conference
,
NULL
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
}
g_slist_free
(
parms
);
}
static
void
_initiate_conference_cb
(
PurpleBlistNode
*
node
,
gpointer
ignored
)
{
PurpleBuddy
*
buddy
;
PurpleConnection
*
gc
;
NMUser
*
user
;
const
char
*
conf_name
;
PurpleConversation
*
chat
=
NULL
;
NMUserRecord
*
user_record
;
NMConference
*
conference
;
g_return_if_fail
(
PURPLE_IS_BUDDY
(
node
));
buddy
=
(
PurpleBuddy
*
)
node
;
gc
=
purple_account_get_connection
(
purple_buddy_get_account
(
buddy
));
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
==
NULL
)
return
;
/* We should already have a userrecord for the buddy */
user_record
=
nm_find_user_record
(
user
,
purple_buddy_get_name
(
buddy
));
if
(
user_record
==
NULL
)
return
;
conf_name
=
_get_conference_name
(
++
user
->
conference_count
);
chat
=
purple_serv_got_joined_chat
(
gc
,
user
->
conference_count
,
conf_name
);
if
(
chat
)
{
conference
=
nm_create_conference
(
NULL
);
nm_conference_set_data
(
conference
,
(
gpointer
)
chat
);
nm_send_create_conference
(
user
,
conference
,
_createconf_resp_send_invite
,
user_record
);
nm_release_conference
(
conference
);
}
}
const
char
*
_get_conference_name
(
int
id
)
{
static
char
*
name
=
NULL
;
g_free
(
name
);
name
=
g_strdup_printf
(
_
(
"GroupWise Conference %d"
),
id
);
return
name
;
}
static
void
_show_privacy_locked_error
(
PurpleConnection
*
gc
,
NMUser
*
user
)
{
char
*
err
;
err
=
g_strdup_printf
(
_
(
"Unable to change server side privacy settings (%s)."
),
nm_error_to_string
(
NMERR_ADMIN_LOCKED
));
purple_notify_error
(
gc
,
NULL
,
err
,
NULL
,
purple_request_cpar_from_connection
(
gc
));
g_free
(
err
);
}
/*******************************************************************************
* Connect and recv callbacks
******************************************************************************/
static
void
novell_ssl_recv_cb
(
GObject
*
stream
,
gpointer
data
)
{
PurpleConnection
*
gc
=
data
;
NMUser
*
user
;
NMERR_T
rc
;
if
(
gc
==
NULL
)
return
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
==
NULL
)
return
;
rc
=
nm_process_new_data
(
user
);
if
(
rc
!=
NM_OK
)
{
if
(
_is_disconnect_error
(
rc
))
{
purple_connection_error
(
gc
,
PURPLE_CONNECTION_ERROR_NETWORK_ERROR
,
_
(
"Error communicating with server. Closing connection."
));
}
else
{
purple_debug_info
(
"novell"
,
"Error processing event or response (%d)."
,
rc
);
}
}
}
static
void
novell_login_callback
(
GObject
*
source_object
,
GAsyncResult
*
res
,
gpointer
data
)
{
GSocketClient
*
client
=
G_SOCKET_CLIENT
(
source_object
);
PurpleConnection
*
gc
=
data
;
GSocketConnection
*
sockconn
;
NMUser
*
user
;
NMConn
*
conn
;
NMERR_T
rc
=
0
;
const
char
*
pwd
=
NULL
;
gchar
*
my_addr
=
NULL
;
char
*
ua
=
NULL
;
GError
*
error
=
NULL
;
sockconn
=
g_socket_client_connect_to_host_finish
(
client
,
res
,
&
error
);
if
(
sockconn
==
NULL
)
{
if
(
g_error_matches
(
error
,
G_IO_ERROR
,
G_IO_ERROR_CANCELLED
))
{
g_error_free
(
error
);
}
else
{
purple_connection_take_error
(
gc
,
error
);
}
return
;
}
user
=
purple_connection_get_protocol_data
(
gc
);
if
((
user
==
NULL
)
||
(
conn
=
user
->
conn
)
==
NULL
)
return
;
purple_connection_update_progress
(
gc
,
_
(
"Authenticating..."
),
2
,
NOVELL_CONNECT_STEPS
);
conn
->
stream
=
G_IO_STREAM
(
sockconn
);
conn
->
input
=
g_data_input_stream_new
(
g_io_stream_get_input_stream
(
conn
->
stream
));
conn
->
output
=
g_object_ref
(
g_io_stream_get_output_stream
(
conn
->
stream
));
g_data_input_stream_set_byte_order
(
conn
->
input
,
G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN
);
g_data_input_stream_set_newline_type
(
conn
->
input
,
G_DATA_STREAM_NEWLINE_TYPE_LF
);
my_addr
=
purple_network_get_my_ip_from_gio
(
sockconn
);
pwd
=
purple_connection_get_password
(
gc
);
ua
=
_user_agent_string
();
rc
=
nm_send_login
(
user
,
pwd
,
my_addr
,
ua
,
_login_resp_cb
,
NULL
);
if
(
rc
==
NM_OK
)
{
GSource
*
source
;
source
=
g_pollable_input_stream_create_source
(
G_POLLABLE_INPUT_STREAM
(
conn
->
input
),
user
->
cancellable
);
g_source_set_callback
(
source
,
(
GSourceFunc
)
novell_ssl_recv_cb
,
gc
,
NULL
);
}
else
{
purple_connection_error
(
gc
,
PURPLE_CONNECTION_ERROR_NETWORK_ERROR
,
_
(
"Unable to connect"
));
}
purple_connection_update_progress
(
gc
,
_
(
"Waiting for response..."
),
3
,
NOVELL_CONNECT_STEPS
);
g_free
(
ua
);
g_free
(
my_addr
);
}
/*******************************************************************************
* Event callback and event handlers
******************************************************************************/
static
void
_evt_receive_message
(
NMUser
*
user
,
NMEvent
*
event
)
{
NMUserRecord
*
user_record
=
NULL
;
NMContact
*
contact
=
NULL
;
PurpleConversation
*
im
;
NMConference
*
conference
;
PurpleMessageFlags
flags
;
char
*
text
=
NULL
;
text
=
g_markup_escape_text
(
nm_event_get_text
(
event
),
-1
);
conference
=
nm_event_get_conference
(
event
);
if
(
conference
)
{
PurpleConversation
*
chat
=
nm_conference_get_data
(
conference
);
/* Is this a single person 'conversation' or a conference? */
if
(
chat
==
NULL
&&
nm_conference_get_participant_count
(
conference
)
==
1
)
{
user_record
=
nm_find_user_record
(
user
,
nm_event_get_source
(
event
));
if
(
user_record
)
{
PurpleConversationManager
*
manager
=
NULL
;
flags
=
0
;
if
(
nm_event_get_type
(
event
)
==
NMEVT_RECEIVE_AUTOREPLY
)
{
flags
|=
PURPLE_MESSAGE_AUTO_RESP
;
}
purple_serv_got_im
(
purple_account_get_connection
(
user
->
client_data
),
nm_user_record_get_display_id
(
user_record
),
text
,
flags
,
nm_event_get_gmt
(
event
));
manager
=
purple_conversation_manager_get_default
();
im
=
purple_conversation_manager_find_im
(
manager
,
PURPLE_ACCOUNT
(
user
->
client_data
),
nm_user_record_get_display_id
(
user_record
));
if
(
im
)
{
contact
=
nm_find_contact
(
user
,
nm_event_get_source
(
event
));
if
(
contact
)
{
purple_conversation_set_title
(
im
,
nm_contact_get_display_name
(
contact
));
}
else
{
const
char
*
name
=
nm_user_record_get_full_name
(
user_record
);
if
(
name
==
NULL
)
name
=
nm_user_record_get_userid
(
user_record
);
purple_conversation_set_title
(
im
,
name
);
}
}
}
else
{
/* this should not happen, see the event code.
* the event code will get the contact details from
* the server if it does not have them before calling
* the event callback.
*/
}
}
else
if
(
chat
)
{
/* get the contact for send if we have one */
NMContact
*
contact
=
nm_find_contact
(
user
,
nm_event_get_source
(
event
));
/* get the user record for the sender */
user_record
=
nm_find_user_record
(
user
,
nm_event_get_source
(
event
));
if
(
user_record
)
{
const
char
*
name
=
nm_contact_get_display_name
(
contact
);
if
(
name
==
NULL
)
{
name
=
nm_user_record_get_full_name
(
user_record
);
if
(
name
==
NULL
)
name
=
nm_user_record_get_display_id
(
user_record
);
}
purple_serv_got_chat_in
(
purple_account_get_connection
(
user
->
client_data
),
purple_chat_conversation_get_id
(
PURPLE_CHAT_CONVERSATION
(
chat
)),
name
,
PURPLE_MESSAGE_RECV
,
text
,
nm_event_get_gmt
(
event
));
}
}
}
g_free
(
text
);
}
static
void
_evt_conference_left
(
NMUser
*
user
,
NMEvent
*
event
)
{
PurpleChatConversation
*
chat
;
NMConference
*
conference
;
conference
=
nm_event_get_conference
(
event
);
if
(
conference
)
{
chat
=
nm_conference_get_data
(
conference
);
if
(
chat
)
{
NMUserRecord
*
ur
=
nm_find_user_record
(
user
,
nm_event_get_source
(
event
));
if
(
ur
)
purple_chat_conversation_remove_user
(
chat
,
nm_user_record_get_display_id
(
ur
),
NULL
);
}
}
}
static
void
_evt_conference_invite_notify
(
NMUser
*
user
,
NMEvent
*
event
)
{
PurpleConversation
*
gconv
;
NMConference
*
conference
;
NMUserRecord
*
user_record
=
NULL
;
char
*
str
=
NULL
;
user_record
=
nm_find_user_record
(
user
,
nm_event_get_source
(
event
));
conference
=
nm_event_get_conference
(
event
);
if
(
user_record
&&
conference
)
{
gconv
=
nm_conference_get_data
(
conference
);
str
=
g_strdup_printf
(
_
(
"%s has been invited to this conversation."
),
nm_user_record_get_display_id
(
user_record
));
purple_conversation_write_system_message
(
gconv
,
str
,
0
);
g_free
(
str
);
}
}
static
void
_evt_conference_invite
(
NMUser
*
user
,
NMEvent
*
event
)
{
NMUserRecord
*
ur
;
PurpleConnection
*
gc
;
GSList
*
parms
=
NULL
;
const
char
*
title
=
NULL
;
const
char
*
secondary
=
NULL
;
const
char
*
name
=
NULL
;
char
*
primary
=
NULL
;
time_t
gmt
;
ur
=
nm_find_user_record
(
user
,
nm_event_get_source
(
event
));
if
(
ur
)
name
=
nm_user_record_get_full_name
(
ur
);
if
(
name
==
NULL
)
name
=
nm_event_get_source
(
event
);
gmt
=
nm_event_get_gmt
(
event
);
title
=
_
(
"Invitation to Conversation"
);
primary
=
g_strdup_printf
(
_
(
"Invitation from: %s
\n\n
Sent: %s"
),
name
,
purple_date_format_full
(
localtime
(
&
gmt
)));
secondary
=
_
(
"Would you like to join the conversation?"
);
/* Set up parms list for the callbacks
* We need to send the NMUser object and
* the NMConference object to the callbacks
*/
parms
=
NULL
;
parms
=
g_slist_append
(
parms
,
user
);
parms
=
g_slist_append
(
parms
,
nm_event_get_conference
(
event
));
/* Prompt the user */
/* TODO: Would it be better to use purple_serv_got_chat_invite() here? */
gc
=
purple_account_get_connection
(
user
->
client_data
);
purple_request_action
(
gc
,
title
,
primary
,
secondary
,
PURPLE_DEFAULT_ACTION_NONE
,
purple_request_cpar_from_connection
(
gc
),
parms
,
2
,
_
(
"Yes"
),
G_CALLBACK
(
_join_conference_cb
),
_
(
"No"
),
G_CALLBACK
(
_reject_conference_cb
));
g_free
(
primary
);
}
static
void
_evt_conference_joined
(
NMUser
*
user
,
NMEvent
*
event
)
{
PurpleConversation
*
chat
=
NULL
;
PurpleConnection
*
gc
;
NMConference
*
conference
=
NULL
;
NMUserRecord
*
ur
=
NULL
;
const
char
*
name
;
const
char
*
conf_name
;
gc
=
purple_account_get_connection
(
user
->
client_data
);
if
(
gc
==
NULL
)
return
;
conference
=
nm_event_get_conference
(
event
);
if
(
conference
)
{
chat
=
nm_conference_get_data
(
conference
);
if
(
nm_conference_get_participant_count
(
conference
)
==
2
&&
chat
==
NULL
)
{
ur
=
nm_conference_get_participant
(
conference
,
0
);
if
(
ur
)
{
conf_name
=
_get_conference_name
(
++
user
->
conference_count
);
chat
=
purple_serv_got_joined_chat
(
gc
,
user
->
conference_count
,
conf_name
);
if
(
chat
)
{
nm_conference_set_data
(
conference
,
(
gpointer
)
chat
);
name
=
nm_user_record_get_display_id
(
ur
);
purple_chat_conversation_add_user
(
PURPLE_CHAT_CONVERSATION
(
chat
),
name
,
NULL
,
PURPLE_CHAT_USER_NONE
,
TRUE
);
}
}
}
if
(
chat
!=
NULL
)
{
ur
=
nm_find_user_record
(
user
,
nm_event_get_source
(
event
));
if
(
ur
)
{
name
=
nm_user_record_get_display_id
(
ur
);
if
(
!
purple_chat_conversation_has_user
(
PURPLE_CHAT_CONVERSATION
(
chat
),
name
))
{
purple_chat_conversation_add_user
(
PURPLE_CHAT_CONVERSATION
(
chat
),
name
,
NULL
,
PURPLE_CHAT_USER_NONE
,
TRUE
);
}
}
}
}
}
static
void
_evt_status_change
(
NMUser
*
user
,
NMEvent
*
event
)
{
PurpleBuddy
*
buddy
=
NULL
;
GSList
*
buddies
;
GSList
*
bnode
;
NMUserRecord
*
user_record
;
const
char
*
display_id
;
int
status
;
user_record
=
nm_event_get_user_record
(
event
);
if
(
user_record
)
{
/* Retrieve new status */
status
=
nm_user_record_get_status
(
user_record
);
/* Update status for buddy in all folders */
display_id
=
nm_user_record_get_display_id
(
user_record
);
buddies
=
purple_blist_find_buddies
(
user
->
client_data
,
display_id
);
for
(
bnode
=
buddies
;
bnode
;
bnode
=
bnode
->
next
)
{
buddy
=
(
PurpleBuddy
*
)
bnode
->
data
;
if
(
buddy
)
{
_update_buddy_status
(
user
,
buddy
,
status
,
nm_event_get_gmt
(
event
));
}
}
g_slist_free
(
buddies
);
}
}
static
void
_evt_user_disconnect
(
NMUser
*
user
,
NMEvent
*
event
)
{
PurpleConnection
*
gc
;
PurpleAccount
*
account
=
user
->
client_data
;
gc
=
purple_account_get_connection
(
account
);
if
(
gc
)
{
if
(
!
purple_account_get_remember_password
(
account
))
{
PurpleCredentialManager
*
manager
=
NULL
;
manager
=
purple_credential_manager_get_default
();
purple_credential_manager_clear_password_async
(
manager
,
account
,
NULL
,
NULL
,
NULL
);
}
purple_connection_error
(
gc
,
PURPLE_CONNECTION_ERROR_NAME_IN_USE
,
_
(
"You have signed on from another location"
));
}
}
static
void
_evt_user_typing
(
NMUser
*
user
,
NMEvent
*
event
)
{
PurpleConnection
*
gc
;
NMUserRecord
*
user_record
=
NULL
;
gc
=
purple_account_get_connection
((
PurpleAccount
*
)
user
->
client_data
);
if
(
gc
)
{
user_record
=
nm_find_user_record
(
user
,
nm_event_get_source
(
event
));
if
(
user_record
)
{
purple_serv_got_typing
(
gc
,
nm_user_record_get_display_id
(
user_record
),
30
,
PURPLE_IM_TYPING
);
}
}
}
static
void
_evt_user_not_typing
(
NMUser
*
user
,
NMEvent
*
event
)
{
PurpleConnection
*
gc
;
NMUserRecord
*
user_record
;
gc
=
purple_account_get_connection
((
PurpleAccount
*
)
user
->
client_data
);
if
(
gc
)
{
user_record
=
nm_find_user_record
(
user
,
nm_event_get_source
(
event
));
if
(
user_record
)
{
purple_serv_got_typing_stopped
(
gc
,
nm_user_record_get_display_id
(
user_record
));
}
}
}
static
void
_evt_undeliverable_status
(
NMUser
*
user
,
NMEvent
*
event
)
{
NMUserRecord
*
ur
;
PurpleConversation
*
gconv
;
char
*
str
;
ur
=
nm_find_user_record
(
user
,
nm_event_get_source
(
event
));
if
(
ur
)
{
PurpleConversationManager
*
manager
=
NULL
;
manager
=
purple_conversation_manager_get_default
();
/* XXX - Should this be PURPLE_CONV_TYPE_IM? */
gconv
=
purple_conversation_manager_find
(
manager
,
PURPLE_ACCOUNT
(
user
->
client_data
),
nm_user_record_get_display_id
(
ur
));
if
(
gconv
)
{
const
char
*
name
=
nm_user_record_get_full_name
(
ur
);
if
(
name
==
NULL
)
{
name
=
nm_user_record_get_display_id
(
ur
);
}
str
=
g_strdup_printf
(
_
(
"%s appears to be offline and did not receive"
" the message that you just sent."
),
name
);
purple_conversation_write_system_message
(
gconv
,
str
,
0
);
g_free
(
str
);
}
}
}
static
void
_event_callback
(
NMUser
*
user
,
NMEvent
*
event
)
{
if
(
user
==
NULL
||
event
==
NULL
)
return
;
switch
(
nm_event_get_type
(
event
))
{
case
NMEVT_STATUS_CHANGE
:
_evt_status_change
(
user
,
event
);
break
;
case
NMEVT_RECEIVE_AUTOREPLY
:
case
NMEVT_RECEIVE_MESSAGE
:
_evt_receive_message
(
user
,
event
);
break
;
case
NMEVT_USER_DISCONNECT
:
_evt_user_disconnect
(
user
,
event
);
break
;
case
NMEVT_USER_TYPING
:
_evt_user_typing
(
user
,
event
);
break
;
case
NMEVT_USER_NOT_TYPING
:
_evt_user_not_typing
(
user
,
event
);
break
;
case
NMEVT_SERVER_DISCONNECT
:
/* Nothing to do? */
break
;
case
NMEVT_INVALID_RECIPIENT
:
break
;
case
NMEVT_UNDELIVERABLE_STATUS
:
_evt_undeliverable_status
(
user
,
event
);
break
;
case
NMEVT_CONFERENCE_INVITE_NOTIFY
:
/* Someone else has been invited to join a
* conference that we are currently a part of
*/
_evt_conference_invite_notify
(
user
,
event
);
break
;
case
NMEVT_CONFERENCE_INVITE
:
/* We have been invited to join a conference */
_evt_conference_invite
(
user
,
event
);
break
;
case
NMEVT_CONFERENCE_JOINED
:
/* Some one has joined a conference that we
* are a part of
*/
_evt_conference_joined
(
user
,
event
);
break
;
case
NMEVT_CONFERENCE_LEFT
:
/* Someone else has left a conference that we
* are currently a part of
*/
_evt_conference_left
(
user
,
event
);
break
;
default
:
purple_debug_info
(
"novell"
,
"_event_callback(): unhandled event, %d"
,
nm_event_get_type
(
event
));
break
;
}
}
/*******************************************************************************
* Protocol Ops
******************************************************************************/
static
void
novell_login
(
PurpleAccount
*
account
)
{
PurpleConnection
*
gc
;
NMUser
*
user
=
NULL
;
const
char
*
server
;
const
char
*
name
;
int
port
;
GError
*
error
=
NULL
;
if
(
account
==
NULL
)
return
;
gc
=
purple_account_get_connection
(
account
);
if
(
gc
==
NULL
)
return
;
purple_connection_set_flags
(
gc
,
PURPLE_CONNECTION_FLAG_NO_IMAGES
);
server
=
purple_account_get_string
(
account
,
"server"
,
NULL
);
if
(
server
==
NULL
||
*
server
==
'\0'
)
{
/* TODO: Would be nice to prompt if not set!
* purple_request_fields(gc, _("Server Address"),...);
*/
/* ...but for now just error out with a nice message. */
purple_connection_error
(
gc
,
PURPLE_CONNECTION_ERROR_INVALID_SETTINGS
,
_
(
"Unable to connect to server. Please enter the "
"address of the server to which you wish to connect."
));
return
;
}
port
=
purple_account_get_int
(
account
,
"port"
,
DEFAULT_PORT
);
name
=
purple_account_get_username
(
account
);
user
=
nm_initialize_user
(
name
,
server
,
port
,
account
,
_event_callback
);
if
(
user
&&
user
->
conn
)
{
/* save user */
purple_connection_set_protocol_data
(
gc
,
user
);
/* connect to the server */
purple_connection_update_progress
(
gc
,
_
(
"Connecting"
),
1
,
NOVELL_CONNECT_STEPS
);
user
->
conn
->
client
=
purple_gio_socket_client_new
(
account
,
&
error
);
if
(
user
->
conn
->
client
==
NULL
)
{
purple_connection_take_error
(
gc
,
error
);
return
;
}
g_socket_client_set_tls
(
user
->
conn
->
client
,
TRUE
);
g_socket_client_connect_to_host_async
(
user
->
conn
->
client
,
user
->
conn
->
addr
,
user
->
conn
->
port
,
user
->
cancellable
,
novell_login_callback
,
gc
);
}
}
static
void
novell_close
(
PurpleConnection
*
gc
)
{
NMUser
*
user
;
NMConn
*
conn
;
if
(
gc
==
NULL
)
return
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
)
{
conn
=
user
->
conn
;
if
(
conn
)
{
nm_release_conn
(
conn
);
}
nm_deinitialize_user
(
user
);
}
purple_connection_set_protocol_data
(
gc
,
NULL
);
}
static
int
novell_send_im
(
PurpleProtocolIM
*
im
,
PurpleConnection
*
gc
,
PurpleMessage
*
msg
)
{
NMUserRecord
*
user_record
=
NULL
;
NMConference
*
conf
=
NULL
;
NMMessage
*
message
;
NMUser
*
user
;
const
char
*
dn
=
NULL
;
char
*
plain
;
gboolean
done
=
TRUE
,
created_conf
=
FALSE
;
NMERR_T
rc
=
NM_OK
;
const
gchar
*
name
=
purple_message_get_recipient
(
msg
);
if
(
gc
==
NULL
||
name
==
NULL
||
purple_message_is_empty
(
msg
))
return
0
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
==
NULL
)
return
0
;
/* Create a new message */
plain
=
purple_unescape_html
(
purple_message_get_contents
(
msg
));
message
=
nm_create_message
(
plain
);
g_free
(
plain
);
/* Need to get the DN for the buddy so we can look up the convo */
dn
=
nm_lookup_dn
(
user
,
name
);
/* Do we already know about the sender? */
user_record
=
nm_find_user_record
(
user
,
dn
);
if
(
user_record
)
{
/* Do we already have an instantiated conference? */
conf
=
nm_find_conversation
(
user
,
dn
);
if
(
conf
==
NULL
)
{
/* If not, create a blank conference */
conf
=
nm_create_conference
(
NULL
);
created_conf
=
TRUE
;
nm_conference_add_participant
(
conf
,
user_record
);
}
nm_message_set_conference
(
message
,
conf
);
/* Make sure conference is instantiated */
if
(
!
nm_conference_is_instantiated
(
conf
))
{
/* It is not, so send the createconf. We will
* have to finish sending the message when we
* get the response with the new conference guid.
*/
rc
=
nm_send_create_conference
(
user
,
conf
,
_createconf_resp_send_msg
,
message
);
_check_for_disconnect
(
user
,
rc
);
done
=
FALSE
;
}
}
else
{
/* If we don't have details for the user, then we don't have
* a conference yet. So create one and send the getdetails
* to the server. We will have to finish sending the message
* when we get the response from the server.
*/
conf
=
nm_create_conference
(
NULL
);
created_conf
=
TRUE
;
nm_message_set_conference
(
message
,
conf
);
rc
=
nm_send_get_details
(
user
,
name
,
_get_details_resp_send_msg
,
message
);
_check_for_disconnect
(
user
,
rc
);
done
=
FALSE
;
}
if
(
done
)
{
/* Did we find everything we needed? */
rc
=
nm_send_message
(
user
,
message
,
_send_message_resp_cb
);
_check_for_disconnect
(
user
,
rc
);
nm_release_message
(
message
);
}
if
(
created_conf
&&
conf
)
nm_release_conference
(
conf
);
return
1
;
}
static
unsigned
int
novell_send_typing
(
PurpleProtocolIM
*
im
,
PurpleConnection
*
gc
,
const
char
*
name
,
PurpleIMTypingState
state
)
{
NMConference
*
conf
=
NULL
;
NMUser
*
user
;
const
char
*
dn
=
NULL
;
NMERR_T
rc
=
NM_OK
;
if
(
gc
==
NULL
||
name
==
NULL
)
return
0
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
==
NULL
)
return
0
;
/* Need to get the DN for the buddy so we can look up the convo */
dn
=
nm_lookup_dn
(
user
,
name
);
if
(
dn
)
{
/* Now find the conference in our list */
conf
=
nm_find_conversation
(
user
,
dn
);
if
(
conf
)
{
rc
=
nm_send_typing
(
user
,
conf
,
((
state
==
PURPLE_IM_TYPING
)
?
TRUE
:
FALSE
),
NULL
);
_check_for_disconnect
(
user
,
rc
);
}
}
return
0
;
}
static
void
novell_convo_closed
(
PurpleProtocolClient
*
client
,
PurpleConnection
*
gc
,
const
char
*
who
)
{
NMUser
*
user
;
NMConference
*
conf
;
const
char
*
dn
;
NMERR_T
rc
=
NM_OK
;
if
(
gc
==
NULL
||
who
==
NULL
)
return
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
&&
(
dn
=
nm_lookup_dn
(
user
,
who
)))
{
conf
=
nm_find_conversation
(
user
,
dn
);
if
(
conf
)
{
rc
=
nm_send_leave_conference
(
user
,
conf
,
NULL
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
}
}
}
static
void
novell_chat_leave
(
PurpleProtocolChat
*
protocol_chat
,
PurpleConnection
*
gc
,
gint
id
)
{
NMConference
*
conference
;
NMUser
*
user
;
PurpleChatConversation
*
chat
;
GSList
*
cnode
;
NMERR_T
rc
=
NM_OK
;
if
(
gc
==
NULL
)
return
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
==
NULL
)
return
;
for
(
cnode
=
user
->
conferences
;
cnode
!=
NULL
;
cnode
=
cnode
->
next
)
{
conference
=
cnode
->
data
;
if
(
conference
&&
(
chat
=
nm_conference_get_data
(
conference
)))
{
if
(
purple_chat_conversation_get_id
(
chat
)
==
id
)
{
rc
=
nm_send_leave_conference
(
user
,
conference
,
NULL
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
break
;
}
}
}
purple_serv_got_chat_left
(
gc
,
id
);
}
static
void
novell_chat_invite
(
PurpleProtocolChat
*
protocol_chat
,
PurpleConnection
*
gc
,
gint
id
,
const
gchar
*
message
,
const
gchar
*
who
)
{
NMConference
*
conference
;
NMUser
*
user
;
PurpleChatConversation
*
chat
;
GSList
*
cnode
;
NMERR_T
rc
=
NM_OK
;
NMUserRecord
*
user_record
=
NULL
;
if
(
gc
==
NULL
)
return
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
==
NULL
)
return
;
user_record
=
nm_find_user_record
(
user
,
who
);
if
(
user_record
==
NULL
)
{
rc
=
nm_send_get_details
(
user
,
who
,
_get_details_resp_send_invite
,
GINT_TO_POINTER
(
id
));
_check_for_disconnect
(
user
,
rc
);
return
;
}
for
(
cnode
=
user
->
conferences
;
cnode
!=
NULL
;
cnode
=
cnode
->
next
)
{
conference
=
cnode
->
data
;
if
(
conference
&&
(
chat
=
nm_conference_get_data
(
conference
)))
{
if
(
purple_chat_conversation_get_id
(
chat
)
==
id
)
{
rc
=
nm_send_conference_invite
(
user
,
conference
,
user_record
,
message
,
_sendinvite_resp_cb
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
break
;
}
}
}
}
static
gint
novell_chat_send
(
PurpleProtocolChat
*
protocol_chat
,
PurpleConnection
*
gc
,
gint
id
,
PurpleMessage
*
msg
)
{
NMConference
*
conference
;
PurpleConversation
*
chat
;
PurpleConversationManager
*
manager
=
NULL
;
GSList
*
cnode
;
NMMessage
*
message
;
NMUser
*
user
;
NMERR_T
rc
=
NM_OK
;
const
char
*
name
;
char
*
str
,
*
plain
;
if
(
gc
==
NULL
||
purple_message_is_empty
(
msg
))
return
-1
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
==
NULL
)
return
-1
;
plain
=
purple_unescape_html
(
purple_message_get_contents
(
msg
));
message
=
nm_create_message
(
plain
);
g_free
(
plain
);
for
(
cnode
=
user
->
conferences
;
cnode
!=
NULL
;
cnode
=
cnode
->
next
)
{
conference
=
cnode
->
data
;
if
(
conference
&&
(
chat
=
nm_conference_get_data
(
conference
)))
{
if
(
purple_chat_conversation_get_id
(
PURPLE_CHAT_CONVERSATION
(
chat
))
==
id
)
{
nm_message_set_conference
(
message
,
conference
);
/* check to see if the conference is instatiated yet */
if
(
!
nm_conference_is_instantiated
(
conference
))
{
nm_message_add_ref
(
message
);
nm_send_create_conference
(
user
,
conference
,
_createconf_resp_send_msg
,
message
);
}
else
{
rc
=
nm_send_message
(
user
,
message
,
_send_message_resp_cb
);
}
nm_release_message
(
message
);
if
(
!
_check_for_disconnect
(
user
,
rc
))
{
/* Use the account alias if it is set */
name
=
purple_account_get_private_alias
(
user
->
client_data
);
if
(
name
==
NULL
||
*
name
==
'\0'
)
{
/* If there is no account alias, try full name */
name
=
nm_user_record_get_full_name
(
user
->
user_record
);
if
(
name
==
NULL
||
*
name
==
'\0'
)
{
/* Fall back to the username that we are signed in with */
name
=
purple_account_get_username
(
user
->
client_data
);
}
}
purple_serv_got_chat_in
(
gc
,
id
,
name
,
purple_message_get_flags
(
msg
),
purple_message_get_contents
(
msg
),
time
(
NULL
));
return
0
;
}
else
return
-1
;
}
}
}
manager
=
purple_conversation_manager_get_default
();
/* The conference was not found, must be closed */
chat
=
purple_conversation_manager_find_chat_by_id
(
manager
,
purple_connection_get_account
(
gc
),
id
);
if
(
chat
)
{
str
=
g_strdup
(
_
(
"This conference has been closed."
" No more messages can be sent."
));
purple_conversation_write_system_message
(
chat
,
str
,
0
);
g_free
(
str
);
}
if
(
message
)
nm_release_message
(
message
);
return
-1
;
}
static
void
novell_add_buddy
(
PurpleProtocolServer
*
protocol_server
,
PurpleConnection
*
gc
,
PurpleBuddy
*
buddy
,
PurpleGroup
*
group
,
const
gchar
*
message
)
{
NMFolder
*
folder
=
NULL
;
NMContact
*
contact
;
NMUser
*
user
;
NMERR_T
rc
=
NM_OK
;
const
char
*
alias
,
*
gname
,
*
bname
;
if
(
gc
==
NULL
||
buddy
==
NULL
||
group
==
NULL
)
return
;
user
=
(
NMUser
*
)
purple_connection_get_protocol_data
(
gc
);
if
(
user
==
NULL
)
return
;
/* If we haven't synched the contact list yet, ignore
* the add_buddy calls. Server side list is the master.
*/
if
(
!
user
->
clist_synched
)
return
;
/* Don't re-add a buddy that is already on our contact list */
if
(
nm_find_user_record
(
user
,
purple_buddy_get_name
(
buddy
))
!=
NULL
)
return
;
contact
=
nm_create_contact
();
nm_contact_set_dn
(
contact
,
purple_buddy_get_name
(
buddy
));
/* Remove the PurpleBuddy (we will add it back after adding it
* to the server side list). Save the alias if there is one.
*/
alias
=
purple_buddy_get_alias
(
buddy
);
bname
=
purple_buddy_get_name
(
buddy
);
if
(
alias
&&
!
purple_strequal
(
alias
,
bname
))
nm_contact_set_display_name
(
contact
,
alias
);
purple_blist_remove_buddy
(
buddy
);
buddy
=
NULL
;
gname
=
purple_group_get_name
(
group
);
if
(
purple_strequal
(
gname
,
NM_ROOT_FOLDER_NAME
))
{
gname
=
""
;
}
folder
=
nm_find_folder
(
user
,
gname
);
if
(
folder
)
{
/* We have everything that we need, so send the createcontact */
rc
=
nm_send_create_contact
(
user
,
folder
,
contact
,
_create_contact_resp_cb
,
contact
);
}
else
{
/* Need to create the folder before we can add the contact */
rc
=
nm_send_create_folder
(
user
,
gname
,
_create_folder_resp_add_contact
,
contact
);
}
_check_for_disconnect
(
user
,
rc
);
}
static
void
novell_remove_buddy
(
PurpleProtocolServer
*
protocol_server
,
PurpleConnection
*
gc
,
PurpleBuddy
*
buddy
,
PurpleGroup
*
group
)
{
NMContact
*
contact
;
NMFolder
*
folder
;
NMUser
*
user
;
const
char
*
dn
,
*
gname
;
NMERR_T
rc
=
NM_OK
;
if
(
gc
==
NULL
||
buddy
==
NULL
||
group
==
NULL
)
return
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
&&
(
dn
=
nm_lookup_dn
(
user
,
purple_buddy_get_name
(
buddy
))))
{
gname
=
purple_group_get_name
(
group
);
if
(
purple_strequal
(
gname
,
NM_ROOT_FOLDER_NAME
))
{
gname
=
""
;
}
folder
=
nm_find_folder
(
user
,
gname
);
if
(
folder
)
{
contact
=
nm_folder_find_contact
(
folder
,
dn
);
if
(
contact
)
{
/* Remove the buddy from the contact */
nm_contact_set_data
(
contact
,
NULL
);
/* Tell the server to remove the contact */
rc
=
nm_send_remove_contact
(
user
,
folder
,
contact
,
_remove_contact_resp_cb
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
}
}
}
}
static
void
novell_remove_group
(
PurpleProtocolServer
*
protocol_server
,
PurpleConnection
*
gc
,
PurpleGroup
*
group
)
{
NMUser
*
user
;
NMERR_T
rc
=
NM_OK
;
if
(
gc
==
NULL
||
group
==
NULL
)
return
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
)
{
NMFolder
*
folder
=
nm_find_folder
(
user
,
purple_group_get_name
(
group
));
if
(
folder
)
{
rc
=
nm_send_remove_folder
(
user
,
folder
,
_remove_folder_resp_cb
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
}
}
}
static
void
novell_alias_buddy
(
PurpleProtocolServer
*
protocol_server
,
PurpleConnection
*
gc
,
const
gchar
*
name
,
const
gchar
*
alias
)
{
NMContact
*
contact
;
NMUser
*
user
;
GList
*
contacts
=
NULL
;
GList
*
cnode
=
NULL
;
const
char
*
dn
=
NULL
,
*
fname
=
NULL
;
NMERR_T
rc
=
NM_OK
;
if
(
gc
==
NULL
||
name
==
NULL
||
alias
==
NULL
)
return
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
&&
(
dn
=
nm_lookup_dn
(
user
,
name
)))
{
/* Alias all of instances of the contact */
contacts
=
nm_find_contacts
(
user
,
dn
);
for
(
cnode
=
contacts
;
cnode
!=
NULL
;
cnode
=
cnode
->
next
)
{
contact
=
(
NMContact
*
)
cnode
->
data
;
if
(
contact
)
{
PurpleGroup
*
group
=
NULL
;
PurpleBuddy
*
buddy
;
NMFolder
*
folder
;
/* Alias the Purple buddy? */
folder
=
nm_find_folder_by_id
(
user
,
nm_contact_get_parent_id
(
contact
));
if
(
folder
)
{
fname
=
nm_folder_get_name
(
folder
);
if
(
*
fname
==
'\0'
)
{
fname
=
NM_ROOT_FOLDER_NAME
;
}
group
=
purple_blist_find_group
(
fname
);
}
if
(
group
)
{
const
char
*
balias
;
buddy
=
purple_blist_find_buddy_in_group
(
user
->
client_data
,
name
,
group
);
balias
=
buddy
?
purple_buddy_get_local_alias
(
buddy
)
:
NULL
;
if
(
balias
&&
!
purple_strequal
(
balias
,
alias
))
purple_buddy_set_local_alias
(
buddy
,
alias
);
}
/* Tell the server to alias the contact */
rc
=
nm_send_rename_contact
(
user
,
contact
,
alias
,
_rename_contact_resp_cb
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
}
}
if
(
contacts
)
g_list_free
(
contacts
);
}
}
static
void
novell_group_buddy
(
PurpleProtocolServer
*
protocol_server
,
PurpleConnection
*
gc
,
const
gchar
*
name
,
const
gchar
*
old_group_name
,
const
gchar
*
new_group_name
)
{
NMFolder
*
old_folder
;
NMFolder
*
new_folder
;
NMContact
*
contact
;
NMUser
*
user
;
const
char
*
dn
;
NMERR_T
rc
=
NM_OK
;
if
(
gc
==
NULL
||
name
==
NULL
||
old_group_name
==
NULL
||
new_group_name
==
NULL
)
return
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
&&
(
dn
=
nm_lookup_dn
(
user
,
name
)))
{
/* Find the old folder */
if
(
purple_strequal
(
old_group_name
,
NM_ROOT_FOLDER_NAME
))
{
old_folder
=
nm_get_root_folder
(
user
);
if
(
nm_folder_find_contact
(
old_folder
,
dn
)
==
NULL
)
old_folder
=
nm_find_folder
(
user
,
old_group_name
);
}
else
{
old_folder
=
nm_find_folder
(
user
,
old_group_name
);
}
if
(
old_folder
&&
(
contact
=
nm_folder_find_contact
(
old_folder
,
dn
)))
{
/* Find the new folder */
new_folder
=
nm_find_folder
(
user
,
new_group_name
);
if
(
new_folder
==
NULL
)
{
if
(
purple_strequal
(
new_group_name
,
NM_ROOT_FOLDER_NAME
))
new_folder
=
nm_get_root_folder
(
user
);
}
if
(
new_folder
)
{
/* Tell the server to move the contact to the new folder */
rc
=
nm_send_move_contact
(
user
,
contact
,
new_folder
,
_move_contact_resp_cb
,
NULL
);
}
else
{
nm_contact_add_ref
(
contact
);
/* Remove the old contact first */
nm_send_remove_contact
(
user
,
old_folder
,
contact
,
_remove_contact_resp_cb
,
NULL
);
/* New folder does not exist yet, so create it */
rc
=
nm_send_create_folder
(
user
,
new_group_name
,
_create_folder_resp_move_contact
,
contact
);
}
_check_for_disconnect
(
user
,
rc
);
}
}
}
static
void
novell_rename_group
(
PurpleProtocolServer
*
protocol_server
,
PurpleConnection
*
gc
,
const
gchar
*
old_name
,
PurpleGroup
*
group
,
GList
*
moved_buddies
)
{
NMERR_T
rc
=
NM_OK
;
NMFolder
*
folder
;
NMUser
*
user
;
if
(
gc
==
NULL
||
old_name
==
NULL
||
group
==
NULL
||
moved_buddies
==
NULL
)
{
return
;
}
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
)
{
const
char
*
gname
=
purple_group_get_name
(
group
);
/* Does new folder exist already? */
if
(
nm_find_folder
(
user
,
gname
))
{
/* purple_group_set_name() adds the buddies
* to the new group and removes the old group...
* so there is nothing more to do here.
*/
return
;
}
if
(
purple_strequal
(
old_name
,
NM_ROOT_FOLDER_NAME
))
{
/* Can't rename the root folder ... need to revisit this */
return
;
}
folder
=
nm_find_folder
(
user
,
old_name
);
if
(
folder
)
{
rc
=
nm_send_rename_folder
(
user
,
folder
,
gname
,
_rename_folder_resp_cb
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
}
}
}
static
const
char
*
novell_list_icon
(
PurpleAccount
*
account
,
PurpleBuddy
*
buddy
)
{
return
"novell"
;
}
static
GList
*
novell_protocol_get_account_options
(
PurpleProtocol
*
protocol
)
{
PurpleAccountOption
*
option
;
GList
*
opts
=
NULL
;
option
=
purple_account_option_string_new
(
_
(
"Server address"
),
"server"
,
NULL
);
opts
=
g_list_append
(
opts
,
option
);
option
=
purple_account_option_int_new
(
_
(
"Server port"
),
"port"
,
DEFAULT_PORT
);
opts
=
g_list_append
(
opts
,
option
);
return
opts
;
}
static
void
novell_tooltip_text
(
PurpleProtocolClient
*
client
,
PurpleBuddy
*
buddy
,
PurpleNotifyUserInfo
*
user_info
,
gboolean
full
)
{
NMUserRecord
*
user_record
=
NULL
;
PurpleConnection
*
gc
;
NMUser
*
user
;
int
status
=
0
;
const
char
*
status_str
=
NULL
;
const
char
*
text
=
NULL
;
if
(
buddy
==
NULL
)
return
;
gc
=
purple_account_get_connection
(
purple_buddy_get_account
(
buddy
));
if
(
gc
==
NULL
||
(
user
=
purple_connection_get_protocol_data
(
gc
))
==
NULL
)
return
;
if
(
PURPLE_BUDDY_IS_ONLINE
(
buddy
))
{
user_record
=
nm_find_user_record
(
user
,
purple_buddy_get_name
(
buddy
));
if
(
user_record
)
{
status
=
nm_user_record_get_status
(
user_record
);
text
=
nm_user_record_get_status_text
(
user_record
);
/* No custom text, so default it ... */
switch
(
status
)
{
case
NM_STATUS_AVAILABLE
:
status_str
=
_
(
"Available"
);
break
;
case
NM_STATUS_AWAY
:
status_str
=
_
(
"Away"
);
break
;
case
NM_STATUS_BUSY
:
status_str
=
_
(
"Busy"
);
break
;
case
NM_STATUS_AWAY_IDLE
:
status_str
=
_
(
"Idle"
);
break
;
case
NM_STATUS_OFFLINE
:
status_str
=
_
(
"Offline"
);
break
;
default
:
status_str
=
_
(
"Unknown"
);
break
;
}
purple_notify_user_info_add_pair_plaintext
(
user_info
,
_
(
"Status"
),
status_str
);
if
(
text
)
{
/* TODO: Check whether it's correct to call add_pair_html,
or if we should be using add_pair_plaintext */
purple_notify_user_info_add_pair_html
(
user_info
,
_
(
"Message"
),
text
);
}
}
}
}
static
void
novell_set_idle
(
PurpleProtocolServer
*
protocol_server
,
PurpleConnection
*
gc
,
gint
time
)
{
NMUser
*
user
;
NMERR_T
rc
=
NM_OK
;
const
char
*
id
=
NULL
;
PurpleStatus
*
status
=
NULL
;
if
(
gc
==
NULL
)
return
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
==
NULL
)
return
;
status
=
purple_account_get_active_status
(
purple_connection_get_account
(
gc
));
id
=
purple_status_get_id
(
status
);
/* Only go idle if active status is available */
if
(
purple_strequal
(
id
,
NOVELL_STATUS_TYPE_AVAILABLE
))
{
if
(
time
>
0
)
{
rc
=
nm_send_set_status
(
user
,
NM_STATUS_AWAY_IDLE
,
NULL
,
NULL
,
NULL
,
NULL
);
}
else
{
rc
=
nm_send_set_status
(
user
,
NM_STATUS_AVAILABLE
,
NULL
,
NULL
,
NULL
,
NULL
);
}
}
_check_for_disconnect
(
user
,
rc
);
}
static
void
novell_get_info
(
PurpleProtocolServer
*
protocol_server
,
PurpleConnection
*
gc
,
const
gchar
*
name
)
{
NMUserRecord
*
user_record
;
NMUser
*
user
;
NMERR_T
rc
;
if
(
gc
==
NULL
||
name
==
NULL
)
return
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
)
{
user_record
=
nm_find_user_record
(
user
,
name
);
if
(
user_record
)
{
_show_info
(
gc
,
user_record
,
g_strdup
(
name
));
}
else
{
rc
=
nm_send_get_details
(
user
,
name
,
_get_details_resp_show_info
,
g_strdup
(
name
));
_check_for_disconnect
(
user
,
rc
);
}
}
}
static
char
*
novell_status_text
(
PurpleProtocolClient
*
client
,
PurpleBuddy
*
buddy
)
{
const
char
*
text
=
NULL
;
const
char
*
dn
=
NULL
;
PurpleAccount
*
account
;
account
=
buddy
?
purple_buddy_get_account
(
buddy
)
:
NULL
;
if
(
buddy
&&
account
)
{
PurpleConnection
*
gc
=
purple_account_get_connection
(
account
);
if
(
gc
)
{
NMUser
*
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
)
{
dn
=
nm_lookup_dn
(
user
,
purple_buddy_get_name
(
buddy
));
if
(
dn
)
{
NMUserRecord
*
user_record
=
nm_find_user_record
(
user
,
dn
);
if
(
user_record
)
{
text
=
nm_user_record_get_status_text
(
user_record
);
if
(
text
)
return
g_strdup
(
text
);
}
}
}
}
}
return
NULL
;
}
static
GList
*
novell_status_types
(
PurpleAccount
*
account
)
{
GList
*
status_types
=
NULL
;
PurpleStatusType
*
type
;
g_return_val_if_fail
(
account
!=
NULL
,
NULL
);
type
=
purple_status_type_new_with_attrs
(
PURPLE_STATUS_AVAILABLE
,
NOVELL_STATUS_TYPE_AVAILABLE
,
NULL
,
TRUE
,
TRUE
,
FALSE
,
"message"
,
_
(
"Message"
),
purple_value_new
(
G_TYPE_STRING
),
NULL
);
status_types
=
g_list_append
(
status_types
,
type
);
type
=
purple_status_type_new_with_attrs
(
PURPLE_STATUS_AWAY
,
NOVELL_STATUS_TYPE_AWAY
,
NULL
,
TRUE
,
TRUE
,
FALSE
,
"message"
,
_
(
"Message"
),
purple_value_new
(
G_TYPE_STRING
),
NULL
);
status_types
=
g_list_append
(
status_types
,
type
);
type
=
purple_status_type_new_with_attrs
(
PURPLE_STATUS_UNAVAILABLE
,
NOVELL_STATUS_TYPE_BUSY
,
_
(
"Busy"
),
TRUE
,
TRUE
,
FALSE
,
"message"
,
_
(
"Message"
),
purple_value_new
(
G_TYPE_STRING
),
NULL
);
status_types
=
g_list_append
(
status_types
,
type
);
type
=
purple_status_type_new_full
(
PURPLE_STATUS_INVISIBLE
,
NOVELL_STATUS_TYPE_APPEAR_OFFLINE
,
NULL
,
TRUE
,
TRUE
,
FALSE
);
status_types
=
g_list_append
(
status_types
,
type
);
type
=
purple_status_type_new_full
(
PURPLE_STATUS_OFFLINE
,
NULL
,
NULL
,
TRUE
,
TRUE
,
FALSE
);
status_types
=
g_list_append
(
status_types
,
type
);
return
status_types
;
}
static
void
novell_set_status
(
PurpleProtocolServer
*
protocol_server
,
PurpleAccount
*
account
,
PurpleStatus
*
status
)
{
PurpleConnection
*
gc
;
gboolean
connected
;
PurplePresence
*
presence
;
PurpleStatusType
*
type
;
PurpleStatusPrimitive
primitive
;
NMUser
*
user
;
NMSTATUS_T
novellstatus
=
NM_STATUS_AVAILABLE
;
NMERR_T
rc
=
NM_OK
;
const
char
*
msg
=
NULL
;
char
*
text
=
NULL
;
connected
=
purple_account_is_connected
(
account
);
presence
=
purple_status_get_presence
(
status
);
type
=
purple_status_get_status_type
(
status
);
primitive
=
purple_status_type_get_primitive
(
type
);
/*
* We don't have any independent statuses, so we don't need to
* do anything when a status is deactivated (because another
* status is about to be activated).
*/
if
(
!
purple_status_is_active
(
status
))
return
;
if
(
!
connected
)
return
;
gc
=
purple_account_get_connection
(
account
);
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
==
NULL
)
return
;
if
(
primitive
==
PURPLE_STATUS_AVAILABLE
)
{
novellstatus
=
NM_STATUS_AVAILABLE
;
}
else
if
(
primitive
==
PURPLE_STATUS_AWAY
)
{
novellstatus
=
NM_STATUS_AWAY
;
}
else
if
(
primitive
==
PURPLE_STATUS_UNAVAILABLE
)
{
novellstatus
=
NM_STATUS_BUSY
;
}
else
if
(
primitive
==
PURPLE_STATUS_INVISIBLE
)
{
novellstatus
=
NM_STATUS_OFFLINE
;
}
else
if
(
purple_presence_is_idle
(
presence
))
{
novellstatus
=
NM_STATUS_AWAY_IDLE
;
}
else
{
novellstatus
=
NM_STATUS_AVAILABLE
;
}
if
(
primitive
==
PURPLE_STATUS_AWAY
||
primitive
==
PURPLE_STATUS_AVAILABLE
||
primitive
==
PURPLE_STATUS_UNAVAILABLE
)
{
msg
=
purple_status_get_attr_string
(
status
,
"message"
);
text
=
g_strdup
(
msg
);
if
(
primitive
==
PURPLE_STATUS_AVAILABLE
)
msg
=
NULL
;
/* no auto replies for online status */
/* Don't want newlines in status text */
purple_util_chrreplace
(
text
,
'\n'
,
' '
);
}
rc
=
nm_send_set_status
(
user
,
novellstatus
,
text
,
msg
,
NULL
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
g_free
(
text
);
}
static
void
novell_add_permit
(
PurpleProtocolPrivacy
*
privacy
,
PurpleConnection
*
gc
,
const
char
*
who
)
{
NMUser
*
user
;
NMERR_T
rc
=
NM_OK
;
const
char
*
name
=
who
;
if
(
gc
==
NULL
||
who
==
NULL
)
return
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
==
NULL
)
return
;
/* Remove first -- we will add it back in when we get
* the okay from the server
*/
purple_account_privacy_permit_remove
(
purple_connection_get_account
(
gc
),
who
,
TRUE
);
if
(
nm_user_is_privacy_locked
(
user
))
{
_show_privacy_locked_error
(
gc
,
user
);
_sync_privacy_lists
(
user
);
return
;
}
/* Work around for problem with un-typed, dotted contexts */
if
(
strchr
(
who
,
'.'
))
{
const
char
*
dn
=
nm_lookup_dn
(
user
,
who
);
if
(
dn
==
NULL
)
{
rc
=
nm_send_get_details
(
user
,
who
,
_get_details_send_privacy_create
,
GINT_TO_POINTER
(
TRUE
));
_check_for_disconnect
(
user
,
rc
);
return
;
}
else
{
name
=
dn
;
}
}
rc
=
nm_send_create_privacy_item
(
user
,
name
,
TRUE
,
_create_privacy_item_permit_resp_cb
,
g_strdup
(
who
));
_check_for_disconnect
(
user
,
rc
);
}
static
void
novell_add_deny
(
PurpleProtocolPrivacy
*
privacy
,
PurpleConnection
*
gc
,
const
char
*
who
)
{
NMUser
*
user
;
NMERR_T
rc
=
NM_OK
;
const
char
*
name
=
who
;
if
(
gc
==
NULL
||
who
==
NULL
)
return
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
==
NULL
)
return
;
/* Remove first -- we will add it back in when we get
* the okay from the server
*/
purple_account_privacy_deny_remove
(
purple_connection_get_account
(
gc
),
who
,
TRUE
);
if
(
nm_user_is_privacy_locked
(
user
))
{
_show_privacy_locked_error
(
gc
,
user
);
_sync_privacy_lists
(
user
);
return
;
}
/* Work around for problem with un-typed, dotted contexts */
if
(
strchr
(
who
,
'.'
))
{
const
char
*
dn
=
nm_lookup_dn
(
user
,
who
);
if
(
dn
==
NULL
)
{
rc
=
nm_send_get_details
(
user
,
who
,
_get_details_send_privacy_create
,
GINT_TO_POINTER
(
FALSE
));
_check_for_disconnect
(
user
,
rc
);
return
;
}
else
{
name
=
dn
;
}
}
rc
=
nm_send_create_privacy_item
(
user
,
name
,
FALSE
,
_create_privacy_item_deny_resp_cb
,
g_strdup
(
who
));
_check_for_disconnect
(
user
,
rc
);
}
static
void
novell_remove_permit
(
PurpleProtocolPrivacy
*
privacy
,
PurpleConnection
*
gc
,
const
char
*
who
)
{
NMUser
*
user
;
NMERR_T
rc
=
NM_OK
;
const
char
*
dn
=
NULL
;
if
(
gc
==
NULL
||
who
==
NULL
)
return
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
==
NULL
)
return
;
if
(
nm_user_is_privacy_locked
(
user
))
{
_show_privacy_locked_error
(
gc
,
user
);
_sync_privacy_lists
(
user
);
return
;
}
dn
=
nm_lookup_dn
(
user
,
who
);
if
(
dn
==
NULL
)
dn
=
who
;
rc
=
nm_send_remove_privacy_item
(
user
,
dn
,
TRUE
,
_remove_privacy_item_resp_cb
,
g_strdup
(
who
));
_check_for_disconnect
(
user
,
rc
);
}
static
void
novell_remove_deny
(
PurpleProtocolPrivacy
*
privacy
,
PurpleConnection
*
gc
,
const
char
*
who
)
{
NMUser
*
user
;
NMERR_T
rc
=
NM_OK
;
const
char
*
dn
=
NULL
;
if
(
gc
==
NULL
||
who
==
NULL
)
return
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
==
NULL
)
return
;
if
(
nm_user_is_privacy_locked
(
user
))
{
_show_privacy_locked_error
(
gc
,
user
);
_sync_privacy_lists
(
user
);
return
;
}
dn
=
nm_lookup_dn
(
user
,
who
);
if
(
dn
==
NULL
)
dn
=
who
;
rc
=
nm_send_remove_privacy_item
(
user
,
dn
,
FALSE
,
_remove_privacy_item_resp_cb
,
g_strdup
(
who
));
_check_for_disconnect
(
user
,
rc
);
}
static
void
novell_set_permit_deny
(
PurpleProtocolPrivacy
*
privacy
,
PurpleConnection
*
gc
)
{
NMERR_T
rc
=
NM_OK
;
const
char
*
dn
,
*
name
=
NULL
;
NMUserRecord
*
user_record
=
NULL
;
GSList
*
node
=
NULL
,
*
copy
=
NULL
;
NMUser
*
user
;
int
i
,
j
,
num_contacts
,
num_folders
;
NMContact
*
contact
;
NMFolder
*
folder
=
NULL
;
PurpleAccount
*
account
;
if
(
gc
==
NULL
)
return
;
account
=
purple_connection_get_account
(
gc
);
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
==
NULL
)
return
;
if
(
user
->
privacy_synched
==
FALSE
)
{
_sync_privacy_lists
(
user
);
user
->
privacy_synched
=
TRUE
;
return
;
}
if
(
nm_user_is_privacy_locked
(
user
))
{
_show_privacy_locked_error
(
gc
,
user
);
_sync_privacy_lists
(
user
);
return
;
}
switch
(
purple_account_get_privacy_type
(
account
))
{
case
PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL
:
rc
=
nm_send_set_privacy_default
(
user
,
FALSE
,
_set_privacy_default_resp_cb
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
/* clear server side deny list */
if
(
rc
==
NM_OK
)
{
copy
=
g_slist_copy
(
user
->
deny_list
);
for
(
node
=
copy
;
node
&&
node
->
data
;
node
=
node
->
next
)
{
rc
=
nm_send_remove_privacy_item
(
user
,
(
const
char
*
)
node
->
data
,
FALSE
,
NULL
,
NULL
);
if
(
_check_for_disconnect
(
user
,
rc
))
break
;
}
g_slist_free
(
copy
);
g_slist_free
(
user
->
deny_list
);
user
->
deny_list
=
NULL
;
}
break
;
case
PURPLE_ACCOUNT_PRIVACY_DENY_ALL
:
rc
=
nm_send_set_privacy_default
(
user
,
TRUE
,
_set_privacy_default_resp_cb
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
/* clear server side allow list */
if
(
rc
==
NM_OK
)
{
copy
=
g_slist_copy
(
user
->
allow_list
);
for
(
node
=
copy
;
node
&&
node
->
data
;
node
=
node
->
next
)
{
rc
=
nm_send_remove_privacy_item
(
user
,
(
const
char
*
)
node
->
data
,
TRUE
,
NULL
,
NULL
);
if
(
_check_for_disconnect
(
user
,
rc
))
break
;
}
g_slist_free
(
copy
);
g_slist_free
(
user
->
allow_list
);
user
->
allow_list
=
NULL
;
}
break
;
case
PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS
:
rc
=
nm_send_set_privacy_default
(
user
,
TRUE
,
_set_privacy_default_resp_cb
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
/* sync allow lists */
if
(
rc
==
NM_OK
)
{
for
(
node
=
user
->
allow_list
;
node
;
node
=
node
->
next
)
{
user_record
=
nm_find_user_record
(
user
,
(
char
*
)
node
->
data
);
if
(
user_record
)
{
name
=
nm_user_record_get_display_id
(
user_record
);
if
(
!
g_slist_find_custom
(
purple_account_privacy_get_permitted
(
account
),
name
,
(
GCompareFunc
)
purple_utf8_strcasecmp
))
{
purple_account_privacy_permit_add
(
account
,
name
,
TRUE
);
}
}
}
for
(
node
=
purple_account_privacy_get_permitted
(
account
);
node
;
node
=
node
->
next
)
{
dn
=
nm_lookup_dn
(
user
,
(
char
*
)
node
->
data
);
if
(
dn
)
{
if
(
!
g_slist_find_custom
(
user
->
allow_list
,
dn
,
(
GCompareFunc
)
purple_utf8_strcasecmp
))
{
rc
=
nm_send_create_privacy_item
(
user
,
dn
,
TRUE
,
_create_privacy_item_deny_resp_cb
,
g_strdup
(
dn
));
_check_for_disconnect
(
user
,
rc
);
}
}
else
{
purple_account_privacy_permit_remove
(
account
,
(
char
*
)
node
->
data
,
TRUE
);
}
}
}
break
;
case
PURPLE_ACCOUNT_PRIVACY_DENY_USERS
:
/* set to default allow */
rc
=
nm_send_set_privacy_default
(
user
,
FALSE
,
_set_privacy_default_resp_cb
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
/* sync deny lists */
if
(
rc
==
NM_OK
)
{
for
(
node
=
user
->
deny_list
;
node
;
node
=
node
->
next
)
{
user_record
=
nm_find_user_record
(
user
,
(
char
*
)
node
->
data
);
if
(
user_record
)
{
name
=
nm_user_record_get_display_id
(
user_record
);
if
(
!
g_slist_find_custom
(
purple_account_privacy_get_denied
(
account
),
name
,
(
GCompareFunc
)
purple_utf8_strcasecmp
))
{
purple_account_privacy_deny_add
(
account
,
name
,
TRUE
);
}
}
}
for
(
node
=
purple_account_privacy_get_denied
(
account
);
node
;
node
=
node
->
next
)
{
name
=
NULL
;
dn
=
nm_lookup_dn
(
user
,
(
char
*
)
node
->
data
);
if
(
dn
)
{
user_record
=
nm_find_user_record
(
user
,
dn
);
name
=
nm_user_record_get_display_id
(
user_record
);
if
(
!
g_slist_find_custom
(
user
->
deny_list
,
dn
,
(
GCompareFunc
)
purple_utf8_strcasecmp
))
{
rc
=
nm_send_create_privacy_item
(
user
,
dn
,
FALSE
,
_create_privacy_item_deny_resp_cb
,
g_strdup
(
name
));
_check_for_disconnect
(
user
,
rc
);
}
}
else
{
purple_account_privacy_deny_remove
(
account
,
(
char
*
)
node
->
data
,
TRUE
);
}
}
}
break
;
case
PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST
:
/* remove users from allow list that are not in buddy list */
copy
=
g_slist_copy
(
user
->
allow_list
);
for
(
node
=
copy
;
node
&&
node
->
data
;
node
=
node
->
next
)
{
if
(
!
nm_find_contacts
(
user
,
node
->
data
))
{
rc
=
nm_send_remove_privacy_item
(
user
,
(
const
char
*
)
node
->
data
,
TRUE
,
NULL
,
NULL
);
if
(
_check_for_disconnect
(
user
,
rc
))
return
;
}
}
g_slist_free
(
copy
);
/* add all buddies to allow list */
num_contacts
=
nm_folder_get_contact_count
(
user
->
root_folder
);
for
(
i
=
0
;
i
<
num_contacts
;
i
++
)
{
contact
=
nm_folder_get_contact
(
user
->
root_folder
,
i
);
dn
=
nm_contact_get_dn
(
contact
);
if
(
dn
&&
!
g_slist_find_custom
(
user
->
allow_list
,
dn
,
(
GCompareFunc
)
purple_utf8_strcasecmp
))
{
rc
=
nm_send_create_privacy_item
(
user
,
dn
,
TRUE
,
_create_privacy_item_deny_resp_cb
,
g_strdup
(
dn
));
if
(
_check_for_disconnect
(
user
,
rc
))
return
;
}
}
num_folders
=
nm_folder_get_subfolder_count
(
user
->
root_folder
);
for
(
i
=
0
;
i
<
num_folders
;
i
++
)
{
folder
=
nm_folder_get_subfolder
(
user
->
root_folder
,
i
);
num_contacts
=
nm_folder_get_contact_count
(
folder
);
for
(
j
=
0
;
j
<
num_contacts
;
j
++
)
{
contact
=
nm_folder_get_contact
(
folder
,
j
);
dn
=
nm_contact_get_dn
(
contact
);
if
(
dn
&&
!
g_slist_find_custom
(
user
->
allow_list
,
dn
,
(
GCompareFunc
)
purple_utf8_strcasecmp
))
{
rc
=
nm_send_create_privacy_item
(
user
,
dn
,
TRUE
,
_create_privacy_item_deny_resp_cb
,
g_strdup
(
dn
));
if
(
_check_for_disconnect
(
user
,
rc
))
return
;
}
}
}
/* set to default deny */
rc
=
nm_send_set_privacy_default
(
user
,
TRUE
,
_set_privacy_default_resp_cb
,
NULL
);
if
(
_check_for_disconnect
(
user
,
rc
))
break
;
break
;
}
}
static
GList
*
novell_blist_node_menu
(
PurpleProtocolClient
*
client
,
PurpleBlistNode
*
node
)
{
GList
*
list
=
NULL
;
PurpleActionMenu
*
act
;
if
(
PURPLE_IS_BUDDY
(
node
))
{
act
=
purple_action_menu_new
(
_
(
"Initiate _Chat"
),
PURPLE_CALLBACK
(
_initiate_conference_cb
),
NULL
,
NULL
);
list
=
g_list_append
(
list
,
act
);
}
return
list
;
}
static
void
novell_keepalive
(
PurpleProtocolServer
*
protocol_server
,
PurpleConnection
*
gc
)
{
NMUser
*
user
;
NMERR_T
rc
=
NM_OK
;
if
(
gc
==
NULL
)
return
;
user
=
purple_connection_get_protocol_data
(
gc
);
if
(
user
==
NULL
)
return
;
rc
=
nm_send_keepalive
(
user
,
NULL
,
NULL
);
_check_for_disconnect
(
user
,
rc
);
}
static
const
char
*
novell_normalize
(
PurpleProtocolClient
*
client
,
PurpleAccount
*
account
,
const
char
*
who
)
{
return
purple_normalize_nocase
(
who
);
}
static
gssize
novell_get_max_message_size
(
PurpleProtocolClient
*
client
,
PurpleConversation
*
conv
)
{
/* XXX: got from pidgin-otr - verify and document it */
return
1792
;
}
static
void
novell_protocol_init
(
NovellProtocol
*
self
)
{
}
static
void
novell_protocol_class_init
(
NovellProtocolClass
*
klass
)
{
PurpleProtocolClass
*
protocol_class
=
PURPLE_PROTOCOL_CLASS
(
klass
);
protocol_class
->
login
=
novell_login
;
protocol_class
->
close
=
novell_close
;
protocol_class
->
status_types
=
novell_status_types
;
protocol_class
->
list_icon
=
novell_list_icon
;
protocol_class
->
get_account_options
=
novell_protocol_get_account_options
;
}
static
void
novell_protocol_class_finalize
(
G_GNUC_UNUSED
NovellProtocolClass
*
klass
)
{
}
static
void
novell_protocol_client_iface_init
(
PurpleProtocolClientInterface
*
client_iface
)
{
client_iface
->
status_text
=
novell_status_text
;
client_iface
->
tooltip_text
=
novell_tooltip_text
;
client_iface
->
blist_node_menu
=
novell_blist_node_menu
;
client_iface
->
convo_closed
=
novell_convo_closed
;
client_iface
->
normalize
=
novell_normalize
;
client_iface
->
get_max_message_size
=
novell_get_max_message_size
;
}
static
void
novell_protocol_server_iface_init
(
PurpleProtocolServerInterface
*
server_iface
)
{
server_iface
->
get_info
=
novell_get_info
;
server_iface
->
set_status
=
novell_set_status
;
server_iface
->
set_idle
=
novell_set_idle
;
server_iface
->
add_buddy
=
novell_add_buddy
;
server_iface
->
remove_buddy
=
novell_remove_buddy
;
server_iface
->
keepalive
=
novell_keepalive
;
server_iface
->
alias_buddy
=
novell_alias_buddy
;
server_iface
->
group_buddy
=
novell_group_buddy
;
server_iface
->
rename_group
=
novell_rename_group
;
server_iface
->
remove_group
=
novell_remove_group
;
}
static
void
novell_protocol_im_iface_init
(
PurpleProtocolIMInterface
*
im_iface
)
{
im_iface
->
send
=
novell_send_im
;
im_iface
->
send_typing
=
novell_send_typing
;
}
static
void
novell_protocol_chat_iface_init
(
PurpleProtocolChatInterface
*
chat_iface
)
{
chat_iface
->
invite
=
novell_chat_invite
;
chat_iface
->
leave
=
novell_chat_leave
;
chat_iface
->
send
=
novell_chat_send
;
}
static
void
novell_protocol_privacy_iface_init
(
PurpleProtocolPrivacyInterface
*
privacy_iface
)
{
privacy_iface
->
add_permit
=
novell_add_permit
;
privacy_iface
->
add_deny
=
novell_add_deny
;
privacy_iface
->
remove_permit
=
novell_remove_permit
;
privacy_iface
->
remove_deny
=
novell_remove_deny
;
privacy_iface
->
set_permit_deny
=
novell_set_permit_deny
;
}
G_DEFINE_DYNAMIC_TYPE_EXTENDED
(
NovellProtocol
,
novell_protocol
,
PURPLE_TYPE_PROTOCOL
,
0
,
G_IMPLEMENT_INTERFACE_DYNAMIC
(
PURPLE_TYPE_PROTOCOL_CLIENT
,
novell_protocol_client_iface_init
)
G_IMPLEMENT_INTERFACE_DYNAMIC
(
PURPLE_TYPE_PROTOCOL_SERVER
,
novell_protocol_server_iface_init
)
G_IMPLEMENT_INTERFACE_DYNAMIC
(
PURPLE_TYPE_PROTOCOL_IM
,
novell_protocol_im_iface_init
)
G_IMPLEMENT_INTERFACE_DYNAMIC
(
PURPLE_TYPE_PROTOCOL_CHAT
,
novell_protocol_chat_iface_init
)
G_IMPLEMENT_INTERFACE_DYNAMIC
(
PURPLE_TYPE_PROTOCOL_PRIVACY
,
novell_protocol_privacy_iface_init
));
static
PurpleProtocol
*
novell_protocol_new
(
void
)
{
return
PURPLE_PROTOCOL
(
g_object_new
(
NOVELL_TYPE_PROTOCOL
,
"id"
,
"prpl-novell"
,
"name"
,
"GroupWise"
,
"description"
,
"GroupWise is a messaging and collaboration platform from Micro Focus"
,
NULL
));
}
static
GPluginPluginInfo
*
novell_query
(
GError
**
error
)
{
return
purple_plugin_info_new
(
"id"
,
"prpl-novell"
,
"name"
,
"Novell GroupWise Protocol"
,
"version"
,
DISPLAY_VERSION
,
"category"
,
N_
(
"Protocol"
),
"summary"
,
N_
(
"Novell GroupWise Messenger Protocol Plugin"
),
"description"
,
N_
(
"Novell GroupWise Messenger Protocol Plugin"
),
"website"
,
PURPLE_WEBSITE
,
"abi-version"
,
PURPLE_ABI_VERSION
,
"flags"
,
PURPLE_PLUGIN_INFO_FLAGS_INTERNAL
|
PURPLE_PLUGIN_INFO_FLAGS_AUTO_LOAD
,
NULL
);
}
static
gboolean
novell_load
(
GPluginPlugin
*
plugin
,
GError
**
error
)
{
PurpleProtocolManager
*
manager
=
purple_protocol_manager_get_default
();
novell_protocol_register_type
(
G_TYPE_MODULE
(
plugin
));
my_protocol
=
novell_protocol_new
();
if
(
!
purple_protocol_manager_register
(
manager
,
my_protocol
,
error
))
{
g_clear_object
(
&
my_protocol
);
return
FALSE
;
}
return
TRUE
;
}
static
gboolean
novell_unload
(
GPluginPlugin
*
plugin
,
GError
**
error
)
{
PurpleProtocolManager
*
manager
=
purple_protocol_manager_get_default
();
if
(
!
purple_protocol_manager_unregister
(
manager
,
my_protocol
,
error
))
{
return
FALSE
;
}
g_clear_object
(
&
my_protocol
);
return
TRUE
;
}
GPLUGIN_NATIVE_PLUGIN_DECLARE
(
novell
)