Mercurial > pidgin
view src/protocols/msn/nexus.c @ 19816:1aa5494587e8
[gaim-migrate @ 16973]
change the soap process to below:
Post one Soap request
After finish one soap request,close the connection,
If there are more, reconect and process it.
to avoid the below problem:
in one socket, If post soap request one by one, The second will always read 0 bytes.
comitted by Ma Yuan<mayuan2006@gmail.com>
committer: Ethan Blanton <elb@pidgin.im>
author | Ma Yuan <mayuan2006@gmail.com> |
---|---|
date | Tue, 22 Aug 2006 06:10:01 +0000 |
parents | bffd1b96207c |
children | cb7433549a6f |
line wrap: on
line source
/** * @file nexus.c MSN Nexus functions * * gaim * * Gaim is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "msn.h" #include "soap.h" #include "nexus.h" #include "notification.h" /*Local Function Prototype*/ static void nexus_login_connect_cb(gpointer data, GaimSslConnection *gsc,GaimInputCondition cond); /************************************************************************** * Main **************************************************************************/ MsnNexus * msn_nexus_new(MsnSession *session) { MsnNexus *nexus; nexus = g_new0(MsnNexus, 1); nexus->session = session; /*we must use SSL connection to do Windows Live ID authentication*/ nexus->soapconn = msn_soap_new(session,nexus,1); nexus->challenge_data = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); return nexus; } void msn_nexus_destroy(MsnNexus *nexus) { if (nexus->challenge_data != NULL) g_hash_table_destroy(nexus->challenge_data); msn_soap_destroy(nexus->soapconn); g_free(nexus); } /************************************************************************** * Login **************************************************************************/ static void nexus_login_error_cb(GaimSslConnection *gsc, GaimSslErrorType error, void *data) { MsnSoapConn * soapconn = data; MsnSession *session; session = soapconn->session; g_return_if_fail(session != NULL); msn_session_set_error(session, MSN_ERROR_AUTH, _("Windows Live ID authentication:Unable to connect")); /* the above line will result in nexus being destroyed, so we don't want * to destroy it here, or we'd crash */ } /*process the SOAP reply, get the Authentication Info*/ static void nexus_login_read_cb(gpointer data, gint source, GaimInputCondition cond) { MsnSoapConn * soapconn = data; MsnNexus *nexus; MsnSession *session; char *base, *c; char *msn_twn_t,*msn_twn_p; char *login_params; char **elems, **cur, **tokens; char * cert_str; nexus = soapconn->parent; g_return_if_fail(nexus != NULL); session = nexus->session; g_return_if_fail(session != NULL); // gaim_debug_misc("msn", "TWN Server Reply: {%s}\n", soapconn->read_buf); /*reply OK, we should process the SOAP body*/ gaim_debug_info("MaYuan","Windows Live ID Reply OK!\n"); //TODO: we should parse it using XML base = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_START_TOKEN); base += strlen(TWN_START_TOKEN); c = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_END_TOKEN); login_params = g_strndup(base, c - base); // gaim_debug_info("msn", "TWN Cert: {%s}\n", login_params); /* Parse the challenge data. */ elems = g_strsplit(login_params, "&", 0); for (cur = elems; *cur != NULL; cur++){ tokens = g_strsplit(*cur, "=", 2); g_hash_table_insert(nexus->challenge_data, tokens[0], tokens[1]); /* Don't free each of the tokens, only the array. */ g_free(tokens); } g_strfreev(elems); msn_twn_t = (char *)g_hash_table_lookup(nexus->challenge_data, "t"); msn_twn_p = (char *)g_hash_table_lookup(nexus->challenge_data, "p"); /*setup the t and p parameter for session*/ if (session->passport_info.t != NULL){ g_free(session->passport_info.t); } session->passport_info.t = g_strdup(msn_twn_t); if (session->passport_info.p != NULL) g_free(session->passport_info.p); session->passport_info.p = g_strdup(msn_twn_p); cert_str = g_strdup_printf("t=%s&p=%s",msn_twn_t,msn_twn_p); msn_got_login_params(session, cert_str); gaim_debug_info("MaYuan","close nexus connection! \n"); g_free(cert_str); g_free(login_params); msn_nexus_destroy(nexus); session->nexus = NULL; return; } static void nexus_login_written_cb(gpointer data, gint source, GaimInputCondition cond) { MsnSoapConn * soapconn = data; soapconn->read_cb = nexus_login_read_cb; // msn_soap_read_cb(data,source,cond); } /*when connect, do the SOAP Style windows Live ID authentication */ void nexus_login_connect_cb(gpointer data, GaimSslConnection *gsc, GaimInputCondition cond) { MsnSoapConn *soapconn; MsnNexus * nexus; MsnSession *session; char *ru,*lc,*id,*tw,*ct,*kpp,*kv,*ver,*rn,*tpf; char *fs0,*fs; char *username, *password; char *request_str, *head, *tail,*challenge_str; gaim_debug_info("MaYuan","starting Windows Live ID authentication\n"); soapconn = data; g_return_if_fail(soapconn != NULL); nexus = soapconn->parent; g_return_if_fail(nexus != NULL); session = soapconn->session; g_return_if_fail(session != NULL); msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE); /*prepare the Windows Live ID authentication token*/ username = g_strdup(gaim_account_get_username(session->account)); password = g_strdup(gaim_connection_get_password(session->account->gc)); lc = (char *)g_hash_table_lookup(nexus->challenge_data, "lc"); id = (char *)g_hash_table_lookup(nexus->challenge_data, "id"); tw = (char *)g_hash_table_lookup(nexus->challenge_data, "tw"); fs0= (char *)g_hash_table_lookup(nexus->challenge_data, "fs"); ru = (char *)g_hash_table_lookup(nexus->challenge_data, "ru"); ct = (char *)g_hash_table_lookup(nexus->challenge_data, "ct"); kpp= (char *)g_hash_table_lookup(nexus->challenge_data, "kpp"); kv = (char *)g_hash_table_lookup(nexus->challenge_data, "kv"); ver= (char *)g_hash_table_lookup(nexus->challenge_data, "ver"); rn = (char *)g_hash_table_lookup(nexus->challenge_data, "rn"); tpf= (char *)g_hash_table_lookup(nexus->challenge_data, "tpf"); /* * add some fail-safe code to avoid windows Gaim Crash bug #1540454 * If any of these string is NULL, will return Authentication Fail! * for when windows g_strdup_printf() implementation get NULL point,It crashed! */ if(!(lc && id && tw && ru && ct && kpp && kv && ver && tpf)){ gaim_debug_error("MaYuan","WLM Authenticate Key Error!\n"); msn_session_set_error(session, MSN_ERROR_AUTH, _("Windows Live ID authentication Failed")); g_free(username); g_free(password); gaim_ssl_close(gsc); msn_nexus_destroy(nexus); session->nexus = NULL; return; } /* * in old MSN NS server's "USR TWN S" return,didn't include fs string * so we use a default "1" for fs. */ if(fs0){ fs = g_strdup(fs0); }else{ fs = g_strdup("1"); } challenge_str = g_strdup_printf( "lc=%s&id=%s&tw=%s&fs=%s&ru=%s&ct=%s&kpp=%s&kv=%s&ver=%s&rn=%s&tpf=%s\r\n", lc,id,tw,fs,ru,ct,kpp,kv,ver,rn,tpf ); g_free(fs); /*build the SOAP windows Live ID XML body */ tail = g_strdup_printf(TWN_ENVELOP_TEMPLATE,username,password,challenge_str ); soapconn->login_path = g_strdup(TWN_POST_URL); head = g_strdup_printf( "POST %s HTTP/1.1\r\n" "Accept: text/*\r\n" "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n" "Host: %s\r\n" "Content-Length: %d\r\n" "Connection: Keep-Alive\r\n" "Cache-Control: no-cache\r\n\r\n", soapconn->login_path,soapconn->login_host,(int)strlen(tail)); request_str = g_strdup_printf("%s%s", head,tail); // gaim_debug_misc("msn", "TWN Sending: {%s}\n", request_str); g_free(head); g_free(tail); g_free(username); g_free(password); /*prepare to send the SOAP request*/ msn_soap_write(soapconn,request_str,nexus_login_written_cb); return; } /************************************************************************** * Connect **************************************************************************/ void msn_nexus_connect(MsnNexus *nexus) { /* Authenticate via Windows Live ID. */ gaim_debug_info("MaYuan","msn_nexus_connect...\n"); msn_soap_init(nexus->soapconn,MSN_TWN_SERVER,1,nexus_login_connect_cb,nexus_login_error_cb); msn_soap_connect(nexus->soapconn); }