Mercurial > pidgin.yaz
diff libpurple/protocols/msn/soap.c @ 20477:9a2a4a0c0003
Add the possibility to create an Address Book, useful for newly registered MSN users.
When changing friendly name, send the new one to the SOAP server in the PRP msn command callback, with escaped html entity chars. Fixes #1294 .
Handle EBADF error sometimes received in SOAP server read callback (observed in win32).
Misc cleanups.
author | Carlos Silva <typ0@pidgin.im> |
---|---|
date | Tue, 07 Aug 2007 02:37:58 +0000 |
parents | 530a92d50c5e |
children | c1c4468207fa |
line wrap: on
line diff
--- a/libpurple/protocols/msn/soap.c Mon Jul 23 18:16:58 2007 +0000 +++ b/libpurple/protocols/msn/soap.c Tue Aug 07 02:37:58 2007 +0000 @@ -26,8 +26,6 @@ #include "msn.h" #include "soap.h" -/*define this Macro to debug soap server action*/ -#undef MSN_SOAP_DEBUG /*local function prototype*/ void msn_soap_set_process_step(MsnSoapConn *soapconn, MsnSoapStep step); @@ -68,7 +66,8 @@ MsnSoapConn * soapconn; MsnSession *session; - purple_debug_info("MSNP14","Soap connection connected!\n"); + purple_debug_info("MSN SOAP","SOAP server connection established!\n"); + soapconn = data; g_return_if_fail(soapconn != NULL); @@ -94,7 +93,7 @@ MsnSoapConn * soapconn = data; g_return_if_fail(data != NULL); - purple_debug_info("MSNP14","Soap connection error!\n"); + purple_debug_info("MSN SOAP","Soap connection error!\n"); msn_soap_set_process_step(soapconn, MSN_SOAP_UNCONNECTED); /*error callback*/ @@ -109,7 +108,7 @@ PurpleSslInputFunction connect_cb, PurpleSslErrorFunction error_cb) { - purple_debug_info("MSNP14","msn_soap_init...\n"); + purple_debug_info("MSN SOAP","msn_soap_init()\n"); soapconn->login_host = g_strdup(host); soapconn->ssl_conn = ssl; soapconn->connect_cb = connect_cb; @@ -203,26 +202,95 @@ static gssize msn_soap_read(MsnSoapConn *soapconn) { - gssize len,requested_len; + gssize len, requested_len; char temp_buf[MSN_SOAP_READ_BUFF_SIZE]; + + if ( soapconn->need_to_read == 0 || soapconn->need_to_read > MSN_SOAP_READ_BUFF_SIZE) { + requested_len = MSN_SOAP_READ_BUFF_SIZE; + } + else { + requested_len = soapconn->need_to_read; + } + + if ( soapconn->ssl_conn ) { + len = purple_ssl_read(soapconn->gsc, temp_buf, requested_len); + } else { + len = read(soapconn->fd, temp_buf, requested_len); + } + + if ( len <= 0 ) { + switch (errno) { -// requested_len = (soapconn->need_to_read > 0) ? soapconn->need_to_read : MSN_SOAP_READ_BUFF_SIZE; - requested_len = MSN_SOAP_READ_BUFF_SIZE; - if(soapconn->ssl_conn){ - len = purple_ssl_read(soapconn->gsc, temp_buf,requested_len); - }else{ - len = read(soapconn->fd, temp_buf,requested_len); + case 0: + case EBADF: /* we are sometimes getting this in Windows */ + case EAGAIN: +#ifdef MSN_SOAP_DEBUG + purple_debug_info("MSN SOAP", + "msn_soap_read(): %s, returning len = %d.\n", + strerror(errno), len); +#endif + return len; + default : purple_debug_error("MSN SOAP", "Read error!" + "read len: %d, error = %s\n", + len, strerror(errno)); + purple_input_remove(soapconn->input_handler); + soapconn->input_handler = -1; + g_free(soapconn->read_buf); + soapconn->read_buf = NULL; + soapconn->read_len = 0; + /* TODO: error handling */ + return len; + } } - if(len >0){ + else { +#ifdef MSN_SOAP_DEBUG + purple_debug_info("MSN SOAP", "Allocating space for more %d bytes from incoming data. Total space now (according to soapconn->read_len = %d\n", len, soapconn->read_len); +#endif soapconn->read_buf = g_realloc(soapconn->read_buf, soapconn->read_len + len + 1); - memcpy(soapconn->read_buf + soapconn->read_len, temp_buf, len); - soapconn->read_len += len; - soapconn->read_buf[soapconn->read_len] = '\0'; + if ( soapconn->read_buf != NULL ) { + memcpy(soapconn->read_buf + soapconn->read_len, temp_buf, len); + soapconn->read_len += len; + soapconn->read_buf[soapconn->read_len] = '\0'; + } + else { + purple_debug_error("MSN SOAP", "Failure re-allocating %d bytes of memory!\n", soapconn->read_len + len + 1); + exit(EXIT_FAILURE); + } + } + #ifdef MSN_SOAP_DEBUG - purple_debug_info("MSNP14","++soap ssl read:{%d}\n",len); - purple_debug_info("MSNP14","nexus ssl read:{%s}\n",soapconn->read_buf); + purple_debug_info("MSN SOAP","Read SOAP bytes: %d\n", len); + + if (len > -1) { + gchar * soapbody = NULL; + xmlnode * node = NULL; + soapbody = g_strstr_len(soapconn->read_buf, soapconn->read_len, "\r\n\r\n"); + if (soapbody != NULL) + node = xmlnode_from_str(soapbody+4, -1); + + if (node != NULL) { + gchar *pretty = xmlnode_to_formatted_str(node, NULL); + gchar *http_headers, *delimiter; + + delimiter = g_strstr_len(soapconn->read_buf, soapconn->read_len,"\r\n\r\n"); + if (delimiter != NULL) { + + http_headers = g_strndup(soapconn->read_buf, delimiter + 4 - soapconn->read_buf); + purple_debug_info("MSN SOAP","Nexus server read data:\n%s%s\n", http_headers, pretty); + g_free(http_headers); + } + else + purple_debug_info("MSN SOAP","Nexus server read data:\n%s\n", soapconn->read_buf); + + g_free(pretty); + xmlnode_free(node); + } + else + purple_debug_info("MSN SOAP","Received data from Nexus server:\n%s\n", soapconn->read_buf); + + } #endif return len; } @@ -237,40 +305,31 @@ char * body_start,*body_len; char *length_start,*length_end; -// purple_debug_misc("MSNP14", "soap read cb\n"); +#ifdef MSN_SOAP_DEBUG + purple_debug_misc("MSN SOAP", "msn_soap_read_cb()\n"); +#endif session = soapconn->session; g_return_if_fail(session != NULL); - if (soapconn->input_handler == -1){ - soapconn->input_handler = purple_input_add(soapconn->gsc->fd, - PURPLE_INPUT_READ, msn_soap_read_cb, soapconn); - } + /*read the request header*/ len = msn_soap_read(soapconn); - if (len < 0 && errno == EAGAIN){ + + if ( len < 0 ) return; - }else if (len < 0) { - purple_debug_error("msn", "read Error!len:%d\n",len); - purple_input_remove(soapconn->input_handler); - soapconn->input_handler = -1; - g_free(soapconn->read_buf); - soapconn->read_buf = NULL; - soapconn->read_len = 0; - /* TODO: error handling */ + + if (soapconn->read_buf == NULL) { return; } - if(soapconn->read_buf == NULL){ - return; - } - - if (strstr(soapconn->read_buf, "HTTP/1.1 302") != NULL) + if ( (strstr(soapconn->read_buf, "HTTP/1.1 302") != NULL) + || ( strstr(soapconn->read_buf, "HTTP/1.1 301") != NULL ) ) { /* Redirect. */ char *location, *c; - purple_debug_error("MSNP14", "soap redirect\n"); + purple_debug_info("MSN SOAP", "HTTP Redirect\n"); location = strstr(soapconn->read_buf, "Location: "); if (location == NULL) { @@ -343,7 +402,7 @@ { const char *error; - purple_debug_error("MSNP14", "soap 401\n"); + purple_debug_error("MSN SOAP", "Received HTTP error 401 Unauthorized\n"); if ((error = strstr(soapconn->read_buf, "WWW-Authenticate")) != NULL) { if ((error = strstr(error, "cbtxt=")) != NULL) @@ -391,8 +450,8 @@ { /*OK! process the SOAP body*/ body_start = (char *)g_strstr_len(soapconn->read_buf, soapconn->read_len,"\r\n\r\n"); - if(!body_start){ - return; + if (!body_start) { + return; } body_start += 4; @@ -402,19 +461,20 @@ length_start = strstr(soapconn->read_buf, "Content-Length: "); length_start += strlen("Content-Length: "); length_end = strstr(length_start, "\r\n"); - body_len = g_strndup(length_start,length_end - length_start); + body_len = g_strndup(length_start, length_end - length_start); /*setup the conn body */ soapconn->body = body_start; soapconn->body_len = atoi(body_len); + g_free(body_len); #ifdef MSN_SOAP_DEBUG - purple_debug_misc("MSNP14","SOAP Read length :%d,body len:%d\n",soapconn->read_len,soapconn->body_len); + purple_debug_misc("MSN SOAP","SOAP Read length: %d, Body len: %d\n", soapconn->read_len, soapconn->body_len); #endif - soapconn->need_to_read = (body_start - soapconn->read_buf +soapconn->body_len) - soapconn->read_len; - if(soapconn->need_to_read >0){ + soapconn->need_to_read = (body_start - soapconn->read_buf + soapconn->body_len) - soapconn->read_len; + if ( soapconn->need_to_read > 0 ) { return; } - g_free(body_len); + //g_free(body_len); /*remove the read handler*/ purple_input_remove(soapconn->input_handler); @@ -431,9 +491,10 @@ msn_soap_close(soapconn); /*call the read callback*/ - if(soapconn->read_cb != NULL){ - soapconn->read_cb(soapconn,source,0); + if ( soapconn->read_cb != NULL ) { + soapconn->read_cb(soapconn, source, 0); } + msn_soap_free_read_buf(soapconn); } return; } @@ -467,8 +528,8 @@ int len, total_len; g_return_if_fail(soapconn != NULL); - if(soapconn->write_buf == NULL){ - purple_debug_error("MSNP14","soap buffer is NULL\n"); + if ( soapconn->write_buf == NULL ) { + purple_debug_error("MSN SOAP","SOAP buffer is NULL\n"); purple_input_remove(soapconn->output_handler); soapconn->output_handler = -1; return; @@ -489,6 +550,7 @@ purple_input_remove(soapconn->output_handler); soapconn->output_handler = -1; /* TODO: notify of the error */ + purple_debug_error("MSN SOAP","Error writing to SSL connection!\n"); return; } soapconn->written_len += len; @@ -509,7 +571,11 @@ soapconn->written_cb(soapconn, source, 0); } /*maybe we need to read the input?*/ - msn_soap_read_cb(soapconn,source,0); + if ( soapconn->input_handler == -1 ) { + soapconn->input_handler = purple_input_add(soapconn->gsc->fd, + PURPLE_INPUT_READ, msn_soap_read_cb, soapconn); + } +// msn_soap_read_cb(soapconn,source,0); } /*write the buffer to SOAP connection*/ @@ -519,6 +585,8 @@ soapconn->write_buf = write_buf; soapconn->written_len = 0; soapconn->written_cb = written_cb; + + msn_soap_free_read_buf(soapconn); /*clear the read buffer first*/ /*start the write*/ @@ -586,18 +654,18 @@ msn_soap_post(MsnSoapConn *soapconn,MsnSoapReq *request, MsnSoapConnectInitFunction msn_soap_init_func) { - if(request != NULL){ + if (request != NULL) { g_queue_push_tail(soapconn->soap_queue, request); } - if(!msn_soap_connected(soapconn)&&(soapconn->step == MSN_SOAP_UNCONNECTED) - &&(!g_queue_is_empty(soapconn->soap_queue))){ + if (!msn_soap_connected(soapconn) && (soapconn->step == MSN_SOAP_UNCONNECTED) + &&(!g_queue_is_empty(soapconn->soap_queue))) { /*not connected?and we have something to process connect it first*/ - purple_debug_info("MSNP14","soap is not connected!\n"); + purple_debug_info("MSN SOAP","No connection to SOAP server. Connecting...\n"); msn_soap_init_func(soapconn); msn_soap_connect(soapconn); return; } - purple_debug_info("MSNP14","soap connected!\n"); + purple_debug_info("MSN SOAP","Connected to SOAP server!\n"); /*if connected, what we only needed to do is to queue the request, * when SOAP request in the queue processed done, will do this command. @@ -618,7 +686,11 @@ char * soap_head = NULL; char * request_str = NULL; - purple_debug_info("MSNP14","msn_soap_post_request()...\n"); +#ifdef MSN_SOAP_DEBUG + xmlnode * node; + + purple_debug_info("MSN SOAP","msn_soap_post_request()...\n"); +#endif msn_soap_set_process_step(soapconn,MSN_SOAP_PROCESSING); soap_head = g_strdup_printf( "POST %s HTTP/1.1\r\n" @@ -637,13 +709,21 @@ request->login_host, strlen(request->body) ); - request_str = g_strdup_printf("%s%s", soap_head,request->body); - g_free(soap_head); + request_str = g_strdup_printf("%s%s", soap_head, request->body); #ifdef MSN_SOAP_DEBUG - purple_debug_info("MSNP14","send to server{%s}\n",request_str); + node = xmlnode_from_str(request->body, -1); + if (node != NULL) { + char *pretty = xmlnode_to_formatted_str(node, NULL); + purple_debug_info("MSN SOAP","Posting request to SOAP server:\n%s%s\n",soap_head, pretty); + g_free(pretty); + xmlnode_free(node); + } + else + purple_debug_info("MSN SOAP","Failed to parse SOAP request:\n%s\n", request_str); #endif - + + g_free(soap_head); /*free read buffer*/ msn_soap_free_read_buf(soapconn); /*post it to server*/