Example #1
0
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);
}
Example #2
0
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;
		}
	}
}
Example #3
0
/* ------------------
 * 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");
		}
	}
}
Example #4
0
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);
}
Example #5
0
/*------------------------------------------------------------------------
 * 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 );
	}
}