Mercurial > pidgin
diff src/protocols/gg/gg.c @ 11360:cf15c1cdcfbd
[gaim-migrate @ 13582]
New Gadu-Gadu implementation.
committer: Tailor Script <tailor@pidgin.im>
| author | Bartoz Oler <bartosz@pidgin.im> |
|---|---|
| date | Sun, 28 Aug 2005 22:46:01 +0000 |
| parents | 90be432e8385 |
| children | 54934c165625 |
line wrap: on
line diff
--- a/src/protocols/gg/gg.c Sun Aug 28 22:21:24 2005 +0000 +++ b/src/protocols/gg/gg.c Sun Aug 28 22:46:01 2005 +0000 @@ -1,89 +1,79 @@ + /* - * gaim - Gadu-Gadu Protocol Plugin - * - * Copyright (C) 2001 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * NOTES * - * 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 - * + * I don't like automatic updates of the buddylist stored on the server, so not + * going to implement this. Maybe some kind of option to enable/disable this + * feature. */ + #include "internal.h" -/* Library from EKG (Eksperymentalny Klient Gadu-Gadu) */ -#include "libgg.h" - -#include "account.h" -#include "accountopt.h" +#include "plugin.h" +#include "version.h" +#include "notify.h" +#include "status.h" #include "blist.h" -#include "connection.h" +#include "accountopt.h" #include "debug.h" -#include "notify.h" -#include "proxy.h" -#include "prpl.h" -#include "server.h" #include "util.h" -#include "version.h" +#include "request.h" -#define GG_CONNECT_STEPS 5 +#include "lib/libgadu.h" -#define AGG_BUF_LEN 1024 +static GaimPlugin *my_protocol = NULL; -#define AGG_GENDER_NONE -1 +typedef struct +{ + char *token_id; -#define AGG_PUBDIR_USERLIST_EXPORT_FORM "/appsvc/fmcontactsput.asp" -#define AGG_PUBDIR_USERLIST_IMPORT_FORM "/appsvc/fmcontactsget.asp" -#define AGG_PUBDIR_SEARCH_FORM "/appsvc/fmpubquery2.asp" -#define AGG_REGISTER_DATA_FORM "/appsvc/fmregister.asp" -#define AGG_PUBDIR_MAX_ENTRIES 200 +} GGPToken; + +typedef struct { -#define AGG_STATUS_AVAIL _("Available") -#define AGG_STATUS_AVAIL_FRIENDS _("Available for friends only") -#define AGG_STATUS_BUSY _("Away") -#define AGG_STATUS_BUSY_FRIENDS _("Away for friends only") -#define AGG_STATUS_INVISIBLE _("Invisible") -#define AGG_STATUS_INVISIBLE_FRIENDS _("Invisible for friends only") -#define AGG_STATUS_NOT_AVAIL _("Unavailable") + char *uin; + char *lastname; + char *firstname; + char *nickname; + char *city; + char *birthyear; + char *gender; + char *active; + char *offset; -#define AGG_HTTP_NONE 0 -#define AGG_HTTP_SEARCH 1 -#define AGG_HTTP_USERLIST_IMPORT 2 -#define AGG_HTTP_USERLIST_EXPORT 3 -#define AGG_HTTP_USERLIST_DELETE 4 -#define AGG_HTTP_PASSWORD_CHANGE 5 + char *last_uin; + +} GGPSearchForm; + +typedef struct { -#define UC_NORMAL 2 + struct gg_session *session; + GGPSearchForm *search_form; + GGPToken *register_token; + GGPToken *chpasswd_token; + void *searchresults_window; -struct agg_data { - struct gg_session *sess; - int own_status; -}; +} GGPInfo; -struct agg_http { - GaimConnection *gc; - gchar *request; - gchar *form; - gchar *host; - int inpa; - int type; -}; - - +/** + * Convert enconding of a given string. + * + * @param locstr Input string. + * @param encsrc Current encoding of the string. + * @param encdst Target encoding of the string. + * + * @return Converted string (it must be g_free()ed when not used. Or NULL if + * locstr is NULL. + */ +/* static gchar *charset_convert(const gchar *locstr, const char *encsrc, const char *encdst) {{{ */ static gchar *charset_convert(const gchar *locstr, const char *encsrc, const char *encdst) { gchar *msg; GError *err = NULL; + if (locstr == NULL) + return NULL; + msg = g_convert_with_fallback(locstr, strlen(locstr), encdst, encsrc, "?", NULL, NULL, &err); if (err != NULL) { gaim_debug_error("gg", "Error converting from %s to %s: %s\n", @@ -97,673 +87,96 @@ return msg; } - -static gboolean invalid_uin(const char *uin) -{ - unsigned long int res = strtol(uin, (char **)NULL, 10); - if (res == ULONG_MAX || res == 0) - return TRUE; - return FALSE; -} - -static gint args_compare(gconstpointer a, gconstpointer b) -{ - return g_ascii_strcasecmp((const gchar *)a,(const gchar *)b); -} - -static gboolean allowed_uin(GaimConnection *gc, char *uin) -{ - GaimAccount *account = gaim_connection_get_account(gc); - - switch (account->perm_deny) { - case 1: - /* permit all, deny none */ - return TRUE; - break; - case 2: - /* deny all, permit none. */ - return FALSE; - break; - case 3: - /* permit some. */ - if (g_slist_find_custom(gc->account->permit, uin, args_compare)) - return TRUE; - return FALSE; - break; - case 4: - /* deny some. */ - if (g_slist_find_custom(gc->account->deny, uin, args_compare)) - return FALSE; - return TRUE; - break; - default: - return TRUE; - break; - } -} - -static char *handle_errcode(GaimConnection *gc, int errcode) -{ - static char msg[AGG_BUF_LEN]; - - switch (errcode) { - case GG_FAILURE_RESOLVING: - g_snprintf(msg, sizeof(msg), _("Unable to resolve hostname.")); - break; - case GG_FAILURE_CONNECTING: - g_snprintf(msg, sizeof(msg), _("Unable to connect to server.")); - break; - case GG_FAILURE_INVALID: - g_snprintf(msg, sizeof(msg), _("Invalid response from server.")); - break; - case GG_FAILURE_READING: - g_snprintf(msg, sizeof(msg), _("Error while reading from socket.")); - break; - case GG_FAILURE_WRITING: - g_snprintf(msg, sizeof(msg), _("Error while writing to socket.")); - break; - case GG_FAILURE_PASSWORD: - g_snprintf(msg, sizeof(msg), _("Authentication failed.")); - break; - default: - g_snprintf(msg, sizeof(msg), _("Unknown Error Code.")); - break; - } - - gaim_connection_error(gc, msg); - - return msg; -} +/* }}} */ -static void agg_set_status(GaimAccount *account, GaimStatus *status) +/* + * Convert string to number. Check wheter a given + * string is a correct UIN. + * + * Return UIN or 0 if an error occurred. + */ +/* static uin_t ggp_str_to_uin(const char *text) {{{ */ +static uin_t ggp_str_to_uin(const char *text) { - GaimConnection *gc; - struct agg_data *gd; - gboolean connected; - GaimStatusType *type; - int primitive; - int status_num; - const char *status_id; - char *msg = NULL; - - connected = gaim_account_is_connected(account); - type = gaim_status_get_type(status); - primitive = gaim_status_type_get_primitive(type); - - if (!gaim_status_is_active(status)) - return; - - if (!connected) { - if (primitive != GAIM_STATUS_OFFLINE) - gaim_account_connect(account); - return; - } - - if (primitive == GAIM_STATUS_OFFLINE) { - gaim_account_disconnect(account); - return; - } - - gc = gaim_account_get_connection(account); - gd = (struct agg_data *)gc->proto_data; - status_num = gd->own_status; - status_id = gaim_status_get_id(status); - - if (!strcmp(status_id, "available")) - status_num = GG_STATUS_AVAIL; - else if (!strcmp(status_id, "available-friends")) - status_num = GG_STATUS_AVAIL | GG_STATUS_FRIENDS_MASK; - else if (!strcmp(status_id, "away")) - status_num = GG_STATUS_BUSY; - else if (!strcmp(status_id, "away-friends")) - status_num = GG_STATUS_BUSY | GG_STATUS_FRIENDS_MASK; - else if (!strcmp(status_id, "invisible")) - status_num = GG_STATUS_INVISIBLE; - else if (!strcmp(status_id, "invisible-friends")) - status_num = GG_STATUS_INVISIBLE | GG_STATUS_FRIENDS_MASK; - else if (!strcmp(status_id, "unavailable")) - status_num = GG_STATUS_NOT_AVAIL; - else - /* Don't need to do anything */ - return; - - /* XXX: this was added between the status_rewrite and now and needs to be fixed */ - if (msg != NULL) { - switch (status_num) { - case GG_STATUS_AVAIL: - status_num = GG_STATUS_AVAIL_DESCR; - break; - case GG_STATUS_BUSY: - status_num = GG_STATUS_BUSY_DESCR; - break; - case GG_STATUS_INVISIBLE: - status_num = GG_STATUS_INVISIBLE_DESCR; - break; - case GG_STATUS_NOT_AVAIL: - status_num = GG_STATUS_NOT_AVAIL_DESCR; - break; - } - } - - gd->own_status = status_num; - - if (msg) - gg_change_status_descr(gd->sess, status_num, msg); - else - gg_change_status(gd->sess, status_num); -} - + char *tmp; + long num; -#if 0 -static void agg_get_away(GaimConnection *gc, const char *who) -{ - GaimBuddy *buddy; - char *dialog_msg, **splitmsg; - - if (invalid_uin(who)) - return; - - buddy = gaim_find_buddy(gaim_connection_get_account(gc), who); - if (buddy->proto_data) { - /* Split at (carriage return/newline)'s, then rejoin later with BRs between. */ - splitmsg = g_strsplit(buddy->proto_data, "\r\n", 0); - - dialog_msg = g_strdup_printf(_("<B>UIN:</B> %s<BR><B>Status:</B> %s<HR>%s"), who, (char *)buddy->proto_data, g_strjoinv("<BR>", splitmsg)); - gaim_notify_userinfo(gc, who, NULL, _("Buddy Information"), buddy->proto_data, dialog_msg, NULL, NULL); - } -} -#endif - -static gchar *get_away_text(GaimBuddy *buddy) -{ - GaimPresence *presence = gaim_buddy_get_presence(buddy); - - if (gaim_presence_is_status_active(presence, "available")) - return AGG_STATUS_AVAIL; - else if (gaim_presence_is_status_active(presence, "available-friends")) - return AGG_STATUS_AVAIL_FRIENDS; - else if (gaim_presence_is_status_active(presence, "away")) - return AGG_STATUS_BUSY; - else if (gaim_presence_is_status_active(presence, "away-friends")) - return AGG_STATUS_BUSY_FRIENDS; - else if (gaim_presence_is_status_active(presence, "invisible")) - return AGG_STATUS_INVISIBLE; - else if (gaim_presence_is_status_active(presence, "invisible-friends")) - return AGG_STATUS_INVISIBLE_FRIENDS; - else if (gaim_presence_is_status_active(presence, "unavailable")) - return AGG_STATUS_NOT_AVAIL; + if (!text) + return 0; - return AGG_STATUS_AVAIL; -} - - -static GList *agg_status_types(GaimAccount *account) -{ - GaimStatusType *type; - GList *types = NULL; - - type = gaim_status_type_new(GAIM_STATUS_OFFLINE, "offline", - _("Offline"), FALSE); - types = g_list_append(types, type); - - type = gaim_status_type_new(GAIM_STATUS_ONLINE, "online", - _("Online"), FALSE); - types = g_list_append(types, type); - - type = gaim_status_type_new_with_attrs( - GAIM_STATUS_AVAILABLE, "available", AGG_STATUS_AVAIL, - TRUE, TRUE, FALSE, - "message", _("Message"), gaim_value_new(GAIM_TYPE_STRING), NULL); - types = g_list_append(types, type); - - type = gaim_status_type_new_with_attrs( - GAIM_STATUS_AWAY, "away", AGG_STATUS_BUSY, - TRUE, TRUE, FALSE, - "message", _("Message"), gaim_value_new(GAIM_TYPE_STRING), NULL); - types = g_list_append(types, type); - - type = gaim_status_type_new_with_attrs( - GAIM_STATUS_HIDDEN, "invisible", AGG_STATUS_INVISIBLE, - TRUE, TRUE, FALSE, - "message", _("Message"), gaim_value_new(GAIM_TYPE_STRING), NULL); - types = g_list_append(types, type); - - type = gaim_status_type_new_with_attrs( - GAIM_STATUS_AVAILABLE, "available-friends", AGG_STATUS_AVAIL_FRIENDS, - TRUE, TRUE, FALSE, - "message", _("Message"), gaim_value_new(GAIM_TYPE_STRING), NULL); - types = g_list_append(types, type); + errno = 0; + num = strtol(text, &tmp, 0); - type = gaim_status_type_new_with_attrs( - GAIM_STATUS_AWAY, "away-friends", AGG_STATUS_BUSY_FRIENDS, - TRUE, TRUE, FALSE, - "message", _("Message"), gaim_value_new(GAIM_TYPE_STRING), NULL); - types = g_list_append(types, type); - - type = gaim_status_type_new_with_attrs( - GAIM_STATUS_HIDDEN, "invisible-friends", AGG_STATUS_INVISIBLE_FRIENDS, - TRUE, TRUE, FALSE, - "message", _("Message"), gaim_value_new(GAIM_TYPE_STRING), NULL); - types = g_list_append(types, type); - - type = gaim_status_type_new_with_attrs( - GAIM_STATUS_UNAVAILABLE, "unavailable", AGG_STATUS_NOT_AVAIL, - TRUE, TRUE, FALSE, - "message", _("Message"), gaim_value_new(GAIM_TYPE_STRING), NULL); - types = g_list_append(types, type); - - return types; -} - -/* Enhance these functions, more options and such stuff */ -static GList *agg_buddy_menu(GaimBuddy *buddy) -{ - GList *m = NULL; - GaimBlistNodeAction *act; - - static char buf[AGG_BUF_LEN]; - g_snprintf(buf, sizeof(buf), _("Status: %s"), get_away_text(buddy)); - - /* um... this seems silly. since in this pass, I'm only converting - over the menu building, I'm not going to mess with it though */ - /* XXX: shouldn't this be in the tooltip instead? */ - act = gaim_blist_node_action_new(buf, NULL, NULL, NULL); - m = g_list_append(m, act); - - return m; -} - + if (*text == '\0' || *tmp != '\0') + return 0; -static GList * -agg_blist_node_menu(GaimBlistNode *node) -{ - if(GAIM_BLIST_NODE_IS_BUDDY(node)) { - return agg_buddy_menu((GaimBuddy *) node); - } else { - return NULL; - } -} - - -static void agg_load_buddy_list(GaimConnection *gc, char *buddylist) -{ - struct agg_data *gd = (struct agg_data *)gc->proto_data; - gchar *ptr = buddylist; - gchar **users_tbl; - int i; - uin_t *userlist = NULL; - int userlist_size = 0; + if ((errno == ERANGE || (num == LONG_MAX || num == LONG_MIN)) || num > UINT_MAX || num < 0) + return 0; - users_tbl = g_strsplit(ptr, "\r\n", AGG_PUBDIR_MAX_ENTRIES); - - /* Parse array of Buddies List */ - for (i = 0; users_tbl[i] != NULL; i++) { - gchar **data_tbl; - gchar *name, *show; - - if (strlen(users_tbl[i])==0) { - gaim_debug(GAIM_DEBUG_MISC, "gg", - "import_buddies_server_results: users_tbl[i] is empty\n"); - continue; - } - - data_tbl = g_strsplit(users_tbl[i], ";", 8); - - show = charset_convert(data_tbl[3], "CP1250", "UTF-8"); - name = data_tbl[6]; - - if (invalid_uin(name)) { - continue; - } + return (uin_t) num; +} +/* }}} */ - gaim_debug(GAIM_DEBUG_MISC, "gg", - "import_buddies_server_results: uin: %s\n", name); - if (!gaim_find_buddy(gc->account, name)) { - GaimBuddy *b; - GaimGroup *g; - /* Default group if none specified on server */ - gchar *group = g_strdup("Gadu-Gadu"); - if (strlen(data_tbl[5])) { - gchar **group_tbl = g_strsplit(data_tbl[5], ",", 2); - if (strlen(group_tbl[0])) { - g_free(group); - group = g_strdup(group_tbl[0]); - } - g_strfreev(group_tbl); - } - /* Add Buddy to our userlist */ - if (!(g = gaim_find_group(group))) { - g = gaim_group_new(group); - gaim_blist_add_group(g, NULL); - } - b = gaim_buddy_new(gc->account, name, strlen(show) ? show : NULL); - gaim_blist_add_buddy(b,NULL,g,NULL); - - userlist_size++; - userlist = g_renew(uin_t, userlist, userlist_size); - userlist[userlist_size - 1] = - (uin_t) strtol((char *)name, (char **)NULL, 10); - - g_free(group); - } - g_free(show); - g_strfreev(data_tbl); - } - g_strfreev(users_tbl); - - if (userlist) { - gg_notify(gd->sess, userlist, userlist_size); - g_free(userlist); - } +/** + * Get UIN of a given account. + * + * @param account Current account. + * + * @return UIN of an account. + */ +/* static ggp_get_uin(GaimAccount *account) {{{ */ +static uin_t ggp_get_uin(GaimAccount *account) +{ + return ggp_str_to_uin(gaim_account_get_username(account)); } - -static void agg_save_buddy_list(GaimConnection *gc, char *existlist) -{ - struct agg_data *gd = (struct agg_data *)gc->proto_data; - GaimBlistNode *gnode, *cnode, *bnode; - char *buddylist = g_strdup(existlist ? existlist : ""); - char *ptr; - - for(gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) { - GaimGroup *g = (GaimGroup *)gnode; - if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) - continue; - for(cnode = gnode->child; cnode; cnode = cnode->next) { - if(!GAIM_BLIST_NODE_IS_CONTACT(cnode)) - continue; - for(bnode = cnode->child; bnode; bnode = bnode->next) { - GaimBuddy *b = (GaimBuddy *)bnode; - - if(!GAIM_BLIST_NODE_IS_BUDDY(bnode)) - continue; - - if(b->account == gc->account) { - gchar *newdata; - /* GG Number */ - gchar *name = b->name; - /* GG Pseudo */ - gchar *show = b->alias ? b->alias : b->name; - /* Group Name */ - gchar *gname = g->name; - - newdata = g_strdup_printf("%s;%s;%s;%s;%s;%s;%s;%s%s\r\n", - show, show, show, show, "", gname, name, "", ""); - - ptr = buddylist; - buddylist = g_strconcat(ptr, newdata, NULL); - - g_free(newdata); - g_free(ptr); - } - } - } - } +/* }}} */ - /* save the list to the gadu gadu server */ - gg_userlist_request(gd->sess, GG_USERLIST_PUT, buddylist); -} - -static void main_callback(gpointer data, gint source, GaimInputCondition cond) +/** + * Create a new GGPSearchForm structure, and set the fields + * to the sane defaults. + * + * @return Newly allocated GGPSearchForm. + */ +/* GGPSearchForm *ggp_searchform_new() {{{ */ +GGPSearchForm *ggp_searchform_new() { - GaimConnection *gc = data; - GaimAccount *account = gaim_connection_get_account(gc); - struct agg_data *gd = gc->proto_data; - struct gg_event *e; - - gaim_debug(GAIM_DEBUG_INFO, "gg", "main_callback enter: begin\n"); - - if (gd->sess->fd != source) - gd->sess->fd = source; - - if (source == 0) { - gaim_connection_error(gc, _("Could not connect")); - return; - } - - if (!(e = gg_watch_fd(gd->sess))) { - gaim_debug(GAIM_DEBUG_ERROR, "gg", - "main_callback: gg_watch_fd failed - CRITICAL!\n"); - gaim_connection_error(gc, _("Unable to read socket")); - return; - } - - switch (e->type) { - case GG_EVENT_NONE: - /* do nothing */ - break; - case GG_EVENT_CONN_SUCCESS: - gaim_debug(GAIM_DEBUG_WARNING, "gg", - "main_callback: CONNECTED AGAIN!?\n"); - break; - case GG_EVENT_CONN_FAILED: - if (gc->inpa) - gaim_input_remove(gc->inpa); - handle_errcode(gc, e->event.failure); - break; - case GG_EVENT_MSG: - { - gchar *imsg; - gchar *jmsg; - gchar user[20]; - - g_snprintf(user, sizeof(user), "%lu", e->event.msg.sender); - if (!allowed_uin(gc, user)) - break; - imsg = charset_convert(e->event.msg.message, "CP1250", "UTF-8"); - gaim_str_strip_cr(imsg); - jmsg = g_markup_escape_text(imsg, -1); - serv_got_im(gc, user, jmsg, 0, e->event.msg.time); - g_free(imsg); - g_free(jmsg); - } - break; - case GG_EVENT_NOTIFY: - { - gchar user[20]; - struct gg_notify_reply *n = e->event.notify; - const char *status_id; - - while (n->uin) { - switch (n->status) { - case GG_STATUS_NOT_AVAIL: - status_id = "unavailable"; - break; - - case GG_STATUS_AVAIL: - status_id = "available"; - break; - - case GG_STATUS_BUSY: - status_id = "away"; - break; - - case GG_STATUS_INVISIBLE: - status_id = "invisible"; - break; - - default: - status_id = "available"; - break; - - } + GGPSearchForm *form; - g_snprintf(user, sizeof(user), "%lu", n->uin); - gaim_prpl_got_user_status(account, user, status_id, NULL); - n++; - } - } - break; - case GG_EVENT_NOTIFY60: - { - gchar user[20]; - const char *status_id; - guint i = 0; - - for (i = 0; e->event.notify60[i].uin; i++) { - GaimBuddy *buddy; - - g_snprintf(user, sizeof(user), "%lu", (long unsigned int)e->event.notify60[i].uin); - - buddy = gaim_find_buddy(gaim_connection_get_account(gc), user); - if (buddy && buddy->proto_data != NULL) { - g_free(buddy->proto_data); - buddy->proto_data = NULL; - } - - switch (e->event.notify60[i].status) { - case GG_STATUS_NOT_AVAIL: - case GG_STATUS_NOT_AVAIL_DESCR: - status_id = "unavailable"; - break; - - case GG_STATUS_AVAIL: - case GG_STATUS_AVAIL_DESCR: - status_id = "available"; - break; - - case GG_STATUS_BUSY: - case GG_STATUS_BUSY_DESCR: - status_id = "away"; - break; + form = g_new0(GGPSearchForm, 1); + form->uin = NULL; + form->lastname = NULL; + form->firstname = NULL; + form->nickname = NULL; + form->city = NULL; + form->birthyear = NULL; + form->gender = NULL; + form->active = NULL; + form->offset = NULL; - case GG_STATUS_INVISIBLE: - case GG_STATUS_INVISIBLE_DESCR: - status_id = "invisible"; - break; - - default: - status_id = "available"; - break; - } - - if (buddy && e->event.notify60[i].descr != NULL) { - buddy->proto_data = g_strdup(e->event.notify60[i].descr); - } - - gaim_prpl_got_user_status(account, user, status_id, NULL); - i++; - } - } - break; - case GG_EVENT_STATUS: - { - gchar user[20]; - const char *status_id; - - switch (e->event.status.status) { - case GG_STATUS_NOT_AVAIL: - status_id = "unavailable"; - break; - - case GG_STATUS_AVAIL: - status_id = "available"; - break; - - case GG_STATUS_BUSY: - status_id = "away"; - break; - - case GG_STATUS_INVISIBLE: - status_id = "invisible"; - break; - - default: - status_id = "available"; - break; - } + form->last_uin = NULL; - g_snprintf(user, sizeof(user), "%lu", e->event.status.uin); - gaim_prpl_got_user_status(account, user, status_id, NULL); - } - break; - case GG_EVENT_STATUS60: - { - gchar user[20]; - const char *status_id; - - GaimBuddy *buddy; - - g_snprintf(user, sizeof(user), "%lu", e->event.status60.uin); - - buddy = gaim_find_buddy(gaim_connection_get_account(gc), user); - if (buddy && buddy->proto_data != NULL) { - g_free(buddy->proto_data); - buddy->proto_data = NULL; - } + return form; +} +/* }}} */ - switch (e->event.status60.status) { - case GG_STATUS_NOT_AVAIL_DESCR: - case GG_STATUS_NOT_AVAIL: - status_id = "unavailable"; - break; - - case GG_STATUS_AVAIL: - case GG_STATUS_AVAIL_DESCR: - status_id = "available"; - break; - - case GG_STATUS_BUSY: - case GG_STATUS_BUSY_DESCR: - status_id = "away"; - break; - - case GG_STATUS_INVISIBLE: - case GG_STATUS_INVISIBLE_DESCR: - status_id = "invisible"; - break; +/* ---------------------------------------------------------------------- */ +/* ----- BUDDYLIST STUFF ------------------------------------------------ */ +/* ---------------------------------------------------------------------- */ - default: - status_id = "available"; - break; - } - - if (buddy && e->event.status60.descr != NULL) { - buddy->proto_data = g_strdup(e->event.status60.descr); - } - - gaim_prpl_got_user_status(account, user, status_id, NULL); - } - break; - case GG_EVENT_ACK: - gaim_debug(GAIM_DEBUG_MISC, "gg", - "main_callback: message %d to %lu sent with status %d\n", - e->event.ack.seq, e->event.ack.recipient, e->event.ack.status); - break; - case GG_EVENT_USERLIST: - { - gaim_debug(GAIM_DEBUG_MISC, "gg", "main_callback: received userlist reply\n"); - switch (e->event.userlist.type) { - case GG_USERLIST_GET_REPLY: - { +/* + * Adapted from the previous GG implementation in Gaim + * by Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL> + */ +/* static void ggp_buddylist_send(GaimConnection *gc) {{{ */ +static void ggp_buddylist_send(GaimConnection *gc) +{ + GGPInfo *info = gc->proto_data; - if (e->event.userlist.reply) { - agg_load_buddy_list(gc, e->event.userlist.reply); - } - break; - } - - case GG_USERLIST_PUT_REPLY: - { - /* ignored */ - } - } - } - - default: - gaim_debug(GAIM_DEBUG_ERROR, "gg", - "main_callback: unsupported event %d\n", e->type); - break; - } - gg_free_event(e); -} - -static void agg_send_buddylist(GaimConnection *gc) -{ GaimBuddyList *blist; GaimBlistNode *gnode, *cnode, *bnode; GaimBuddy *buddy; - struct agg_data *gd = (struct agg_data *)gc->proto_data; uin_t *userlist = NULL; + gchar *types = NULL; int userlist_size = 0; if ((blist = gaim_get_blist()) != NULL) @@ -781,1061 +194,1612 @@ if (!GAIM_BLIST_NODE_IS_BUDDY(bnode)) continue; buddy = (GaimBuddy *)bnode; - if (invalid_uin(buddy->name)) + + if (buddy->account != gc->account) continue; + userlist_size++; - userlist = g_renew(uin_t, userlist, userlist_size); - userlist[userlist_size - 1] = - (uin_t) strtol(buddy->name, (char **)NULL, 10); + userlist = (uin_t *) g_renew(uin_t, userlist, userlist_size); + types = (gchar *) g_renew(gchar, types, userlist_size); + userlist[userlist_size - 1] = ggp_str_to_uin(buddy->name); + types[userlist_size - 1] = GG_USER_NORMAL; + gaim_debug_info("gg", "ggp_buddylist_send: adding %d\n", userlist[userlist_size - 1]); } } } } if (userlist) { - gg_notify(gd->sess, userlist, userlist_size); + int ret = gg_notify_ex(info->session, userlist, types, userlist_size); g_free(userlist); - } - - agg_save_buddy_list(gc, NULL); -} - -void login_callback(gpointer data, gint source, GaimInputCondition cond) -{ - GaimConnection *gc = data; - struct agg_data *gd = gc->proto_data; - struct gg_event *e; - - gaim_debug(GAIM_DEBUG_INFO, "gg", "login_callback...\n"); - if (!g_list_find(gaim_connections_get_all(), gc)) { - close(source); - return; - } - - gaim_debug(GAIM_DEBUG_INFO, "gg", "Found GG connection\n"); - - if (source == 0) { - gaim_connection_error(gc, _("Unable to connect.")); - return; - } - - gd->sess->fd = source; - - gaim_debug(GAIM_DEBUG_MISC, "gg", "Source is valid.\n"); - if (gc->inpa == 0) { - gaim_debug(GAIM_DEBUG_MISC, "gg", - "login_callback.. checking gc->inpa .. is 0.. setting fd watch\n"); - gc->inpa = gaim_input_add(gd->sess->fd, GAIM_INPUT_READ, login_callback, gc); - gaim_debug(GAIM_DEBUG_INFO, "gg", "Adding watch on fd\n"); - } - gaim_debug(GAIM_DEBUG_INFO, "gg", "Checking State.\n"); - switch (gd->sess->state) { - case GG_STATE_READING_DATA: - gaim_connection_update_progress(gc, _("Reading data"), 1, GG_CONNECT_STEPS); - break; - case GG_STATE_CONNECTING_GG: - gaim_connection_update_progress(gc, _("Balancer handshake"), 2, GG_CONNECT_STEPS); - break; - case GG_STATE_READING_KEY: - gaim_connection_update_progress(gc, _("Reading server key"), 3, GG_CONNECT_STEPS); - break; - case GG_STATE_READING_REPLY: - gaim_connection_update_progress(gc, _("Exchanging key hash"), 4, GG_CONNECT_STEPS); - break; - default: - gaim_debug(GAIM_DEBUG_INFO, "gg", "No State found\n"); - break; - } - gaim_debug(GAIM_DEBUG_MISC, "gg", "gg_watch_fd\n"); - if (!(e = gg_watch_fd(gd->sess))) { - gaim_debug(GAIM_DEBUG_ERROR, "gg", - "login_callback: gg_watch_fd failed - CRITICAL!\n"); - gaim_connection_error(gc, _("Critical error in GG library\n")); - return; - } - - /* If we are GG_STATE_CONNECTING_GG then we still need to connect, as - we could not use gaim_proxy_connect in libgg.c */ - switch( gd->sess->state ) { - case GG_STATE_CONNECTING_GG: - { - struct in_addr ip; - char buf[256]; - - /* Remove watch on initial socket - now that we have ip and port of login server */ - gaim_input_remove(gc->inpa); - - ip.s_addr = gd->sess->server_ip; + g_free(types); - if (gaim_proxy_connect(gc->account, inet_ntoa(ip), gd->sess->port, login_callback, gc) < 0) { - g_snprintf(buf, sizeof(buf), _("Connect to %s failed"), inet_ntoa(ip)); - gaim_connection_error(gc, buf); - return; - } - break; - } - case GG_STATE_READING_KEY: - /* Set new watch on login server ip */ - if(gc->inpa) - gc->inpa = gaim_input_add(gd->sess->fd, GAIM_INPUT_READ, login_callback, gc); - gaim_debug(GAIM_DEBUG_INFO, "gg", - "Setting watch on connection with login server.\n"); - break; - }/* end switch() */ - - gaim_debug(GAIM_DEBUG_MISC, "gg", "checking gg_event\n"); - switch (e->type) { - case GG_EVENT_NONE: - /* nothing */ - break; - case GG_EVENT_CONN_SUCCESS: - /* Setup new input handler */ - if (gc->inpa) - gaim_input_remove(gc->inpa); - gc->inpa = gaim_input_add(gd->sess->fd, GAIM_INPUT_READ, main_callback, gc); - - /* Our signon is complete */ - gaim_connection_set_state(gc, GAIM_CONNECTED); - - /* Send the server our buddy list */ - agg_send_buddylist(gc); - - break; - case GG_EVENT_CONN_FAILED: - gaim_input_remove(gc->inpa); - gc->inpa = 0; - handle_errcode(gc, e->event.failure); - break; - default: - gaim_debug(GAIM_DEBUG_MISC, "gg", "no gg_event\n"); - break; - } - gaim_debug(GAIM_DEBUG_INFO, "gg", "Returning from login_callback\n"); - gg_free_event(e); -} - -static void agg_keepalive(GaimConnection *gc) -{ - struct agg_data *gd = (struct agg_data *)gc->proto_data; - if (gg_ping(gd->sess) < 0) { - gaim_connection_error(gc, _("Unable to ping server")); - return; - } -} - -static void agg_login(GaimAccount *account, GaimStatus *status) -{ - GaimConnection *gc = gaim_account_get_connection(account); - struct agg_data *gd = gc->proto_data = g_new0(struct agg_data, 1); - char buf[80]; - -#if 0 - gc->checkbox = _("Send as message"); -#endif - - gd->sess = g_new0(struct gg_session, 1); - - gaim_connection_update_progress(gc, _("Looking up GG server"), 0, GG_CONNECT_STEPS); - - if (invalid_uin(account->username)) { - gaim_connection_error(gc, _("Invalid Gadu-Gadu UIN specified")); - return; - } - - gc->inpa = 0; - - /* - if (gg_login(gd->sess, strtol(user->username, (char **)NULL, 10), user->password, 1) < 0) { - gaim_debug(GAIM_DEBUG_MISC, "gg", "uin=%u, pass=%s", strtol(user->username, (char **)NULL, 10), user->password); - gaim_connection_error(gc, _("Unable to connect.")); - signoff(gc); - return; - } - - gg_login() sucks for me, so I'm using gaim_proxy_connect() - */ - - gd->sess->uin = (uin_t) strtol(account->username, (char **)NULL, 10); - gd->sess->password = g_strdup(gaim_connection_get_password(gc)); - gd->sess->state = GG_STATE_CONNECTING; - gd->sess->check = GG_CHECK_WRITE; - gd->sess->async = 1; - if (gaim_proxy_connect(account, GG_APPMSG_HOST, GG_APPMSG_PORT, login_callback, gc) < 0) { - g_snprintf(buf, sizeof(buf), _("Connect to %s failed"), GG_APPMSG_HOST); - gaim_connection_error(gc, buf); - return; + gaim_debug_info("gg", "send: ret=%d; size=%d\n", ret, userlist_size); } } - -static void agg_close(GaimConnection *gc) -{ - struct agg_data *gd = (struct agg_data *)gc->proto_data; - if (gc->inpa) - gaim_input_remove(gc->inpa); - gg_logoff(gd->sess); - gd->own_status = GG_STATUS_NOT_AVAIL; - gg_free_session(gd->sess); - g_free(gc->proto_data); -} - -static int agg_send_im(GaimConnection *gc, const char *who, const char *msg, GaimConvImFlags flags) -{ - struct agg_data *gd = (struct agg_data *)gc->proto_data; - - if (invalid_uin(who)) { - gaim_notify_error(gc, NULL, - _("You are trying to send a message to an " - "invalid Gadu-Gadu UIN."), NULL); - return -1; - } - - if (strlen(msg) > 0) { - gchar *imsg = charset_convert(msg, "UTF-8", "CP1250"); - if (imsg != NULL && strlen(imsg) > 0) { - if (gg_send_message(gd->sess, GG_CLASS_CHAT, - strtol(who, (char **)NULL, 10), imsg) < 0) - return -1; - } - if (imsg != NULL) - g_free(imsg); - } - return 1; -} - -static void agg_add_buddy(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *group) -{ - struct agg_data *gd = (struct agg_data *)gc->proto_data; - if (invalid_uin(buddy->name)) - return; - gg_add_notify(gd->sess, strtol(buddy->name, (char **)NULL, 10)); - agg_save_buddy_list(gc, NULL); -} - -static void agg_rem_buddy(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *group) -{ - struct agg_data *gd = (struct agg_data *)gc->proto_data; - if (invalid_uin(buddy->name)) - return; - gg_remove_notify(gd->sess, strtol(buddy->name, (char **)NULL, 10)); - agg_save_buddy_list(gc, NULL); -} - -static void agg_buddy_free (GaimBuddy *buddy) -{ - if (buddy->proto_data) { - g_free(buddy->proto_data); - buddy->proto_data = NULL; - } -} - -static void search_results(GaimConnection *gc, gchar *webdata) -{ - gchar **webdata_tbl; - gchar *buf; - char *ptr; - int i, j; - - if ((ptr = strstr(webdata, "query_results:")) == NULL || (ptr = strchr(ptr, '\n')) == NULL) { - gaim_debug(GAIM_DEBUG_MISC, "gg", "search_callback: pubdir result [%s]\n", webdata); - gaim_notify_error(gc, NULL, _("Couldn't get search results"), NULL); - return; - } - ptr++; - - buf = g_strconcat("<B>", _("Gadu-Gadu Search Engine"), "</B><BR>\n", NULL); - - webdata_tbl = g_strsplit(ptr, "\n", AGG_PUBDIR_MAX_ENTRIES); - - j = 0; - - /* Parse array */ - /* XXX - Make this use a GString */ - for (i = 0; webdata_tbl[i] != NULL; i++) { - gchar *p, *oldibuf; - static gchar *ibuf; - - g_strdelimit(webdata_tbl[i], "\t\n", ' '); +/* }}} */ - /* GG_PUBDIR_HOST service returns 7 lines of data per directory entry */ - if (i % 8 == 0) - j = 0; - - p = charset_convert(g_strstrip(webdata_tbl[i]), "CP1250", "UTF-8"); - - oldibuf = ibuf; - - switch (j) { - case 0: - ibuf = g_strconcat("---------------------------------<BR>\n", NULL); - oldibuf = ibuf; - ibuf = g_strconcat(oldibuf, "<B>", _("Active"), ":</B> ", - (atoi(p) == 2) ? _("Yes") : _("No"), "<BR>\n", NULL); - g_free(oldibuf); - break; - case 1: - ibuf = g_strconcat(oldibuf, "<B>", _("UIN"), ":</B> ", p, "<BR>\n", NULL); - g_free(oldibuf); - break; - case 2: - ibuf = g_strconcat(oldibuf, "<B>", _("First Name"), ":</B> ", p, "<BR>\n", NULL); - g_free(oldibuf); - break; - case 3: - ibuf = - g_strconcat(oldibuf, "<B>", _("Last Name"), ":</B> ", p, "<BR>\n", NULL); - g_free(oldibuf); - break; - case 4: - ibuf = g_strconcat(oldibuf, "<B>", _("Nick"), ":</B> ", p, "<BR>\n", NULL); - g_free(oldibuf); - break; - case 5: - /* Hack, invalid_uin does what we really want here but may change in future */ - if (invalid_uin(p)) - ibuf = - g_strconcat(oldibuf, "<B>", _("Birth Year"), ":</B> <BR>\n", NULL); - else - ibuf = - g_strconcat(oldibuf, "<B>", _("Birth Year"), ":</B> ", p, "<BR>\n", - NULL); - g_free(oldibuf); - break; - case 6: - if (atoi(p) == GG_GENDER_FEMALE) - ibuf = g_strconcat(oldibuf, "<B>", _("Sex"), ":</B> woman<BR>\n", NULL); - else if (atoi(p) == GG_GENDER_MALE) - ibuf = g_strconcat(oldibuf, "<B>", _("Sex"), ":</B> man<BR>\n", NULL); - else - ibuf = g_strconcat(oldibuf, "<B>", _("Sex"), ":</B> <BR>\n", NULL); - g_free(oldibuf); - break; - case 7: - ibuf = g_strconcat(oldibuf, "<B>", _("City"), ":</B> ", p, "<BR>\n", NULL); - g_free(oldibuf); - - /* We have all lines, so add them to buffer */ - { - gchar *oldbuf = buf; - buf = g_strconcat(oldbuf, ibuf, NULL); - g_free(oldbuf); - } - - g_free(ibuf); - break; - } - - g_free(p); - - j++; - } - - g_strfreev(webdata_tbl); - - gaim_notify_formatted(gc, NULL, _("Buddy Information"), NULL, - buf, NULL, NULL); - - g_free(buf); -} - -static void -change_pass(GaimPluginAction *action) +/** + * Load buddylist from server into the rooster. + * + * @param gc GaimConnection + * @param buddylist Pointer to the buddylist that will be loaded. + */ +/* static void ggp_buddylist_load(GaimConnection *gc, char *buddylist) {{{ */ +static void ggp_buddylist_load(GaimConnection *gc, char *buddylist) { - GaimConnection *gc = (GaimConnection *) action->context; - GaimAccount *account = gaim_connection_get_account(gc); - gaim_account_request_change_password(account); -} - -#if 0 -static void import_buddies_server_results(GaimConnection *gc, gchar *webdata) -{ - gchar *ptr; + GaimBuddy *buddy; + GaimGroup *group; gchar **users_tbl; int i; - if (strstr(webdata, "no_data:")) { - gaim_notify_error(gc, NULL, - _("There is no Buddy List stored on the " - "Gadu-Gadu server."), NULL); - return; - } - if ((ptr = strstr(webdata, "get_results:")) == NULL || (ptr = strchr(ptr, ':')) == NULL) { - gaim_debug(GAIM_DEBUG_MISC, "gg", "import_buddies_server_results: import buddies result [%s]\n", webdata); - gaim_notify_error(gc, NULL, - _("Couldn't Import Buddy List from Server"), NULL); - return; - } - ptr++; + users_tbl = g_strsplit(buddylist, "\r\n", 200); - users_tbl = g_strsplit(ptr, "\n", AGG_PUBDIR_MAX_ENTRIES); - - /* Parse array of Buddies List */ for (i = 0; users_tbl[i] != NULL; i++) { gchar **data_tbl; gchar *name, *show; - if (strlen(users_tbl[i])==0) { - gaim_debug(GAIM_DEBUG_MISC, "gg", - "import_buddies_server_results: users_tbl[i] is empty\n"); + if (strlen(users_tbl[i]) == 0) continue; - } - g_strdelimit(users_tbl[i], "\r\t\n\015", ' '); data_tbl = g_strsplit(users_tbl[i], ";", 8); show = charset_convert(data_tbl[3], "CP1250", "UTF-8"); name = data_tbl[6]; - if (invalid_uin(name)) { + gaim_debug_info("gg", "got buddy: name=%s show=%s\n", name, show); + + if (gaim_find_buddy(gaim_connection_get_account(gc), name)) { + g_free(show); + g_strfreev(data_tbl); continue; } - gaim_debug(GAIM_DEBUG_MISC, "gg", - "import_buddies_server_results: uin: %s\n", name); - if (!gaim_find_buddy(gc->account, name)) { - GaimBuddy *b; - GaimGroup *g; - /* Default group if none specified on server */ - gchar *group = g_strdup("Gadu-Gadu"); - if (strlen(data_tbl[5])) { - gchar **group_tbl = g_strsplit(data_tbl[5], ",", 2); - if (strlen(group_tbl[0])) { - g_free(group); - group = g_strdup(group_tbl[0]); - } - g_strfreev(group_tbl); + gchar *g = g_strdup("Gadu-Gadu"); + + if (strlen(data_tbl[5])) { + /* Hard limit to at most 50 groups */ + gchar **group_tbl = g_strsplit(data_tbl[5], ",", 50); + if (strlen(group_tbl[0]) > 0) { + g_free(g); + g = g_strdup(group_tbl[0]); } - /* Add Buddy to our userlist */ - if (!(g = gaim_find_group(group))) { - g = gaim_group_new(group); - gaim_blist_add_group(g, NULL); - } - b = gaim_buddy_new(gc->account, name, strlen(show) ? show : NULL); - gaim_blist_add_buddy(b, NULL, g, NULL); - g_free(group); + g_strfreev(group_tbl); } + + buddy = gaim_buddy_new(gaim_connection_get_account(gc), name, strlen(show) ? show : NULL); + if (!(group = gaim_find_group(g))) { + group = gaim_group_new(g); + gaim_blist_add_group(group, NULL); + } + + gaim_blist_add_buddy(buddy, NULL, group, NULL); + g_free(g); + g_free(show); g_strfreev(data_tbl); } g_strfreev(users_tbl); -} + + ggp_buddylist_send(gc); -static void export_buddies_server_results(GaimConnection *gc, gchar *webdata) +} +/* }}} */ + +/* + */ +/* static void ggp_generic_status_handler(GaimConnection *gc, uin_t uin, int status, const char *descr) {{{ */ +static void ggp_generic_status_handler(GaimConnection *gc, uin_t uin, int status, const char *descr) { - if (strstr(webdata, "put_success:")) { - gaim_notify_info(gc, NULL, - _("Buddy List successfully transferred to " - "Gadu-Gadu server"), NULL); - return; + gchar *from; + const char *st; + gchar *msg; + + from = g_strdup_printf("%ld", (unsigned long int)uin); + switch (status) { + case GG_STATUS_NOT_AVAIL: + case GG_STATUS_NOT_AVAIL_DESCR: + st = "offline"; + break; + case GG_STATUS_AVAIL: + case GG_STATUS_AVAIL_DESCR: + st = "online"; + break; + case GG_STATUS_BUSY: + case GG_STATUS_BUSY_DESCR: + st = "away"; + break; + case GG_STATUS_BLOCKED: + /* user is blocking us.... */ + st = "blocked"; + break; + default: + st = "online"; + gaim_debug_info("gg", "GG_EVENT_NOTIFY: Unknown status: %d\n", status); + break; } - gaim_debug(GAIM_DEBUG_MISC, "gg", - "export_buddies_server_results: webdata [%s]\n", webdata); - gaim_notify_error(gc, NULL, - _("Couldn't transfer Buddy List to Gadu-Gadu server"), - NULL); + gaim_debug_info("gg", "st = %s\n", st); + msg = charset_convert(descr, "CP1250", "UTF-8"); + gaim_prpl_got_user_status(gaim_connection_get_account(gc), from, st, "message", msg, NULL); + g_free(from); + g_free(msg); } +/* }}} */ -static void delete_buddies_server_results(GaimConnection *gc, gchar *webdata) +/* + */ +/* static void ggp_pubdir_start_search(GaimConnection *gc, GGPSearchForm *form) {{{ */ +static void ggp_pubdir_start_search(GaimConnection *gc, GGPSearchForm *form) { - if (strstr(webdata, "put_success:")) { - gaim_notify_info(gc, NULL, - _("Buddy List successfully deleted from " - "Gadu-Gadu server"), NULL); + GGPInfo *info = gc->proto_data; + gg_pubdir50_t req; + + gaim_debug_info("gg", "It's time to perform a search...\n"); + + if ((req = gg_pubdir50_new(GG_PUBDIR50_SEARCH)) == NULL) { + gaim_debug_error("gg", "ggp_bmenu_show_details: Unable to create req variable.\n"); return; } - gaim_debug(GAIM_DEBUG_MISC, "gg", - "delete_buddies_server_results: webdata [%s]\n", webdata); - gaim_notify_error(gc, NULL, - _("Couldn't delete Buddy List from Gadu-Gadu server"), - NULL); -} -#endif + if (form->uin != NULL) { + gaim_debug_info("gg", " uin: %s\n", form->uin); + gg_pubdir50_add(req, GG_PUBDIR50_UIN, form->uin); + } else { + if (form->lastname != NULL) { + gaim_debug_info("gg", " lastname: %s\n", form->lastname); + gg_pubdir50_add(req, GG_PUBDIR50_LASTNAME, form->lastname); + } + + if (form->firstname != NULL) { + gaim_debug_info("gg", " firstname: %s\n", form->firstname); + gg_pubdir50_add(req, GG_PUBDIR50_FIRSTNAME, form->firstname); + } + + if (form->nickname != NULL) { + gaim_debug_info("gg", " nickname: %s\n", form->nickname); + gg_pubdir50_add(req, GG_PUBDIR50_NICKNAME, form->nickname); + } -static void password_change_server_results(GaimConnection *gc, gchar *webdata) -{ - if (strstr(webdata, "reg_success:")) { - gaim_notify_info(gc, NULL, - _("Password changed successfully"), NULL); + if (form->city != NULL) { + gaim_debug_info("gg", " city: %s\n", form->city); + gg_pubdir50_add(req, GG_PUBDIR50_CITY, form->city); + } + + if (form->birthyear != NULL) { + gaim_debug_info("gg", " birthyear: %s\n", form->birthyear); + gg_pubdir50_add(req, GG_PUBDIR50_BIRTHYEAR, form->birthyear); + } + + if (form->gender != NULL) { + gaim_debug_info("gg", " gender: %s\n", form->gender); + gg_pubdir50_add(req, GG_PUBDIR50_GENDER, form->gender); + } + + if (form->active != NULL) { + gaim_debug_info("gg", " active: %s\n", form->active); + gg_pubdir50_add(req, GG_PUBDIR50_ACTIVE, form->active); + } + } + + gaim_debug_info("gg", "offset: %s\n", form->offset); + gg_pubdir50_add(req, GG_PUBDIR50_START, g_strdup(form->offset)); + + if (gg_pubdir50(info->session, req) == 0) { + gaim_debug_warning("gg", "ggp_bmenu_show_details: Search failed.\n"); return; } - gaim_debug(GAIM_DEBUG_MISC, "gg", - "password_change_server_results: webdata [%s]\n", webdata); - gaim_notify_error(gc, NULL, - _("Password couldn't be changed"), NULL); + gg_pubdir50_free(req); +} +/* }}} */ + +/* + * Return converted to the UTF-8 value of the specified field. + * + * @param res Public directory look-up result + * @param num Id of the record + * @param fileld Name of the field + * + * @return UTF-8 encoded value of the field + */ +/* static char *ggp_get_pubdir_info(gg_pubdir50_t res, int num, const char *field) {{{ */ +static char *ggp_get_pubdir_info(gg_pubdir50_t res, int num, const char *field) +{ + char *tmp; + + tmp = charset_convert(gg_pubdir50_get(res, num, field), "CP1250", "UTF-8"); + + return (tmp == NULL) ? g_strdup("") : tmp; +} +/* }}} */ + +static void ggp_callback_show_next(GaimConnection *gc, GList *row) +{ + GGPInfo *info = gc->proto_data; + + g_free(info->search_form->offset); + info->search_form->offset = g_strdup(info->search_form->last_uin); + gaim_debug_info("gg", "london calling... offset = %s\n", info->search_form->offset); + ggp_pubdir_start_search(gc, info->search_form); } -static void http_results(gpointer data, gint source, GaimInputCondition cond) +static void ggp_callback_add_buddy(GaimConnection *gc, GList *row) { - struct agg_http *hdata = data; - GaimConnection *gc = hdata->gc; - char *webdata; - int len; - char read_data; + gaim_blist_request_add_buddy(gaim_connection_get_account(gc), + g_list_nth_data(row, 0), NULL, NULL); +} - gaim_debug(GAIM_DEBUG_INFO, "gg", "http_results: begin\n"); +/* + */ +/* static void ggp_callback_recv(gpointer _gc, gint fd, GaimInputCondition cond) {{{ */ +static void ggp_callback_recv(gpointer _gc, gint fd, GaimInputCondition cond) +{ + GaimConnection *gc = _gc; + GGPInfo *info = gc->proto_data; + struct gg_event *ev; + int i; - if (!g_list_find(gaim_connections_get_all(), gc)) { - gaim_debug(GAIM_DEBUG_ERROR, "gg", - "search_callback: g_slist_find error\n"); - gaim_input_remove(hdata->inpa); - g_free(hdata); - close(source); + if (!(ev = gg_watch_fd(info->session))) { + gaim_debug_error("gg", "ggp_callback_recv: gg_watch_fd failed -- CRITICAL!\n"); + gaim_connection_error(gc, _("Unable to read socket")); return; } - webdata = NULL; - len = 0; + switch (ev->type) { + case GG_EVENT_NONE: + /* Nothing happened. */ + break; + case GG_EVENT_MSG: + { + gchar *from; + gchar *msg; + gchar *tmp; + + from = g_strdup_printf("%lu", (unsigned long int)ev->event.msg.sender); - while (read(source, &read_data, 1) > 0 || errno == EWOULDBLOCK) { - if (errno == EWOULDBLOCK) { - errno = 0; - continue; - } + msg = charset_convert((const char *)ev->event.msg.message, + "CP1250", "UTF-8"); + gaim_str_strip_cr(msg); + tmp = g_markup_escape_text(msg, -1); + gaim_debug_info("gg", "msg form (%s): %s (class = %d)\n", from, tmp, ev->event.msg.msgclass); + serv_got_im(gc, from, tmp, 0, ev->event.msg.time); + g_free(msg); + g_free(tmp); + g_free(from); + } + break; + case GG_EVENT_ACK: + gaim_debug_info("gg", "message sent to: %ld, delivery status=%d, seq=%d\n", + ev->event.ack.recipient, ev->event.ack.status, ev->event.ack.seq); + break; + case GG_EVENT_NOTIFY: + case GG_EVENT_NOTIFY_DESCR: + { + struct gg_notify_reply *n; + char *descr; - if (!read_data) - continue; + gaim_debug_info("gg", "notify_pre: (%d) status: %d\n", + ev->event.notify->uin, + ev->event.notify->status); + + n = (ev->type == GG_EVENT_NOTIFY) ? ev->event.notify + : ev->event.notify_descr.notify; - len++; - webdata = g_realloc(webdata, len); - webdata[len - 1] = read_data; - } + for (; n->uin; n++) { + descr = (ev->type == GG_EVENT_NOTIFY) ? NULL + : ev->event.notify_descr.descr; + gaim_debug_info("gg", "notify: (%d) status: %d; descr: %s\n", + n->uin, n->status, descr); + + ggp_generic_status_handler(gc, + n->uin, n->status, descr); + } + } + break; + case GG_EVENT_NOTIFY60: + gaim_debug_info("gg", "notify60_pre: (%d) status=%d; version=%d; descr=%s\n", + ev->event.notify60->uin, ev->event.notify60->status, + ev->event.notify60->version, ev->event.notify60->descr); + + for (i = 0; ev->event.notify60[i].uin; i++) { + gaim_debug_info("gg", "notify60: (%d) status=%d; version=%d; descr=%s\n", + ev->event.notify60[i].uin, ev->event.notify60[i].status, + ev->event.notify60[i].version, ev->event.notify60[i].descr); - webdata = g_realloc(webdata, len + 1); - webdata[len] = 0; + ggp_generic_status_handler(gc, + ev->event.notify60[i].uin, + ev->event.notify60[i].status, + ev->event.notify60[i].descr); + } + break; + case GG_EVENT_STATUS: + gaim_debug_info("gg", "status: (%d) status=%d; descr=%s\n", + ev->event.status.uin, ev->event.status.status, + ev->event.status.descr); - gaim_input_remove(hdata->inpa); - close(source); - - gaim_debug(GAIM_DEBUG_MISC, "gg", - "http_results: type %d, webdata [%s]\n", hdata->type, webdata); + ggp_generic_status_handler(gc, + ev->event.status.uin, + ev->event.status.status, + ev->event.status.descr); + break; + case GG_EVENT_STATUS60: + gaim_debug_info("gg", "status60: (%d) status=%d; version=%d; descr=%s\n", + ev->event.status60.uin, + ev->event.status60.status, + ev->event.status60.version, + ev->event.status60.descr); - switch (hdata->type) { - case AGG_HTTP_SEARCH: - search_results(gc, webdata); - break; -#if 0 - case AGG_HTTP_USERLIST_IMPORT: - import_buddies_server_results(gc, webdata); - break; - case AGG_HTTP_USERLIST_EXPORT: - export_buddies_server_results(gc, webdata); - break; - case AGG_HTTP_USERLIST_DELETE: - delete_buddies_server_results(gc, webdata); - break; -#endif - case AGG_HTTP_PASSWORD_CHANGE: - password_change_server_results(gc, webdata); - break; - case AGG_HTTP_NONE: - default: - gaim_debug(GAIM_DEBUG_ERROR, "gg", - "http_results: unsupported type %d\n", hdata->type); - break; - } + ggp_generic_status_handler(gc, + ev->event.status60.uin, + ev->event.status60.status, + ev->event.status60.descr); + break; + case GG_EVENT_USERLIST: + if (ev->event.userlist.type == GG_USERLIST_GET_REPLY) { + gaim_debug_info("gg", "GG_USERLIST_GET_REPLY\n"); + if (ev->event.userlist.reply != NULL) { + ggp_buddylist_load(gc, ev->event.userlist.reply); + } + break; + } else { + gaim_debug_info("gg", "GG_USERLIST_PUT_REPLY. Userlist stored on the server.\n"); + } + break; + case GG_EVENT_PUBDIR50_SEARCH_REPLY: + { + GaimNotifySearchResults *results; + GaimNotifySearchColumn *column; + gg_pubdir50_t req = ev->event.pubdir50; + int res_count = 0; + int start; + int i; + + res_count = gg_pubdir50_count(req); + if (res_count < 1) { + gaim_debug_info("gg", "GG_EVENT_PUBDIR50_SEARCH_REPLY: Nothing found\n"); + return; + } + res_count = (res_count > 20) ? 20 : res_count; + + results = gaim_notify_searchresults_new(); + + column = gaim_notify_searchresults_column_new("UIN"); + gaim_notify_searchresults_column_add(results, column); + + column = gaim_notify_searchresults_column_new("First name"); + gaim_notify_searchresults_column_add(results, column); + + column = gaim_notify_searchresults_column_new("Nick name"); + gaim_notify_searchresults_column_add(results, column); - g_free(webdata); - g_free(hdata); -} + column = gaim_notify_searchresults_column_new("City"); + gaim_notify_searchresults_column_add(results, column); -static void http_req_callback(gpointer data, gint source, GaimInputCondition cond) -{ - struct agg_http *hdata = data; - GaimConnection *gc = hdata->gc; - gchar *request = hdata->request; - gchar *buf; + column = gaim_notify_searchresults_column_new("Birth year"); + gaim_notify_searchresults_column_add(results, column); - gaim_debug(GAIM_DEBUG_INFO, "gg", "http_req_callback: begin\n"); + gaim_debug_info("gg", "Going with %d entries\n", res_count); + + start = (int)ggp_str_to_uin(gg_pubdir50_get(req, 0, GG_PUBDIR50_START)); + gaim_debug_info("gg", "start = %d\n", start); - if (!g_list_find(gaim_connections_get_all(), gc)) { - gaim_debug(GAIM_DEBUG_ERROR, "gg", - "http_req_callback: g_slist_find error\n"); - g_free(request); - g_free(hdata); - close(source); - return; - } + for (i = 0; i < res_count; i++) { + GList *row = NULL; + char *birth = ggp_get_pubdir_info(req, i, GG_PUBDIR50_BIRTHYEAR); + + /* TODO: Status will be displayed as an icon. */ + /* row = g_list_append(row, ggp_get_pubdir_info(req, i, GG_PUBDIR50_STATUS)); */ + row = g_list_append(row, ggp_get_pubdir_info(req, i, GG_PUBDIR50_UIN)); + row = g_list_append(row, ggp_get_pubdir_info(req, i, GG_PUBDIR50_FIRSTNAME)); + row = g_list_append(row, ggp_get_pubdir_info(req, i, GG_PUBDIR50_NICKNAME)); + row = g_list_append(row, ggp_get_pubdir_info(req, i, GG_PUBDIR50_CITY)); + row = g_list_append(row, (birth && strncmp(birth, "0", 1)) ? birth : g_strdup("-")); + gaim_notify_searchresults_row_add(results, row); + if (i == res_count - 1) { + g_free(info->search_form->last_uin); + info->search_form->last_uin = ggp_get_pubdir_info(req, i, GG_PUBDIR50_UIN); + } + } - if (source == 0) { - g_free(request); - g_free(hdata); - return; + gaim_notify_searchresults_button_add(results, GAIM_NOTIFY_BUTTON_CONTINUE, ggp_callback_show_next); + gaim_notify_searchresults_button_add(results, GAIM_NOTIFY_BUTTON_ADD_BUDDY, ggp_callback_add_buddy); + if (info->searchresults_window == NULL) { + void *h = gaim_notify_searchresults(gc, _("Gadu-Gadu Public Directory"), + _("Search results"), NULL, results, NULL, NULL); + info->searchresults_window = h; + } else { + gaim_notify_searchresults_new_rows(gc, results, info->searchresults_window, NULL); + } + } + break; + default: + gaim_debug_error("gg", "unsupported event type=%d\n", ev->type); + break; } - gaim_debug(GAIM_DEBUG_MISC, "gg", - "http_req_callback: http request [%s]\n", request); - - buf = g_strdup_printf("POST %s HTTP/1.0\r\n" - "Host: %s\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "User-Agent: " GG_HTTP_USERAGENT "\r\n" - "Content-Length: %d\r\n" - "Pragma: no-cache\r\n" "\r\n" "%s\r\n", - hdata->form, hdata->host, (int)strlen(request), request); - - g_free(request); + gg_free_event(ev); +} +/* }}} */ - if (write(source, buf, strlen(buf)) < strlen(buf)) { - g_free(buf); - g_free(hdata); - close(source); - gaim_notify_error(gc, NULL, - _("Error communicating with Gadu-Gadu server"), - _("Gaim was unable to complete your request due " - "to a problem communicating with the Gadu-Gadu " - "HTTP server. Please try again later.")); - return; - } - - g_free(buf); +/** + * Set offline status for all buddies. + * + * @param gc Connection handler + */ +/* static void ggp_buddylist_offline(GaimConnection *gc) {{{ */ +static void ggp_buddylist_offline(GaimConnection *gc) +{ + GaimBuddyList *blist; + GaimBlistNode *gnode, *cnode, *bnode; + GaimBuddy *buddy; - hdata->inpa = gaim_input_add(source, GAIM_INPUT_READ, http_results, hdata); -} - -#if 0 -static void import_buddies_server(GaimConnection *gc) -{ - struct agg_http *hi = g_new0(struct agg_http, 1); - gchar *u = gg_urlencode(gaim_account_get_username(gc->account)); - gchar *p = gg_urlencode(gaim_connection_get_password(gc)); + if ((blist = gaim_get_blist()) != NULL) + { + for (gnode = blist->root; gnode != NULL; gnode = gnode->next) + { + if (!GAIM_BLIST_NODE_IS_GROUP(gnode)) + continue; + for (cnode = gnode->child; cnode != NULL; cnode = cnode->next) + { + if (!GAIM_BLIST_NODE_IS_CONTACT(cnode)) + continue; + for (bnode = cnode->child; bnode != NULL; bnode = bnode->next) + { + if (!GAIM_BLIST_NODE_IS_BUDDY(bnode)) + continue; - hi->gc = gc; - hi->type = AGG_HTTP_USERLIST_IMPORT; - hi->form = AGG_PUBDIR_USERLIST_IMPORT_FORM; - hi->host = GG_PUBDIR_HOST; - hi->request = g_strdup_printf("FmNum=%s&Pass=%s", u, p); + buddy = (GaimBuddy *)bnode; - g_free(u); - g_free(p); + if (buddy->account != gc->account) + continue; - if (gaim_proxy_connect(gc->account, GG_PUBDIR_HOST, GG_PUBDIR_PORT, http_req_callback, hi) < 0) { - gaim_notify_error(gc, NULL, - _("Unable to import Gadu-Gadu buddy list"), - _("Gaim was unable to connect to the Gadu-Gadu " - "buddy list server. Please try again later.")); - g_free(hi->request); - g_free(hi); - return; + gaim_prpl_got_user_status( + gaim_connection_get_account(gc), + buddy->name, "offline", NULL); + gaim_debug_info("gg", "ggp_buddylist_offline: gone: %s\n", buddy->name); + } + } + } } } - -static void export_buddies_server(GaimConnection *gc) -{ - struct agg_http *he = g_new0(struct agg_http, 1); - gchar *ptr; - gchar *u = gg_urlencode(gaim_account_get_username(gc->account)); - gchar *p = gg_urlencode(gaim_connection_get_password(gc)); +/* }}} */ +/** + * Get all the buddies in the current account. + * + * @param account Current account. + * + * @return List of buddies. + */ +/* static char *ggp_buddylist_dump(GaimAccount *account) {{{ */ +static char *ggp_buddylist_dump(GaimAccount *account) +{ + GaimBuddyList *blist; GaimBlistNode *gnode, *cnode, *bnode; - - he->gc = gc; - he->type = AGG_HTTP_USERLIST_EXPORT; - he->form = AGG_PUBDIR_USERLIST_EXPORT_FORM; - he->host = GG_PUBDIR_HOST; - he->request = g_strdup_printf("FmNum=%s&Pass=%s&Contacts=", u, p); + GaimGroup *group; + GaimBuddy *buddy; - g_free(u); - g_free(p); + char *buddylist = g_strdup(""); + char *ptr; - for(gnode = gaim_get_blist()->root; gnode; gnode = gnode->next) { - GaimGroup *g = (GaimGroup *)gnode; - int num_added=0; - if(!GAIM_BLIST_NODE_IS_GROUP(gnode)) + if ((blist = gaim_get_blist()) == NULL) + return NULL; + + for (gnode = blist->root; gnode != NULL; gnode = gnode->next) { + if (!GAIM_BLIST_NODE_IS_GROUP(gnode)) continue; - for(cnode = gnode->child; cnode; cnode = cnode->next) { - if(!GAIM_BLIST_NODE_IS_CONTACT(cnode)) + + group = (GaimGroup *)gnode; + + for (cnode = gnode->child; cnode != NULL; cnode = cnode->next) { + if (!GAIM_BLIST_NODE_IS_CONTACT(cnode)) continue; - for(bnode = cnode->child; bnode; bnode = bnode->next) { - GaimBuddy *b = (GaimBuddy *)bnode; - if(!GAIM_BLIST_NODE_IS_BUDDY(bnode)) + for (bnode = cnode->child; bnode != NULL; bnode = bnode->next) { + if (!GAIM_BLIST_NODE_IS_BUDDY(bnode)) continue; - if(b->account == gc->account) { - gchar *newdata; - /* GG Number */ - gchar *name = gg_urlencode(b->name); - /* GG Pseudo */ - gchar *show = gg_urlencode(b->alias ? b->alias : b->name); - /* Group Name */ - gchar *gname = gg_urlencode(g->name); - - ptr = he->request; - newdata = g_strdup_printf("%s;%s;%s;%s;%s;%s;%s", - show, show, show, show, "", gname, name); + buddy = (GaimBuddy *)bnode; + if (buddy->account != account) + continue; - if(num_added > 0) - he->request = g_strconcat(ptr, "%0d%0a", newdata, NULL); - else - he->request = g_strconcat(ptr, newdata, NULL); - - num_added++; + gchar *newdata; + /* GG Number */ + gchar *name = buddy->name; + /* GG Pseudo */ + gchar *show = buddy->alias ? buddy->alias : buddy->name; + /* Group Name */ + gchar *gname = group->name; - g_free(newdata); - g_free(ptr); + newdata = g_strdup_printf("%s;%s;%s;%s;%s;%s;%s;%s%s\r\n", + show, show, show, show, "", gname, name, "", ""); - g_free(gname); - g_free(show); - g_free(name); - } + ptr = buddylist; + buddylist = g_strconcat(ptr, newdata, NULL); + + g_free(newdata); + g_free(ptr); } } } - if (gaim_proxy_connect(gc->account, GG_PUBDIR_HOST, GG_PUBDIR_PORT, http_req_callback, he) < 0) { - gaim_notify_error(gc, NULL, - _("Couldn't export buddy list"), - _("Gaim was unable to connect to the buddy " - "list server. Please try again later.")); - g_free(he->request); - g_free(he); + return buddylist; +} +/* }}} */ + +/** + * Request buddylist from the server. + * Buddylist is received in the ggp_callback_recv(). + * + * @param Current action handler. + */ +/* static void ggp_action_buddylist_get(GaimPluginAction *action) {{{ */ +static void ggp_action_buddylist_get(GaimPluginAction *action) +{ + GaimConnection *gc = (GaimConnection *)action->context; + GGPInfo *info = gc->proto_data; + + gaim_debug_info("gg", "Downloading...\n"); + + gg_userlist_request(info->session, GG_USERLIST_GET, NULL); +} +/* }}} */ + +/** + * Upload the buddylist to the server. + * + * @param action Current action handler. + */ +/* static void ggp_action_buddylist_put(GaimPluginAction *action) {{{ */ +static void ggp_action_buddylist_put(GaimPluginAction *action) +{ + GaimConnection *gc = (GaimConnection *)action->context; + GGPInfo *info = gc->proto_data; + + char *buddylist = ggp_buddylist_dump(gaim_connection_get_account(gc)); + + gaim_debug_info("gg", "Uploading...\n"); + + if (buddylist == NULL) + return; + + gg_userlist_request(info->session, GG_USERLIST_PUT, buddylist); + g_free(buddylist); +} +/* }}} */ + +/** + * Delete buddylist from the server. + * + * @param action Current action handler. + */ +/* static void ggp_action_buddylist_delete(GaimPluginAction *action) {{{ */ +static void ggp_action_buddylist_delete(GaimPluginAction *action) +{ + GaimConnection *gc = (GaimConnection *)action->context; + GGPInfo *info = gc->proto_data; + + gaim_debug_info("gg", "Deleting...\n"); + + gg_userlist_request(info->session, GG_USERLIST_PUT, NULL); +} +/* }}} */ + +/* + */ +/* static void ggp_callback_buddylist_save_ok(GaimConnection *gc, gchar *file) {{{ */ +static void ggp_callback_buddylist_save_ok(GaimConnection *gc, gchar *file) +{ + GaimAccount *account = gaim_connection_get_account(gc); + + FILE *fh; + char *buddylist = ggp_buddylist_dump(account); + gchar *msg; + + gaim_debug_info("gg", "Saving...\n"); + gaim_debug_info("gg", "file = %s\n", file); + + if (buddylist == NULL) { + gaim_notify_info(account, _("Save Buddylist..."), + _("Your buddylist is empty, nothing was written to the file."), + NULL); return; } -} -static void delete_buddies_server(GaimConnection *gc) -{ - struct agg_http *he = g_new0(struct agg_http, 1); - gchar *u = gg_urlencode(gaim_account_get_username(gc->account)); - gchar *p = gg_urlencode(gaim_connection_get_password(gc)); + if ((fh = g_fopen(file, "wb")) == NULL) { + msg = g_strconcat(_("Couldn't open file"), ": ", file, "\n", NULL); + gaim_debug_error("gg", "Could not open file: %s\n", file); + gaim_notify_error(account, _("Couldn't open file"), msg, NULL); + g_free(msg); + g_free(file); + return; + } + + fwrite(buddylist, sizeof(char), g_utf8_strlen(buddylist, -1), fh); + fclose(fh); + g_free(buddylist); + + gaim_notify_info(account, _("Save Buddylist..."), + _("Buddylist saved successfully!"), NULL); +} +/* }}} */ - he->gc = gc; - he->type = AGG_HTTP_USERLIST_DELETE; - he->form = AGG_PUBDIR_USERLIST_EXPORT_FORM; - he->host = GG_PUBDIR_HOST; - he->request = g_strdup_printf("FmNum=%s&Pass=%s&Delete=1", u, p); +/* + */ +/* static void ggp_callback_buddylist_load_ok(GaimConnection *gc, gchar *file) {{{ */ +static void ggp_callback_buddylist_load_ok(GaimConnection *gc, gchar *file) +{ + GaimAccount *account = gaim_connection_get_account(gc); + char *buddylist, *tmp, *ptr; + FILE *fh; + gchar *msg; - if (gaim_proxy_connect(gc->account, GG_PUBDIR_HOST, GG_PUBDIR_PORT, http_req_callback, he) < 0) { - gaim_notify_error(gc, NULL, - _("Unable to delete Gadu-Gadu buddy list"), - _("Gaim was unable to connect to the buddy " - "list server. Please try again later.")); - g_free(he->request); - g_free(he); + buddylist = g_strdup(""); + tmp = g_new0(gchar, 50); + + gaim_debug_info("gg", "file_name = %s\n", file); + + if ((fh = g_fopen(file, "rb")) == NULL) { + msg = g_strconcat(_("Couldn't open file"), ": ", file, "\n", NULL); + gaim_debug_error("gg", "Could not open file: %s\n", file); + gaim_notify_error(account, _("Could't open file"), msg, NULL); + g_free(msg); + g_free(file); return; } + + while (fread(tmp, sizeof(gchar), 49, fh) == 49) { + tmp[49] = '\0'; + /* gaim_debug_info("gg", "read: %s\n", tmp); */ + ptr = g_strconcat(buddylist, tmp, NULL); + memset(tmp, '\0', 50); + g_free(buddylist); + buddylist = ptr; + } + fclose(fh); + g_free(tmp); + + ggp_buddylist_load(gc, buddylist); + g_free(buddylist); + + gaim_notify_info(account, + _("Load Buddylist..."), + _("Buddylist loaded successfully!"), NULL); } -#endif +/* }}} */ + +/* + */ +/* static void ggp_action_buddylist_save(GaimPluginAction *action) {{{ */ +static void ggp_action_buddylist_save(GaimPluginAction *action) +{ + GaimConnection *gc = (GaimConnection *)action->context; + + gaim_request_file(action, _("Save buddylist..."), NULL, TRUE, + G_CALLBACK(ggp_callback_buddylist_save_ok), NULL, gc); +} +/* }}} */ -#if 0 -static void agg_dir_search(GaimConnection *gc, const char *first, const char *middle, - const char *last, const char *maiden, const char *city, const char *state, - const char *country, const char *email) +/* + */ +/* static void ggp_action_buddylist_load(GaimPluginAction *action) {{{ */ +static void ggp_action_buddylist_load(GaimPluginAction *action) +{ + GaimConnection *gc = (GaimConnection *)action->context; + + gaim_request_file(action, "Load buddylist from file...", NULL, FALSE, + G_CALLBACK(ggp_callback_buddylist_load_ok), NULL, gc); +} +/* }}} */ + +/* + */ +/* static void ggp_callback_change_passwd_ok(GaimConnection *gc, GaimRequestFields *fields) {{{ */ +static void ggp_callback_change_passwd_ok(GaimConnection *gc, GaimRequestFields *fields) { - struct agg_http *srch = g_new0(struct agg_http, 1); - srch->gc = gc; - srch->type = AGG_HTTP_SEARCH; - srch->form = AGG_PUBDIR_SEARCH_FORM; - srch->host = GG_PUBDIR_HOST; + GaimAccount *account; + GGPInfo *info = gc->proto_data; + struct gg_http *h; + gchar *cur, *p1, *p2, *t; + + cur = charset_convert(gaim_request_fields_get_string(fields, "password_cur"), + "UTF-8", "CP1250"); + p1 = charset_convert(gaim_request_fields_get_string(fields, "password1"), + "UTF-8", "CP1250"); + p2 = charset_convert(gaim_request_fields_get_string(fields, "password2"), + "UTF-8", "CP1250"); + t = charset_convert(gaim_request_fields_get_string(fields, "token"), + "UTF-8", "CP1250"); + + account = gaim_connection_get_account(gc); + + if (cur == NULL || p1 == NULL || p2 == NULL || t == NULL || + *cur == '\0' || *p1 == '\0' || *p2 == '\0' || *t == '\0') { + gaim_notify_error(account, NULL, _("Fill in the fields."), NULL); + goto exit_err; + } + + if (g_utf8_collate(p1, p2) != 0) { + gaim_notify_error(account, NULL, _("New passwords do not match."), NULL); + goto exit_err; + } - if (email && strlen(email)) { - gchar *eemail = gg_urlencode(email); - srch->request = g_strdup_printf("Mode=1&Email=%s", eemail); - g_free(eemail); - } else { - gchar *new_first = charset_convert(first, "UTF-8", "CP1250"); - gchar *new_last = charset_convert(last, "UTF-8", "CP1250"); - gchar *new_city = charset_convert(city, "UTF-8", "CP1250"); + if (g_utf8_collate(cur, gaim_account_get_password(account)) != 0) { + gaim_notify_error(account, NULL, + _("Your current password is different from the one that you specified."), + NULL); + goto exit_err; + } + + gaim_debug_info("gg", "change_passwd: old=%s; p1=%s; token=%s\n", + cur, p1, info->chpasswd_token->token_id); + + /* XXX: this e-mail should be a pref... */ + h = gg_change_passwd4(ggp_get_uin(account), + "user@example.net", gaim_account_get_password(account), + p1, info->chpasswd_token->token_id, t, 0); - gchar *enew_first = gg_urlencode(new_first); - gchar *enew_last = gg_urlencode(new_last); - gchar *enew_city = gg_urlencode(new_city); + if (h == NULL) { + gaim_notify_error(account, NULL, + _("Unable to change password. Error occured.\n"), + NULL); + goto exit_err; + } + + gaim_account_set_password(account, p1); + + gg_change_passwd_free(h); + + gaim_notify_info(account, _("Change password for the Gadu-Gadu account"), + _("Password was changed successfully!"), NULL); + +exit_err: + g_free(cur); + g_free(p1); + g_free(p2); + g_free(t); + g_free(info->chpasswd_token->token_id); + g_free(info->chpasswd_token); +} +/* }}} */ - g_free(new_first); - g_free(new_last); - g_free(new_city); +/* + */ +/* static void ggp_callback_register_account_ok(GaimConnection *gc, GaimRequestFields *fields) {{{ */ +static void ggp_callback_register_account_ok(GaimConnection *gc, GaimRequestFields *fields) +{ + GaimAccount *account; + GGPInfo *info = gc->proto_data; + struct gg_http *h = NULL; + struct gg_pubdir *s; + uin_t uin; + gchar *email, *p1, *p2, *t; - /* For active only add &ActiveOnly= */ - srch->request = g_strdup_printf("Mode=0&FirstName=%s&LastName=%s&Gender=%d" - "&NickName=%s&City=%s&MinBirth=%d&MaxBirth=%d", - enew_first, enew_last, AGG_GENDER_NONE, - "", enew_city, 0, 0); + email = charset_convert(gaim_request_fields_get_string(fields, "email"), + "UTF-8", "CP1250"); + p1 = charset_convert(gaim_request_fields_get_string(fields, "password1"), + "UTF-8", "CP1250"); + p2 = charset_convert(gaim_request_fields_get_string(fields, "password2"), + "UTF-8", "CP1250"); + t = charset_convert(gaim_request_fields_get_string(fields, "token"), + "UTF-8", "CP1250"); + + account = gaim_connection_get_account(gc); - g_free(enew_first); - g_free(enew_last); - g_free(enew_city); + if (email == NULL || p1 == NULL || p2 == NULL || t == NULL || + *email == '\0' || *p1 == '\0' || *p2 == '\0' || *t == '\0') { + gaim_notify_error(account, NULL, _("Fill in the fields."), NULL); + goto exit_err; + } + + if (g_utf8_collate(p1, p2) != 0) { + gaim_notify_error(account, NULL, _("Passwords do not match."), NULL); + goto exit_err; + } + + h = gg_register3(email, p1, info->register_token->token_id, t, 0); + if (h == NULL || !(s = h->data) || !s->success) { + gaim_notify_error(account, NULL, + _("Unable to register new account. Error occured.\n"), + NULL); + goto exit_err; } - if (gaim_proxy_connect(gc->account, GG_PUBDIR_HOST, GG_PUBDIR_PORT, http_req_callback, srch) < 0) { - gaim_notify_error(gc, NULL, - _("Unable to access directory"), - _("Gaim was unable to search the Directory " - "because it was unable to connect to the " - "directory server. Please try again later.")); - g_free(srch->request); - g_free(srch); + uin = s->uin; + gaim_debug_info("gg", "registered uin: %d\n", uin); + + gaim_notify_info(NULL, _("New Gadu-Gadu Account Registered"), + _("Registration completed successfully!"), NULL); + +exit_err: + gg_register_free(h); + g_free(email); + g_free(p1); + g_free(p2); + g_free(t); + g_free(info->register_token->token_id); + g_free(info->register_token); +} +/* }}} */ + +/* + */ +/* static void ggp_callback_find_buddies(GaimConnection *gc, GaimRequestFields *fields) {{{ */ +static void ggp_callback_find_buddies(GaimConnection *gc, GaimRequestFields *fields) +{ + GGPInfo *info = gc->proto_data; + GGPSearchForm *form; + + form = ggp_searchform_new(); + /* + * TODO: Fail if we have already a form attached. Only one search + * at a time will be allowed for now. + */ + info->search_form = form; + + form->lastname = charset_convert(gaim_request_fields_get_string(fields, "lastname"), + "UTF-8", "CP1250"); + form->firstname = charset_convert(gaim_request_fields_get_string(fields, "firstname"), + "UTF-8", "CP1250"); + form->nickname = charset_convert(gaim_request_fields_get_string(fields, "nickname"), + "UTF-8", "CP1250"); + form->city = charset_convert(gaim_request_fields_get_string(fields, "city"), + "UTF-8", "CP1250"); + form->birthyear = charset_convert(gaim_request_fields_get_string(fields, "year"), + "UTF-8", "CP1250"); + + switch (gaim_request_fields_get_choice(fields, "gender")) { + case 1: + form->gender = g_strdup(GG_PUBDIR50_GENDER_MALE); + break; + case 2: + form->gender = g_strdup(GG_PUBDIR50_GENDER_FEMALE); + break; + default: + form->gender = NULL; + break; + } + + form->active = gaim_request_fields_get_bool(fields, "active") + ? g_strdup(GG_PUBDIR50_ACTIVE_TRUE) : NULL; + + form->offset = g_strdup("0"); + + ggp_pubdir_start_search(gc, form); +} +/* }}} */ + +/* + */ +/* static void ggp_find_buddies(GaimPluginAction *action) {{{ */ +static void ggp_find_buddies(GaimPluginAction *action) +{ + GaimConnection *gc = (GaimConnection *)action->context; + + GaimRequestFields *fields; + GaimRequestFieldGroup *group; + GaimRequestField *field; + + fields = gaim_request_fields_new(); + group = gaim_request_field_group_new(NULL); + gaim_request_fields_add_group(fields, group); + + field = gaim_request_field_string_new("lastname", _("Last name"), NULL, FALSE); + gaim_request_field_string_set_masked(field, FALSE); + gaim_request_field_group_add_field(group, field); + + field = gaim_request_field_string_new("firstname", _("First name"), NULL, FALSE); + gaim_request_field_string_set_masked(field, FALSE); + gaim_request_field_group_add_field(group, field); + + field = gaim_request_field_string_new("nickname", _("Nickname"), NULL, FALSE); + gaim_request_field_string_set_masked(field, FALSE); + gaim_request_field_group_add_field(group, field); + + field = gaim_request_field_string_new("city", _("City"), NULL, FALSE); + gaim_request_field_string_set_masked(field, FALSE); + gaim_request_field_group_add_field(group, field); + + field = gaim_request_field_string_new("year", _("Year of birth"), NULL, FALSE); + gaim_request_field_group_add_field(group, field); + + field = gaim_request_field_choice_new("gender", "Gender", 0); + gaim_request_field_choice_add(field, "Male or female"); + gaim_request_field_choice_add(field, "Male"); + gaim_request_field_choice_add(field, "Female"); + gaim_request_field_group_add_field(group, field); + + field = gaim_request_field_bool_new("active", _("Only online"), FALSE); + gaim_request_field_group_add_field(group, field); + + gaim_request_fields(gc, + _("Find buddies"), + _("Find buddies"), + _("Please, enter your search criteria below"), + fields, + _("OK"), G_CALLBACK(ggp_callback_find_buddies), + _("Cancel"), NULL, + gc); +} +/* }}} */ + +/* + */ +/* static void ggp_change_passwd(GaimPluginAction *action) {{{ */ +static void ggp_change_passwd(GaimPluginAction *action) +{ + GaimConnection *gc = (GaimConnection *)action->context; + GGPInfo *info = gc->proto_data; + GGPToken *token; + + GaimRequestFields *fields; + GaimRequestFieldGroup *group; + GaimRequestField *field; + + struct gg_http *req; + struct gg_token *t; + gchar *msg; + + gaim_debug_info("gg", "token: requested.\n"); + + /* TODO: This should be async. */ + if ((req = gg_token(0)) == NULL) { + gaim_notify_error(gaim_connection_get_account(gc), + _("Token Error"), + _("Unable to fetch the token.\n"), NULL); return; } + + t = req->data; + + token = g_new0(GGPToken, 1); + token->token_id = g_strdup(t->tokenid); + info->chpasswd_token = token; + + + fields = gaim_request_fields_new(); + group = gaim_request_field_group_new(NULL); + gaim_request_fields_add_group(fields, group); + + field = gaim_request_field_string_new("password_cur", _("Current password"), "", FALSE); + gaim_request_field_string_set_masked(field, TRUE); + gaim_request_field_group_add_field(group, field); + + field = gaim_request_field_string_new("password1", _("Password"), "", FALSE); + gaim_request_field_string_set_masked(field, TRUE); + gaim_request_field_group_add_field(group, field); + + field = gaim_request_field_string_new("password2", _("Password (retype)"), "", FALSE); + gaim_request_field_string_set_masked(field, TRUE); + gaim_request_field_group_add_field(group, field); + + field = gaim_request_field_string_new("token", _("Enter current token"), "", FALSE); + gaim_request_field_string_set_masked(field, FALSE); + gaim_request_field_group_add_field(group, field); + + /* original size: 60x24 */ + field = gaim_request_field_image_new("token_img", _("Current token"), req->body, req->body_size); + gaim_request_field_group_add_field(group, field); + + gg_token_free(req); + + msg = g_strdup_printf("%s %d", + _("Please, enter your current password and your new password for UIN: "), + ggp_get_uin(gaim_connection_get_account(gc))); + + gaim_request_fields(gc, + _("Change Gadu-Gadu Password"), + _("Change Gadu-Gadu Password"), + msg, + fields, _("OK"), G_CALLBACK(ggp_callback_change_passwd_ok), + _("Cancel"), NULL, gc); + + g_free(msg); +} +/* }}} */ + +/* ---------------------------------------------------------------------- */ +/* ----- GaimPluginProtocolInfo ----------------------------------------- */ +/* ---------------------------------------------------------------------- */ + +/* + */ +/* static const char *ggp_list_icon(GaimAccount *account, GaimBuddy *buddy) {{{ */ +static const char *ggp_list_icon(GaimAccount *account, GaimBuddy *buddy) +{ + return "gadu-gadu"; +} +/* }}} */ + +/* + */ +/* static void ggp_list_emblems(GaimBuddy *b, const char **se, const char **sw, const char **nw, const char **ne) {{{ */ +static void ggp_list_emblems(GaimBuddy *b, const char **se, const char **sw, const char **nw, const char **ne) +{ + GaimPresence *presence = gaim_buddy_get_presence(b); + + /* + * Note to myself: + * The only valid status types are those defined + * in prpl_info->status_types. + * + * Usable icons: away, blocked, dnd, extendedaway, + * freeforchat, ignored, invisible, na, offline. + */ + + if (!GAIM_BUDDY_IS_ONLINE(b)) { + *se = "offline"; + } else if (gaim_presence_is_status_active(presence, "away")) { + *se = "away"; + } else if (gaim_presence_is_status_active(presence, "online")) { + *se = "online"; + } else if (gaim_presence_is_status_active(presence, "offline")) { + *se = "offline"; + } else if (gaim_presence_is_status_active(presence, "blocked")) { + *se = "blocked"; + } else { + *se = "offline"; + gaim_debug_info("gg", "ggp_list_emblems: unknown status\n"); + } } -#endif +/* }}} */ -static void agg_change_passwd(GaimConnection *gc, const char *old, const char *new) +/* + */ +/* static char *ggp_status_text(GaimBuddy *b) {{{ */ +static char *ggp_status_text(GaimBuddy *b) { - struct agg_http *hpass = g_new0(struct agg_http, 1); - gchar *u = gg_urlencode(gaim_account_get_username(gc->account)); - gchar *p = gg_urlencode(gaim_connection_get_password(gc)); - gchar *enew = gg_urlencode(new); - gchar *eold = gg_urlencode(old); + GaimStatus *status; + const char *msg; + char *text; + char *tmp; - hpass->gc = gc; - hpass->type = AGG_HTTP_PASSWORD_CHANGE; - hpass->form = AGG_REGISTER_DATA_FORM; - hpass->host = GG_REGISTER_HOST; + status = gaim_presence_get_active_status(gaim_buddy_get_presence(b)); - /* We are using old password as place for email - it's ugly */ - hpass->request = g_strdup_printf("fmnumber=%s&fmpwd=%s&pwd=%s&email=%s&code=%u", - u, p, enew, eold, gg_http_hash(old, new)); + msg = gaim_status_get_attr_string(status, "message"); - g_free(u); - g_free(p); - g_free(enew); - g_free(eold); + if (msg != NULL) { + tmp = gaim_markup_strip_html(msg); + text = g_markup_escape_text(tmp, -1); + g_free(tmp); - if (gaim_proxy_connect(gc->account, GG_REGISTER_HOST, GG_REGISTER_PORT, http_req_callback, hpass) < 0) { - gaim_notify_error(gc, NULL, - _("Unable to change Gadu-Gadu password"), - _("Gaim was unable to change your password " - "due to an error connecting to the " - "Gadu-Gadu server. Please try again " - "later.")); - g_free(hpass->request); - g_free(hpass); - return; + return text; + } else { + tmp = g_strdup(gaim_status_get_name(status)); + text = g_markup_escape_text(tmp, -1); + g_free(tmp); + + return text; } } +/* }}} */ -static GList *agg_actions(GaimPlugin *plugin, gpointer context) +/* + */ +/* static char *ggp_tooltip_text(GaimBuddy *b) {{{ */ +static char *ggp_tooltip_text(GaimBuddy *b) +{ + GaimStatus *status; + char *text; + gchar *ret; + const char *msg, *name; + + status = gaim_presence_get_active_status(gaim_buddy_get_presence(b)); + msg = gaim_status_get_attr_string(status, "message"); + name = gaim_status_get_name(status); + + if (msg != NULL) { + char *tmp = gaim_markup_strip_html(msg); + text = g_markup_escape_text(tmp, -1); + g_free(tmp); + + ret = g_strdup_printf("\n<b>%s:</b> %s: %s", + _("Status"), name, text); + + g_free(text); + } else { + ret = g_strdup_printf("\n<b>%s:</b> %s", + _("Status"), name); + } + + return ret; +} +/* }}} */ + +/* + */ +/* static GList *ggp_status_types(GaimAccount *account) {{{ */ +static GList *ggp_status_types(GaimAccount *account) +{ + GaimStatusType *type; + GList *types = NULL; + + type = gaim_status_type_new_with_attrs(GAIM_STATUS_OFFLINE, "offline", _("Offline"), + TRUE, TRUE, FALSE, "message", _("Message"), + gaim_value_new(GAIM_TYPE_STRING), NULL); + types = g_list_append(types, type); + + type = gaim_status_type_new_with_attrs(GAIM_STATUS_ONLINE, "online", _("Online"), + TRUE, TRUE, FALSE, "message", _("Message"), + gaim_value_new(GAIM_TYPE_STRING), NULL); + types = g_list_append(types, type); + + /* + * Without this selecting Available or Invisible as own status doesn't + * work. It's not used and not needed to show status of buddies. + */ + type = gaim_status_type_new_with_attrs(GAIM_STATUS_AVAILABLE, "available", _("Available"), + TRUE, TRUE, FALSE, "message", _("Message"), + gaim_value_new(GAIM_TYPE_STRING), NULL); + types = g_list_append(types, type); + + type = gaim_status_type_new_with_attrs(GAIM_STATUS_HIDDEN, "invisible", _("Invisible"), + TRUE, TRUE, FALSE, "message", _("Message"), + gaim_value_new(GAIM_TYPE_STRING), NULL); + types = g_list_append(types, type); + + /* type = gaim_status_type_new_with_attrs(GAIM_STATUS_UNAVAILABLE, "not-available", "Not Available", */ + /* TRUE, TRUE, FALSE, "message", _("Message"), */ + /* gaim_value_new(GAIM_TYPE_STRING), NULL); */ + /* types = g_list_append(types, type); */ + + type = gaim_status_type_new_with_attrs(GAIM_STATUS_AWAY, "away", _("Busy"), + TRUE, TRUE, FALSE, "message", _("Message"), + gaim_value_new(GAIM_TYPE_STRING), NULL); + types = g_list_append(types, type); + + type = gaim_status_type_new_with_attrs(GAIM_STATUS_HIDDEN, "blocked", _("Blocked"), + TRUE, TRUE, FALSE, "message", _("Message"), + gaim_value_new(GAIM_TYPE_STRING), NULL); + types = g_list_append(types, type); + + return types; +} +/* }}} */ + +/* + */ +/* static GList *ggp_blist_node_menu(GaimBlistNode *node) {{{ */ +static GList *ggp_blist_node_menu(GaimBlistNode *node) { GList *m = NULL; - GaimPluginAction *act = NULL; - -#if 0 - act = gaim_plugin_action_new(_("Directory Search"), show_find_info); - m = g_list_append(m, act); - m = g_list_append(m, NULL); -#endif - - act = gaim_plugin_action_new(_("Change Password"), change_pass); - m = g_list_append(m, act); -#if 0 - act = gaim_plugin_action_new(_("Import Buddy List from Server"), - import_buddies_server); - m = g_list_append(m, act); + if (!GAIM_BLIST_NODE_IS_BUDDY(node)) + return NULL; - act = gaim_plugin_action_new(_("Export Buddy List to Server"), - export_buddies_server); - m = g_list_append(m, act); - - act = gaim_plugin_action_new(_("Delete Buddy List from Server"), - delete_buddies_server); - m = g_list_append(m, act); -#endif + /* act = gaim_blist_node_action_new("Change Password", ggp_bmenu_change_passwd, NULL, NULL); */ + /* m = g_list_append(m, act); */ return m; } +/* }}} */ -static void agg_get_info(GaimConnection *gc, const char *who) +/* + */ +/* static void ggp_login(GaimAccount *account, GaimStatus *status) {{{ */ +static void ggp_login(GaimAccount *account, GaimStatus *status) { - struct agg_http *srch = g_new0(struct agg_http, 1); - srch->gc = gc; - srch->type = AGG_HTTP_SEARCH; - srch->form = AGG_PUBDIR_SEARCH_FORM; - srch->host = GG_PUBDIR_HOST; + GaimConnection *gc = gaim_account_get_connection(account); + struct gg_login_params *glp = g_new0(struct gg_login_params, 1); + GGPInfo *info = g_new0(GGPInfo, 1); + + info->session = NULL; + info->searchresults_window = NULL; + + gc->proto_data = info; + + glp->uin = ggp_get_uin(account); + glp->password = (char *)gaim_account_get_password(account); + + glp->async = 0; + glp->status = GG_STATUS_AVAIL; + glp->tls = 0; + + info->session = gg_login(glp); + if (info->session == NULL) { + gaim_connection_error(gc, _("Connection failed.")); + g_free(glp); + return; + } + gaim_debug_info("gg", "ggp_login: so far so good.\n"); + + gc->inpa = gaim_input_add(info->session->fd, GAIM_INPUT_READ, ggp_callback_recv, gc); - /* If it's invalid uin then maybe it's nickname? */ - if (invalid_uin(who)) { - gchar *new_who = charset_convert(who, "UTF-8", "CP1250"); - gchar *enew_who = gg_urlencode(new_who); + gg_change_status(info->session, GG_STATUS_AVAIL); + gaim_connection_set_state(gc, GAIM_CONNECTED); + ggp_buddylist_send(gc); +} +/* }}} */ + +/* + */ +/* static void ggp_close(GaimConnection *gc) {{{ */ +static void ggp_close(GaimConnection *gc) +{ + GGPInfo *info; - g_free(new_who); + if (gc == NULL) { + gaim_debug_info("gg", "gc == NULL\n"); + return; + } + + info = gc->proto_data; + + /* XXX: Any way to pass description here? */ + if (info->session != NULL) + gg_change_status(info->session, GG_STATUS_NOT_AVAIL); + + if (gc->inpa > 0) + gaim_input_remove(gc->inpa); + + gg_logoff(info->session); + gg_free_session(info->session); + ggp_buddylist_offline(gc); - srch->request = g_strdup_printf("Mode=0&FirstName=%s&LastName=%s&Gender=%d" - "&NickName=%s&City=%s&MinBirth=%d&MaxBirth=%d", - "", "", AGG_GENDER_NONE, enew_who, "", 0, 0); + gaim_debug_info("gg", "Connection closed.\n"); +} +/* }}} */ + +/* + */ +/* static int ggp_send_im(GaimConnection *gc, const char *who, const char *msg, GaimConvImFlags flags) {{{ */ +static int ggp_send_im(GaimConnection *gc, const char *who, const char *msg, GaimConvImFlags flags) +{ + GGPInfo *info = gc->proto_data; + const char *tmp; + + if (strlen(msg) == 0) + return 1; + + tmp = charset_convert(msg, "UTF-8", "CP1250"); - g_free(enew_who); - } else - srch->request = g_strdup_printf("Mode=3&UserId=%s", who); + if (tmp != NULL && strlen(tmp) > 0) { + if (gg_send_message(info->session, GG_CLASS_CHAT, ggp_str_to_uin(who), tmp) < 0) { + return -1; + } + } + + return 1; +} +/* }}} */ + +/* + */ +/* static void ggp_get_info(GaimConnection *gc, const char *name) { {{{ */ +static void ggp_get_info(GaimConnection *gc, const char *name) +{ + GGPInfo *info = gc->proto_data; + GGPSearchForm *form; - if (gaim_proxy_connect(gc->account, GG_PUBDIR_HOST, GG_PUBDIR_PORT, http_req_callback, srch) < 0) { - gaim_notify_error(gc, NULL, - _("Unable to access user profile."), - _("Gaim was unable to access this user's " - "profile due to an error connecting to the " - "directory server. Please try again later.")); - g_free(srch->request); - g_free(srch); + form = ggp_searchform_new(); + info->search_form = form; + + form->uin = g_strdup(name); + form->offset = g_strdup("0"); + form->last_uin = g_strdup("0"); + + ggp_pubdir_start_search(gc, form); +} +/* }}} */ + +/* + */ +/* static void ggp_set_status(GaimAccount *account, GaimStatus *status) {{{ */ +static void ggp_set_status(GaimAccount *account, GaimStatus *status) +{ + GaimStatusPrimitive prim; + GaimConnection *gc; + GGPInfo *info; + const char *status_id; + int new_status, new_status_descr; + + prim = gaim_status_type_get_primitive(gaim_status_get_type(status)); + + if (!gaim_status_is_active(status)) + return; + + if (prim == GAIM_STATUS_OFFLINE) { + gaim_account_disconnect(account); + return; + } + + if (!gaim_account_is_connected(account)) { + gaim_account_connect(account); return; } -} + + gc = gaim_account_get_connection(account); + info = gc->proto_data; + + status_id = gaim_status_get_id(status); + + gaim_debug_info("gg", "ggp_set_status: Requested status = %s\n", status_id); -static const char *agg_list_icon(GaimAccount *a, GaimBuddy *b) -{ - return "gadu-gadu"; -} + if (strcmp(status_id, "available") == 0) { + new_status = GG_STATUS_AVAIL; + new_status_descr = GG_STATUS_AVAIL_DESCR; + } else if (strcmp(status_id, "away") == 0) { + new_status = GG_STATUS_BUSY; + new_status_descr = GG_STATUS_BUSY_DESCR; + } else if (strcmp(status_id, "invisible") == 0) { + new_status = GG_STATUS_INVISIBLE; + new_status_descr = GG_STATUS_INVISIBLE_DESCR; + } else { + new_status = GG_STATUS_AVAIL; + new_status_descr = GG_STATUS_AVAIL_DESCR; + gaim_debug_info("gg", "ggp_set_status: uknown status requested (status_id=%s)\n", status_id); + } -static void agg_list_emblems(GaimBuddy *b, const char **se, const char **sw, - const char **nw, const char **ne) -{ - GaimPresence *presence = gaim_buddy_get_presence(b); + const char *msg = gaim_status_get_attr_string(status, "message"); + + if (msg == NULL) { + gaim_debug_info("gg", "ggp_set_status: msg == NULL\n"); + gg_change_status(info->session, new_status); + } else { + char *tmp = charset_convert(msg, "UTF-8", "CP1250"); + gaim_debug_info("gg", "ggp_set_status: msg != NULL. msg = %s\n", tmp); + gaim_debug_info("gg", "ggp_set_status: gg_change_status_descr() = %d\n", + gg_change_status_descr(info->session, new_status_descr, tmp)); + g_free(tmp); + } - if (!GAIM_BUDDY_IS_ONLINE(b)) - *se = "offline"; - else if (gaim_presence_is_status_active(presence, "away") || - gaim_presence_is_status_active(presence, "away-friends")) - { - *se = "away"; - } - else if (gaim_presence_is_status_active(presence, "invisible") || - gaim_presence_is_status_active(presence, "invisible-friends")) - { - *se = "invisible"; +} +/* }}} */ + +/* + */ +/* static void ggp_add_buddy(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *group) {{{ */ +static void ggp_add_buddy(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *group) +{ + GGPInfo *info = gc->proto_data; + + gg_add_notify(info->session, ggp_str_to_uin(buddy->name)); +} +/* }}} */ + +/* + */ +/* static void ggp_remove_buddy(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *group) {{{ */ +static void ggp_remove_buddy(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *group) +{ + GGPInfo *info = gc->proto_data; + + gg_remove_notify(info->session, ggp_str_to_uin(buddy->name)); +} +/* }}} */ + +/* + */ +/* static void ggp_keepalive(GaimConnection *gc) {{{ */ +static void ggp_keepalive(GaimConnection *gc) +{ + GGPInfo *info = gc->proto_data; + + /* gaim_debug_info("gg", "Keeping connection alive....\n"); */ + + if (gg_ping(info->session) < 0) { + gaim_debug_info("gg", "Not connected to the server " + "or gg_session is not correct\n"); + gaim_connection_error(gc, _("Not connected to the server.")); } } +/* }}} */ + +/* + */ +/* static void ggp_register_user(GaimAccount *account) {{{ */ +static void ggp_register_user(GaimAccount *account) +{ + GaimConnection *gc; + GaimRequestFields *fields; + GaimRequestFieldGroup *group; + GaimRequestField *field; + GGPInfo *info; + GGPToken *token; + + struct gg_http *req; + struct gg_token *t; + + gaim_debug_info("gg", "token: requested.\n"); + + if ((req = gg_token(0)) == NULL) { + gaim_notify_error(account, _("Token Error"), + _("Unable to fetch the token.\n"), NULL); + return; + } + t = req->data; + + gc = gaim_account_get_connection(account); + + info = g_new0(GGPInfo, 1); + gc->proto_data = info; + + token = g_new0(GGPToken, 1); + token->token_id = g_strdup(t->tokenid); + info->register_token = token; + + fields = gaim_request_fields_new(); + group = gaim_request_field_group_new(NULL); + gaim_request_fields_add_group(fields, group); + + field = gaim_request_field_string_new("email", _("e-Mail"), "", FALSE); + gaim_request_field_string_set_masked(field, FALSE); + gaim_request_field_group_add_field(group, field); + + field = gaim_request_field_string_new("password1", _("Password"), "", FALSE); + gaim_request_field_string_set_masked(field, TRUE); + gaim_request_field_group_add_field(group, field); + + field = gaim_request_field_string_new("password2", _("Password (retype)"), "", FALSE); + gaim_request_field_string_set_masked(field, TRUE); + gaim_request_field_group_add_field(group, field); + + field = gaim_request_field_string_new("token", _("Enter current token"), "", FALSE); + gaim_request_field_string_set_masked(field, FALSE); + gaim_request_field_group_add_field(group, field); + + /* original size: 60x24 */ + field = gaim_request_field_image_new("token_img", _("Current token"), req->body, req->body_size); + gaim_request_field_group_add_field(group, field); + + gg_token_free(req); -static void agg_set_permit_deny_dummy(GaimConnection *gc) -{ - /* It's implemented on client side because GG server doesn't support this */ + gaim_request_fields(account, + _("Register New Gadu-Gadu Account"), + _("Register New Gadu-Gadu Account"), + _("Please, fill in the following fields"), + fields, _("OK"), G_CALLBACK(ggp_callback_register_account_ok), + _("Cancel"), NULL, gc); } +/* }}} */ -static void agg_permit_deny_dummy(GaimConnection *gc, const char *who) -{ - /* It's implemented on client side because GG server doesn't support this */ -} - -static void agg_group_buddy (GaimConnection *gc, const char *who, - const char *old_group, const char *new_group) +/* + */ +/* static GList *ggp_actions(GaimPlugin *plugin, gpointer context) {{{ */ +static GList *ggp_actions(GaimPlugin *plugin, gpointer context) { - GaimBuddy *buddy = gaim_find_buddy(gaim_connection_get_account(gc), who); - gchar *newdata; - /* GG Number */ - gchar *name = buddy->name; - /* GG Pseudo */ - gchar *show = buddy->alias ? buddy->alias : buddy->name; - /* Group Name */ - const gchar *gname = new_group; + GList *m = NULL; + GaimPluginAction *act; + + act = gaim_plugin_action_new(_("Find buddies"), ggp_find_buddies); + m = g_list_append(m, act); + + m = g_list_append(m, NULL); + + act = gaim_plugin_action_new(_("Change password"), ggp_change_passwd); + m = g_list_append(m, act); + + m = g_list_append(m, NULL); + + act = gaim_plugin_action_new(_("Upload buddylist to Server"), ggp_action_buddylist_put); + m = g_list_append(m, act); - newdata = g_strdup_printf("%s;%s;%s;%s;%s;%s;%s;%s%s\r\n", - show, show, show, show, "", gname, name, "", ""); - agg_save_buddy_list(gc, newdata); - g_free(newdata); -} + act = gaim_plugin_action_new(_("Download buddylist from Server"), ggp_action_buddylist_get); + m = g_list_append(m, act); + + act = gaim_plugin_action_new(_("Delete buddylist from Server"), ggp_action_buddylist_delete); + m = g_list_append(m, act); + + act = gaim_plugin_action_new(_("Save buddylist to file"), ggp_action_buddylist_save); + m = g_list_append(m, act); -static void agg_rename_group (GaimConnection *gc, const char *old_name, - GaimGroup *group, GList *moved_buddies) -{ - agg_save_buddy_list(gc, NULL); + act = gaim_plugin_action_new(_("Load buddylist from file"), ggp_action_buddylist_load); + m = g_list_append(m, act); + + return m; } +/* }}} */ -static GaimPlugin *my_protocol = NULL; - +/* prpl_info setup {{{ */ static GaimPluginProtocolInfo prpl_info = { - 0, - NULL, /* user_splits */ - NULL, /* protocol_options */ + OPT_PROTO_REGISTER_NOSCREENNAME, + NULL, /* user_splits */ + NULL, /* protocol_options */ NO_BUDDY_ICONS, /* icon_spec */ - agg_list_icon, /* list_icon */ - agg_list_emblems, /* list_emblems */ - NULL, /* status_text */ - NULL, /* tooltip_text */ - agg_status_types, /* status_types */ - agg_blist_node_menu, /* blist_node_menu */ - NULL, /* chat_info */ - NULL, /* chat_info_defaults */ - agg_login, /* login */ - agg_close, /* close */ - agg_send_im, /* send_im */ - NULL, /* set_info */ - NULL, /* send_typing */ - agg_get_info, /* get_info */ - agg_set_status, /* set_away */ - NULL, /* set_idle */ - agg_change_passwd, /* change_passwd */ - agg_add_buddy, /* add_buddy */ - NULL, /* add_buddies */ - agg_rem_buddy, /* remove_buddy */ - NULL, /* remove_buddies */ - agg_permit_deny_dummy, /* add_permit */ - agg_permit_deny_dummy, /* add_deny */ - agg_permit_deny_dummy, /* rem_permit */ - agg_permit_deny_dummy, /* rem_deny */ - agg_set_permit_deny_dummy, /* set_permit_deny */ - NULL, /* join_chat */ - NULL, /* reject_chat */ - NULL, /* get_chat_name */ - NULL, /* chat_invite */ - NULL, /* chat_leave */ - NULL, /* chat_whisper */ - NULL, /* chat_send */ - agg_keepalive, /* keepalive */ - NULL, /* register_user */ - NULL, /* get_cb_info */ - NULL, /* get_cb_away */ - NULL, /* alias_buddy */ - agg_group_buddy, /* group_buddy */ - agg_rename_group, /* rename_group */ - agg_buddy_free, /* buddy_free */ - NULL, /* convo_closed */ - NULL, /* normalize */ - NULL, /* set_buddy_icon */ - NULL, /* 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 */ + ggp_list_icon, /* list_icon */ + ggp_list_emblems, /* list_emblems */ + ggp_status_text, /* status_text */ + ggp_tooltip_text, /* tooltip_text */ + ggp_status_types, /* status_types */ + ggp_blist_node_menu, /* blist_node_menu */ + NULL, /* chat_info */ + NULL, /* chat_info_defaults */ + ggp_login, /* login */ + ggp_close, /* close */ + ggp_send_im, /* send_im */ + NULL, /* set_info */ + NULL, /* send_typing */ + ggp_get_info, /* get_info */ + ggp_set_status, /* set_away */ + NULL, /* set_idle */ + NULL, /* change_passwd */ + ggp_add_buddy, /* add_buddy */ + NULL, /* add_buddies */ + ggp_remove_buddy, /* remove_buddy */ + NULL, /* remove_buddies */ + NULL, /* add_permit */ + NULL, /* add_deny */ + NULL, /* rem_permit */ + NULL, /* rem_deny */ + NULL, /* set_permit_deny */ + NULL, /* join_chat */ + NULL, /* reject_chat */ + NULL, /* get_chat_name */ + NULL, /* chat_invite */ + NULL, /* chat_leave */ + NULL, /* chat_whisper */ + NULL, /* chat_send */ + ggp_keepalive, /* keepalive */ + ggp_register_user, /* register_user */ + NULL, /* get_cb_info */ + NULL, /* get_cb_away */ + NULL, /* alias_buddy */ + NULL, /* group_buddy */ + NULL, /* rename_group */ + NULL, /* buddy_free */ + NULL, /* convo_closed */ + NULL, /* normalize */ + NULL, /* set_buddy_icon */ + NULL, /* 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 */ }; +/* }}} */ -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 */ +/* GaimPluginInfo setup {{{ */ +static GaimPluginInfo info = { + GAIM_PLUGIN_MAGIC, /* magic */ + GAIM_MAJOR_VERSION, /* major_version */ + GAIM_MINOR_VERSION, /* minor_version */ + GAIM_PLUGIN_PROTOCOL, /* plugin type */ + NULL, /* ui_requirement */ + 0, /* flags */ + NULL, /* dependencies */ + GAIM_PRIORITY_DEFAULT, /* priority */ + + "prpl-gg", /* id */ + "Gadu-Gadu", /* name */ + VERSION, /* version */ - "prpl-gg", /**< id */ - "Gadu-Gadu", /**< name */ - VERSION, /**< version */ - /** summary */ - N_("Gadu-Gadu Protocol Plugin"), - /** description */ - N_("Gadu-Gadu Protocol Plugin"), - "Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>", /**< author */ - GAIM_WEBSITE, /**< homepage */ + N_("Gadu-Gadu Protocol Plugin"), /* summary */ + N_("Polish popular IM"), /* description */ + "boler@sourceforge.net", /* author */ + GAIM_WEBSITE, /* homepage */ + + NULL, /* load */ + NULL, /* unload */ + NULL, /* destroy */ - NULL, /**< load */ - NULL, /**< unload */ - NULL, /**< destroy */ + NULL, /* ui_info */ + &prpl_info, /* extra_info */ + NULL, /* prefs_info */ + ggp_actions /* actions */ +}; +/* }}} */ - NULL, /**< ui_info */ - &prpl_info, /**< extra_info */ - NULL, - agg_actions -}; - -static void -init_plugin(GaimPlugin *plugin) +/* + */ +/* static void init_plugin(GaimPlugin *plugin) {{{ */ +static void init_plugin(GaimPlugin *plugin) { GaimAccountOption *option; - option = gaim_account_option_string_new(_("Nick"), "nick", - "Gadu-Gadu User"); - prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, - option); + option = gaim_account_option_string_new(_("Nickname"), "nick", _("Gadu-Gadu User")); + prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option); my_protocol = plugin; } +/* }}} */ -GAIM_INIT_PLUGIN(gg, init_plugin, info) +GAIM_INIT_PLUGIN(gadu-gadu, init_plugin, info); + +/* vim: set ts=4 sts=0 sw=4 noet: */
