--- a/src/protocols/novell/novell.c Wed Oct 18 16:28:51 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3573 +0,0 @@ -/* - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "internal.h" -#include "accountopt.h" -#include "debug.h" -#include "prpl.h" -#include "server.h" -#include "nmuser.h" -#include "notify.h" -#include "util.h" -#include "sslconn.h" -#include "request.h" -#include "network.h" -#include "privacy.h" -#include "status.h" -#include "version.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" - -static GaimPlugin *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, GaimBuddy * buddy, int status, int gmt); - -static void -_remove_gaim_buddies(NMUser * user); - -static void -_add_contacts_to_gaim_blist(NMUser * user, NMFolder * folder); - -static void -_add_gaim_buddies(NMUser * user); - -static void -_sync_contact_list(NMUser *user); - -static void -_sync_privacy_lists(NMUser *user); - -static void -_show_info(GaimConnection * gc, NMUserRecord * user_record); - -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) -{ - GaimConnection *gc; - const char *alias; - NMERR_T rc; - - if (user == NULL) - return; - - gc = gaim_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 = gaim_account_get_alias(user->client_data); - if (alias == NULL || *alias == '\0') { - alias = nm_user_record_get_full_name(user->user_record); - - if (alias) - gaim_account_set_alias(user->client_data, alias); - } - - /* Tell Gaim that we are connected */ - gaim_connection_set_state(gc, GAIM_CONNECTED); - - _sync_contact_list(user); - - rc = nm_send_set_status(user, NM_STATUS_AVAILABLE, NULL, NULL, NULL, - NULL); - _check_for_disconnect(user, rc); - - } else { - - char *err = g_strdup_printf(_("Login failed (%s)."), - nm_error_to_string (ret_code)); - - /* Don't attempt to auto-reconnect if our password - * was invalid. - */ - if (ret_code == NMERR_AUTHENTICATION_FAILED || - ret_code == NMERR_CREDENTIALS_MISSING || - ret_code == NMERR_PASSWORD_INVALID) { - gc->wants_to_die = TRUE; - } - gaim_connection_error(gc, 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) -{ - GaimBuddy *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 Gaim buddies and update their statuses */ - const char *name = nm_user_record_get_display_id(user_record); - - if (name) { - buddies = gaim_find_buddies((GaimAccount *) user->client_data, name); - for (bnode = buddies; bnode; bnode = bnode->next) { - buddy = (GaimBuddy *) 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 { - - gaim_debug(GAIM_DEBUG_INFO, "novell", - "_get_status_resp_cb(): rc = 0x%X\n", 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) { - gaim_debug(GAIM_DEBUG_INFO, "novell", - "_rename_contact_resp_cb(): rc = 0x%X\n", 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) -{ - GaimConversation *gconv; - GaimConnection *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) { - - /* Set the title for the conversation */ - /* XXX - Should this be GAIM_CONV_TYPE_IM? */ - gconv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_ANY, - nm_user_record_get_display_id(user_record), - (GaimAccount *) user->client_data); - if (gconv) { - - dn = nm_user_record_get_dn(user_record); - if (dn) { - cntct = nm_find_contact(user, dn); - } - - if (cntct) { - gaim_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) - gaim_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 = gaim_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)); - - gaim_notify_error(gc, NULL, err, NULL); - g_free(err); - } - - if (msg) - nm_release_message(msg); - } -} - -/* Set up the new GaimBuddy 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; - GaimBuddy *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 */ - gaim_blist_rename_buddy(buddy, - nm_user_record_get_display_id(user_record)); - - alias = gaim_buddy_get_alias(buddy); - if (alias == NULL || *alias == '\0' || (strcmp(alias, buddy->name) == 0)) { - gaim_blist_alias_buddy(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);*/ - - } - - if (contact) - nm_release_contact(contact); -} - -/* Add the new contact into the GaimBuddy 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; - GaimGroup *group; - GaimBuddy *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 */ - if (folder_name && (group = gaim_find_group(folder_name))) { - - 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 && strcmp(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 gaim buddy list if it is not there */ - buddy = gaim_find_buddy_in_group(user->client_data, display_id, group); - if (buddy == NULL) { - buddy = gaim_buddy_new(user->client_data, display_id, alias); - gaim_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 Gaim 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 { - GaimConnection *gc = gaim_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)); - gaim_notify_error(gc, NULL, err, NULL); - 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) -{ - GaimConnection *gc; - char *err = NULL; - - if (user == NULL) - return; - - if (ret_code != NM_OK) { - gc = gaim_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)); - gaim_notify_error(gc, NULL, err, NULL); - 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? */ - - gaim_debug(GAIM_DEBUG_INFO, "novell", - "_remove_contact_resp_cb(): rc = 0x%x\n", 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? */ - - gaim_debug(GAIM_DEBUG_INFO, "novell", - "_remove_folder_resp_cb(): rc = 0x%x\n", 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? */ - - gaim_debug(GAIM_DEBUG_INFO, "novell", - "_move_contact_resp_cb(): rc = 0x%x\n", 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? */ - - gaim_debug(GAIM_DEBUG_INFO, "novell", - "_rename_folder_resp_cb(): rc = 0x%x\n", ret_code); - } -} - -static void -_sendinvite_resp_cb(NMUser *user, NMERR_T ret_code, - gpointer resp_data, gpointer user_data) -{ - char *err; - GaimConnection *gc; - - if (user == NULL) - return; - - if (ret_code != NM_OK) { - gc = gaim_account_get_connection(user->client_data); - err = g_strdup_printf(_("Unable to invite user (%s)."), nm_error_to_string(ret_code)); - gaim_notify_error(gc, NULL, err, NULL); - g_free(err); - - gaim_debug(GAIM_DEBUG_INFO, "novell", - "_sendinvite_resp_cb(): rc = 0x%x\n", 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))) { - - GaimConnection *gc = gaim_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)); - - gaim_notify_error(gc, NULL, err, NULL); - g_free(err); - } - - if (msg) - 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) { - - if (folder_name) - 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 { - GaimConnection *gc = gaim_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)); - - gaim_notify_error(gc, NULL, err, NULL); - g_free(err); - } - - if (folder_name) - 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); - - if (folder_name) - 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 { - GaimConnection *gc = gaim_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)); - - gaim_notify_error(gc, NULL, err, NULL); - - 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) -{ - GaimConversation *chat; - GaimConnection *gc; - NMUserRecord *ur; - NMConference *conference = user_data; - const char *name, *conf_name; - int i, count; - - if (user == NULL || conference == NULL) - return; - - gc = gaim_account_get_connection(user->client_data); - - if (ret_code == NM_OK) { - conf_name = _get_conference_name(++user->conference_count); - chat = 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); - gaim_conv_chat_add_user(GAIM_CONV_CHAT(chat), name, NULL, - GAIM_CBFLAGS_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) -{ - GaimConnection *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(gaim_account_get_connection(user->client_data), - user_record); - } - } else { - gc = gaim_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)); - gaim_notify_error(gc, NULL, err, NULL); - g_free(err); - } - - if (name) - 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) -{ - GaimConnection *gc; - NMUserRecord *user_record = resp_data; - char *err; - gboolean allowed = GPOINTER_TO_INT(user_data); - const char *display_id; - - if (user == NULL) - return; - - gc = gaim_account_get_connection(user->client_data); - display_id = nm_user_record_get_display_id(user_record); - - if (ret_code == NM_OK) { - - if (allowed) { - - if (!g_slist_find_custom(gc->account->permit, - display_id, (GCompareFunc)nm_utf8_strcasecmp)) { - gaim_privacy_permit_add(gc->account, display_id, TRUE); - } - - } else { - - if (!g_slist_find_custom(gc->account->permit, - display_id, (GCompareFunc)nm_utf8_strcasecmp)) { - gaim_privacy_deny_add(gc->account, display_id, TRUE); - } - } - - } else { - - err = g_strdup_printf(_("Unable to add user to privacy list (%s)."), - nm_error_to_string(ret_code)); - gaim_notify_error(gc, NULL, err, NULL); - 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) -{ - GaimConnection *gc; - NMUserRecord *user_record; - char *who = user_data; - char *err; - NMERR_T rc = NM_OK; - const char *display_id = NULL; - - if (user == NULL) - return; - - gc = gaim_account_get_connection(user->client_data); - - 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(gc->account->deny, - display_id, (GCompareFunc)nm_utf8_strcasecmp)) { - - gaim_privacy_deny_add(gc->account, display_id, TRUE); - } - - } else { - rc = nm_send_get_details(user, who, - _get_details_resp_add_privacy_item, - (gpointer)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)); - gaim_notify_error(gc, NULL, err, NULL); - g_free(err); - - } - - if (who) - 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) -{ - GaimConnection *gc; - NMUserRecord *user_record; - char *who = user_data; - char *err; - NMERR_T rc = NM_OK; - const char *display_id = NULL; - - if (user == NULL) - return; - - gc = gaim_account_get_connection(user->client_data); - - 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(gc->account->permit, - display_id, - (GCompareFunc)nm_utf8_strcasecmp)) { - - gaim_privacy_permit_add(gc->account, display_id, TRUE); - } - - } else { - rc = nm_send_get_details(user, who, - _get_details_resp_add_privacy_item, - (gpointer)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)); - gaim_notify_error(gc, NULL, err, NULL); - g_free(err); - - } - - if (who) - 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; - GaimConnection *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 = gaim_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)); - gaim_notify_error(gc, NULL, err, NULL); - g_free(err); - - } -} - -static void -_remove_privacy_item_resp_cb(NMUser *user, NMERR_T ret_code, - gpointer resp_data, gpointer user_data) -{ - GaimConnection *gc; - char *who = user_data; - char *err; - - if (user == NULL) - return; - - if (ret_code != NM_OK) { - - gc = gaim_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)); - gaim_notify_error(gc, NULL, err, NULL); - g_free(err); - } - - if (who) - g_free(who); -} - -static void -_set_privacy_default_resp_cb(NMUser *user, NMERR_T ret_code, - gpointer resp_data, gpointer user_data) -{ - GaimConnection *gc; - char *err; - - if (user == NULL) - return; - - if (ret_code != NM_OK) { - - gc = gaim_account_get_connection(user->client_data); - err = g_strdup_printf(_("Unable to change server side privacy settings (%s)."), - nm_error_to_string(ret_code)); - gaim_notify_error(gc, NULL, err, NULL); - 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; - GaimConnection *gc; - NMUserRecord *user_record = resp_data; - char *err; - GSList *cnode; - NMConference *conference; - gpointer chat; - long id = (long) user_data; - - if (user == NULL) - return; - - gc = gaim_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 (gaim_conv_chat_get_id(GAIM_CONV_CHAT(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)); - gaim_notify_error(gc, NULL, err, NULL); - 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; - GaimConnection *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 = gaim_account_get_connection(user->client_data); - gaim_notify_error(gc, NULL, err, NULL); - g_free(err); - } -} - -/******************************************************************************* - * Helper functions - ******************************************************************************/ - -static char * -_user_agent_string() -{ - -#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("Gaim/%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("Gaim/%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) -{ - GaimConnection *gc = gaim_account_get_connection(user->client_data); - - if (_is_disconnect_error(err)) { - - gaim_connection_error(gc, _("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 Gaim buddy list - */ -static void -_update_buddy_status(NMUser *user, GaimBuddy * buddy, int novellstatus, int gmt) -{ - GaimAccount *account; - const char *status_id; - const char *text = NULL; - const char *dn; - int idle = 0; - gboolean loggedin = TRUE; - - account = buddy->account; - - 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; - loggedin = FALSE; - break; - case NM_STATUS_AWAY_IDLE: - status_id = NOVELL_STATUS_TYPE_AWAY; - idle = gmt; - break; - default: - status_id = NOVELL_STATUS_TYPE_OFFLINE; - loggedin = FALSE; - break; - } - - /* Get status text for the user */ - dn = nm_lookup_dn(user, buddy->name); - if (dn) { - NMUserRecord *user_record = nm_find_user_record(user, dn); - if (user_record) { - text = nm_user_record_get_status_text(user_record); - } - } - - gaim_prpl_got_user_status(account, buddy->name, status_id, - "message", text, NULL); - gaim_prpl_got_user_idle(account, buddy->name, - (novellstatus == NM_STATUS_AWAY_IDLE), idle); -} - -/* Iterate through the cached Gaim buddy list and remove buddies - * that are not in the server side list. - */ -static void -_remove_gaim_buddies(NMUser *user) -{ - GaimBlistNode *gnode; - GaimBlistNode *cnode; - GaimBlistNode *bnode; - GaimGroup *group; - GaimBuddy *buddy; - GaimBuddyList *blist; - GSList *rem_list = NULL; - GSList *l; - NMFolder *folder = NULL; - const char *gname = NULL; - - if ((blist = gaim_get_blist())) { - for (gnode = blist->root; gnode; gnode = gnode->next) { - if (!GAIM_BLIST_NODE_IS_GROUP(gnode)) - continue; - group = (GaimGroup *) gnode; - for (cnode = gnode->child; cnode; cnode = cnode->next) { - if (!GAIM_BLIST_NODE_IS_CONTACT(cnode)) - continue; - for (bnode = cnode->child; bnode; bnode = bnode->next) { - if (!GAIM_BLIST_NODE_IS_BUDDY(bnode)) - continue; - buddy = (GaimBuddy *) bnode; - if (buddy->account == user->client_data) { - gname = group->name; - if (strcmp(group->name, NM_ROOT_FOLDER_NAME) == 0) - gname = ""; - folder = nm_find_folder(user, gname); - if (folder == NULL || - !nm_folder_find_contact_by_display_id(folder, buddy->name)) { - rem_list = g_slist_append(rem_list, buddy); - } - } - } - } - } - - if (rem_list) { - for (l = rem_list; l; l = l->next) { - gaim_blist_remove_buddy(l->data); - } - g_slist_free(rem_list); - } - } -} - -/* Add all of the contacts in the given folder to the Gaim buddy list */ -static void -_add_contacts_to_gaim_blist(NMUser * user, NMFolder * folder) -{ - NMUserRecord *user_record = NULL; - NMContact *contact = NULL; - GaimBuddy *buddy = NULL; - GaimGroup *group; - NMERR_T cnt = 0, i; - const char *text = NULL; - const char *name = NULL; - const char *fname = NULL; - int status = 0; - - /* If this is the root folder give it a name. Gaim 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 Gaim group exist already? */ - group = gaim_find_group(fname); - if (group == NULL) { - group = gaim_group_new(fname); - gaim_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 = gaim_find_buddy_in_group(user->client_data, name, group); - if (buddy == NULL) { - /* Add it to the gaim buddy list */ - buddy = gaim_buddy_new(user->client_data, - name, - nm_contact_get_display_name(contact)); - - gaim_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); - text = nm_user_record_get_status_text(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 Gaim buddy list. */ -static void -_add_gaim_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 Gaim 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_gaim_blist(user, folder); - } - } - - /* Add contacts for the root folder */ - _add_contacts_to_gaim_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_gaim_buddies(user); - _add_gaim_buddies(user); - user->clist_synched = TRUE; -} - -static void -_sync_privacy_lists(NMUser *user) -{ - GSList *node = NULL, *rem_list = NULL; - GaimConnection *gc; - const char *name, *dn; - NMUserRecord *user_record; - - if (user == NULL) - return; - - gc = gaim_account_get_connection(user->client_data); - if (gc == NULL) - return; - - /* Set the Gaim privacy setting */ - if (user->default_deny) { - if (user->allow_list == NULL) { - gc->account->perm_deny = GAIM_PRIVACY_DENY_ALL; - } else { - gc->account->perm_deny = GAIM_PRIVACY_ALLOW_USERS; - } - } else { - if (user->deny_list == NULL) { - gc->account->perm_deny = GAIM_PRIVACY_ALLOW_ALL; - } else { - gc->account->perm_deny = GAIM_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(gc->account->permit, - name, (GCompareFunc)nm_utf8_strcasecmp)) { - gaim_privacy_permit_add(gc->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(gc->account->deny, - name, (GCompareFunc)nm_utf8_strcasecmp)) { - gaim_privacy_deny_add(gc->account, name, TRUE); - } - } - - - /* Remove stuff */ - for (node = gc->account->permit; node; node = node->next) { - dn = nm_lookup_dn(user, (char *)node->data); - if (dn != NULL && - !g_slist_find_custom(user->allow_list, - dn, (GCompareFunc)nm_utf8_strcasecmp)) { - rem_list = g_slist_append(rem_list, node->data); - } - } - - if (rem_list) { - for (node = rem_list; node; node = node->next) { - gaim_privacy_permit_remove(gc->account, (char *)node->data, TRUE); - } - g_free(rem_list); - rem_list = NULL; - } - - for (node = gc->account->deny; node; node = node->next) { - dn = nm_lookup_dn(user, (char *)node->data); - if (dn != NULL && - !g_slist_find_custom(user->deny_list, - dn, (GCompareFunc)nm_utf8_strcasecmp)) { - rem_list = g_slist_append(rem_list, node->data); - } - } - - if (rem_list) { - for (node = rem_list; node; node = node->next) { - gaim_privacy_deny_remove(gc->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 (strcmp(tag, "telephoneNumber") == 0) - return _("Telephone Number"); - else if (strcmp(tag, "L") == 0) - return _("Location"); - else if (strcmp(tag, "OU") == 0) - return _("Department"); - else if (strcmp(tag, "personalTitle") == 0) - return _("Personal Title"); - else if (strcmp(tag, "Title") == 0) - return _("Title"); - else if (strcmp(tag, "mailstop") == 0) - return _("Mailstop"); - else if (strcmp(tag, "Internet EMail Address") == 0) - return _("E-Mail Address"); - else - return tag; -} - -/* Display a dialog box showing the properties for the given user record */ -static void -_show_info(GaimConnection * gc, NMUserRecord * user_record) -{ - GString *info_text; - int count, i; - NMProperty *property; - const char *tag, *value; - - info_text = g_string_new(""); - - tag = _("User ID"); - value = nm_user_record_get_userid(user_record); - if (value) { - g_string_append_printf(info_text, "<b>%s:</b> %s<br>", tag, value); - } - -/* tag = _("DN"); - value = nm_user_record_get_dn(user_record); - if (value) { - g_string_append_printf(info_text, "<b>%s:</b> %s<br>", - tag, value); - } -*/ - - tag = _("Full name"); - value = nm_user_record_get_full_name(user_record); - if (value) { - g_string_append_printf(info_text, "<b>%s:</b> %s<br>", tag, value); - } - - count = nm_user_record_get_property_count(user_record); - for (i = 0; i < count; i++) { - property = nm_user_record_get_property(user_record, i); - if (property) { - tag = _map_property_tag(nm_property_get_tag(property)); - value = nm_property_get_value(property); - if (tag && value) { - g_string_append_printf(info_text, "<b>%s:</b> %s<br>", - tag, value); - } - nm_release_property(property); - } - } - - gaim_notify_userinfo(gc, nm_user_record_get_userid(user_record), - info_text->str, NULL, NULL); - - g_string_free(info_text, TRUE); -} - -/* 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 gaim_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 gaim_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(GaimBlistNode *node, gpointer ignored) -{ - GaimBuddy *buddy; - GaimConnection *gc; - - NMUser *user; - const char *conf_name; - GaimConversation *chat = NULL; - NMUserRecord *user_record; - NMConference *conference; - - g_return_if_fail(GAIM_BLIST_NODE_IS_BUDDY(node)); - - buddy = (GaimBuddy *) node; - gc = gaim_account_get_connection(buddy->account); - - user = gc->proto_data; - if (user == NULL) - return; - - /* We should already have a userrecord for the buddy */ - user_record = nm_find_user_record(user, buddy->name); - if (user_record == NULL) - return; - - conf_name = _get_conference_name(++user->conference_count); - chat = 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; - - if (name) - g_free(name); - - name = g_strdup_printf(_("GroupWise Conference %d"), id); - - return name; -} - -static void -_show_privacy_locked_error(GaimConnection *gc, NMUser *user) -{ - char *err; - - err = g_strdup_printf(_("Unable to change server side privacy settings (%s)."), - nm_error_to_string(NMERR_ADMIN_LOCKED)); - gaim_notify_error(gc, NULL, err, NULL); - g_free(err); -} - -/******************************************************************************* - * Connect and recv callbacks - ******************************************************************************/ - -static void -novell_ssl_connect_error(GaimSslConnection * gsc, - GaimSslErrorType error, gpointer data) -{ - gaim_connection_error((GaimConnection *)data, - _("Unable to make SSL connection to server.")); -} - -static void -novell_ssl_recv_cb(gpointer data, GaimSslConnection * gsc, - GaimInputCondition condition) -{ - GaimConnection *gc = data; - NMUser *user; - NMERR_T rc; - - if (gc == NULL) - return; - - user = gc->proto_data; - if (user == NULL) - return; - - rc = nm_process_new_data(user); - if (rc != NM_OK) { - - if (_is_disconnect_error(rc)) { - - gaim_connection_error(gc, - _("Error communicating with server." - " Closing connection.")); - } else { - gaim_debug(GAIM_DEBUG_INFO, "novell", - "Error processing event or response (%d).\n", rc); - } - } -} - -static void -novell_ssl_connected_cb(gpointer data, GaimSslConnection * gsc, - GaimInputCondition cond) -{ - GaimConnection *gc = data; - NMUser *user; - NMConn *conn; - NMERR_T rc = 0; - const char *pwd = NULL; - const char *my_addr = NULL; - char *ua = NULL; - - if (gc == NULL || gsc == NULL) - return; - - user = gc->proto_data; - if ((user == NULL) || (conn = user->conn) == NULL) - return; - - conn->ssl_conn = g_new0(NMSSLConn, 1); - conn->ssl_conn->data = gsc; - conn->ssl_conn->read = (nm_ssl_read_cb) gaim_ssl_read; - conn->ssl_conn->write = (nm_ssl_write_cb) gaim_ssl_write; - - gaim_connection_update_progress(gc, _("Authenticating..."), - 2, NOVELL_CONNECT_STEPS); - - my_addr = gaim_network_get_my_ip(gsc->fd); - pwd = gaim_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) { - conn->connected = TRUE; - gaim_ssl_input_add(gsc, novell_ssl_recv_cb, gc); - } else { - gaim_connection_error(gc, _("Unable to connect to server.")); - } - - gaim_connection_update_progress(gc, _("Waiting for response..."), - 3, NOVELL_CONNECT_STEPS); - - g_free(ua); -} - -/******************************************************************************* - * Event callback and event handlers - ******************************************************************************/ - -static void -_evt_receive_message(NMUser * user, NMEvent * event) -{ - NMUserRecord *user_record = NULL; - NMContact *contact = NULL; - GaimConversation *gconv; - NMConference *conference; - GaimMessageFlags flags; - char *text = NULL; - - text = g_markup_escape_text(nm_event_get_text(event), -1); - - conference = nm_event_get_conference(event); - if (conference) { - - GaimConversation *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) { - - flags = 0; - if (nm_event_get_type(event) == NMEVT_RECEIVE_AUTOREPLY) - flags |= GAIM_MESSAGE_AUTO_RESP; - - serv_got_im(gaim_account_get_connection(user->client_data), - nm_user_record_get_display_id(user_record), - text, flags, - nm_event_get_gmt(event)); - - gconv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, - nm_user_record_get_display_id(user_record), - (GaimAccount *) user->client_data); - if (gconv) { - - contact = nm_find_contact(user, nm_event_get_source(event)); - if (contact) { - - gaim_conversation_set_title( - gconv, 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); - - gaim_conversation_set_title(gconv, 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); - } - - serv_got_chat_in(gaim_account_get_connection(user->client_data), - gaim_conv_chat_get_id(GAIM_CONV_CHAT(chat)), - name, 0, text, nm_event_get_gmt(event)); - } - } - } - - g_free(text); -} - -static void -_evt_conference_left(NMUser * user, NMEvent * event) -{ - GaimConversation *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) - gaim_conv_chat_remove_user(GAIM_CONV_CHAT(chat), - nm_user_record_get_display_id(ur), - NULL); - } - } -} - -static void -_evt_conference_invite_notify(NMUser * user, NMEvent * event) -{ - GaimConversation *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)); - gaim_conversation_write(gconv, NULL, str, - GAIM_MESSAGE_SYSTEM, time(NULL)); - g_free(str); - } -} - -static void -_evt_conference_invite(NMUser * user, NMEvent * event) -{ - NMUserRecord *ur; - GaimConnection *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, gaim_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 */ - gc = gaim_account_get_connection(user->client_data); - gaim_request_action(gc, title, primary, secondary, - GAIM_DEFAULT_ACTION_NONE, 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) -{ - GaimConversation *chat = NULL; - GaimConnection *gc; - NMConference *conference = NULL; - NMUserRecord *ur = NULL; - const char *name; - const char *conf_name; - - gc = gaim_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 = - 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); - gaim_conv_chat_add_user(GAIM_CONV_CHAT(chat), name, NULL, - GAIM_CBFLAGS_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 (!gaim_conv_chat_find_user(GAIM_CONV_CHAT(chat), name)) { - gaim_conv_chat_add_user(GAIM_CONV_CHAT(chat), name, NULL, - GAIM_CBFLAGS_NONE, TRUE); - } - } - } - } -} - -static void -_evt_status_change(NMUser * user, NMEvent * event) -{ - GaimBuddy *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 = gaim_find_buddies(user->client_data, display_id); - for (bnode = buddies; bnode; bnode = bnode->next) { - buddy = (GaimBuddy *) 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) -{ - GaimConnection *gc; - - gc = gaim_account_get_connection((GaimAccount *) user->client_data); - if (gc) - gaim_connection_error(gc, _("You have been logged out because you" - " logged in at another workstation.")); -} - -static void -_evt_user_typing(NMUser * user, NMEvent * event) -{ - GaimConnection *gc; - NMUserRecord *user_record = NULL; - - gc = gaim_account_get_connection((GaimAccount *) user->client_data); - if (gc) { - user_record = nm_find_user_record(user, nm_event_get_source(event)); - if (user_record) { - serv_got_typing(gc, nm_user_record_get_display_id(user_record), - 30, GAIM_TYPING); - } - } -} - -static void -_evt_user_not_typing(NMUser * user, NMEvent * event) -{ - GaimConnection *gc; - NMUserRecord *user_record; - - gc = gaim_account_get_connection((GaimAccount *) user->client_data); - if (gc) { - user_record = nm_find_user_record(user, nm_event_get_source(event)); - if (user_record) { - serv_got_typing_stopped(gc, - nm_user_record_get_display_id(user_record)); - } - } -} - -static void -_evt_undeliverable_status(NMUser * user, NMEvent * event) -{ - NMUserRecord *ur; - GaimConversation *gconv; - char *str; - - ur = nm_find_user_record(user, nm_event_get_source(event)); - if (ur) { - /* XXX - Should this be GAIM_CONV_TYPE_IM? */ - gconv = - gaim_find_conversation_with_account(GAIM_CONV_TYPE_ANY, - nm_user_record_get_display_id(ur), - user->client_data); - 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); - gaim_conversation_write(gconv, NULL, str, - GAIM_MESSAGE_SYSTEM, time(NULL)); - 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: - gaim_debug(GAIM_DEBUG_INFO, "novell", - "_event_callback(): unhandled event, %d\n", - nm_event_get_type(event)); - break; - } -} - -/******************************************************************************* - * Prpl Ops - ******************************************************************************/ - -static void -novell_login(GaimAccount * account) -{ - GaimConnection *gc; - NMUser *user = NULL; - const char *server; - const char *name; - int port; - - if (account == NULL) - return; - - gc = gaim_account_get_connection(account); - if (gc == NULL) - return; - - server = gaim_account_get_string(account, "server", NULL); - if (server == NULL || *server == '\0') { - - /* TODO: Would be nice to prompt if not set! - * gaim_request_fields(gc, _("Server Address"),...); - */ - - /* ...but for now just error out with a nice message. */ - gaim_connection_error(gc, _("Unable to connect to server." - " Please enter the address of the server" - " you wish to connect to.")); - return; - } - - port = gaim_account_get_int(account, "port", DEFAULT_PORT); - name = gaim_account_get_username(account); - - user = nm_initialize_user(name, server, port, account, _event_callback); - if (user) { - /* save user */ - gc->proto_data = user; - - /* connect to the server */ - gaim_connection_update_progress(gc, _("Connecting"), - 1, NOVELL_CONNECT_STEPS); - - user->conn->use_ssl = TRUE; - if (gaim_ssl_connect(user->client_data, user->conn->addr, - user->conn->port, novell_ssl_connected_cb, - novell_ssl_connect_error, gc) == NULL) { - gaim_connection_error(gc, _("Error." - " SSL support is not installed.")); - } - } -} - -static void -novell_close(GaimConnection * gc) -{ - NMUser *user; - NMConn *conn; - - if (gc == NULL) - return; - - user = gc->proto_data; - if (user) { - conn = user->conn; - if (conn && conn->ssl_conn) { - gaim_ssl_close(user->conn->ssl_conn->data); - } - nm_deinitialize_user(user); - } - gc->proto_data = NULL; -} - -static int -novell_send_im(GaimConnection * gc, const char *name, - const char *message_body, GaimMessageFlags flags) -{ - 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; - - if (gc == NULL || name == NULL || - message_body == NULL || *message_body == '\0') - return 0; - - user = gc->proto_data; - if (user == NULL) - return 0; - - /* Create a new message */ - plain = gaim_unescape_html(message_body); - 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(GaimConnection * gc, const char *name, GaimTypingState state) -{ - NMConference *conf = NULL; - NMUser *user; - const char *dn = NULL; - NMERR_T rc = NM_OK; - - if (gc == NULL || name == NULL) - return 0; - - user = gc->proto_data; - 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 == GAIM_TYPING) ? TRUE : FALSE), NULL); - _check_for_disconnect(user, rc); - - } - - } - - return 0; -} - -static void -novell_convo_closed(GaimConnection * gc, const char *who) -{ - NMUser *user; - NMConference *conf; - const char *dn; - NMERR_T rc = NM_OK; - - if (gc == NULL || who == NULL) - return; - - user = gc->proto_data; - 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(GaimConnection * gc, int id) -{ - NMConference *conference; - NMUser *user; - GaimConversation *chat; - GSList *cnode; - NMERR_T rc = NM_OK; - - if (gc == NULL) - return; - - user = gc->proto_data; - 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 (gaim_conv_chat_get_id(GAIM_CONV_CHAT(chat)) == id) { - rc = nm_send_leave_conference(user, conference, NULL, NULL); - _check_for_disconnect(user, rc); - break; - } - } - } - - serv_got_chat_left(gc, id); -} - -static void -novell_chat_invite(GaimConnection *gc, int id, - const char *message, const char *who) -{ - NMConference *conference; - NMUser *user; - GaimConversation *chat; - GSList *cnode; - NMERR_T rc = NM_OK; - NMUserRecord *user_record = NULL; - - if (gc == NULL) - return; - - user = gc->proto_data; - 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 (gaim_conv_chat_get_id(GAIM_CONV_CHAT(chat)) == id) { - rc = nm_send_conference_invite(user, conference, user_record, - message, _sendinvite_resp_cb, NULL); - _check_for_disconnect(user, rc); - break; - } - } - } -} - -static int -novell_chat_send(GaimConnection * gc, int id, const char *text, GaimMessageFlags flags) -{ - NMConference *conference; - GaimConversation *chat; - GSList *cnode; - NMMessage *message; - NMUser *user; - NMERR_T rc = NM_OK; - const char *name; - char *str, *plain; - - if (gc == NULL || text == NULL) - return -1; - - user = gc->proto_data; - if (user == NULL) - return -1; - - plain = gaim_unescape_html(text); - 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 (gaim_conv_chat_get_id(GAIM_CONV_CHAT(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 = gaim_account_get_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 = gaim_account_get_username(user->client_data); - } - } - - serv_got_chat_in(gc, id, name, 0, text, time(NULL)); - return 0; - } else - return -1; - - } - } - } - - - /* The conference was not found, must be closed */ - chat = gaim_find_chat(gc, id); - if (chat) { - str = g_strdup_printf(_("This conference has been closed." - " No more messages can be sent.")); - gaim_conversation_write(chat, NULL, str, GAIM_MESSAGE_SYSTEM, time(NULL)); - g_free(str); - } - - if (message) - nm_release_message(message); - - return -1; -} - -static void -novell_add_buddy(GaimConnection * gc, GaimBuddy *buddy, GaimGroup * group) -{ - NMFolder *folder = NULL; - NMContact *contact; - NMUser *user; - NMERR_T rc = NM_OK; - const char *alias, *gname; - - if (gc == NULL || buddy == NULL || group == NULL) - return; - - user = (NMUser *) gc->proto_data; - 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; - - contact = nm_create_contact(); - nm_contact_set_dn(contact, buddy->name); - - /* Remove the GaimBuddy (we will add it back after adding it - * to the server side list). Save the alias if there is one. - */ - alias = gaim_buddy_get_alias(buddy); - if (alias && strcmp(alias, buddy->name)) - nm_contact_set_display_name(contact, alias); - - gaim_blist_remove_buddy(buddy); - buddy = NULL; - - if (strcmp(group->name, NM_ROOT_FOLDER_NAME) == 0) { - gname = ""; - } else { - gname = group->name; - } - - 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(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *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 = (NMUser *) gc->proto_data; - if (user && (dn = nm_lookup_dn(user, buddy->name))) { - if (strcmp(group->name, NM_ROOT_FOLDER_NAME) == 0) { - gname = ""; - } else { - gname = group->name; - } - 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(GaimConnection * gc, GaimGroup *group) -{ - NMUser *user; - NMERR_T rc = NM_OK; - - if (gc == NULL || group == NULL) - return; - - user = (NMUser *) gc->proto_data; - if (user) { - NMFolder *folder = nm_find_folder(user, group->name); - - if (folder) { - rc = nm_send_remove_folder(user, folder, - _remove_folder_resp_cb, NULL); - _check_for_disconnect(user, rc); - } - } -} - -static void -novell_alias_buddy(GaimConnection * gc, const char *name, const char *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 = (NMUser *) gc->proto_data; - 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) { - GaimGroup *group = NULL; - GaimBuddy *buddy; - NMFolder *folder; - - /* Alias the Gaim 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 = gaim_find_group(fname); - } - - if (group) { - buddy = gaim_find_buddy_in_group(user->client_data, - name, group); - if (buddy && strcmp(buddy->alias, alias)) - gaim_blist_alias_buddy(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(GaimConnection * gc, - const char *name, const char *old_group_name, - const char *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 = (NMUser *) gc->proto_data; - if (user && (dn = nm_lookup_dn(user, name))) { - - /* Find the old folder */ - if (strcmp(old_group_name, NM_ROOT_FOLDER_NAME) == 0) { - 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 (strcmp(new_group_name, NM_ROOT_FOLDER_NAME) == 0) - 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(GaimConnection * gc, const char *old_name, - GaimGroup *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 = gc->proto_data; - if (user) { - /* Does new folder exist already? */ - if (nm_find_folder(user, group->name)) { - /* gaim_blist_rename_group() adds the buddies - * to the new group and removes the old group... - * so there is nothing more to do here. - */ - return; - } - - if (strcmp(old_name, NM_ROOT_FOLDER_NAME) == 0) { - /* 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, group->name, - _rename_folder_resp_cb, NULL); - _check_for_disconnect(user, rc); - } - } -} - -static void -novell_list_emblems(GaimBuddy * buddy, const char **se, const char **sw, const char **nw, const char **ne) -{ - NMUserRecord *user_record = NULL; - GaimConnection *gc; - NMUser *user; - int status = 0; - - gc = gaim_account_get_connection(buddy->account); - - if (gc == NULL || (user = gc->proto_data) == NULL) - return; - - user_record = nm_find_user_record(user, buddy->name); - - if (user_record) - status = nm_user_record_get_status(user_record); - - switch (status) { - case NM_STATUS_AVAILABLE: - *se = ""; - break; - case NM_STATUS_AWAY: - *se = "away"; - break; - case NM_STATUS_BUSY: - *se = "occupied"; - break; - case NM_STATUS_UNKNOWN: - *se = "error"; - break; - } -} - -static const char * -novell_list_icon(GaimAccount * account, GaimBuddy * buddy) -{ - return "novell"; -} - -static void -novell_tooltip_text(GaimBuddy * buddy, GString * str, gboolean full) -{ - NMUserRecord *user_record = NULL; - GaimConnection *gc; - NMUser *user; - int status = 0; - const char *status_str = NULL; - const char *text = NULL; - - if (buddy == NULL) - return; - - gc = gaim_account_get_connection(buddy->account); - if (gc == NULL || (user = gc->proto_data) == NULL) - return; - - if (GAIM_BUDDY_IS_ONLINE(buddy)) { - user_record = nm_find_user_record(user, buddy->name); - 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; - } - - if (text) - g_string_append_printf(str, "\n<b>%s:</b> %s" - "\n<b>%s:</b> %s", - _("Status"), status_str, - _("Message"), text); - else - g_string_append_printf(str, "\n<b>%s:</b> %s", - _("Status"), status_str); - } - } -} - -static void -novell_set_idle(GaimConnection * gc, int time) -{ - NMUser *user; - NMERR_T rc = NM_OK; - const char *id = NULL; - GaimStatus *status = NULL; - - if (gc == NULL) - return; - - user = gc->proto_data; - if (user == NULL) - return; - - status = gaim_account_get_active_status(gaim_connection_get_account(gc)); - id = gaim_status_get_id(status); - - /* Only go idle if active status is available */ - if (!strcmp(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(GaimConnection * gc, const char *name) -{ - NMUserRecord *user_record; - NMUser *user; - NMERR_T rc; - - if (gc == NULL || name == NULL) - return; - - user = (NMUser *) gc->proto_data; - if (user) { - - user_record = nm_find_user_record(user, name); - if (user_record) { - - _show_info(gc, user_record); - - } 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(GaimBuddy * buddy) -{ - const char *text = NULL; - const char *dn = NULL; - - if (buddy && buddy->account) { - GaimConnection *gc = gaim_account_get_connection(buddy->account); - - if (gc && gc->proto_data) { - NMUser *user = gc->proto_data; - - dn = nm_lookup_dn(user, buddy->name); - 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(GaimAccount *account) -{ - GList *status_types = NULL; - GaimStatusType *type; - - g_return_val_if_fail(account != NULL, NULL); - - type = gaim_status_type_new_with_attrs(GAIM_STATUS_AVAILABLE, NOVELL_STATUS_TYPE_AVAILABLE, - NULL, TRUE, TRUE, FALSE, - "message", _("Message"), gaim_value_new(GAIM_TYPE_STRING), - NULL); - status_types = g_list_append(status_types, type); - - type = gaim_status_type_new_with_attrs(GAIM_STATUS_AWAY, NOVELL_STATUS_TYPE_AWAY, - NULL, TRUE, TRUE, FALSE, - "message", _("Message"), gaim_value_new(GAIM_TYPE_STRING), - NULL); - status_types = g_list_append(status_types, type); - - type = gaim_status_type_new_with_attrs(GAIM_STATUS_UNAVAILABLE, NOVELL_STATUS_TYPE_BUSY, - _("Busy"), TRUE, TRUE, FALSE, - "message", _("Message"), gaim_value_new(GAIM_TYPE_STRING), - NULL); - status_types = g_list_append(status_types, type); - - type = gaim_status_type_new_full(GAIM_STATUS_INVISIBLE, NOVELL_STATUS_TYPE_APPEAR_OFFLINE, - NULL, TRUE, TRUE, FALSE); - status_types = g_list_append(status_types, type); - - type = gaim_status_type_new_full(GAIM_STATUS_OFFLINE, NULL, NULL, FALSE, TRUE, FALSE); - status_types = g_list_append(status_types, type); - - return status_types; -} - -static void -novell_set_status(GaimAccount *account, GaimStatus *status) -{ - GaimConnection *gc; - gboolean connected; - GaimPresence *presence; - GaimStatusType *type; - GaimStatusPrimitive primitive; - NMUser *user; - NMSTATUS_T novellstatus = NM_STATUS_AVAILABLE; - NMERR_T rc = NM_OK; - const char *msg = NULL; - char *text = NULL; - - connected = gaim_account_is_connected(account); - presence = gaim_status_get_presence(status); - type = gaim_status_get_type(status); - primitive = gaim_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 (!gaim_status_is_active(status)) - return; - - if (!connected) - return; - - gc = gaim_account_get_connection(account); - user = gc->proto_data; - if (user == NULL) - return; - - if (primitive == GAIM_STATUS_AVAILABLE) { - novellstatus = NM_STATUS_AVAILABLE; - } else if (primitive == GAIM_STATUS_AWAY) { - novellstatus = NM_STATUS_AWAY; - } else if (primitive == GAIM_STATUS_UNAVAILABLE) { - novellstatus = NM_STATUS_BUSY; - } else if (primitive == GAIM_STATUS_INVISIBLE) { - novellstatus = NM_STATUS_OFFLINE; - } else if (gaim_presence_is_idle(presence)) { - novellstatus = NM_STATUS_AWAY_IDLE; - } else { - novellstatus = NM_STATUS_AVAILABLE; - } - - if (primitive == GAIM_STATUS_AWAY || primitive == GAIM_STATUS_AVAILABLE || - primitive == GAIM_STATUS_UNAVAILABLE) { - msg = gaim_status_get_attr_string(status, "message"); - text = g_strdup(msg); - - if (primitive == GAIM_STATUS_AVAILABLE) - msg = NULL; /* no auto replies for online status */ - - /* Don't want newlines in status text */ - gaim_util_chrreplace(text, '\n', ' '); - } - - rc = nm_send_set_status(user, novellstatus, text, msg, NULL, NULL); - _check_for_disconnect(user, rc); - - if (text) - g_free(text); -} - -static void -novell_add_permit(GaimConnection *gc, const char *who) -{ - NMUser *user; - NMERR_T rc = NM_OK; - const char *name = who; - - if (gc == NULL || who == NULL) - return; - - user = gc->proto_data; - if (user == NULL) - return; - - /* Remove first -- we will add it back in when we get - * the okay from the server - */ - gaim_privacy_permit_remove(gc->account, 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, - (gpointer)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(GaimConnection *gc, const char *who) -{ - NMUser *user; - NMERR_T rc = NM_OK; - const char *name = who; - - if (gc == NULL || who == NULL) - return; - - user = gc->proto_data; - if (user == NULL) - return; - - /* Remove first -- we will add it back in when we get - * the okay from the server - */ - gaim_privacy_deny_remove(gc->account, 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, - (gpointer)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_rem_permit(GaimConnection *gc, const char *who) -{ - NMUser *user; - NMERR_T rc = NM_OK; - const char *dn = NULL; - - if (gc == NULL || who == NULL) - return; - - user = gc->proto_data; - 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_rem_deny(GaimConnection *gc, const char *who) -{ - NMUser *user; - NMERR_T rc = NM_OK; - const char *dn = NULL; - - if (gc == NULL || who == NULL) - return; - - user = gc->proto_data; - 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(GaimConnection *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; - - if (gc == NULL) - return; - - user = gc->proto_data; - 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 (gc->account->perm_deny) { - - case GAIM_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 GAIM_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 GAIM_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(gc->account->permit, - name, (GCompareFunc)nm_utf8_strcasecmp)) { - gaim_privacy_permit_add(gc->account, name , TRUE); - } - } - } - - for (node = gc->account->permit; 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->allow_list, - dn, (GCompareFunc)nm_utf8_strcasecmp)) { - rc = nm_send_create_privacy_item(user, dn, TRUE, - _create_privacy_item_deny_resp_cb, - g_strdup(dn)); - } - } else { - gaim_privacy_permit_remove(gc->account, (char *)node->data, TRUE); - } - } - } - break; - - case GAIM_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(gc->account->deny, - name, (GCompareFunc)nm_utf8_strcasecmp)) { - gaim_privacy_deny_add(gc->account, name , TRUE); - } - } - } - - for (node = gc->account->deny; 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)nm_utf8_strcasecmp)) { - rc = nm_send_create_privacy_item(user, dn, FALSE, - _create_privacy_item_deny_resp_cb, - g_strdup(name)); - } - } else { - gaim_privacy_deny_remove(gc->account, (char *)node->data, TRUE); - } - } - - } - break; - - case GAIM_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)nm_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)nm_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(GaimBlistNode *node) -{ - GList *list = NULL; - GaimMenuAction *act; - - if(GAIM_BLIST_NODE_IS_BUDDY(node)) { - act = gaim_menu_action_new(_("Initiate _Chat"), - GAIM_CALLBACK(_initiate_conference_cb), - NULL, NULL); - list = g_list_append(list, act); - } - - return list; -} - -static void -novell_keepalive(GaimConnection *gc) -{ - NMUser *user; - NMERR_T rc = NM_OK; - - if (gc == NULL) - return; - - user = gc->proto_data; - if (user == NULL) - return; - - rc = nm_send_keepalive(user, NULL, NULL); - _check_for_disconnect(user, rc); -} - -static GaimPluginProtocolInfo prpl_info = { - 0, - NULL, /* user_splits */ - NULL, /* protocol_options */ - NO_BUDDY_ICONS, /* icon_spec */ - novell_list_icon, /* list_icon */ - novell_list_emblems, /* list_emblems */ - novell_status_text, /* status_text */ - novell_tooltip_text, /* tooltip_text */ - novell_status_types, /* status_types */ - novell_blist_node_menu, /* blist_node_menu */ - NULL, /* chat_info */ - NULL, /* chat_info_defaults */ - novell_login, /* login */ - novell_close, /* close */ - novell_send_im, /* send_im */ - NULL, /* set_info */ - novell_send_typing, /* send_typing */ - novell_get_info, /* get_info */ - novell_set_status, /* set_status */ - novell_set_idle, /* set_idle */ - NULL, /* change_passwd */ - novell_add_buddy, /* add_buddy */ - NULL, /* add_buddies */ - novell_remove_buddy, /* remove_buddy */ - NULL, /* remove_buddies */ - novell_add_permit, /* add_permit */ - novell_add_deny, /* add_deny */ - novell_rem_permit, /* rem_permit */ - novell_rem_deny, /* rem_deny */ - novell_set_permit_deny, /* set_permit_deny */ - NULL, /* join_chat */ - NULL, /* reject_chat */ - NULL, /* get_chat_name */ - novell_chat_invite, /* chat_invite */ - novell_chat_leave, /* chat_leave */ - NULL, /* chat_whisper */ - novell_chat_send, /* chat_send */ - novell_keepalive, /* keepalive */ - NULL, /* register_user */ - NULL, /* get_cb_info */ - NULL, /* get_cb_away */ - novell_alias_buddy, /* alias_buddy */ - novell_group_buddy, /* group_buddy */ - novell_rename_group, /* rename_group */ - NULL, /* buddy_free */ - novell_convo_closed, /* convo_closed */ - gaim_normalize_nocase, /* normalize */ - NULL, /* set_buddy_icon */ - novell_remove_group, /* remove_group */ - NULL, /* get_cb_real_name */ - NULL, /* set_chat_topic */ - NULL, /* find_blist_chat */ - NULL, /* roomlist_get_list */ - NULL, /* roomlist_cancel */ - NULL, /* roomlist_expand_category */ - NULL, /* can_receive_file */ - NULL, /* send_file */ - NULL, /* new_xfer */ - NULL, /* offline_message */ - NULL, /* whiteboard_prpl_ops */ -}; - -static GaimPluginInfo info = { - GAIM_PLUGIN_MAGIC, - GAIM_MAJOR_VERSION, - GAIM_MINOR_VERSION, - GAIM_PLUGIN_PROTOCOL, /**< type */ - NULL, /**< ui_requirement */ - 0, /**< flags */ - NULL, /**< dependencies */ - GAIM_PRIORITY_DEFAULT, /**< priority */ - "prpl-novell", /**< id */ - "GroupWise", /**< name */ - VERSION, /**< version */ - /** summary */ - N_("Novell GroupWise Messenger Protocol Plugin"), - /** description */ - N_("Novell GroupWise Messenger Protocol Plugin"), - NULL, /**< author */ - GAIM_WEBSITE, /**< homepage */ - - NULL, /**< load */ - NULL, /**< unload */ - NULL, /**< destroy */ - - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, - NULL -}; - -static void -init_plugin(GaimPlugin * plugin) -{ - GaimAccountOption *option; - - option = gaim_account_option_string_new(_("Server address"), "server", NULL); - prpl_info.protocol_options = - g_list_append(prpl_info.protocol_options, option); - - option = gaim_account_option_int_new(_("Server port"), "port", DEFAULT_PORT); - prpl_info.protocol_options = - g_list_append(prpl_info.protocol_options, option); - - my_protocol = plugin; -} - -GAIM_INIT_PLUGIN(novell, init_plugin, info);