Mercurial > pidgin
diff src/protocols/gg/gg.c @ 2846:4b3f17ca66bf
[gaim-migrate @ 2859]
so here it comes - some bugs fixed, new ones introduced:
- password changing (was in part 1)
- update to latest libgg (fixes password change on alpha)
- auto away on idle (remembers GG_STATE_FRIENDS_MASK)
- handle_errcode() can now use hide_login_progress()
- remove encode_postdata() and use gg_urlencode() from libgg
+ encode only fields (not whole url)
- fixed status related ugly bug in GG_EVENT_NOTIFY (!!!)
- remove linefeed from messages
Thanks, Arkadiusz Miskiewicz
committer: Tailor Script <tailor@pidgin.im>
author | Eric Warmenhoven <eric@warmenhoven.org> |
---|---|
date | Wed, 05 Dec 2001 09:48:56 +0000 |
parents | d8e67ff8022f |
children | b1e300a85678 |
line wrap: on
line diff
--- a/src/protocols/gg/gg.c Tue Dec 04 19:51:27 2001 +0000 +++ b/src/protocols/gg/gg.c Wed Dec 05 09:48:56 2001 +0000 @@ -1,6 +1,6 @@ /* * gaim - Gadu-Gadu Protocol Plugin - * $Id: gg.c 2848 2001-12-02 20:42:30Z warmenhoven $ + * $Id: gg.c 2859 2001-12-05 09:48:56Z warmenhoven $ * * Copyright (C) 2001 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL> * @@ -65,6 +65,7 @@ #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 #define AGG_STATUS_AVAIL _("Available") @@ -80,11 +81,13 @@ #define AGG_HTTP_USERLIST_IMPORT 2 #define AGG_HTTP_USERLIST_EXPORT 3 #define AGG_HTTP_USERLIST_DELETE 4 +#define AGG_HTTP_PASSWORD_CHANGE 5 #define UC_NORMAL 2 struct agg_data { struct gg_session *sess; + int own_status; }; struct agg_http { @@ -170,7 +173,7 @@ return gg_localenc; } -static char *handle_errcode(int errcode, gboolean show) +static char *handle_errcode(struct gaim_connection *gc, int errcode) { static char msg[AGG_BUF_LEN]; @@ -198,73 +201,51 @@ break; } - if (show) - do_error_dialog(msg, _("Gadu-Gadu Error")); + hide_login_progress(gc, msg); return msg; } -static gchar *encode_postdata(const gchar *data) -{ - gchar *p = NULL; - int i, j = 0; - for (i = 0; i < strlen(data); i++) { - /* locale insensitive, doesn't reflect RFC (1738 section 2.2, 1866 section 8.2.1) */ - if ((data[i] >= 'a' && data[i] <= 'z') - || (data[i] >= 'A' && data[i] <= 'Z') - || (data[i] >= '0' && data[i] <= '9') - || data[i] == '=' || data[i] == '&') { - p = g_realloc(p, j + 1); - p[j] = data[i]; - j++; - } else { - p = g_realloc(p, j + 4); /* remember, sprintf appends a '\0' */ - sprintf(p + j, "%%%02x", (unsigned char)data[i]); - j += 3; - } - } - p = g_realloc(p, j + 1); - p[j] = '\0'; - - if (p && strlen(p)) - return p; - else - return g_strdup(data); -} - static void agg_set_away(struct gaim_connection *gc, char *state, char *msg) { struct agg_data *gd = (struct agg_data *)gc->proto_data; + int status = gd->own_status; if (gc->away) gc->away = NULL; if (!g_strcasecmp(state, AGG_STATUS_AVAIL)) - gg_change_status(gd->sess, GG_STATUS_AVAIL); + status = GG_STATUS_AVAIL; else if (!g_strcasecmp(state, AGG_STATUS_AVAIL_FRIENDS)) - gg_change_status(gd->sess, GG_STATUS_AVAIL | GG_STATUS_FRIENDS_MASK); + status = GG_STATUS_AVAIL | GG_STATUS_FRIENDS_MASK; else if (!g_strcasecmp(state, AGG_STATUS_BUSY)) { - gg_change_status(gd->sess, GG_STATUS_BUSY); + status = GG_STATUS_BUSY; gc->away = ""; } else if (!g_strcasecmp(state, AGG_STATUS_BUSY_FRIENDS)) { - gg_change_status(gd->sess, GG_STATUS_BUSY | GG_STATUS_FRIENDS_MASK); + status = GG_STATUS_BUSY | GG_STATUS_FRIENDS_MASK; gc->away = ""; } else if (!g_strcasecmp(state, AGG_STATUS_INVISIBLE)) { - gg_change_status(gd->sess, GG_STATUS_INVISIBLE); + status = GG_STATUS_INVISIBLE; gc->away = ""; } else if (!g_strcasecmp(state, AGG_STATUS_INVISIBLE_FRIENDS)) { - gg_change_status(gd->sess, GG_STATUS_INVISIBLE | GG_STATUS_FRIENDS_MASK); + status = GG_STATUS_INVISIBLE | GG_STATUS_FRIENDS_MASK; gc->away = ""; } else if (!g_strcasecmp(state, AGG_STATUS_NOT_AVAIL)) { - gg_change_status(gd->sess, GG_STATUS_NOT_AVAIL); + status = GG_STATUS_NOT_AVAIL; gc->away = ""; } else if (!g_strcasecmp(state, GAIM_AWAY_CUSTOM)) { if (msg) { - gg_change_status(gd->sess, GG_STATUS_BUSY); + status = GG_STATUS_BUSY; gc->away = ""; } else - gg_change_status(gd->sess, GG_STATUS_AVAIL); + status = GG_STATUS_AVAIL; + + if (gd->own_status & GG_STATUS_FRIENDS_MASK) + status |= GG_STATUS_FRIENDS_MASK; } + + gd->own_status = status; + gg_change_status(gd->sess, status); } static gchar *get_away_text(int uc) @@ -359,6 +340,7 @@ if (!(e = gg_watch_fd(gd->sess))) { debug_printf("main_callback: gg_watch_fd failed - CRITICAL!\n"); + hide_login_progress(gc, _("Unable to read socket")); signoff(gc); return; } @@ -373,7 +355,7 @@ case GG_EVENT_CONN_FAILED: if (gc->inpa) gaim_input_remove(gc->inpa); - handle_errcode(e->event.failure, TRUE); + handle_errcode(gc, e->event.failure); signoff(gc); break; case GG_EVENT_MSG: @@ -385,6 +367,7 @@ if (!allowed_uin(gc, user)) break; imsg = charset_convert(e->event.msg.message, "CP1250", find_local_charset()); + strip_linefeed(imsg); /* e->event.msg.time - we don't know what this time is for */ serv_got_im(gc, user, imsg, 0, time((time_t) NULL)); g_free(imsg); @@ -404,8 +387,7 @@ case GG_STATUS_AVAIL: case GG_STATUS_BUSY: case GG_STATUS_INVISIBLE: - case GG_STATUS_FRIENDS_MASK: - status = UC_NORMAL | (e->event.status.status << 5); + status = UC_NORMAL | (n->status << 5); break; default: status = UC_NORMAL; @@ -431,7 +413,6 @@ case GG_STATUS_AVAIL: case GG_STATUS_BUSY: case GG_STATUS_INVISIBLE: - case GG_STATUS_FRIENDS_MASK: status = UC_NORMAL | (e->event.status.status << 5); break; default: @@ -440,8 +421,8 @@ } g_snprintf(user, sizeof(user), "%lu", e->event.status.uin); - serv_got_update(gc, user, (status == UC_UNAVAILABLE) ? 0 : 1, 0, 0, 0, status, - 0); + serv_got_update(gc, user, (status == UC_UNAVAILABLE) ? 0 : 1, 0, 0, 0, + status, 0); } break; case GG_EVENT_ACK: @@ -479,18 +460,17 @@ gc->inpa = gaim_input_add(gd->sess->fd, GAIM_INPUT_READ, login_callback, gc); switch (gd->sess->state) { - case GG_STATE_CONNECTING_HTTP: - case GG_STATE_WRITING_HTTP: - set_login_progress(gc, 2, _("Handshake")); + case GG_STATE_READING_DATA: + set_login_progress(gc, 2, _("Reading data")); break; case GG_STATE_CONNECTING_GG: - set_login_progress(gc, 3, _("Connecting to GG server")); + set_login_progress(gc, 3, _("Balancer handshake")); break; - case GG_STATE_WAITING_FOR_KEY: - set_login_progress(gc, 4, _("Waiting for server key")); + case GG_STATE_READING_KEY: + set_login_progress(gc, 4, _("Reading server key")); break; - case GG_STATE_SENDING_KEY: - set_login_progress(gc, 5, _("Sending key")); + case GG_STATE_READING_REPLY: + set_login_progress(gc, 5, _("Exchanging key hash")); break; default: break; @@ -498,6 +478,7 @@ if (!(e = gg_watch_fd(gd->sess))) { debug_printf("login_callback: gg_watch_fd failed - CRITICAL!\n"); + hide_login_progress(gc, _("Critical error in GG library\n")); signoff(gc); return; } @@ -522,7 +503,7 @@ case GG_EVENT_CONN_FAILED: gaim_input_remove(gc->inpa); gc->inpa = 0; - handle_errcode(e->event.failure, TRUE); + handle_errcode(gc, e->event.failure); signoff(gc); break; default: @@ -536,6 +517,7 @@ { struct agg_data *gd = (struct agg_data *)gc->proto_data; if (gg_ping(gd->sess) < 0) { + hide_login_progress(gc, _("Unable to ping server")); signoff(gc); return; } @@ -578,7 +560,7 @@ gd->sess->uin = (uin_t) strtol(user->username, (char **)NULL, 10); gd->sess->password = g_strdup(user->password); - gd->sess->state = GG_STATE_CONNECTING_HTTP; + gd->sess->state = GG_STATE_CONNECTING; gd->sess->check = GG_CHECK_WRITE; gd->sess->async = 1; gd->sess->fd = proxy_connect(GG_APPMSG_HOST, GG_APPMSG_PORT, login_callback, gc); @@ -599,6 +581,7 @@ gg_logoff(gd->sess); gg_free_session(gd->sess); g_free(gc->proto_data); + gd->own_status = GG_STATUS_NOT_AVAIL; } static int agg_send_im(struct gaim_connection *gc, char *who, char *msg, int flags) @@ -614,7 +597,8 @@ if (strlen(msg) > 0) { imsg = charset_convert(msg, find_local_charset(), "CP1250"); - if (gg_send_message(gd->sess, (flags & IM_FLAG_CHECKBOX) ? GG_CLASS_MSG : GG_CLASS_CHAT, + if (gg_send_message(gd->sess, (flags & IM_FLAG_CHECKBOX) + ? GG_CLASS_MSG : GG_CLASS_CHAT, strtol(who, (char **)NULL, 10), imsg) < 0) return -1; g_free(imsg); @@ -848,6 +832,18 @@ do_error_dialog(_("Couldn't delete Buddies List from Server"), _("Gadu-Gadu Error")); } +static void password_change_server_results(struct gaim_connection *gc, gchar *webdata) +{ + if (strstr(webdata, "reg_success:")) { + do_error_dialog(_("Password changed sucessfully"), + _("Gadu-Gadu Information")); + return; + } + + debug_printf("delete_buddies_server_results: webdata [%s]\n", webdata); + do_error_dialog(_("Password couldn't be changed"), _("Gadu-Gadu Error")); +} + static void http_results(gpointer data, gint source, GaimInputCondition cond) { struct agg_http *hdata = data; @@ -904,6 +900,9 @@ case AGG_HTTP_USERLIST_DELETE: delete_buddies_server_results(gc, webdata); break; + case AGG_HTTP_PASSWORD_CHANGE: + password_change_server_results(gc, webdata); + break; case AGG_HTTP_NONE: default: debug_printf("http_results: unsupported type %d\n", hdata->type); @@ -920,7 +919,6 @@ struct gaim_connection *gc = hdata->gc; gchar *request = hdata->request; gchar *buf; - char *ptr; debug_printf("http_req_callback: begin\n"); @@ -938,10 +936,7 @@ return; } - ptr = encode_postdata(request); - g_free(request); - - debug_printf("http_req_callback: http request [%s]\n", ptr); + debug_printf("http_req_callback: http request [%s]\n", request); buf = g_strdup_printf("POST %s HTTP/1.0\r\n" "Host: %s\r\n" @@ -949,9 +944,9 @@ "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, strlen(ptr), ptr); + hdata->form, hdata->host, strlen(request), request); - g_free(ptr); + g_free(request); if (write(source, buf, strlen(buf)) < strlen(buf)) { g_free(buf); @@ -970,12 +965,17 @@ { struct agg_http *hi = g_new0(struct agg_http, 1); static char msg[AGG_BUF_LEN]; + gchar *u = gg_urlencode(gc->username); + gchar *p = gg_urlencode(gc->password); 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", gc->username, gc->password); + hi->request = g_strdup_printf("FmNum=%s&Pass=%s", u, p); + + g_free(u); + g_free(p); if (proxy_connect(GG_PUBDIR_HOST, GG_PUBDIR_PORT, http_req_callback, hi) < 0) { g_snprintf(msg, sizeof(msg), _("Buddies List import from Server failed (%s)"), @@ -992,13 +992,19 @@ struct agg_http *he = g_new0(struct agg_http, 1); static char msg[AGG_BUF_LEN]; gchar *ptr; + gchar *u = gg_urlencode(gc->username); + gchar *p = gg_urlencode(gc->password); + GSList *gr = gc->groups; 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=", gc->username, gc->password); + he->request = g_strdup_printf("FmNum=%s&Pass=%s&Contacts=", u, p); + + g_free(u); + g_free(p); while (gr) { struct group *g = gr->data; @@ -1007,17 +1013,24 @@ struct buddy *b = m->data; gchar *newdata; /* GG Number */ - gchar *name = b->name; + gchar *name = gg_urlencode(b->name); /* GG Pseudo */ - gchar *show = strlen(b->show) ? b->show : b->name; + gchar *show = gg_urlencode(strlen(b->show) ? b->show : b->name); + /* Group Name */ + gchar *gname = gg_urlencode(g->name); ptr = he->request; newdata = g_strdup_printf("%s;%s;%s;%s;%s;%s;%s\r\n", - show, show, show, show, "", g->name, name); + show, show, show, show, "", gname, name); he->request = g_strconcat(ptr, newdata, NULL); + g_free(newdata); g_free(ptr); + g_free(gname); + g_free(show); + g_free(name); + m = g_slist_next(m); } gr = g_slist_next(gr); @@ -1037,12 +1050,14 @@ { struct agg_http *he = g_new0(struct agg_http, 1); static char msg[AGG_BUF_LEN]; + gchar *u = gg_urlencode(gc->username); + gchar *p = gg_urlencode(gc->password); 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", gc->username, gc->password); + he->request = g_strdup_printf("FmNum=%s&Pass=%s&Delete=1", u, p); if (proxy_connect(GG_PUBDIR_HOST, GG_PUBDIR_PORT, http_req_callback, he) < 0) { g_snprintf(msg, sizeof(msg), _("Deletion of Buddies List from Server failed (%s)"), @@ -1055,7 +1070,8 @@ } static void agg_dir_search(struct gaim_connection *gc, char *first, char *middle, - char *last, char *maiden, char *city, char *state, char *country, char *email) + char *last, char *maiden, char *city, char *state, + char *country, char *email) { struct agg_http *srch = g_new0(struct agg_http, 1); static char msg[AGG_BUF_LEN]; @@ -1066,25 +1082,36 @@ srch->host = GG_PUBDIR_HOST; if (email && strlen(email)) { - srch->request = g_strdup_printf("Mode=1&Email=%s", 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, find_local_charset(), "CP1250"); gchar *new_last = charset_convert(last, find_local_charset(), "CP1250"); gchar *new_city = charset_convert(city, find_local_charset(), "CP1250"); - /* 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", - new_first, new_last, AGG_GENDER_NONE, - "", new_city, 0, 0); + gchar *enew_first = gg_urlencode(new_first); + gchar *enew_last = gg_urlencode(new_last); + gchar *enew_city = gg_urlencode(new_city); g_free(new_first); g_free(new_last); g_free(new_city); + + /* 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); + + g_free(enew_first); + g_free(enew_last); + g_free(enew_city); } if (proxy_connect(GG_PUBDIR_HOST, GG_PUBDIR_PORT, http_req_callback, srch) < 0) { - g_snprintf(msg, sizeof(msg), _("Connect to search service failed (%s)"), GG_PUBDIR_HOST); + g_snprintf(msg, sizeof(msg), _("Connect to search service failed (%s)"), + GG_PUBDIR_HOST); do_error_dialog(msg, _("Gadu-Gadu Error")); g_free(srch->request); g_free(srch); @@ -1092,10 +1119,45 @@ } } +static void agg_change_passwd(struct gaim_connection *gc, char *old, char *new) +{ + struct agg_http *hpass = g_new0(struct agg_http, 1); + static char msg[AGG_BUF_LEN]; + gchar *u = gg_urlencode(gc->username); + gchar *p = gg_urlencode(gc->password); + gchar *enew = gg_urlencode(new); + gchar *eold = gg_urlencode(old); + + hpass->gc = gc; + hpass->type = AGG_HTTP_PASSWORD_CHANGE; + hpass->form = AGG_REGISTER_DATA_FORM; + hpass->host = GG_REGISTER_HOST; + + /* 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)); + + g_free(u); + g_free(p); + g_free(enew); + g_free(eold); + + if (proxy_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, http_req_callback, hpass) < 0) { + g_snprintf(msg, sizeof(msg), _("Changing Password failed (%s)"), + GG_REGISTER_HOST); + do_error_dialog(msg, _("Gadu-Gadu Error")); + g_free(hpass->request); + g_free(hpass); + return; + } +} + static void agg_do_action(struct gaim_connection *gc, char *action) { if (!strcmp(action, _("Directory Search"))) { show_find_info(gc); + } else if (!strcmp(action, _("Change Password"))) { + show_change_passwd(gc); } else if (!strcmp(action, _("Import Buddies List from Server"))) { import_buddies_server(gc); } else if (!strcmp(action, _("Export Buddies List to Server"))) { @@ -1110,6 +1172,9 @@ GList *m = NULL; m = g_list_append(m, _("Directory Search")); + m = g_list_append(m, NULL); + m = g_list_append(m, _("Change Password")); + m = g_list_append(m, NULL); m = g_list_append(m, _("Import Buddies List from Server")); m = g_list_append(m, _("Export Buddies List to Server")); m = g_list_append(m, _("Delete Buddies List from Server")); @@ -1130,17 +1195,21 @@ /* If it's invalid uin then maybe it's nickname? */ if (invalid_uin(who)) { gchar *new_who = charset_convert(who, find_local_charset(), "CP1250"); + gchar *enew_who = gg_urlencode(new_who); + + g_free(new_who); srch->request = g_strdup_printf("Mode=0&FirstName=%s&LastName=%s&Gender=%d" "&NickName=%s&City=%s&MinBirth=%d&MaxBirth=%d", - "", "", AGG_GENDER_NONE, new_who, "", 0, 0); + "", "", AGG_GENDER_NONE, enew_who, "", 0, 0); - g_free(new_who); + g_free(enew_who); } else srch->request = g_strdup_printf("Mode=3&UserId=%s", who); if (proxy_connect(GG_PUBDIR_HOST, GG_PUBDIR_PORT, http_req_callback, srch) < 0) { - g_snprintf(msg, sizeof(msg), _("Connect to search service failed (%s)"), GG_PUBDIR_HOST); + g_snprintf(msg, sizeof(msg), _("Connect to search service failed (%s)"), + GG_PUBDIR_HOST); do_error_dialog(msg, _("Gadu-Gadu Error")); g_free(srch->request); g_free(srch); @@ -1199,7 +1268,7 @@ ret->get_dir = agg_get_info; ret->dir_search = agg_dir_search; ret->set_idle = NULL; - ret->change_passwd = NULL; + ret->change_passwd = agg_change_passwd; ret->add_buddy = agg_add_buddy; ret->add_buddies = agg_add_buddies; ret->remove_buddy = agg_rem_buddy; @@ -1245,3 +1314,13 @@ } #endif + +/* + * Local variables: + * c-indentation-style: k&r + * c-basic-offset: 8 + * indent-tabs-mode: notnil + * End: + * + * vim: shiftwidth=8: + */