comparison libpurple/protocols/msn/nexus.c @ 19843:60bc06498746

Committing khc's msnp14 changes from Trac Ticket #148. --rlaager committer: Richard Laager <rlaager@wiktel.com>
author Ka-Hing Cheung <khc@hxbc.us>
date Sun, 15 Apr 2007 04:12:27 +0000
parents 783b05e528b0
children 14b8fb8d27b3
comparison
equal deleted inserted replaced
16121:6167ee79ecd0 19843:60bc06498746
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
29 #undef NEXUS_LOGIN_TWN
30
31 /*Local Function Prototype*/
32 static void nexus_login_connect_cb(gpointer data, PurpleSslConnection *gsc,PurpleInputCondition cond);
27 33
28 /************************************************************************** 34 /**************************************************************************
29 * Main 35 * Main
30 **************************************************************************/ 36 **************************************************************************/
31 37
34 { 40 {
35 MsnNexus *nexus; 41 MsnNexus *nexus;
36 42
37 nexus = g_new0(MsnNexus, 1); 43 nexus = g_new0(MsnNexus, 1);
38 nexus->session = session; 44 nexus->session = session;
45 /*we must use SSL connection to do Windows Live ID authentication*/
46 nexus->soapconn = msn_soap_new(session,nexus,1);
47
39 nexus->challenge_data = g_hash_table_new_full(g_str_hash, 48 nexus->challenge_data = g_hash_table_new_full(g_str_hash,
40 g_str_equal, g_free, g_free); 49 g_str_equal, g_free, g_free);
41 50
42 return nexus; 51 return nexus;
43 } 52 }
44 53
45 void 54 void
46 msn_nexus_destroy(MsnNexus *nexus) 55 msn_nexus_destroy(MsnNexus *nexus)
47 { 56 {
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) 57 if (nexus->challenge_data != NULL)
56 g_hash_table_destroy(nexus->challenge_data); 58 g_hash_table_destroy(nexus->challenge_data);
57 59
58 if (nexus->input_handler > 0) 60 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); 61 g_free(nexus);
64 } 62 }
65 63
64 #if 0 /* khc */
66 /************************************************************************** 65 /**************************************************************************
67 * Util 66 * Util
68 **************************************************************************/ 67 **************************************************************************/
69 68
70 static gssize 69 static gssize
119 nexus->written_len = 0; 118 nexus->written_len = 0;
120 119
121 nexus->written_cb(nexus, source, 0); 120 nexus->written_cb(nexus, source, 0);
122 } 121 }
123 122
123 #endif
124 /************************************************************************** 124 /**************************************************************************
125 * Login 125 * Login
126 **************************************************************************/ 126 **************************************************************************/
127 127 static void
128 static void 128 nexus_login_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error, void *data)
129 login_connect_cb(gpointer data, PurpleSslConnection *gsc, 129 {
130 PurpleInputCondition cond); 130 MsnSoapConn * soapconn = data;
131 131 MsnSession *session;
132 static void 132
133 login_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error, void *data) 133 session = soapconn->session;
134 { 134 g_return_if_fail(session != NULL);
135
136 soapconn->gsc = NULL;
137
138 msn_session_set_error(session, MSN_ERROR_AUTH, _("Windows Live ID authentication:Unable to connect"));
139 /* the above line will result in nexus being destroyed, so we don't want
140 * to destroy it here, or we'd crash */
141 }
142
143 /*process the SOAP reply, get the Authentication Info*/
144 static void
145 nexus_login_read_cb(gpointer data, gint source, PurpleInputCondition cond)
146 {
147 MsnSoapConn * soapconn = data;
135 MsnNexus *nexus; 148 MsnNexus *nexus;
136 MsnSession *session; 149 MsnSession *session;
137 150
138 nexus = data; 151 char *base, *c;
152 char *msn_twn_t,*msn_twn_p;
153 char *login_params;
154 char **elems, **cur, **tokens;
155 char * cert_str;
156
157 nexus = soapconn->parent;
139 g_return_if_fail(nexus != NULL); 158 g_return_if_fail(nexus != NULL);
140
141 nexus->gsc = NULL;
142
143 session = nexus->session; 159 session = nexus->session;
144 g_return_if_fail(session != NULL); 160 g_return_if_fail(session != NULL);
145 161
146 msn_session_set_error(session, MSN_ERROR_AUTH, _("Unable to connect")); 162 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 163
148 * to destroy it here, or we'd crash */ 164 /*reply OK, we should process the SOAP body*/
165 purple_debug_info("MaYuan","Windows Live ID Reply OK!\n");
166
167 //TODO: we should parse it using XML
168 #ifdef NEXUS_LOGIN_TWN
169 base = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_START_TOKEN);
170 base += strlen(TWN_START_TOKEN);
171 c = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_END_TOKEN);
172 #else
173 base = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_LIVE_START_TOKEN);
174 base += strlen(TWN_LIVE_START_TOKEN);
175 c = g_strstr_len(soapconn->read_buf, soapconn->read_len, TWN_LIVE_END_TOKEN);
176 #endif
177 login_params = g_strndup(base, c - base);
178
179 // purple_debug_info("msn", "TWN Cert: {%s}\n", login_params);
180
181 /* Parse the challenge data. */
182 elems = g_strsplit(login_params, "&amp;", 0);
183
184 for (cur = elems; *cur != NULL; cur++){
185 tokens = g_strsplit(*cur, "=", 2);
186 g_hash_table_insert(nexus->challenge_data, tokens[0], tokens[1]);
187 /* Don't free each of the tokens, only the array. */
188 g_free(tokens);
189 }
190
191 g_strfreev(elems);
192
193 msn_twn_t = (char *)g_hash_table_lookup(nexus->challenge_data, "t");
194 msn_twn_p = (char *)g_hash_table_lookup(nexus->challenge_data, "p");
195
196 /*setup the t and p parameter for session*/
197 if (session->passport_info.t != NULL){
198 g_free(session->passport_info.t);
199 }
200 session->passport_info.t = g_strdup(msn_twn_t);
201
202 if (session->passport_info.p != NULL)
203 g_free(session->passport_info.p);
204 session->passport_info.p = g_strdup(msn_twn_p);
205
206 cert_str = g_strdup_printf("t=%s&p=%s",msn_twn_t,msn_twn_p);
207 msn_got_login_params(session, cert_str);
208
209 purple_debug_info("MaYuan","close nexus connection! \n");
210 g_free(cert_str);
211 g_free(login_params);
212 msn_nexus_destroy(nexus);
213 session->nexus = NULL;
214
215 return;
149 } 216 }
150 217
151 static void 218 static void
152 nexus_login_written_cb(gpointer data, gint source, PurpleInputCondition cond) 219 nexus_login_written_cb(gpointer data, gint source, PurpleInputCondition cond)
153 { 220 {
221 MsnSoapConn * soapconn = data;
222
223 soapconn->read_cb = nexus_login_read_cb;
224 // msn_soap_read_cb(data,source,cond);
225 }
226
227
228 /*when connect, do the SOAP Style windows Live ID authentication */
229 void
230 nexus_login_connect_cb(gpointer data, PurpleSslConnection *gsc,
231 PurpleInputCondition cond)
232 {
233 MsnSoapConn *soapconn;
234 MsnNexus * nexus;
235 MsnSession *session;
236 char *ru,*lc,*id,*tw,*ct,*kpp,*kv,*ver,*rn,*tpf;
237 char *fs0,*fs;
238 char *username, *password;
239 char *request_str, *head, *tail;
240 #ifdef NEXUS_LOGIN_TWN
241 char *challenge_str;
242 #else
243 char *rst1_str,*rst2_str,*rst3_str;
244 #endif
245
246 purple_debug_info("MaYuan","starting Windows Live ID authentication\n");
247
248 soapconn = data;
249 g_return_if_fail(soapconn != NULL);
250
251 nexus = soapconn->parent;
252 g_return_if_fail(nexus != NULL);
253
254 session = soapconn->session;
255 g_return_if_fail(session != NULL);
256
257 msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE);
258
259 /*prepare the Windows Live ID authentication token*/
260 username = g_strdup(purple_account_get_username(session->account));
261 password = g_strdup(purple_connection_get_password(session->account->gc));
262
263 lc = (char *)g_hash_table_lookup(nexus->challenge_data, "lc");
264 id = (char *)g_hash_table_lookup(nexus->challenge_data, "id");
265 tw = (char *)g_hash_table_lookup(nexus->challenge_data, "tw");
266 fs0= (char *)g_hash_table_lookup(nexus->challenge_data, "fs");
267 ru = (char *)g_hash_table_lookup(nexus->challenge_data, "ru");
268 ct = (char *)g_hash_table_lookup(nexus->challenge_data, "ct");
269 kpp= (char *)g_hash_table_lookup(nexus->challenge_data, "kpp");
270 kv = (char *)g_hash_table_lookup(nexus->challenge_data, "kv");
271 ver= (char *)g_hash_table_lookup(nexus->challenge_data, "ver");
272 rn = (char *)g_hash_table_lookup(nexus->challenge_data, "rn");
273 tpf= (char *)g_hash_table_lookup(nexus->challenge_data, "tpf");
274
275 /*
276 * add some fail-safe code to avoid windows Purple Crash bug #1540454
277 * If any of these string is NULL, will return Authentication Fail!
278 * for when windows g_strdup_printf() implementation get NULL point,It crashed!
279 */
280 if(!(lc && id && tw && ru && ct && kpp && kv && ver && tpf)){
281 purple_debug_error("MaYuan","WLM Authenticate Key Error!\n");
282 msn_session_set_error(session, MSN_ERROR_AUTH, _("Windows Live ID authentication Failed"));
283 g_free(username);
284 g_free(password);
285 purple_ssl_close(gsc);
286 msn_nexus_destroy(nexus);
287 session->nexus = NULL;
288 return;
289 }
290
291 /*
292 * in old MSN NS server's "USR TWN S" return,didn't include fs string
293 * so we use a default "1" for fs.
294 */
295 if(fs0){
296 fs = g_strdup(fs0);
297 }else{
298 fs = g_strdup("1");
299 }
300
301 #ifdef NEXUS_LOGIN_TWN
302 challenge_str = g_strdup_printf(
303 "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",
304 lc,id,tw,fs,ru,ct,kpp,kv,ver,rn,tpf
305 );
306
307 /*build the SOAP windows Live ID XML body */
308 tail = g_strdup_printf(TWN_ENVELOP_TEMPLATE,username,password,challenge_str );
309 g_free(challenge_str);
310 #else
311 rst1_str = g_strdup_printf(
312 "id=%s&amp;tw=%s&amp;fs=%s&amp;kpp=%s&amp;kv=%s&amp;ver=%s&amp;rn=%s",
313 id,tw,fs,kpp,kv,ver,rn
314 );
315 rst2_str = g_strdup_printf(
316 "fs=%s&amp;id=%s&amp;kv=%s&amp;rn=%s&amp;tw=%s&amp;ver=%s",
317 fs,id,kv,rn,tw,ver
318 );
319 rst3_str = g_strdup_printf("id=%s",id);
320 tail = g_strdup_printf(TWN_LIVE_ENVELOP_TEMPLATE,username,password,rst1_str,rst2_str,rst3_str);
321 g_free(rst1_str);
322 g_free(rst2_str);
323 g_free(rst3_str);
324 #endif
325 g_free(fs);
326
327 soapconn->login_path = g_strdup(TWN_POST_URL);
328 head = g_strdup_printf(
329 "POST %s HTTP/1.1\r\n"
330 "Accept: text/*\r\n"
331 "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n"
332 "Host: %s\r\n"
333 "Content-Length: %d\r\n"
334 "Connection: Keep-Alive\r\n"
335 "Cache-Control: no-cache\r\n\r\n",
336 soapconn->login_path,soapconn->login_host,(int)strlen(tail));
337
338 request_str = g_strdup_printf("%s%s", head,tail);
339 purple_debug_misc("msn", "TWN Sending: {%s}\n", request_str);
340
341 g_free(head);
342 g_free(tail);
343 g_free(username);
344 g_free(password);
345
346 /*prepare to send the SOAP request*/
347 msn_soap_write(soapconn,request_str,nexus_login_written_cb);
348
349 return;
350 }
351
352 #if 0 /* khc */
353 static void
354 nexus_connect_written_cb(gpointer data, gint source, PurpleInputCondition cond)
355 {
154 MsnNexus *nexus = data; 356 MsnNexus *nexus = data;
155 MsnSession *session;
156 int len; 357 int len;
157 358 char *da_login;
158 session = nexus->session; 359 char *base, *c;
159 g_return_if_fail(session != NULL);
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 /* Get the PassportURLs line. */
167 len = msn_ssl_read(nexus); 367 len = msn_ssl_read(nexus);
168 368
169 if (len < 0 && errno == EAGAIN) 369 if (len < 0 && errno == EAGAIN)
170 return; 370 return;
171 else if (len < 0) { 371 else if (len < 0) {
183 return; 383 return;
184 384
185 purple_input_remove(nexus->input_handler); 385 purple_input_remove(nexus->input_handler);
186 nexus->input_handler = 0; 386 nexus->input_handler = 0;
187 387
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"); 388 base = strstr(nexus->read_buf, "PassportURLs");
432 389
433 if (base == NULL) 390 if (base == NULL)
434 { 391 {
435 g_free(nexus->read_buf); 392 g_free(nexus->read_buf);
466 nexus->login_host, PURPLE_SSL_DEFAULT_PORT, 423 nexus->login_host, PURPLE_SSL_DEFAULT_PORT,
467 login_connect_cb, login_error_cb, nexus); 424 login_connect_cb, login_error_cb, nexus);
468 } 425 }
469 426
470 427
428 #endif
429
471 /************************************************************************** 430 /**************************************************************************
472 * Connect 431 * Connect
473 **************************************************************************/ 432 **************************************************************************/
474 433
434 #if 0 /* khc */
475 static void 435 static void
476 nexus_connect_cb(gpointer data, PurpleSslConnection *gsc, 436 nexus_connect_cb(gpointer data, PurpleSslConnection *gsc,
477 PurpleInputCondition cond) 437 PurpleInputCondition cond)
478 { 438 {
479 MsnNexus *nexus; 439 MsnNexus *nexus;
498 nexus_write_cb, nexus); 458 nexus_write_cb, nexus);
499 459
500 nexus_write_cb(nexus, gsc->fd, PURPLE_INPUT_WRITE); 460 nexus_write_cb(nexus, gsc->fd, PURPLE_INPUT_WRITE);
501 } 461 }
502 462
463 #endif
464
503 void 465 void
504 msn_nexus_connect(MsnNexus *nexus) 466 msn_nexus_connect(MsnNexus *nexus)
505 { 467 {
506 nexus->gsc = purple_ssl_connect(nexus->session->account, 468 /* Authenticate via Windows Live ID. */
507 "nexus.passport.com", PURPLE_SSL_DEFAULT_PORT, 469 purple_debug_info("MaYuan","msn_nexus_connect...\n");
508 nexus_connect_cb, login_error_cb, nexus); 470 msn_soap_init(nexus->soapconn,MSN_TWN_SERVER,1,nexus_login_connect_cb,nexus_login_error_cb);
509 } 471 msn_soap_connect(nexus->soapconn);
472 }
473