libpurple/protocols/mxit/protocol.c

branch
mxit-2.x.y
changeset 33828
7a40d62c81d8
parent 33681
e3e608e00598
parent 33821
062af32ae5b7
child 33848
07ffa66fd57b
equal deleted inserted replaced
33681:e3e608e00598 33828:7a40d62c81d8
265 static void mxit_cb_http_rx( PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message ) 265 static void mxit_cb_http_rx( PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message )
266 { 266 {
267 struct MXitSession* session = (struct MXitSession*) user_data; 267 struct MXitSession* session = (struct MXitSession*) user_data;
268 268
269 /* clear outstanding request */ 269 /* clear outstanding request */
270 session->http_out_req = NULL; 270 session->async_calls = g_slist_remove( session->async_calls, url_data );
271 271
272 if ( ( !url_text ) || ( len == 0 ) ) { 272 if ( ( !url_text ) || ( len == 0 ) ) {
273 /* error with request */ 273 /* error with request */
274 purple_debug_error( MXIT_PLUGIN_ID, "HTTP response error (%s)\n", error_message ); 274 purple_debug_error( MXIT_PLUGIN_ID, "HTTP response error (%s)\n", error_message );
275 return; 275 return;
291 * @param pktlen The length of the packet data 291 * @param pktlen The length of the packet data
292 * @return Return -1 on error, otherwise 0 292 * @return Return -1 on error, otherwise 0
293 */ 293 */
294 static void mxit_write_http_get( struct MXitSession* session, struct tx_packet* packet ) 294 static void mxit_write_http_get( struct MXitSession* session, struct tx_packet* packet )
295 { 295 {
296 PurpleUtilFetchUrlData* url_data;
296 char* part = NULL; 297 char* part = NULL;
297 char* url = NULL; 298 char* url = NULL;
298 299
299 if ( packet->datalen > 0 ) { 300 if ( packet->datalen > 0 ) {
300 char* tmp = NULL; 301 char* tmp = NULL;
309 #ifdef DEBUG_PROTOCOL 310 #ifdef DEBUG_PROTOCOL
310 purple_debug_info( MXIT_PLUGIN_ID, "HTTP GET: '%s'\n", url ); 311 purple_debug_info( MXIT_PLUGIN_ID, "HTTP GET: '%s'\n", url );
311 #endif 312 #endif
312 313
313 /* send the HTTP request */ 314 /* send the HTTP request */
314 session->http_out_req = purple_util_fetch_url_request( url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, mxit_cb_http_rx, session ); 315 url_data = purple_util_fetch_url_request( url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, mxit_cb_http_rx, session );
316 if ( url_data )
317 session->async_calls = g_slist_prepend( session->async_calls, url_data );
315 318
316 g_free( url ); 319 g_free( url );
317 if ( part ) 320 if ( part )
318 g_free( part ); 321 g_free( part );
319 } 322 }
456 packet->data = g_malloc0( datalen ); 459 packet->data = g_malloc0( datalen );
457 packet->cmd = cmd; 460 packet->cmd = cmd;
458 packet->headerlen = 0; 461 packet->headerlen = 0;
459 462
460 /* create generic packet header */ 463 /* create generic packet header */
461 hlen = snprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc ), CP_REC_TERM ); /* client msisdn */ 464 hlen = snprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc ), CP_REC_TERM ); /* client mxitid */
462 465
463 if ( session->http ) { 466 if ( session->http ) {
464 /* http connection only */ 467 /* http connection only */
465 hlen += sprintf( header + hlen, "s=" ); 468 hlen += snprintf( header + hlen, sizeof( header ) - hlen, "s=" );
466 if ( session->http_sesid > 0 ) { 469 if ( session->http_sesid > 0 ) {
467 hlen += sprintf( header + hlen, "%u%c", session->http_sesid, CP_FLD_TERM ); /* http session id */ 470 hlen += snprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_sesid, CP_FLD_TERM ); /* http session id */
468 } 471 }
469 session->http_seqno++; 472 session->http_seqno++;
470 hlen += sprintf( header + hlen, "%u%c", session->http_seqno, CP_REC_TERM ); /* http request sequence id */ 473 hlen += snprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_seqno, CP_REC_TERM ); /* http request sequence id */
471 } 474 }
472 475
473 hlen += sprintf( header + hlen, "cm=%i%c", cmd, CP_REC_TERM ); /* packet command */ 476 hlen += snprintf( header + hlen, sizeof( header ) - hlen, "cm=%i%c", cmd, CP_REC_TERM ); /* packet command */
474 477
475 if ( !session->http ) { 478 if ( !session->http ) {
476 /* socket connection only */ 479 /* socket connection only */
477 packet->headerlen += sprintf( packet->header, "ln=%i%c", ( datalen + hlen ), CP_REC_TERM ); /* packet length */ 480 packet->headerlen = snprintf( packet->header, sizeof( packet->header ), "ln=%i%c", ( datalen + hlen ), CP_REC_TERM ); /* packet length */
478 } 481 }
479 482
480 /* copy the header to packet */ 483 /* copy the header to packet */
481 memcpy( packet->header + packet->headerlen, header, hlen ); 484 memcpy( packet->header + packet->headerlen, header, hlen );
482 packet->headerlen += hlen; 485 packet->headerlen += hlen;
769 ); 772 );
770 773
771 /* include "custom resource" information */ 774 /* include "custom resource" information */
772 splashId = splash_current( session ); 775 splashId = splash_current( session );
773 if ( splashId != NULL ) 776 if ( splashId != NULL )
774 datalen += sprintf( data + datalen, "%ccr=%s", CP_REC_TERM, splashId ); 777 datalen += snprintf( data + datalen, sizeof( data ) - datalen, "%ccr=%s", CP_REC_TERM, splashId );
775 778
776 /* queue packet for transmission */ 779 /* queue packet for transmission */
777 mxit_queue_packet( session, data, datalen, CP_CMD_LOGIN ); 780 mxit_queue_packet( session, data, datalen, CP_CMD_LOGIN );
778 781
779 g_free( clientVersion ); 782 g_free( clientVersion );
833 ( username ? username : "" ), CP_FLD_TERM, nr_attrib 836 ( username ? username : "" ), CP_FLD_TERM, nr_attrib
834 ); 837 );
835 838
836 /* add attributes */ 839 /* add attributes */
837 for ( i = 0; i < nr_attrib; i++ ) 840 for ( i = 0; i < nr_attrib; i++ )
838 datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] ); 841 datalen += snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
839 842
840 /* queue packet for transmission */ 843 /* queue packet for transmission */
841 mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_GET ); 844 mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_GET );
842 } 845 }
843 846
865 "ms=%s%c%i", /* "ms"=password\1nr_attibutes */ 868 "ms=%s%c%i", /* "ms"=password\1nr_attibutes */
866 ( password ) ? password : "", CP_FLD_TERM, nr_attrib 869 ( password ) ? password : "", CP_FLD_TERM, nr_attrib
867 ); 870 );
868 871
869 /* add attributes */ 872 /* add attributes */
870 for ( i = 1; i < nr_attrib * 3; i+=3 ) 873 for ( i = 1; i < nr_attrib * 3; i+=3 ) {
871 datalen += sprintf( data + datalen, "%c%s%c%s%c%s", /* \1name\1type\1value */ 874 if ( parts == NULL || parts[i] == NULL || parts[i + 1] == NULL || parts[i + 2] == NULL ) {
875 purple_debug_error( MXIT_PLUGIN_ID, "Invalid profile update attributes = '%s' - nbr=%u\n", attributes, nr_attrib );
876 g_strfreev( parts );
877 return;
878 }
879 datalen += snprintf( data + datalen, sizeof( data ) - datalen,
880 "%c%s%c%s%c%s", /* \1name\1type\1value */
872 CP_FLD_TERM, parts[i], CP_FLD_TERM, parts[i + 1], CP_FLD_TERM, parts[i + 2] ); 881 CP_FLD_TERM, parts[i], CP_FLD_TERM, parts[i + 1], CP_FLD_TERM, parts[i + 2] );
882 }
873 883
874 /* queue packet for transmission */ 884 /* queue packet for transmission */
875 mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_SET ); 885 mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_SET );
876 886
877 /* freeup the memory */ 887 /* freeup the memory */
898 "ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */ 908 "ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */
899 CP_SUGGEST_FRIENDS, CP_FLD_TERM, "", CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib ); 909 CP_SUGGEST_FRIENDS, CP_FLD_TERM, "", CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib );
900 910
901 /* add attributes */ 911 /* add attributes */
902 for ( i = 0; i < nr_attrib; i++ ) 912 for ( i = 0; i < nr_attrib; i++ )
903 datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] ); 913 datalen += snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
904 914
905 /* queue packet for transmission */ 915 /* queue packet for transmission */
906 mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS ); 916 mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
907 } 917 }
908 918
927 "ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */ 937 "ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */
928 CP_SUGGEST_SEARCH, CP_FLD_TERM, text, CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib ); 938 CP_SUGGEST_SEARCH, CP_FLD_TERM, text, CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib );
929 939
930 /* add attributes */ 940 /* add attributes */
931 for ( i = 0; i < nr_attrib; i++ ) 941 for ( i = 0; i < nr_attrib; i++ )
932 datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] ); 942 datalen += snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, attribute[i] );
933 943
934 /* queue packet for transmission */ 944 /* queue packet for transmission */
935 mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS ); 945 mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
936 } 946 }
937 947
954 presence, CP_FLD_TERM 964 presence, CP_FLD_TERM
955 ); 965 );
956 966
957 /* append status message (if one is set) */ 967 /* append status message (if one is set) */
958 if ( statusmsg ) 968 if ( statusmsg )
959 datalen += sprintf( data + datalen, "%s", statusmsg ); 969 datalen += snprintf( data + datalen, sizeof( data ) - datalen, "%s", statusmsg );
960 970
961 /* queue packet for transmission */ 971 /* queue packet for transmission */
962 mxit_queue_packet( session, data, datalen, CP_CMD_STATUS ); 972 mxit_queue_packet( session, data, datalen, CP_CMD_STATUS );
963 } 973 }
964 974
1062 /*------------------------------------------------------------------------ 1072 /*------------------------------------------------------------------------
1063 * Send an deny subscription (invite) packet to the MXit server. 1073 * Send an deny subscription (invite) packet to the MXit server.
1064 * 1074 *
1065 * @param session The MXit session object 1075 * @param session The MXit session object
1066 * @param username The username of the contact being denied 1076 * @param username The username of the contact being denied
1067 */ 1077 * @param reason The message describing the reason for the rejection (can be NULL).
1068 void mxit_send_deny_sub( struct MXitSession* session, const char* username ) 1078 */
1079 void mxit_send_deny_sub( struct MXitSession* session, const char* username, const char* reason )
1069 { 1080 {
1070 char data[CP_MAX_PACKET]; 1081 char data[CP_MAX_PACKET];
1071 int datalen; 1082 int datalen;
1072 1083
1073 /* convert the packet to a byte stream */ 1084 /* convert the packet to a byte stream */
1074 datalen = snprintf( data, sizeof( data ), 1085 datalen = snprintf( data, sizeof( data ),
1075 "ms=%s", /* "ms"=username */ 1086 "ms=%s", /* "ms"=username */
1076 username 1087 username
1077 ); 1088 );
1078 1089
1090 /* append reason (if one is set) */
1091 if ( reason )
1092 datalen += snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, reason );
1093
1079 /* queue packet for transmission */ 1094 /* queue packet for transmission */
1080 mxit_queue_packet( session, data, datalen, CP_CMD_DENY ); 1095 mxit_queue_packet( session, data, datalen, CP_CMD_DENY );
1081 } 1096 }
1082 1097
1083 1098
1173 groupname, CP_FLD_TERM, nr_usernames 1188 groupname, CP_FLD_TERM, nr_usernames
1174 ); 1189 );
1175 1190
1176 /* add usernames */ 1191 /* add usernames */
1177 for ( i = 0; i < nr_usernames; i++ ) 1192 for ( i = 0; i < nr_usernames; i++ )
1178 datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, usernames[i] ); 1193 datalen += snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
1179 1194
1180 /* queue packet for transmission */ 1195 /* queue packet for transmission */
1181 mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_CREATE ); 1196 mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_CREATE );
1182 } 1197 }
1183 1198
1202 roomid, CP_FLD_TERM, nr_usernames 1217 roomid, CP_FLD_TERM, nr_usernames
1203 ); 1218 );
1204 1219
1205 /* add usernames */ 1220 /* add usernames */
1206 for ( i = 0; i < nr_usernames; i++ ) 1221 for ( i = 0; i < nr_usernames; i++ )
1207 datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, usernames[i] ); 1222 datalen += snprintf( data + datalen, sizeof( data ) - datalen, "%c%s", CP_FLD_TERM, usernames[i] );
1208 1223
1209 /* queue packet for transmission */ 1224 /* queue packet for transmission */
1210 mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_INVITE ); 1225 mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_INVITE );
1211 } 1226 }
1212 1227
1228 int size; 1243 int size;
1229 1244
1230 purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %i bytes to user '%s'\n", filename, buflen, username ); 1245 purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %i bytes to user '%s'\n", filename, buflen, username );
1231 1246
1232 /* convert the packet to a byte stream */ 1247 /* convert the packet to a byte stream */
1233 datalen = sprintf( data, "ms=" ); 1248 datalen = snprintf( data, sizeof( data ), "ms=" );
1234 1249
1235 /* map chunk header over data buffer */ 1250 /* map chunk header over data buffer */
1236 chunk = &data[datalen]; 1251 chunk = &data[datalen];
1237 1252
1238 size = mxit_chunk_create_senddirect( chunk_data( chunk ), username, filename, buf, buflen ); 1253 size = mxit_chunk_create_senddirect( chunk_data( chunk ), username, filename, buf, buflen );
1264 int size; 1279 int size;
1265 1280
1266 purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_reject\n" ); 1281 purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_reject\n" );
1267 1282
1268 /* convert the packet to a byte stream */ 1283 /* convert the packet to a byte stream */
1269 datalen = sprintf( data, "ms=" ); 1284 datalen = snprintf( data, sizeof( data ), "ms=" );
1270 1285
1271 /* map chunk header over data buffer */ 1286 /* map chunk header over data buffer */
1272 chunk = &data[datalen]; 1287 chunk = &data[datalen];
1273 1288
1274 size = mxit_chunk_create_reject( chunk_data( chunk ), fileid ); 1289 size = mxit_chunk_create_reject( chunk_data( chunk ), fileid );
1302 int size; 1317 int size;
1303 1318
1304 purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_accept\n" ); 1319 purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_accept\n" );
1305 1320
1306 /* convert the packet to a byte stream */ 1321 /* convert the packet to a byte stream */
1307 datalen = sprintf( data, "ms=" ); 1322 datalen = snprintf( data, sizeof( data ), "ms=" );
1308 1323
1309 /* map chunk header over data buffer */ 1324 /* map chunk header over data buffer */
1310 chunk = &data[datalen]; 1325 chunk = &data[datalen];
1311 1326
1312 size = mxit_chunk_create_get( chunk_data(chunk), fileid, filesize, offset ); 1327 size = mxit_chunk_create_get( chunk_data(chunk), fileid, filesize, offset );
1338 int size; 1353 int size;
1339 1354
1340 purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_received\n" ); 1355 purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_received\n" );
1341 1356
1342 /* convert the packet to a byte stream */ 1357 /* convert the packet to a byte stream */
1343 datalen = sprintf( data, "ms=" ); 1358 datalen = snprintf( data, sizeof( data ), "ms=" );
1344 1359
1345 /* map chunk header over data buffer */ 1360 /* map chunk header over data buffer */
1346 chunk = &data[datalen]; 1361 chunk = &data[datalen];
1347 1362
1348 size = mxit_chunk_create_received( chunk_data(chunk), fileid, status ); 1363 size = mxit_chunk_create_received( chunk_data(chunk), fileid, status );
1375 int size; 1390 int size;
1376 1391
1377 purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %i bytes\n", avatarlen ); 1392 purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %i bytes\n", avatarlen );
1378 1393
1379 /* convert the packet to a byte stream */ 1394 /* convert the packet to a byte stream */
1380 datalen = sprintf( data, "ms=" ); 1395 datalen = snprintf( data, sizeof( data ), "ms=" );
1381 1396
1382 /* map chunk header over data buffer */ 1397 /* map chunk header over data buffer */
1383 chunk = &data[datalen]; 1398 chunk = &data[datalen];
1384 1399
1385 size = mxit_chunk_create_set_avatar( chunk_data(chunk), avatar, avatarlen ); 1400 size = mxit_chunk_create_set_avatar( chunk_data(chunk), avatar, avatarlen );
1414 int size; 1429 int size;
1415 1430
1416 purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_avatar: %s\n", mxitId ); 1431 purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_avatar: %s\n", mxitId );
1417 1432
1418 /* convert the packet to a byte stream */ 1433 /* convert the packet to a byte stream */
1419 datalen = sprintf( data, "ms=" ); 1434 datalen = snprintf( data, sizeof( data ), "ms=" );
1420 1435
1421 /* map chunk header over data buffer */ 1436 /* map chunk header over data buffer */
1422 chunk = &data[datalen]; 1437 chunk = &data[datalen];
1423 1438
1424 size = mxit_chunk_create_get_avatar( chunk_data(chunk), mxitId, avatarId ); 1439 size = mxit_chunk_create_get_avatar( chunk_data(chunk), mxitId, avatarId );
2433 if ( packet->errcode == MXIT_ERRCODE_REDIRECT ) { 2448 if ( packet->errcode == MXIT_ERRCODE_REDIRECT ) {
2434 mxit_perform_redirect( session, packet->errmsg ); 2449 mxit_perform_redirect( session, packet->errmsg );
2435 return 0; 2450 return 0;
2436 } 2451 }
2437 else { 2452 else {
2438 snprintf( errmsg, sizeof( errmsg ), _( "Login error: %s (%i)" ), errdesc, packet->errcode ); 2453 g_snprintf( errmsg, sizeof( errmsg ), _( "Login error: %s (%i)" ), errdesc, packet->errcode );
2439 purple_connection_error_reason( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, errmsg ); 2454 purple_connection_error_reason( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, errmsg );
2440 return -1; 2455 return -1;
2441 } 2456 }
2442 case CP_CMD_LOGOUT : 2457 case CP_CMD_LOGOUT :
2443 snprintf( errmsg, sizeof( errmsg ), _( "Logout error: %s (%i)" ), errdesc, packet->errcode ); 2458 g_snprintf( errmsg, sizeof( errmsg ), _( "Logout error: %s (%i)" ), errdesc, packet->errcode );
2444 purple_connection_error_reason( session->con, PURPLE_CONNECTION_ERROR_NAME_IN_USE, _( errmsg ) ); 2459 purple_connection_error_reason( session->con, PURPLE_CONNECTION_ERROR_NAME_IN_USE, _( errmsg ) );
2445 return -1; 2460 return -1;
2446 case CP_CMD_CONTACT : 2461 case CP_CMD_CONTACT :
2447 mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Error" ), _( errdesc ) ); 2462 mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Error" ), _( errdesc ) );
2448 break; 2463 break;
2860 } 2875 }
2861 session->flags &= ~MXIT_FLAG_LOGGEDIN; 2876 session->flags &= ~MXIT_FLAG_LOGGEDIN;
2862 } 2877 }
2863 session->flags &= ~MXIT_FLAG_CONNECTED; 2878 session->flags &= ~MXIT_FLAG_CONNECTED;
2864 2879
2865 /* cancel outstanding HTTP request */ 2880 /* cancel all outstanding async calls */
2866 if ( ( session->http ) && ( session->http_out_req ) ) { 2881 while ( session->async_calls ) {
2867 purple_util_fetch_url_cancel( (PurpleUtilFetchUrlData*) session->http_out_req ); 2882 purple_util_fetch_url_cancel( session->async_calls->data );
2868 session->http_out_req = NULL; 2883 session->async_calls = g_slist_delete_link(session->async_calls, session->async_calls);
2869 } 2884 }
2870 2885
2871 /* remove the input cb function */ 2886 /* remove the input cb function */
2872 if ( session->con->inpa ) { 2887 if ( session->con->inpa ) {
2873 purple_input_remove( session->con->inpa ); 2888 purple_input_remove( session->con->inpa );

mercurial