static void spin_prefs_cb(PurpleUtilFetchUrlData* url_data, gpointer userp,JsonNode* node, const gchar* error_message) { PurpleConnection* gc = (PurpleConnection*) userp; JsonNode *prefsok/* ,*diablock */; JsonObject *object; /* gint diablock_value; */ PurpleAccount* account; SpinData* spin; if(!PURPLE_CONNECTION_IS_VALID(gc)) return; spin = (SpinData*) gc->proto_data; account = purple_connection_get_account(gc); if(!node) { gchar* err_text = g_strdup_printf(_("Could not receive prefs: %s"), error_message); purple_connection_error_reason(gc,PURPLE_CONNECTION_ERROR_NETWORK_ERROR, err_text); g_free(err_text); return; } if(JSON_NODE_TYPE(node) != JSON_NODE_OBJECT) { purple_connection_error_reason(gc,PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Invalid prefs format received")); return; } object = json_node_get_object(node); prefsok = json_object_get_member(object,"prefsok"); if(!prefsok || JSON_NODE_TYPE(prefsok) != JSON_NODE_VALUE || !json_node_get_int(prefsok)) { purple_connection_error_reason(gc,PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Prefs not OK")); return; } /* diablock = json_object_get_member(object,"diablock"); */ /* if(!diablock || JSON_NODE_TYPE(diablock) != JSON_NODE_VALUE) */ /* { */ /* purple_connection_error_reason(gc,PURPLE_CONNECTION_ERROR_NETWORK_ERROR, */ /* _("Invalid prefs entry received")); */ /* return; */ /* } */ /* if(json_node_get_value_type(diablock) == G_TYPE_STRING) */ /* diablock_value = g_ascii_strtoll(json_node_get_string(diablock),NULL,10); */ /* else */ /* diablock_value = json_node_get_int(diablock); */ /* switch(diablock_value) */ /* { */ /* case 0: */ /* account->perm_deny = PURPLE_PRIVACY_DENY_USERS; */ /* break; */ /* case 1: */ /* account->perm_deny = PURPLE_PRIVACY_DENY_ALL; */ /* break; */ /* case 2: */ /* account->perm_deny = PURPLE_PRIVACY_ALLOW_BUDDYLIST; */ /* break; */ /* } */ spin_connect_add_state(spin,SPIN_STATE_GOT_INITIAL_PREFS); }
static void tcp_pending(gpointer data, gint source, PurpleInputCondition cond) { PurpleConnection *gc = (PurpleConnection *) data; qq_data *qd; qq_connection *conn; guint8 buf[1024]; /* set to 16 when test tcp_rxqueue */ gint buf_len; gint bytes; guint8 *pkt; guint16 pkt_len; gchar *error_msg; guint8 *jump; gint jump_len; g_return_if_fail(gc != NULL && gc->proto_data != NULL); qd = (qq_data *) gc->proto_data; if(cond != PURPLE_INPUT_READ) { purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Socket error")); return; } conn = connection_find(qd, source); g_return_if_fail(conn != NULL); /* test code, not using tcp_rxqueue memset(pkt,0, sizeof(pkt)); buf_len = read(qd->fd, pkt, sizeof(pkt)); if (buf_len > 2) { packet_process(gc, pkt + 2, buf_len - 2); } return; */ buf_len = read(source, buf, sizeof(buf)); if (buf_len < 0) { if (errno == EAGAIN) /* No worries */ return; error_msg = g_strdup_printf(_("Lost connection with server: %s"), g_strerror(errno)); purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_msg); g_free(error_msg); return; } else if (buf_len == 0) { purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Server closed the connection")); return; } /* keep alive will be sent in 30 seconds since last_receive * QQ need a keep alive packet in every 60 seconds gc->last_received = time(NULL); */ #if 1 purple_debug_info("TCP_PENDING", "Read %d bytes, tcp_rxlen is %d\n", buf_len, conn->tcp_rxlen); #endif conn->tcp_rxqueue = g_realloc(conn->tcp_rxqueue, buf_len + conn->tcp_rxlen); memcpy(conn->tcp_rxqueue + conn->tcp_rxlen, buf, buf_len); conn->tcp_rxlen += buf_len; pkt = g_newa(guint8, MAX_PACKET_SIZE); while (PURPLE_CONNECTION_IS_VALID(gc)) { if (qd->openconns == NULL) { break; } if (conn->tcp_rxqueue == NULL) { conn->tcp_rxlen = 0; break; } if (conn->tcp_rxlen < QQ_TCP_HEADER_LENGTH) { break; } bytes = 0; bytes += qq_get16(&pkt_len, conn->tcp_rxqueue + bytes); if (conn->tcp_rxlen < pkt_len) { break; } #if 1 qq_show_packet("tcp_pending", conn->tcp_rxqueue, pkt_len); #endif /* purple_debug_info("TCP_PENDING", "Packet len=%d, rxlen=%d\n", pkt_len, conn->tcp_rxlen); */ if ( pkt_len < QQ_TCP_HEADER_LENGTH || *(conn->tcp_rxqueue + bytes) != QQ_PACKET_TAG || *(conn->tcp_rxqueue + pkt_len - 1) != QQ_PACKET_TAIL) { /* HEY! This isn't even a QQ. What are you trying to pull? */ purple_debug_warning("TCP_PENDING", "Packet error, no header or tail tag\n"); jump = memchr(conn->tcp_rxqueue + 1, QQ_PACKET_TAIL, conn->tcp_rxlen - 1); if ( !jump ) { purple_debug_warning("TCP_PENDING", "Failed to find next tail, clear receive buffer\n"); g_free(conn->tcp_rxqueue); conn->tcp_rxqueue = NULL; conn->tcp_rxlen = 0; return; } /* jump and over QQ_PACKET_TAIL */ jump_len = (jump - conn->tcp_rxqueue) + 1; purple_debug_warning("TCP_PENDING", "Find next tail at %d, jump %d\n", jump_len, jump_len + 1); g_memmove(conn->tcp_rxqueue, jump, conn->tcp_rxlen - jump_len); conn->tcp_rxlen -= jump_len; continue; } /* get packet */ memset(pkt, 0, MAX_PACKET_SIZE); g_memmove(pkt, conn->tcp_rxqueue + bytes, pkt_len - bytes); /* jump to next packet */ conn->tcp_rxlen -= pkt_len; if (conn->tcp_rxlen) { /* purple_debug_info("TCP_PENDING", "shrink tcp_rxqueue to %d\n", conn->tcp_rxlen); */ jump = g_memdup(conn->tcp_rxqueue + pkt_len, conn->tcp_rxlen); g_free(conn->tcp_rxqueue); conn->tcp_rxqueue = jump; } else { /* purple_debug_info("TCP_PENDING", "free tcp_rxqueue\n"); */ g_free(conn->tcp_rxqueue); conn->tcp_rxqueue = NULL; } /* packet_process may call disconnect and destory data like conn * do not call packet_process before jump, * break if packet_process return FALSE */ if (packet_process(gc, pkt, pkt_len - bytes) == FALSE) { purple_debug_info("TCP_PENDING", "Connection has been destory\n"); break; } } }
/* ------------------ * called on every sent packet * ------------------ */ void jabber_send_signal_cb(PurpleConnection *pc, xmlnode **packet, gpointer unused) { if (NULL == packet) return; g_return_if_fail(PURPLE_CONNECTION_IS_VALID(pc)); // if we are sending a presence stanza, add new child node // so others know we support openpgp if (g_str_equal((*packet)->name, "presence")) { const char* status_str = NULL; xmlnode* status_node; // check if user selected a main key const char* fpr = purple_prefs_get_string(PREF_MY_KEY); if (fpr == NULL) fpr = ""; if (strcmp(fpr,"") != 0) {// user did select a key // get status message from packet status_node = xmlnode_get_child(*packet,"status"); if (status_node != NULL) { status_str = xmlnode_get_data(status_node); } // sign status message if (status_str == NULL) status_str = ""; purple_debug_info(PLUGIN_ID, "signing status '%s' with key %s\n",status_str,fpr); char* sig_str = sign(status_str,fpr); if (sig_str == NULL) { purple_debug_error(PLUGIN_ID,"sign failed\n"); return; } // create special "x" childnode purple_debug_info(PLUGIN_ID, "sending presence with signature\n"); xmlnode *x_node = xmlnode_new_child(*packet,"x"); xmlnode_set_namespace(x_node, NS_SIGNED); xmlnode_insert_data(x_node, sig_str,-1); }else { purple_debug_info(PLUGIN_ID, "no key selecteded!\n"); } }else if (g_str_equal((*packet)->name, "message")) { const char* to = xmlnode_get_attrib(*packet,"to"); xmlnode* body_node = xmlnode_get_child(*packet,"body"); if (body_node != NULL && to != NULL) { // get message char* message = g_strdup(xmlnode_get_data(body_node)); char* enc_str = NULL; char* bare_jid = get_bare_jid(to); // get encryption key struct list_item *item = g_hash_table_lookup(list_fingerprints,bare_jid); if (item == NULL) { purple_debug_info(PLUGIN_ID, "there is no key for encrypting message to %s\n",bare_jid); return; } // do not encrypt if mode_sec is disabled if (item->mode_sec == FALSE) return; char* fpr_to = item->fpr; purple_debug_info(PLUGIN_ID, "found key for encryption to user %s: %s\n",bare_jid,fpr_to); free(bare_jid); // encrypt message enc_str = encrypt(message,fpr_to); if (enc_str != NULL) { // remove message from body xmlnode_clear_data(body_node); xmlnode_insert_data(body_node,"[ERROR: This message is encrypted, and you are unable to decrypt it.]",-1); // add special "x" childnode for encrypted text purple_debug_info(PLUGIN_ID, "sending encrypted message\n"); xmlnode *x_node = xmlnode_new_child(*packet,"x"); xmlnode_set_namespace(x_node, NS_ENC); xmlnode_insert_data(x_node, enc_str,-1); }else { purple_debug_error(PLUGIN_ID, "could not encrypt message\n"); } }else { // ignore this type of messages //purple_debug_warning(PLUGIN_ID, "empty message or empty 'to'\n"); } } }
static void spin_receive_friends_cb(PurpleUtilFetchUrlData* url_data, gpointer userp, JsonNode* node, const gchar* error_message) { PurpleConnection* gc = (PurpleConnection*) userp; if(!PURPLE_CONNECTION_IS_VALID(gc)) return; if(!node) { purple_debug_error("spin","friend list error:%s\n",error_message); purple_connection_error_reason(gc,PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("could not receive friend list")); return; } SpinData* spin = (SpinData*) gc->proto_data; PurpleAccount* account = purple_connection_get_account(gc); GHashTable* found_buddies = g_hash_table_new(g_direct_hash,g_direct_equal); GSList* account_buddies = purple_find_buddies(account,NULL); if(!node || JSON_NODE_TYPE(node) != JSON_NODE_ARRAY) { purple_connection_error_reason (gc,PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("invalid friend list format")); goto exit; } JsonArray* friends = json_node_get_array(node); guint i; for(i = 0; i < json_array_get_length(friends); ++i) { node = json_array_get_element(friends,i); JsonArray* entry; if(JSON_NODE_TYPE(node) != JSON_NODE_ARRAY || json_array_get_length(entry = json_node_get_array(node)) != 7) { purple_debug_info("spin","invalid friend list entry\n"); continue; } const gchar* id = json_node_get_string(json_array_get_element(entry,0)); const gchar* name = json_node_get_string(json_array_get_element(entry,1)); guint online = json_node_get_int(json_array_get_element(entry,2)); const gchar* away = json_node_get_string(json_array_get_element(entry,3)); const gchar* photo =json_node_get_string(json_array_get_element(entry,5)); purple_debug_info("spin","got friend info: %s %s %i %s %s\n", id,name,online, away,photo); if(!name || !away || !photo || !id) continue; PurpleBuddy* buddy = spin_sync_buddy(spin,account_buddies,id,name, online,away,photo); g_hash_table_insert(found_buddies,buddy,(gpointer)0x1); } GSList* b; for(b = account_buddies; b; b = b->next) { if(!g_hash_table_lookup(found_buddies,b->data)) { spin_notify_nick_removed (spin,purple_buddy_get_name((PurpleBuddy*) b->data)); purple_blist_remove_buddy((PurpleBuddy*)b->data); } } spin_connect_add_state(spin,SPIN_STATE_GOT_INITIAL_FRIEND_LIST); exit: g_slist_free(account_buddies); g_hash_table_destroy(found_buddies); }
/*------------------------------------------------------------------------ * Register a new account with MXit * * @param gc The connection object * @param fields This is the fields filled-in by the user */ static void mxit_cb_register_ok( PurpleConnection *gc, PurpleRequestFields *fields ) { struct MXitSession* session = purple_connection_get_protocol_data( gc ); struct MXitProfile* profile = session->profile; const char* str; const char* pin; const char* err = NULL; int len; int i; purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_register_ok\n" ); if ( !PURPLE_CONNECTION_IS_VALID( gc ) ) { purple_debug_error( MXIT_PLUGIN_ID, "Unable to register; account offline.\n" ); return; } /* nickname */ str = purple_request_fields_get_string( fields, "nickname" ); if ( ( !str ) || ( strlen( str ) < 3 ) ) { err = _( "The Display Name you entered is too short." ); goto out; } g_strlcpy( profile->nickname, str, sizeof( profile->nickname ) ); /* birthdate */ str = purple_request_fields_get_string( fields, "bday" ); if ( ( !str ) || ( strlen( str ) < 10 ) || ( !validateDate( str ) ) ) { err = _( "The birthday you entered is invalid. The correct format is: 'YYYY-MM-DD'." ); goto out; } g_strlcpy( profile->birthday, str, sizeof( profile->birthday ) ); /* gender */ profile->male = ( purple_request_fields_get_choice( fields, "male" ) != 0 ); /* pin */ pin = purple_request_fields_get_string( fields, "pin" ); if ( !pin ) { err = _( "The PIN you entered is invalid." ); goto out; } len = strlen( pin ); if ( ( len < 7 ) || ( len > 10 ) ) { err = _( "The PIN you entered has an invalid length [7-10]." ); goto out; } for ( i = 0; i < len; i++ ) { if ( !g_ascii_isdigit( pin[i] ) ) { err = _( "The PIN is invalid. It should only consist of digits [0-9]." ); goto out; } } str = purple_request_fields_get_string( fields, "pin2" ); if ( ( !str ) || ( strcmp( pin, str ) != 0 ) ) { err = _( "The two PINs you entered do not match." ); goto out; } g_strlcpy( profile->pin, pin, sizeof( profile->pin ) ); out: if ( !err ) { purple_account_set_password( session->acc, session->profile->pin, NULL, NULL ); mxit_login_connect( session ); } else { /* show error to user */ mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Registration Error" ), err ); mxit_register_view( session ); } }