pidgin/pidgin

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\nSent: %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)