comparison libpurple/protocols/msn/nexus.c @ 20422:48e26f248251

propagate from branch 'im.pidgin.pidgin' (head 371fb91ec4fdb33fa482efe55111fe58d8758c3b) to branch 'im.pidgin.cpw.khc.msnp14' (head 4cf4cd7a1b3bad8fe87d03a56db8b8228ee22d95)
author Stu Tomlinson <stu@nosnilmot.com>
date Sat, 26 May 2007 12:38:24 +0000
parents 14b8fb8d27b3
children 4403cecc7cd6
comparison
equal deleted inserted replaced
17343:8c056932bcc2 20422:48e26f248251
20 * You should have received a copy of the GNU General Public License 20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software 21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */ 23 */
24 #include "msn.h" 24 #include "msn.h"
25 #include "soap.h"
25 #include "nexus.h" 26 #include "nexus.h"
26 #include "notification.h" 27 #include "notification.h"
28 #undef NEXUS_LOGIN_TWN
29
30 /*Local Function Prototype*/
31 static void nexus_login_connect_cb(gpointer data, PurpleSslConnection *gsc,PurpleInputCondition cond);
27 32
28 /************************************************************************** 33 /**************************************************************************
29 * Main 34 * Main
30 **************************************************************************/ 35 **************************************************************************/
31 36
34 { 39 {
35 MsnNexus *nexus; 40 MsnNexus *nexus;
36 41
37 nexus = g_new0(MsnNexus, 1); 42 nexus = g_new0(MsnNexus, 1);
38 nexus->session = session; 43 nexus->session = session;
44 /*we must use SSL connection to do Windows Live ID authentication*/
45 nexus->soapconn = msn_soap_new(session,nexus,1);
46
39 nexus->challenge_data = g_hash_table_new_full(g_str_hash, 47 nexus->challenge_data = g_hash_table_new_full(g_str_hash,
40 g_str_equal, g_free, g_free); 48 g_str_equal, g_free, g_free);
41 49
42 return nexus; 50 return nexus;
43 } 51 }
44 52
45 void 53 void
46 msn_nexus_destroy(MsnNexus *nexus) 54 msn_nexus_destroy(MsnNexus *nexus)
47 { 55 {
48 if (nexus->gsc)
49 purple_ssl_close(nexus->gsc);
50
51 g_free(nexus->login_host);
52
53 g_free(nexus->login_path);
54
55 if (nexus->challenge_data != NULL) 56 if (nexus->challenge_data != NULL)
56 g_hash_table_destroy(nexus->challenge_data); 57 g_hash_table_destroy(nexus->challenge_data);
57 58
58 if (nexus->input_handler > 0) 59 msn_soap_destroy(nexus->soapconn);
59 purple_input_remove(nexus->input_handler);
60 g_free(nexus->write_buf);
61 g_free(nexus->read_buf);
62
63 g_free(nexus); 60 g_free(nexus);
64 } 61 }
65 62
63 #if 0 /* khc */
66 /************************************************************************** 64 /**************************************************************************
67 * Util 65 * Util
68 **************************************************************************/ 66 **************************************************************************/
69 67
70 static gssize 68 static gssize
119 nexus->written_len = 0; 117 nexus->written_len = 0;
120 118
121 nexus->written_cb(nexus, source, 0); 119 nexus->written_cb(nexus, source, 0);
122 } 120 }
123 121
122 #endif
124 /************************************************************************** 123 /**************************************************************************
125 * Login 124 * Login
126 **************************************************************************/ 125 **************************************************************************/
127 126 static void
128 static void 127 nexus_login_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error, void *data)
129 login_connect_cb(gpointer data, PurpleSslConnection *gsc, 128 {
130 PurpleInputCondition cond); 129 MsnSoapConn * soapconn = data;
131 130 MsnSession *session;
132 static void 131
133 login_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error, void *data) 132 session = soapconn->session;
134 { 133 g_return_if_fail(session != NULL);
134
135 soapconn->gsc = NULL;
136
137 msn_session_set_error(session, MSN_ERROR_AUTH, _("Windows Live ID authentication:Unable to connect"));
138 /* the above line will result in nexus being destroyed, so we don't want
139 * to destroy it here, or we'd crash */
140 }
141
142 /*process the SOAP reply, get the Authentication Info*/
143 static void
144 nexus_login_read_cb(gpointer data, gint source, PurpleInputCondition cond)
145 {
146 MsnSoapConn * soapconn = data;
135 MsnNexus *nexus; 147 MsnNexus *nexus;
136 MsnSession *session; 148 MsnSession *session;
137 149
138 nexus = data; 150 char *base, *c;
151 char *msn_twn_t,*msn_twn_p;
152 char *login_params;
153 char **elems, **cur, **tokens;
154 char * cert_str;
155
156 nexus = soapconn->parent;
139 g_return_if_fail(nexus != NULL); 157 g_return_if_fail(nexus != NULL);
140
141 nexus->gsc = NULL;
142
143 session = nexus->session; 158 session = nexus->session;
144 g_return_if_fail(session != NULL); 159 g_return_if_fail(session != NULL);
145 160
146 msn_session_set_error(session, MSN_ERROR_AUTH, _("Unable to connect")); 161 purple_debug_misc("msn", "TWN Server Reply: {%s}\n", soapconn->read_buf);
147 /* the above line will result in nexus being destroyed, so we don't want 162
148 * to destroy it here, or we'd crash */ 163 /*reply OK, we should process the SOAP body*/
164 purple_debug_info("MaYuan","Windows Live ID Reply OK!\n");
165
166 //TODO: we should parse it using XML
167 #ifdef NEXUS_LOGIN_TWN
168 base = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_START_TOKEN);
169 base += strlen(TWN_START_TOKEN);
170 c = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_END_TOKEN);
171 #else
172 base = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_LIVE_START_TOKEN);
173 base += strlen(TWN_LIVE_START_TOKEN);
174 c = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_LIVE_END_TOKEN);
175 #endif
176 login_params = g_strndup(base, c - base);
177
178 // purple_debug_info("msn", "TWN Cert: {%s}\n", login_params);
179
180 /* Parse the challenge data. */
181 elems = g_strsplit(login_params, "&amp;", 0);
182
183 for (cur = elems; *cur != NULL; cur++){
184 tokens = g_strsplit(*cur, "=", 2);
185 g_hash_table_insert(nexus->challenge_data, tokens[0], tokens[1]);
186 /* Don't free each of the tokens, only the array. */
187 g_free(tokens);
188 }
189
190 g_strfreev(elems);
191
192 msn_twn_t = (char *)g_hash_table_lookup(nexus->challenge_data, "t");
193 msn_twn_p = (char *)g_hash_table_lookup(nexus->challenge_data, "p");
194
195 /*setup the t and p parameter for session*/
196 if (session->passport_info.t != NULL){
197 g_free(session->passport_info.t);
198 }
199 session->passport_info.t = g_strdup(msn_twn_t);
200
201 if (session->passport_info.p != NULL)
202 g_free(session->passport_info.p);
203 session->passport_info.p = g_strdup(msn_twn_p);
204
205 cert_str = g_strdup_printf("t=%s&p=%s",msn_twn_t,msn_twn_p);
206 msn_got_login_params(session, cert_str);
207
208 purple_debug_info("MaYuan","close nexus connection! \n");
209 g_free(cert_str);
210 g_free(login_params);
211 msn_nexus_destroy(nexus);
212 session->nexus = NULL;
213
214 return;
149 } 215 }
150 216
151 static void 217 static void
152 nexus_login_written_cb(gpointer data, gint source, PurpleInputCondition cond) 218 nexus_login_written_cb(gpointer data, gint source, PurpleInputCondition cond)
153 { 219 {
220 MsnSoapConn * soapconn = data;
221
222 soapconn->read_cb = nexus_login_read_cb;
223 // msn_soap_read_cb(data,source,cond);
224 }
225
226
227 /*when connect, do the SOAP Style windows Live ID authentication */
228 void
229 nexus_login_connect_cb(gpointer data, PurpleSslConnection *gsc,
230 PurpleInputCondition cond)
231 {
232 MsnSoapConn *soapconn;
233 MsnNexus * nexus;
234 MsnSession *session;
235 char *ru,*lc,*id,*tw,*ct,*kpp,*kv,*ver,*rn,*tpf;
236 char *fs0,*fs;
237 char *username, *password;
238 char *request_str, *head, *tail;
239 #ifdef NEXUS_LOGIN_TWN
240 char *challenge_str;
241 #else
242 char *rst1_str,*rst2_str,*rst3_str;
243 #endif
244
245 purple_debug_info("MaYuan","starting Windows Live ID authentication\n");
246
247 soapconn = data;
248 g_return_if_fail(soapconn != NULL);
249
250 nexus = soapconn->parent;
251 g_return_if_fail(nexus != NULL);
252
253 session = soapconn->session;
254 g_return_if_fail(session != NULL);
255
256 msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE);
257
258 /*prepare the Windows Live ID authentication token*/
259 username = g_strdup(purple_account_get_username(session->account));
260 password = g_strdup(purple_connection_get_password(session->account->gc));
261
262 lc = (char *)g_hash_table_lookup(nexus->challenge_data, "lc");
263 id = (char *)g_hash_table_lookup(nexus->challenge_data, "id");
264 tw = (char *)g_hash_table_lookup(nexus->challenge_data, "tw");
265 fs0= (char *)g_hash_table_lookup(nexus->challenge_data, "fs");
266 ru = (char *)g_hash_table_lookup(nexus->challenge_data, "ru");
267 ct = (char *)g_hash_table_lookup(nexus->challenge_data, "ct");
268 kpp= (char *)g_hash_table_lookup(nexus->challenge_data, "kpp");
269 kv = (char *)g_hash_table_lookup(nexus->challenge_data, "kv");
270 ver= (char *)g_hash_table_lookup(nexus->challenge_data, "ver");
271 rn = (char *)g_hash_table_lookup(nexus->challenge_data, "rn");
272 tpf= (char *)g_hash_table_lookup(nexus->challenge_data, "tpf");
273
274 /*
275 * add some fail-safe code to avoid windows Purple Crash bug #1540454
276 * If any of these string is NULL, will return Authentication Fail!
277 * for when windows g_strdup_printf() implementation get NULL point,It crashed!
278 */
279 if(!(lc && id && tw && ru && ct && kpp && kv && ver && tpf)){
280 purple_debug_error("MaYuan","WLM Authenticate Key Error!\n");
281 msn_session_set_error(session, MSN_ERROR_AUTH, _("Windows Live ID authentication Failed"));
282 g_free(username);
283 g_free(password);
284 purple_ssl_close(gsc);
285 msn_nexus_destroy(nexus);
286 session->nexus = NULL;
287 return;
288 }
289
290 /*
291 * in old MSN NS server's "USR TWN S" return,didn't include fs string
292 * so we use a default "1" for fs.
293 */
294 if(fs0){
295 fs = g_strdup(fs0);
296 }else{
297 fs = g_strdup("1");
298 }
299
300 #ifdef NEXUS_LOGIN_TWN
301 challenge_str = g_strdup_printf(
302 "lc=%s&amp;id=%s&amp;tw=%s&amp;fs=%s&amp;ru=%s&amp;ct=%s&amp;kpp=%s&amp;kv=%s&amp;ver=%s&amp;rn=%s&amp;tpf=%s\r\n",
303 lc,id,tw,fs,ru,ct,kpp,kv,ver,rn,tpf
304 );
305
306 /*build the SOAP windows Live ID XML body */
307 tail = g_strdup_printf(TWN_ENVELOP_TEMPLATE,username,password,challenge_str );
308 g_free(challenge_str);
309 #else
310 rst1_str = g_strdup_printf(
311 "id=%s&amp;tw=%s&amp;fs=%s&amp;kpp=%s&amp;kv=%s&amp;ver=%s&amp;rn=%s",
312 id,tw,fs,kpp,kv,ver,rn
313 );
314 rst2_str = g_strdup_printf(
315 "fs=%s&amp;id=%s&amp;kv=%s&amp;rn=%s&amp;tw=%s&amp;ver=%s",
316 fs,id,kv,rn,tw,ver
317 );
318 rst3_str = g_strdup_printf("id=%s",id);
319 tail = g_strdup_printf(TWN_LIVE_ENVELOP_TEMPLATE,username,password,rst1_str,rst2_str,rst3_str);
320 g_free(rst1_str);
321 g_free(rst2_str);
322 g_free(rst3_str);
323 #endif
324 g_free(fs);
325
326 soapconn->login_path = g_strdup(TWN_POST_URL);
327 head = g_strdup_printf(
328 "POST %s HTTP/1.1\r\n"
329 "Accept: text/*\r\n"
330 "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n"
331 "Host: %s\r\n"
332 "Content-Length: %d\r\n"
333 "Connection: Keep-Alive\r\n"
334 "Cache-Control: no-cache\r\n\r\n",
335 soapconn->login_path,soapconn->login_host,(int)strlen(tail));
336
337 request_str = g_strdup_printf("%s%s", head,tail);
338 purple_debug_misc("msn", "TWN Sending: {%s}\n", request_str);
339
340 g_free(head);
341 g_free(tail);
342 g_free(username);
343 g_free(password);
344
345 /*prepare to send the SOAP request*/
346 msn_soap_write(soapconn,request_str,nexus_login_written_cb);
347
348 return;
349 }
350
351 #if 0 /* khc */
352 static void
353 nexus_connect_written_cb(gpointer data, gint source, PurpleInputCondition cond)
354 {
154 MsnNexus *nexus = data; 355 MsnNexus *nexus = data;
155 MsnSession *session;
156 int len; 356 int len;
157 357
158 session = nexus->session; 358 char *da_login;
159 g_return_if_fail(session != NULL); 359 char *base, *c;
160 360
161 if (nexus->input_handler == 0) 361 if (nexus->input_handler == 0)
162 /* TODO: Use purple_ssl_input_add()? */ 362 /* TODO: Use purple_ssl_input_add()? */
163 nexus->input_handler = purple_input_add(nexus->gsc->fd, 363 nexus->input_handler = purple_input_add(nexus->gsc->fd,
164 PURPLE_INPUT_READ, nexus_login_written_cb, nexus); 364 PURPLE_INPUT_READ, nexus_connect_written_cb, nexus);
165 365
166 366
367 /* Get the PassportURLs line. */
167 len = msn_ssl_read(nexus); 368 len = msn_ssl_read(nexus);
168 369
169 if (len < 0 && errno == EAGAIN) 370 if (len < 0 && errno == EAGAIN)
170 return; 371 return;
171 else if (len < 0) { 372 else if (len < 0) {
183 return; 384 return;
184 385
185 purple_input_remove(nexus->input_handler); 386 purple_input_remove(nexus->input_handler);
186 nexus->input_handler = 0; 387 nexus->input_handler = 0;
187 388
188 purple_ssl_close(nexus->gsc);
189 nexus->gsc = NULL;
190
191 purple_debug_misc("msn", "ssl buffer: {%s}", nexus->read_buf);
192
193 if (strstr(nexus->read_buf, "HTTP/1.1 302") != NULL)
194 {
195 /* Redirect. */
196 char *location, *c;
197
198 location = strstr(nexus->read_buf, "Location: ");
199 if (location == NULL)
200 {
201 g_free(nexus->read_buf);
202 nexus->read_buf = NULL;
203 nexus->read_len = 0;
204
205 return;
206 }
207 location = strchr(location, ' ') + 1;
208
209 if ((c = strchr(location, '\r')) != NULL)
210 *c = '\0';
211
212 /* Skip the http:// */
213 if ((c = strchr(location, '/')) != NULL)
214 location = c + 2;
215
216 if ((c = strchr(location, '/')) != NULL)
217 {
218 g_free(nexus->login_path);
219 nexus->login_path = g_strdup(c);
220
221 *c = '\0';
222 }
223
224 g_free(nexus->login_host);
225 nexus->login_host = g_strdup(location);
226
227 nexus->gsc = purple_ssl_connect(session->account,
228 nexus->login_host, PURPLE_SSL_DEFAULT_PORT,
229 login_connect_cb, login_error_cb, nexus);
230 }
231 else if (strstr(nexus->read_buf, "HTTP/1.1 401 Unauthorized") != NULL)
232 {
233 const char *error;
234
235 if ((error = strstr(nexus->read_buf, "WWW-Authenticate")) != NULL)
236 {
237 if ((error = strstr(error, "cbtxt=")) != NULL)
238 {
239 const char *c;
240 char *temp;
241
242 error += strlen("cbtxt=");
243
244 if ((c = strchr(error, '\n')) == NULL)
245 c = error + strlen(error);
246
247 temp = g_strndup(error, c - error);
248 error = purple_url_decode(temp);
249 g_free(temp);
250 }
251 }
252
253 msn_session_set_error(session, MSN_ERROR_AUTH, error);
254 }
255 else if (strstr(nexus->read_buf, "HTTP/1.1 503 Service Unavailable"))
256 {
257 msn_session_set_error(session, MSN_ERROR_SERV_UNAVAILABLE, NULL);
258 }
259 else if (strstr(nexus->read_buf, "HTTP/1.1 200 OK"))
260 {
261 char *base, *c;
262 char *login_params;
263
264 #if 0
265 /* All your base are belong to us. */
266 base = buffer;
267
268 /* For great cookie! */
269 while ((base = strstr(base, "Set-Cookie: ")) != NULL)
270 {
271 base += strlen("Set-Cookie: ");
272
273 c = strchr(base, ';');
274
275 session->login_cookies =
276 g_list_append(session->login_cookies,
277 g_strndup(base, c - base));
278 }
279 #endif
280
281 base = strstr(nexus->read_buf, "Authentication-Info: ");
282
283 g_return_if_fail(base != NULL);
284
285 base = strstr(base, "from-PP='");
286 base += strlen("from-PP='");
287 c = strchr(base, '\'');
288
289 login_params = g_strndup(base, c - base);
290
291 msn_got_login_params(session, login_params);
292
293 g_free(login_params);
294
295 msn_nexus_destroy(nexus);
296 session->nexus = NULL;
297 return;
298 }
299
300 g_free(nexus->read_buf);
301 nexus->read_buf = NULL;
302 nexus->read_len = 0;
303
304 }
305
306 /* this guards against missing hash entries */
307 static char *
308 nexus_challenge_data_lookup(GHashTable *challenge_data, const char *key)
309 {
310 char *entry;
311
312 return (entry = (char *)g_hash_table_lookup(challenge_data, key)) ?
313 entry : "(null)";
314 }
315
316 void
317 login_connect_cb(gpointer data, PurpleSslConnection *gsc,
318 PurpleInputCondition cond)
319 {
320 MsnNexus *nexus;
321 MsnSession *session;
322 char *username, *password;
323 char *request_str, *head, *tail;
324 char *buffer = NULL;
325 guint32 ctint;
326
327 nexus = data;
328 g_return_if_fail(nexus != NULL);
329
330 session = nexus->session;
331 g_return_if_fail(session != NULL);
332
333 msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE);
334
335 username =
336 g_strdup(purple_url_encode(purple_account_get_username(session->account)));
337
338 password =
339 g_strdup(purple_url_encode(purple_connection_get_password(session->account->gc)));
340
341 ctint = strtoul((char *)g_hash_table_lookup(nexus->challenge_data, "ct"), NULL, 10) + 200;
342
343 head = g_strdup_printf(
344 "GET %s HTTP/1.1\r\n"
345 "Authorization: Passport1.4 OrgVerb=GET,OrgURL=%s,sign-in=%s",
346 nexus->login_path,
347 (char *)g_hash_table_lookup(nexus->challenge_data, "ru"),
348 username);
349
350 tail = g_strdup_printf(
351 "lc=%s,id=%s,tw=%s,fs=%s,ru=%s,ct=%" G_GUINT32_FORMAT ",kpp=%s,kv=%s,ver=%s,tpf=%s\r\n"
352 "User-Agent: MSMSGS\r\n"
353 "Host: %s\r\n"
354 "Connection: Keep-Alive\r\n"
355 "Cache-Control: no-cache\r\n",
356 nexus_challenge_data_lookup(nexus->challenge_data, "lc"),
357 nexus_challenge_data_lookup(nexus->challenge_data, "id"),
358 nexus_challenge_data_lookup(nexus->challenge_data, "tw"),
359 nexus_challenge_data_lookup(nexus->challenge_data, "fs"),
360 nexus_challenge_data_lookup(nexus->challenge_data, "ru"),
361 ctint,
362 nexus_challenge_data_lookup(nexus->challenge_data, "kpp"),
363 nexus_challenge_data_lookup(nexus->challenge_data, "kv"),
364 nexus_challenge_data_lookup(nexus->challenge_data, "ver"),
365 nexus_challenge_data_lookup(nexus->challenge_data, "tpf"),
366 nexus->login_host);
367
368 buffer = g_strdup_printf("%s,pwd=XXXXXXXX,%s\r\n", head, tail);
369 request_str = g_strdup_printf("%s,pwd=%s,%s\r\n", head, password, tail);
370
371 purple_debug_misc("msn", "Sending: {%s}\n", buffer);
372
373 g_free(buffer);
374 g_free(head);
375 g_free(tail);
376 g_free(username);
377 g_free(password);
378
379 nexus->write_buf = request_str;
380 nexus->written_len = 0;
381
382 nexus->read_len = 0;
383
384 nexus->written_cb = nexus_login_written_cb;
385
386 nexus->input_handler = purple_input_add(gsc->fd, PURPLE_INPUT_WRITE,
387 nexus_write_cb, nexus);
388
389 nexus_write_cb(nexus, gsc->fd, PURPLE_INPUT_WRITE);
390
391 return;
392
393
394 }
395
396 static void
397 nexus_connect_written_cb(gpointer data, gint source, PurpleInputCondition cond)
398 {
399 MsnNexus *nexus = data;
400 int len;
401 char *da_login;
402 char *base, *c;
403
404 if (nexus->input_handler == 0)
405 /* TODO: Use purple_ssl_input_add()? */
406 nexus->input_handler = purple_input_add(nexus->gsc->fd,
407 PURPLE_INPUT_READ, nexus_connect_written_cb, nexus);
408
409 /* Get the PassportURLs line. */
410 len = msn_ssl_read(nexus);
411
412 if (len < 0 && errno == EAGAIN)
413 return;
414 else if (len < 0) {
415 purple_input_remove(nexus->input_handler);
416 nexus->input_handler = 0;
417 g_free(nexus->read_buf);
418 nexus->read_buf = NULL;
419 nexus->read_len = 0;
420 /* TODO: error handling */
421 return;
422 }
423
424 if (g_strstr_len(nexus->read_buf, nexus->read_len,
425 "\r\n\r\n") == NULL)
426 return;
427
428 purple_input_remove(nexus->input_handler);
429 nexus->input_handler = 0;
430
431 base = strstr(nexus->read_buf, "PassportURLs"); 389 base = strstr(nexus->read_buf, "PassportURLs");
432 390
433 if (base == NULL) 391 if (base == NULL)
434 { 392 {
435 g_free(nexus->read_buf); 393 g_free(nexus->read_buf);
466 nexus->login_host, PURPLE_SSL_DEFAULT_PORT, 424 nexus->login_host, PURPLE_SSL_DEFAULT_PORT,
467 login_connect_cb, login_error_cb, nexus); 425 login_connect_cb, login_error_cb, nexus);
468 } 426 }
469 427
470 428
429 #endif
430
471 /************************************************************************** 431 /**************************************************************************
472 * Connect 432 * Connect
473 **************************************************************************/ 433 **************************************************************************/
474 434
435 #if 0 /* khc */
475 static void 436 static void
476 nexus_connect_cb(gpointer data, PurpleSslConnection *gsc, 437 nexus_connect_cb(gpointer data, PurpleSslConnection *gsc,
477 PurpleInputCondition cond) 438 PurpleInputCondition cond)
478 { 439 {
479 MsnNexus *nexus; 440 MsnNexus *nexus;
498 nexus_write_cb, nexus); 459 nexus_write_cb, nexus);
499 460
500 nexus_write_cb(nexus, gsc->fd, PURPLE_INPUT_WRITE); 461 nexus_write_cb(nexus, gsc->fd, PURPLE_INPUT_WRITE);
501 } 462 }
502 463
464 #endif
465
503 void 466 void
504 msn_nexus_connect(MsnNexus *nexus) 467 msn_nexus_connect(MsnNexus *nexus)
505 { 468 {
506 nexus->gsc = purple_ssl_connect(nexus->session->account, 469 /* Authenticate via Windows Live ID. */
507 "nexus.passport.com", PURPLE_SSL_DEFAULT_PORT, 470 purple_debug_info("MaYuan","msn_nexus_connect...\n");
508 nexus_connect_cb, login_error_cb, nexus); 471 msn_soap_init(nexus->soapconn,MSN_TWN_SERVER,1,nexus_login_connect_cb,nexus_login_error_cb);
509 } 472 msn_soap_connect(nexus->soapconn);
473 }