static void
buddytimezone_submitfields_cb(PurpleRequestFields * fields, PurpleBlistNode * data)
{
    PurpleBlistNode *node;
    PurpleRequestField *list;

    /* timezone stuff */
    purple_debug(PURPLE_DEBUG_INFO, PLUGIN_STATIC_NAME, "buddytimezone_submitfields_cb(%p,%p)\n", fields, data);

    switch (data->type)
    {
        case PURPLE_BLIST_BUDDY_NODE:
            node = (PurpleBlistNode *) purple_buddy_get_contact((PurpleBuddy *) data);
            break;
        case PURPLE_BLIST_CONTACT_NODE:
        case PURPLE_BLIST_GROUP_NODE:
            /* code handles either case */
            node = data;
            break;
        case PURPLE_BLIST_CHAT_NODE:
        case PURPLE_BLIST_OTHER_NODE:
        default:
            /* Not applicable */
            return;
    }

    list = purple_request_fields_get_field(fields, CONTROL_NAME);
    if (ui_ops != NULL && ui_ops->get_timezone_menu_selection != NULL)
    {
        const char *seldata = ui_ops->get_timezone_menu_selection(list->ui_data);
        if (seldata == NULL)
            purple_blist_node_remove_setting(node, SETTING_NAME);
        else
            purple_blist_node_set_string(node, SETTING_NAME, seldata);
    }
    else
    {
        const GList *sellist;
        void *seldata = NULL;
        sellist = purple_request_field_list_get_selected(list);
        if (sellist)
            seldata = purple_request_field_list_get_data(list, sellist->data);

        /* Otherwise, it's fixed value and this means deletion */
        if (seldata == TIMEZONE_FLAG)
            purple_blist_node_set_string(node, SETTING_NAME, sellist->data);
        else if (seldata == DISABLED_FLAG)
            purple_blist_node_set_string(node, SETTING_NAME, "none");
        else
            purple_blist_node_remove_setting(node, SETTING_NAME);
	}
}
Exemple #2
0
static void plainprpl_add_buddy_by_contact_request_ok(void *ptr, PurpleRequestFields *fields)
{
	PurpleBuddy *buddy = (PurpleBuddy *) ptr;
	PurpleAccount *account = buddy->account;
	plain_plugin_state *pstate;
	plain_buddy_state *bstate;
	char *addr_str;
	const char *name;
	IP addr;

	name = purple_request_fields_get_string(fields, "name");
	//invite_msg = purple_request_fields_get_string(fields, "invite_msg");
	if (name == NULL && strlen(name) == 0) {
		purple_notify_error(ptr, "Invalid Name", _("Name was empty."), _("You need to enter a name."));
		purple_blist_remove_buddy(buddy);
	} else {
		addr_str = g_strdup(buddy->name);
		purple_blist_node_set_string(PURPLE_BLIST_NODE(buddy), "addr_str", addr_str);
		assert(purple_blist_node_get_string(PURPLE_BLIST_NODE(buddy), "addr_str") != NULL);
		purple_blist_rename_buddy(buddy, name);
		g_free(addr_str);

		pstate = purple_connection_get_protocol_data(buddy->account->gc);
		bstate = add_buddy_sdata(buddy, pstate);

		assert(addr_parse_full(&addr, addr_str, PLAIN_DEFAULT_PORT_STR, pstate->sockaf) == 0);
		addr_parse_full(&addr, addr_str, PLAIN_DEFAULT_PORT_STR, pstate->sockaf);
		memcpy(&bstate->addr, &addr, sizeof(IP));

		purple_prpl_got_user_status(account, buddy->name, PLAIN_STATUS_ONLINE, NULL);
	}

	pstate->block_unknown = FALSE;
}
void
translate_receiving_chat_msg_cb(const gchar *original_phrase, const gchar *translated_phrase, const gchar *detected_language, gpointer userdata)
{
	struct TranslateConvMessage *convmsg = userdata;
	PurpleChat *chat;
	gchar *html_text;
	const gchar *stored_lang = "";
	const gchar *language_name = NULL;
	gchar *message;
	
	if (detected_language)
	{
		chat = purple_blist_find_chat(convmsg->account, convmsg->conv->name);
		stored_lang = purple_blist_node_get_string((PurpleBlistNode *)chat, DEST_LANG_SETTING);
		purple_blist_node_set_string((PurpleBlistNode *)chat, DEST_LANG_SETTING, detected_language);
		
		language_name = get_language_name(detected_language);
		
		if (language_name != NULL)
		{
			message = g_strdup_printf("Now translating to %s (auto-detected)", language_name);
			purple_conversation_write(convmsg->conv, NULL, message, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG, time(NULL));
			g_free(message);
		}
	}
	
	html_text = purple_strdup_withhtml(translated_phrase);
	
	purple_conversation_write(convmsg->conv, convmsg->sender, html_text, convmsg->flags, time(NULL));
	
	g_free(html_text);
	g_free(convmsg->sender);
	g_free(convmsg);
}
static void
translate_action_blist_cb(PurpleBlistNode *node, PurpleKeyValuePair *pair)
{
	PurpleConversation *conv = NULL;
	gchar *message;
	PurpleChat *chat;
	PurpleContact *contact;
	PurpleBuddy *buddy;

	if (pair == NULL)
		purple_blist_node_set_string(node, DEST_LANG_SETTING, NULL);
	else
		purple_blist_node_set_string(node, DEST_LANG_SETTING, pair->key);
	
	switch(node->type)
	{
		case PURPLE_BLIST_CHAT_NODE:
			chat = (PurpleChat *) node;
			conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT,
							purple_chat_get_name(chat),
							chat->account);
			break;
		case PURPLE_BLIST_CONTACT_NODE:
			contact = (PurpleContact *) node;
			node = (PurpleBlistNode *)purple_contact_get_priority_buddy(contact);
			//fallthrough intentional
		case PURPLE_BLIST_BUDDY_NODE:
			buddy = (PurpleBuddy *) node;
			conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
							purple_buddy_get_name(buddy),
							purple_buddy_get_account(buddy));
			break;
			
		default:
			break;
	}
	
	if (conv != NULL && pair != NULL)
	{
		message = g_strdup_printf("Now translating to %s", (const gchar *)pair->value);
		purple_conversation_write(conv, NULL, message, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG, time(NULL));
		g_free(message);
	}
}
Exemple #5
0
void
lh_util_add_buddy(const gchar *group, PurpleGroup *purple_group,
			const gchar *buddy, const gchar *alias, PurpleAccount *account,
			const gchar *buddynotes, gint signed_on, gint signed_off, gint lastseen,
			gint last_seen, const gchar *gf_theme, const gchar *icon_file, gchar *lastsaid)
{
	PurpleBuddy *purple_buddy = NULL;
	PurpleBlistNode *node = NULL;
	
	purple_buddy = purple_buddy_new(account, buddy, alias);
	node = (PurpleBlistNode *)purple_buddy;

	purple_blist_add_buddy(purple_buddy, NULL, purple_group, NULL);
#if PURPLE_VERSION_CHECK(3,0,0)
	purple_account_add_buddy(account, purple_buddy, NULL);
#else
	purple_account_add_buddy(account, purple_buddy);
#endif

	if(buddynotes)
		purple_blist_node_set_string(node, "notes", buddynotes);
	if(signed_on)
		purple_blist_node_set_int(node, "signedon", signed_on);
	if(signed_off)
		purple_blist_node_set_int(node, "signedoff", signed_off);
	if(lastseen)
		purple_blist_node_set_int(node, "lastseen", lastseen);
	if(last_seen)
		purple_blist_node_set_int(node, "last_seen", last_seen);
	if(gf_theme)
		purple_blist_node_set_string(node, "guifications-theme", gf_theme);
	if(icon_file)
		purple_blist_node_set_string(node, "buddy_icon", icon_file);
	if(lastsaid)
		purple_blist_node_set_string(node, "lastsaid", lastsaid);

	purple_debug_info("listhandler: import",
			"group: %s\tbuddy: %s\talias: %s\thas been added to the list\n",
			group, buddy, alias ? alias : "NULL");

	return;
}
void rc_push_contact(PurpleAccount *acct,
    const char * buddyname)
{
  PurpleGroup * grp = purple_find_group(GROUP_NAME);
  if (!grp) {
    trace("Group %s Not Found. Create one.", GROUP_NAME);
    grp = purple_group_new(GROUP_NAME);
  }

  PurpleBuddy * buddy;
  // if we can find it in 'Recent Contacts', skip
  if ((buddy = purple_find_buddy_in_group(acct, buddyname, grp)) != NULL) {
    trace("Buddy %s is already in %s", buddyname, GROUP_NAME);
    purple_blist_add_buddy(buddy, NULL, grp, NULL);
    return;
  }

  buddy = purple_find_buddy(acct, buddyname);
  if (!buddy) {
    trace("Buddy %s Not Found. You SUCK!", buddyname);
    return;
  }

  PurpleBlistNode * node = PURPLE_BLIST_NODE(buddy); 

  // back up group info
  PurpleGroup * orig_grp = 	purple_buddy_get_group(buddy);
  purple_blist_node_set_string(node, NODE_GROUP_KEY, orig_grp->name);

  // back up offline info
  gboolean offline = purple_blist_node_get_bool(node, NODE_OFFLINE_KEY);
  purple_blist_node_set_bool(node, NODE_ORIG_OFFLINE_KEY, offline);
  purple_blist_node_set_bool(node, NODE_OFFLINE_KEY, TRUE);

  // Add to Recent Contacts Group
  trace(">>>>>>> Add %s", buddyname);
  purple_blist_add_buddy(buddy, NULL, grp, NULL);

  // Clean up old group if needed
  rc_pop_contacts(grp);
}
Exemple #7
0
Contact *QuetzalContactsFactory::addContact(const QString &id, const QVariantMap &data)
{
	QByteArray group = data.value(QLatin1String("group")).toString().toUtf8();
	if (group.isEmpty()) {
		// For compatibility with other implementations
		// Looks like libpurple doesn't support multiple groups
		// Or does it at some unknown way
		group = data.value(QLatin1String("tags")).toStringList().value(0).toUtf8();
	}
	QString name = data.value(QLatin1String("name")).toString();
	
	const char *groupName = group.isEmpty() ? "Buddies" : group.constData();
	PurpleGroup *pg = purple_find_group(groupName);
	if (!pg) {
		pg = purple_group_new(groupName);
		purple_blist_add_group(pg, quetzal_blist_get_last_sibling(purple_blist_get_root()));
	}
	PurpleContact *pc = purple_contact_new();
	purple_blist_add_contact(pc, pg, quetzal_blist_get_last_child(PURPLE_BLIST_NODE(pg)));
	PurpleBuddy *buddy = purple_buddy_new(m_account->purple(), id.toUtf8().constData(),
										  name.toUtf8().constData());
	PurpleBlistNode *node = PURPLE_BLIST_NODE(buddy);
	purple_blist_add_buddy(buddy, pc, pg, quetzal_blist_get_last_child(PURPLE_BLIST_NODE(pc)));
	QMapIterator<QString, QVariant> it(data.value(QLatin1String("quetzal_settings")).toMap());
	while (it.hasNext()) {
		it.next();
		QByteArray key = it.key().toUtf8();
		QVariant::Type type = it.value().type();
		if (type == QVariant::Bool) {
			purple_blist_node_set_bool(node, key.constData(), it.value().toBool());
		} else if (type == QVariant::Int || type == QVariant::UInt
				 || type == QVariant::LongLong || type == QVariant::ULongLong) {
			purple_blist_node_set_int(node, key.constData(), it.value().toInt());
		} else {
			purple_blist_node_set_string(node, key.constData(), it.value().toString().toUtf8());
		}
	}
	QuetzalContact *contact = reinterpret_cast<QuetzalContact*>(node->ui_data);
	contact->update(buddy);
	return contact;
}
Exemple #8
0
static PurpleBuddy* spin_sync_buddy(SpinData* spin,
				    GSList* buddies,const gchar* id,
				    const gchar* name,guint online,
				    const gchar* away,const gchar* photo)
{
  PurpleAccount* account = purple_connection_get_account(spin->gc);
  /* gchar* lower_name = g_utf8_strdown(name,-1); */
  PurpleBuddy* buddy = spin_find_buddy_in_list(buddies,id);
  if(!buddy)
    {
      purple_debug_info("spin","adding buddy: %s\n",/*lower_*/name);
      buddy = purple_buddy_new(account,/*lower_*/name,NULL);
      purple_blist_add_buddy(buddy,NULL,NULL,NULL);
      purple_blist_node_set_string(&buddy->node,"spin-id",id);
    }
  /* purple_normalize here? */
  if(g_strcmp0(purple_buddy_get_name(buddy),name) != 0)
    {
      spin_notify_nick_changed(spin,purple_buddy_get_name(buddy),name);
      purple_blist_rename_buddy(buddy,name);
    }

  spin_sync_photo(spin,buddy,photo);

  /* do not set status if we got a status after the HTTP request */
  if(g_hash_table_lookup(spin->updated_status_list,
			 purple_normalize(account,name)))
    return buddy;

  if(online && *away)
    purple_prpl_got_user_status(account,/*lower_*/name,"away",
				"message",away,NULL);
  else if(online)
    purple_prpl_got_user_status(account,/*lower_*/name,"available",NULL);
  else
    purple_prpl_got_user_status(account,/*lower_*/name,"offline",NULL);

  return buddy;
  /* g_free(lower_name); */
}
Exemple #9
0
static void plainprpl_add_buddy_ok(void *ptr, PurpleRequestFields *fields)
{
	PurpleBuddy *buddy;
	PurpleConnection *gc;
	plain_plugin_state *pstate;
	plain_buddy_state *bstate;
	const char *addr_str;
	//const char* invite_msg;

	purple_debug_info("plainprpl", "plainprpl_add_buddy_ok\n");

	buddy = (PurpleBuddy *) ptr;
	gc = purple_account_get_connection(buddy->account);

	addr_str = purple_request_fields_get_string(fields, "addr_str");
	//invite_msg = purple_request_fields_get_string(fields, "invite_msg");

	if (addr_str == NULL || strlen(addr_str) == 0) {
		purple_notify_error(ptr, "Invalid Address", _("The address was empty."), _("You need to enter a host name or an IP address."));
		purple_blist_remove_buddy(buddy);
	} else {
		/* Finalize buddy creation */
		purple_debug_info("plainprpl", "Add buddy %s\n", buddy->name);
		purple_blist_node_set_string(PURPLE_BLIST_NODE(buddy), "addr_str", addr_str);
		assert(purple_blist_node_get_string(PURPLE_BLIST_NODE(buddy), "addr_str") != NULL);

		pstate = purple_connection_get_protocol_data(gc);
		bstate = add_buddy_sdata(buddy, pstate);
		pstate->time_next = 0; //handle now

		purple_prpl_got_user_status(buddy->account, buddy->name, PLAIN_STATUS_OFFLINE, NULL);
		/*
		if (invite_msg) {
			plainprpl_send_im(gc, buddy->name, invite_msg,  0);
		}*/
	}
}
Exemple #10
0
static void plainprpl_change_address_ok(void *ptr, PurpleRequestFields *fields)
{
	PurpleBuddy *buddy;
	plain_buddy_state *bstate;
	plain_plugin_state *pstate;
	PurpleRequestField *field;

	buddy = (PurpleBuddy *) ptr;
	bstate = purple_buddy_get_protocol_data(buddy);
	pstate = purple_connection_get_protocol_data(buddy->account->gc);

	field = purple_request_fields_get_field(fields, "addr_str");
	const char *addr_str = purple_request_field_string_get_value(field);

	purple_blist_node_set_string(PURPLE_BLIST_NODE(buddy), "addr_str", addr_str);
	//resolve address again
	bstate->state = BUDDY_STATE_RESOLVE;
	bstate->state_step = 0;
	bstate->state_next = 0;
	bstate->time_recv = 0;
	bstate->time_send = 0;
	//handle now
	pstate->time_next = 0;
}
Exemple #11
0
static void tgp_info_update_photo_id (PurpleBlistNode *node, long long photo) {
  char *llid = g_strdup_printf ("%" G_GINT64_FORMAT, (gint64) photo);
  debug ("tgp_info_update_photo_id %s", llid);
  purple_blist_node_set_string (node, TGP_INFO_PHOTO_ID, llid);
  g_free (llid);
}
Exemple #12
0
PurpleStoredImage *
purple_buddy_icons_node_set_custom_icon(PurpleBlistNode *node,
                                        guchar *icon_data, size_t icon_len)
{
	char *old_icon;
	PurpleStoredImage *old_img;
	PurpleStoredImage *img = NULL;

	g_return_val_if_fail(node != NULL, NULL);

	if (!PURPLE_BLIST_NODE_IS_CONTACT(node) &&
	    !PURPLE_BLIST_NODE_IS_CHAT(node) &&
	    !PURPLE_BLIST_NODE_IS_GROUP(node)) {
		return NULL;
	}

	old_img = g_hash_table_lookup(pointer_icon_cache, node);

	if (icon_data != NULL && icon_len > 0) {
		img = purple_buddy_icon_data_new(icon_data, icon_len, NULL);
	}

	old_icon = g_strdup(purple_blist_node_get_string(node,
	                                                 "custom_buddy_icon"));
	if (img && purple_buddy_icons_is_caching()) {
		const char *filename = purple_imgstore_get_filename(img);
		purple_blist_node_set_string(node, "custom_buddy_icon",
		                             filename);
		ref_filename(filename);
	} else {
		purple_blist_node_remove_setting(node, "custom_buddy_icon");
	}
	unref_filename(old_icon);

	if (img)
		g_hash_table_insert(pointer_icon_cache, node, img);
	else
		g_hash_table_remove(pointer_icon_cache, node);

	if (PURPLE_BLIST_NODE_IS_CONTACT(node)) {
		PurpleBlistNode *child;
		for (child = purple_blist_node_get_first_child(node);
		     child;
			 child = purple_blist_node_get_sibling_next(child))
		{
			PurpleBuddy *buddy;
			PurpleConversation *conv;

			if (!PURPLE_BLIST_NODE_IS_BUDDY(child))
				continue;

			buddy = (PurpleBuddy *)child;

			conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, purple_buddy_get_name(buddy), purple_buddy_get_account(buddy));
			if (conv)
				purple_conversation_update(conv, PURPLE_CONV_UPDATE_ICON);

			/* Is this call necessary anymore? Can the buddies
			 * themselves need updating when the custom buddy
			 * icon changes? */
			purple_blist_update_node_icon((PurpleBlistNode*)buddy);
		}
	} else if (PURPLE_BLIST_NODE_IS_CHAT(node)) {
		PurpleConversation *conv = NULL;

		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, purple_chat_get_name((PurpleChat*)node), purple_chat_get_account((PurpleChat*)node));
		if (conv) {
			purple_conversation_update(conv, PURPLE_CONV_UPDATE_ICON);
		}
	}

	purple_blist_update_node_icon(node);

	if (old_img) {
		purple_imgstore_unref(old_img);
	} else if (old_icon) {
		/* The old icon may not have been loaded into memory.  In that
		 * case, we'll need to uncache the filename.  The filenames
		 * are ref-counted, so this is safe. */
		purple_buddy_icon_data_uncache_file(old_icon);
	}
	g_free(old_icon);

	return img;
}
Exemple #13
0
void
purple_buddy_icon_update(PurpleBuddyIcon *icon)
{
	PurpleConversation *conv;
	PurpleAccount *account;
	const char *username;
	PurpleBuddyIcon *icon_to_set;
	GSList *buddies;

	g_return_if_fail(icon != NULL);

	account  = purple_buddy_icon_get_account(icon);
	username = purple_buddy_icon_get_username(icon);

	/* If no data exists (icon->img == NULL), then call the functions below
	 * with NULL to unset the icon.  They will then unref the icon and it should
	 * be destroyed.  The only way it wouldn't be destroyed is if someone
	 * else is holding a reference to it, in which case they can kill
	 * the icon when they realize it has no data. */
	icon_to_set = icon->img ? icon : NULL;

	/* Ensure that icon remains valid throughout */
	purple_buddy_icon_ref(icon);

	buddies = purple_find_buddies(account, username);
	while (buddies != NULL)
	{
		PurpleBuddy *buddy = (PurpleBuddy *)buddies->data;
		char *old_icon;

		purple_buddy_set_icon(buddy, icon_to_set);
		old_icon = g_strdup(purple_blist_node_get_string((PurpleBlistNode *)buddy,
		                                                 "buddy_icon"));
		if (icon->img && purple_buddy_icons_is_caching())
		{
			const char *filename = purple_imgstore_get_filename(icon->img);
			purple_blist_node_set_string((PurpleBlistNode *)buddy,
			                             "buddy_icon",
			                             filename);

			if (icon->checksum && *icon->checksum)
			{
				purple_blist_node_set_string((PurpleBlistNode *)buddy,
				                             "icon_checksum",
				                             icon->checksum);
			}
			else
			{
				purple_blist_node_remove_setting((PurpleBlistNode *)buddy,
				                                 "icon_checksum");
			}
			ref_filename(filename);
		}
		else if (!icon->img)
		{
			purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "buddy_icon");
			purple_blist_node_remove_setting((PurpleBlistNode *)buddy, "icon_checksum");
		}
		unref_filename(old_icon);
		g_free(old_icon);

		buddies = g_slist_delete_link(buddies, buddies);
	}

	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, username, account);

	if (conv != NULL)
		purple_conv_im_set_icon(PURPLE_CONV_IM(conv), icon_to_set);

	/* icon's refcount was incremented above */
	purple_buddy_icon_unref(icon);
}
Exemple #14
0
static void
migrate_buddy_icon(PurpleBlistNode *node, const char *setting_name,
                   const char *dirname, const char *filename)
{
	char *path;

	if (filename[0] != '/')
	{
		path = g_build_filename(dirname, filename, NULL);
		if (g_file_test(path, G_FILE_TEST_EXISTS))
		{
			g_free(path);
			return;
		}
		g_free(path);

		path = g_build_filename(old_icons_dir, filename, NULL);
	}
	else
		path = g_strdup(filename);

	if (g_file_test(path, G_FILE_TEST_EXISTS))
	{
		guchar *icon_data;
		size_t icon_len;
		FILE *file;
		char *new_filename;

		if (!read_icon_file(path, &icon_data, &icon_len))
		{
			g_free(path);
			delete_buddy_icon_settings(node, setting_name);
			return;
		}

		if (icon_data == NULL || icon_len <= 0)
		{
			/* This really applies to the icon_len check.
			 * icon_data should never be NULL if
			 * read_icon_file() returns TRUE. */
			purple_debug_error("buddyicon", "Empty buddy icon file: %s\n", path);
			delete_buddy_icon_settings(node, setting_name);
			g_free(path);
			return;
		}

		g_free(path);

		new_filename = purple_util_get_image_filename(icon_data, icon_len);
		if (new_filename == NULL)
		{
			purple_debug_error("buddyicon",
				"New icon filename is NULL. This should never happen! "
				"The old filename was: %s\n", path);
			delete_buddy_icon_settings(node, setting_name);
			g_return_if_reached();
		}

		path = g_build_filename(dirname, new_filename, NULL);
		if ((file = g_fopen(path, "wb")) != NULL)
		{
			if (!fwrite(icon_data, icon_len, 1, file))
			{
				purple_debug_error("buddyicon", "Error writing %s: %s\n",
				                   path, g_strerror(errno));
			}
			else
				purple_debug_info("buddyicon", "Wrote migrated cache file: %s\n", path);

			fclose(file);
		}
		else
		{
			purple_debug_error("buddyicon", "Unable to create file %s: %s\n",
			                   path, g_strerror(errno));
			g_free(new_filename);
			g_free(path);

			delete_buddy_icon_settings(node, setting_name);
			return;
		}
		g_free(path);

		purple_blist_node_set_string(node,
		                             setting_name,
		                             new_filename);
		ref_filename(new_filename);

		g_free(new_filename);

		if (purple_strequal(setting_name, "buddy_icon"))
		{
			const char *hash;

			hash = purple_blist_node_get_string(node, "avatar_hash");
			if (hash != NULL)
			{
				purple_blist_node_set_string(node, "icon_checksum", hash);
				purple_blist_node_remove_setting(node, "avatar_hash");
			}
		}
	}
	else
	{
		purple_debug_error("buddyicon", "Old icon file doesn't exist: %s\n", path);
		delete_buddy_icon_settings(node, setting_name);
		g_free(path);
	}
}
Exemple #15
0
static void
silcpurple_add_buddy_save(bool success, void *context)
{
	SilcPurpleBuddyRes r = context;
	PurpleBuddy *b = r->b;
	SilcClient client = r->client;
	SilcClientEntry client_entry;
	SilcAttributePayload attr;
	SilcAttribute attribute;
	SilcVCardStruct vcard;
	SilcAttributeObjMime message, extension;
#ifdef SILC_ATTRIBUTE_USER_ICON
	SilcAttributeObjMime usericon;
#endif
	SilcAttributeObjPk serverpk, usersign, serversign;
	gboolean usign_success = TRUE, ssign_success = TRUE;
	char filename[512], filename2[512], *fingerprint = NULL, *tmp;
	SilcUInt32 len;
	int i;

	if (!success) {
		/* The user did not trust the public key. */
		silcpurple_add_buddy_pk_no(r);
		silc_free(r);
		return;
	}

	if (r->offline) {
		/* User is offline.  Associate the imported public key with
		   this user. */
		fingerprint = silc_hash_fingerprint(NULL, r->offline_pk,
						    r->offline_pk_len);
		for (i = 0; i < strlen(fingerprint); i++)
			if (fingerprint[i] == ' ')
				fingerprint[i] = '_';
		g_snprintf(filename, sizeof(filename) - 1,
			   "%s" G_DIR_SEPARATOR_S "clientkeys" G_DIR_SEPARATOR_S "clientkey_%s.pub",
			   silcpurple_silcdir(), fingerprint);
		purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename);
		purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL);
		silc_free(fingerprint);
		silc_free(r->offline_pk);
		silc_free(r);
		return;
	}

	/* Get the client entry. */
	client_entry = silc_client_get_client_by_id(r->client, r->conn,
						    &r->client_id);
	if (!client_entry) {
		silc_free(r);
		return;
	}

	memset(&vcard, 0, sizeof(vcard));
	memset(&message, 0, sizeof(message));
	memset(&extension, 0, sizeof(extension));
#ifdef SILC_ATTRIBUTE_USER_ICON
	memset(&usericon, 0, sizeof(usericon));
#endif
	memset(&serverpk, 0, sizeof(serverpk));
	memset(&usersign, 0, sizeof(usersign));
	memset(&serversign, 0, sizeof(serversign));

	/* Now that we have the public key and we trust it now we
	   save the attributes of the buddy and update its status. */

	if (client_entry->attrs) {
		silc_dlist_start(client_entry->attrs);
		while ((attr = silc_dlist_get(client_entry->attrs))
		       != SILC_LIST_END) {
			attribute = silc_attribute_get_attribute(attr);

			switch (attribute) {
			case SILC_ATTRIBUTE_USER_INFO:
				if (!silc_attribute_get_object(attr, (void *)&vcard,
							       sizeof(vcard)))
					continue;
				break;

			case SILC_ATTRIBUTE_STATUS_MESSAGE:
				if (!silc_attribute_get_object(attr, (void *)&message,
							       sizeof(message)))
					continue;
				break;

			case SILC_ATTRIBUTE_EXTENSION:
				if (!silc_attribute_get_object(attr, (void *)&extension,
							       sizeof(extension)))
					continue;
				break;

#ifdef SILC_ATTRIBUTE_USER_ICON
			case SILC_ATTRIBUTE_USER_ICON:
				if (!silc_attribute_get_object(attr, (void *)&usericon,
							       sizeof(usericon)))
					continue;
				break;
#endif

			case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
				if (serverpk.type)
					continue;
				if (!silc_attribute_get_object(attr, (void *)&serverpk,
							       sizeof(serverpk)))
					continue;
				break;

			case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
				if (usersign.data)
					continue;
				if (!silc_attribute_get_object(attr, (void *)&usersign,
							       sizeof(usersign)))
					continue;
				break;

			case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
				if (serversign.data)
					continue;
				if (!silc_attribute_get_object(attr, (void *)&serversign,
							       sizeof(serversign)))
					continue;
				break;

			default:
				break;
			}
		}
	}

	/* Verify the attribute signatures */

	if (usersign.data) {
		SilcPKCS pkcs;
		unsigned char *verifyd;
		SilcUInt32 verify_len;

		silc_pkcs_alloc((unsigned char*)"rsa", &pkcs);
		verifyd = silc_attribute_get_verify_data(client_entry->attrs,
							 FALSE, &verify_len);
		if (verifyd && silc_pkcs_public_key_set(pkcs, client_entry->public_key)){
			if (!silc_pkcs_verify_with_hash(pkcs, client->sha1hash,
							usersign.data,
							usersign.data_len,
							verifyd, verify_len))
				usign_success = FALSE;
		}
		silc_free(verifyd);
	}

	if (serversign.data && purple_strequal(serverpk.type, "silc-rsa")) {
		SilcPublicKey public_key;
		SilcPKCS pkcs;
		unsigned char *verifyd;
		SilcUInt32 verify_len;

		if (silc_pkcs_public_key_decode(serverpk.data, serverpk.data_len,
						&public_key)) {
			silc_pkcs_alloc((unsigned char *)"rsa", &pkcs);
			verifyd = silc_attribute_get_verify_data(client_entry->attrs,
								 TRUE, &verify_len);
			if (verifyd && silc_pkcs_public_key_set(pkcs, public_key)) {
				if (!silc_pkcs_verify_with_hash(pkcs, client->sha1hash,
							       serversign.data,
							       serversign.data_len,
							       verifyd, verify_len))
					ssign_success = FALSE;
			}
			silc_pkcs_public_key_free(public_key);
			silc_free(verifyd);
		}
	}

	fingerprint = silc_fingerprint(client_entry->fingerprint,
				       client_entry->fingerprint_len);
	for (i = 0; i < strlen(fingerprint); i++)
		if (fingerprint[i] == ' ')
			fingerprint[i] = '_';

	if (usign_success || ssign_success) {
		struct passwd *pw;
		struct stat st;

		memset(filename2, 0, sizeof(filename2));

		/* Filename for dir */
		tmp = fingerprint + strlen(fingerprint) - 9;
		g_snprintf(filename, sizeof(filename) - 1,
			   "%s" G_DIR_SEPARATOR_S "friends" G_DIR_SEPARATOR_S "%s",
			   silcpurple_silcdir(), tmp);

		pw = getpwuid(getuid());
		if (!pw)
			return;

		/* Create dir if it doesn't exist */
		if ((g_stat(filename, &st)) == -1) {
			if (errno == ENOENT) {
				if (pw->pw_uid == geteuid()) {
					int ret = g_mkdir(filename, 0755);
					if (ret < 0)
						return;
				}
			}
		}

		/* Save VCard */
		g_snprintf(filename2, sizeof(filename2) - 1,
			   "%s" G_DIR_SEPARATOR_S "vcard", filename);
		if (vcard.full_name) {
			tmp = (char *)silc_vcard_encode(&vcard, &len);
			silc_file_writefile(filename2, tmp, len);
			silc_free(tmp);
		}

		/* Save status message */
		if (message.mime) {
			memset(filename2, 0, sizeof(filename2));
			g_snprintf(filename2, sizeof(filename2) - 1,
				   "%s" G_DIR_SEPARATOR_S "status_message.mime",
				   filename);
			silc_file_writefile(filename2, (char *)message.mime,
					    message.mime_len);
		}

		/* Save extension data */
		if (extension.mime) {
			memset(filename2, 0, sizeof(filename2));
			g_snprintf(filename2, sizeof(filename2) - 1,
				   "%s" G_DIR_SEPARATOR_S "extension.mime",
				   filename);
			silc_file_writefile(filename2, (char *)extension.mime,
					    extension.mime_len);
		}

#ifdef SILC_ATTRIBUTE_USER_ICON
		/* Save user icon */
		if (usericon.mime) {
			SilcMime m = silc_mime_decode(usericon.mime,
						      usericon.mime_len);
			if (m) {
				const char *type = silc_mime_get_field(m, "Content-Type");
				if (purple_strequal(type, "image/jpeg") ||
				    purple_strequal(type, "image/gif") ||
				    purple_strequal(type, "image/bmp") ||
				    purple_strequal(type, "image/png")) {
					const unsigned char *data;
					SilcUInt32 data_len;
					data = silc_mime_get_data(m, &data_len);
					if (data) {
						/* TODO: Check if SILC gives us something to use as the checksum instead */
						purple_buddy_icons_set_for_user(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), g_memdup(data, data_len), data_len, NULL);
					}
				}
				silc_mime_free(m);
			}
		}
#endif
	}

	/* Save the public key path to buddy properties, as it is used
	   to identify the buddy in the network (and not the nickname). */
	memset(filename, 0, sizeof(filename));
	g_snprintf(filename, sizeof(filename) - 1,
		   "%s" G_DIR_SEPARATOR_S "clientkeys" G_DIR_SEPARATOR_S "clientkey_%s.pub",
		   silcpurple_silcdir(), fingerprint);
	purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename);

	/* Update online status */
	purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_AVAILABLE, NULL);

	/* Finally, start watching this user so we receive its status
	   changes from the server */
	g_snprintf(filename2, sizeof(filename2) - 1, "+%s", filename);
	silc_client_command_call(r->client, r->conn, NULL, "WATCH", "-pubkey",
				 filename2, NULL);

	silc_free(fingerprint);
	silc_free(r);
}