示例#1
0
/* ------------------
 * called before display of received messages
 * ------------------ */
static gboolean
receiving_im_msg_cb(PurpleAccount *account, char **sender, char **buffer,
				    PurpleConversation *conv, PurpleMessageFlags *flags, void *data)
{
	char sys_msg_buffer[1000];

	// check if the user with the jid=conv->name has signed his presence
	char* bare_jid = get_bare_jid(*sender);

	// set default message
	sprintf(sys_msg_buffer,"Encryption disabled");

	// get encryption key
	struct list_item* item = g_hash_table_lookup(list_fingerprints,bare_jid);
	if (item != NULL)
	{
		if (item->mode_sec == TRUE)
			sprintf(sys_msg_buffer,"Encryption enabled");

		// display a basic message, only if mode changed
		if (item->mode_sec != item->mode_sec_old)
			purple_conversation_write(conv,"",sys_msg_buffer,PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG,time(NULL));
		item->mode_sec_old = item->mode_sec;
	}
	free(bare_jid);

	return FALSE;
}
示例#2
0
/* ------------------
 * called before message is sent
 * ------------------ */
void sending_im_msg_cb(PurpleAccount *account, const char *receiver,
                       char **message)
{
	PurpleConversation *gconv = NULL;

	// search for conversation
	gconv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, receiver, account);
	if(gconv)
	{
		// check if the user with the jid=conv->name has signed his presence
		char* bare_jid = get_bare_jid(gconv->name);
		// get stored info about user
		struct list_item* item = g_hash_table_lookup(list_fingerprints,bare_jid);
		if (item != NULL)
		{
			// if we are in private mode
			if (item->mode_sec == TRUE)
			{
				// try to get key
				if (is_key_available(item->fpr,FALSE,FALSE,NULL) == FALSE)
				{
					// we do not have key of receiver
					// -> cancel message sending
					free (*message);
					*message = NULL;

					// tell user of this
					purple_conversation_write(gconv,"","The key of the receiver is not available, please ask the receiver for the key before trying to encrypt messages.",PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG,time(NULL));
				}
			}
		}
		free(bare_jid);
	}
}
示例#3
0
/* ------------------
 * conversation extended menu
 * ------------------ */
void
conversation_extended_menu_cb(PurpleConversation *conv, GList **list)
{
	char buffer[1000];
	PurpleMenuAction *action = NULL;

	// check if the user with the jid=conv->name has signed his presence
	char* bare_jid = get_bare_jid(conv->name);
	// get stored info about user
	struct list_item* item = g_hash_table_lookup(list_fingerprints,bare_jid);
	if (item != NULL)
	{
		// on display encryption menu item, if user sent signed presence
		action = purple_menu_action_new("Toggle OPENPGP encryption", PURPLE_CALLBACK(menu_action_toggle_cb),NULL,NULL);
		*list = g_list_append(*list, action);

		sprintf(buffer,"Send own public key to '%s'",bare_jid);
		action = purple_menu_action_new(buffer, PURPLE_CALLBACK(menu_action_sendkey_cb),NULL,NULL);
		*list = g_list_append(*list, action);
		
		sprintf(buffer,"Try to retrieve key of '%s' from server",bare_jid);
		action = purple_menu_action_new(buffer, PURPLE_CALLBACK(menu_action_retrievekey_cb),NULL,NULL);
		*list = g_list_append(*list, action);
	}
	free(bare_jid);
}
示例#4
0
/* ------------------
 * try to retrieve key from server
 * ------------------ */
static void
menu_action_retrievekey_cb(PurpleConversation *conv, void* data)
{
	char sys_msg_buffer[1000];
	// check if the user with the jid=conv->name has signed his presence
	char* bare_jid = get_bare_jid(conv->name);

	// get stored info about user
	struct list_item* item = g_hash_table_lookup(list_fingerprints,bare_jid);
	if (item != NULL)
	{
		char* userid = NULL;
		if (is_key_available(item->fpr,FALSE,TRUE,&userid) == FALSE)
		{
			sprintf(sys_msg_buffer,"Did not find key with ID '%s' on keyservers.",item->fpr);
			purple_conversation_write(conv,"",sys_msg_buffer,PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG,time(NULL));
		}else
		{
			// found key -> enable mode_enc
			sprintf(sys_msg_buffer,"Found key with ID '%s'/'%s' for '%s' on keyservers.",item->fpr,userid,bare_jid);
			purple_conversation_write(conv,"",sys_msg_buffer,PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG,time(NULL));
			purple_conversation_write(conv,"","Encryption enabled",PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG,time(NULL));
			item->mode_sec = TRUE;
		}
		if (userid != NULL)
			free(userid);
	}

	free(bare_jid);
}
示例#5
0
/* ------------------
 * called on new conversations
 * ------------------ */
void conversation_created_cb(PurpleConversation *conv, char* data)
{
	char sys_msg_buffer[1000];
	if (purple_conversation_get_type(conv) != PURPLE_CONV_TYPE_IM)
		return;

	purple_debug_info(PLUGIN_ID, "conversation name: %s\n",conv->name);

	// check if the user with the jid=conv->name has signed his presence
	char* bare_jid = get_bare_jid(conv->name);

	// get stored info about user
	struct list_item* item = g_hash_table_lookup(list_fingerprints,bare_jid);
	if (item == NULL)
	{
		sprintf(sys_msg_buffer,"No encryption support in client of '%s'",bare_jid);
	}else
	{
		sprintf(sys_msg_buffer,"Client of user %s supports encryption",bare_jid);
	}

	// display a basic message
	purple_conversation_write(conv,"",sys_msg_buffer,PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG,time(NULL));

	if (item != NULL)
	{
		char* userid = NULL;
		// check if we have key locally
		if (is_key_available(item->fpr,FALSE,FALSE,&userid) == FALSE)
		{
			if (userid != NULL)
				free(userid);
			userid = NULL;

			sprintf(sys_msg_buffer,"User has key with ID '%s', but we do not have it locally, try Options->\"Try to retrieve key of '%s' from server\"",item->fpr,bare_jid);
			purple_conversation_write(conv,"",sys_msg_buffer,PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG,time(NULL));
		}else
		{
			// key is already available locally -> enable mode_enc
			sprintf(sys_msg_buffer,"'%s' uses key with id '%s'/'%s'",bare_jid,userid,item->fpr);
			purple_conversation_write(conv,"",sys_msg_buffer,PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG,time(NULL));
			item->mode_sec = TRUE;
		}
		if (userid != NULL)
			free(userid);
		userid = NULL;
		// if we have the key now, move to secure mode
		if (item->mode_sec == TRUE)
			sprintf(sys_msg_buffer,"Encryption enabled");
		else
			sprintf(sys_msg_buffer,"Encryption disabled");
	}else
		sprintf(sys_msg_buffer,"Encryption disabled");

	// display message about received message
	purple_conversation_write(conv,"",sys_msg_buffer,PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG,time(NULL));

	free(bare_jid);
}
示例#6
0
/* ------------------
 * conversation menu action, that toggles mode_sec
 * ------------------ */
static void
menu_action_toggle_cb(PurpleConversation *conv, void* data)
{
	// check if the user with the jid=conv->name has signed his presence
	char* bare_jid = get_bare_jid(conv->name);

	// get stored info about user
	struct list_item* item = g_hash_table_lookup(list_fingerprints,bare_jid);
	if (item != NULL)
	{
		item->mode_sec = !(item->mode_sec);
		item->mode_sec_old = item->mode_sec;

		// tell user, that we toggled mode
		purple_conversation_write(conv,"",item->mode_sec?"Encryption enabled":"Encryption disabled",PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG,time(NULL));
	}
	free(bare_jid);
}
示例#7
0
/* ------------------
 * called on received presence
 * ------------------ */
static gboolean
jabber_presence_received(PurpleConnection *pc, const char *type,
                         const char *from, xmlnode *presence)
{
	const xmlnode* parent_node = presence;
	xmlnode* x_node = NULL;

	// check if presence has special "x" childnode
	x_node = xmlnode_get_child_with_namespace(parent_node,"x",NS_SIGNED);
	if (x_node != NULL)
	{
		// user supports openpgp encryption
		purple_debug_info(PLUGIN_ID, "user %s supports openpgp encryption!\n",from);

		char* x_node_data = xmlnode_get_data(x_node);
		if (x_node_data != NULL)
		{
			// try to verify
			char* fpr = verify(x_node_data);
			if (fpr != NULL)
			{
				char* bare_jid = get_bare_jid(from);
				purple_debug_info(PLUGIN_ID, "user %s has fingerprint %s\n",bare_jid,fpr);

				// add key to list
				struct list_item *item = malloc(sizeof(struct list_item));
				item->fpr = fpr;
				g_hash_table_replace(list_fingerprints,bare_jid,item);
			}else
			{
				purple_debug_error(PLUGIN_ID, "could not verify presence of user %s\n",from);
			}
		}else
		{
			purple_debug_info(PLUGIN_ID, "user %s sent empty signed presence\n",from);
		}
	}

	/* We don't want the plugin to stop processing */
	return FALSE;
}
示例#8
0
static void
xmpp_stream_process_presence(XmppStream *stream, xmlnode *root)
{
    xmlnode   *node;
    XmppBuddy *buddy;
    gchar     *value;
    gchar     *full_jid;
    gchar     *bare_jid;
    gchar     *show;
    gchar     *status;
    gchar     *photo;

    if (!xmlnode_has_prop(root, "from")) {
        hybrid_debug_error("xmpp", "invalid presence.");
        return;
    }

    full_jid = xmlnode_prop(root, "from");
    bare_jid = get_bare_jid(full_jid);

    if (xmlnode_has_prop(root, "type")) {

        value = xmlnode_prop(root, "type");
        if (g_strcmp0(value, "unavailable") == 0) {

            if (!(buddy = xmpp_buddy_find(stream->account, bare_jid))) {
                goto presence_over;
            }

            xmpp_buddy_set_show(buddy, full_jid, value);
            g_free(value);
            goto presence_over;

        } else if (g_strcmp0(value, "subscribed") == 0) {
            
            hybrid_message_box_show(HYBRID_MESSAGE_INFO, 
                    "(<b>%s</b>) has accepted your request.", bare_jid);
            g_free(value);
            goto presence_over;

        } else if (g_strcmp0(value, "subscribe") == 0) {

            hybrid_buddy_request_window_create(stream->account->account,
                    full_jid, NULL);
            g_free(value);
            goto presence_over;
        }

        g_free(value);
    }

    if (!(buddy = xmpp_buddy_find(stream->account, bare_jid))) {
        goto presence_over;
    }

    /*
     * If the presence message doesn't have a <show> label,
     * then it means the current status of the buddy is 'avaiable'.
     */
    if ((node = xmlnode_find(root, "show"))) {

        show = xmlnode_content(node);
        xmpp_buddy_set_show(buddy, full_jid, show);
        g_free(show);

    } else {
        xmpp_buddy_set_show(buddy, full_jid, "avaiable");
    }

    if ((node = xmlnode_find(root, "status"))) {

        status = xmlnode_content(node);
        xmpp_buddy_set_status(buddy, full_jid, status);
        g_free(status);

    } 
    /*
     * Check whether it has a photo label, then we can
     * determine whether to fetch the buddy's photo.
     */
    if ((node = xmlnode_find(root, "photo"))) {

        photo = xmlnode_content(node);

        if (g_strcmp0(photo, buddy->photo) != 0) {

            xmpp_buddy_set_photo(buddy, photo);
            xmpp_buddy_get_info(stream, buddy->jid,
                    (trans_callback)buddy_get_info_cb, buddy);
        }

        g_free(photo);
    }
    
presence_over:
    g_free(full_jid);
    g_free(bare_jid);
}
示例#9
0
static void
xmpp_stream_process_message(XmppStream *stream, xmlnode *root)
{
    gchar         *value;
    gchar         *bare_jid;
    xmlnode       *node;
    HybridAccount *account;

    g_return_if_fail(stream != NULL);
    g_return_if_fail(root != NULL);

    account = stream->account->account;

    if (!xmlnode_has_prop(root, "type")) {
        hybrid_debug_error("xmpp", 
                "invalid message received without a type property.");
        return;
    }

    value = xmlnode_prop(root, "type");

    if (g_strcmp0(value, "chat") != 0) {

        hybrid_debug_error("xmpp", "unsupported message type.");
        g_free(value);

        return;
    }

    g_free(value);

    if (!xmlnode_has_prop(root, "from")) {
        
        hybrid_debug_error("xmpp", "invalid message without a from property.");
        return;
    }

    value = xmlnode_prop(root, "from");
    bare_jid = get_bare_jid(value);
    g_free(value);

    if ((node = xmlnode_find(root, "composing"))) {
        hybrid_conv_got_inputing(account, bare_jid, FALSE);
    }

    if ((node = xmlnode_find(root, "active"))) {
        hybrid_conv_clear_inputing(account, bare_jid);
    }

    if ((node = xmlnode_find(root, "paused"))) {
        hybrid_conv_stop_inputing(account, bare_jid);
    }

    if ((node = xmlnode_find(root, "body"))) {

        value = xmlnode_content(node);
        hybrid_conv_got_message(account, bare_jid, value, time(NULL));
        g_free(value);

        return;
    }

}
示例#10
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");
		}
	}
}
示例#11
0
/* ------------------
 * called on received message
 * ------------------ */
static gboolean
jabber_message_received(PurpleConnection *pc, const char *type, const char *id,
                        const char *from, const char *to, xmlnode *message)
{
	const xmlnode* parent_node = message;
	xmlnode* x_node = NULL;
	xmlnode* body_node = NULL;

	if (parent_node == NULL)
		return FALSE;

	// check if message is a key
	body_node = xmlnode_get_child(parent_node,"body");
	if (body_node != NULL)
	{
		char* data = xmlnode_get_data(body_node);
		if (data != NULL)
		{
			char* header = "-----BEGIN PGP PUBLIC KEY BLOCK-----";
			if (strncmp(data,header,strlen(header)) == 0)
			{
				// if we received a ascii armored key
				// try to import it
				//purple_conversation_write(conv,"","received key",PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LOG,time(NULL));
				if (import_key(data) == TRUE)
				{
					xmlnode_clear_data(body_node);
					xmlnode_insert_data(body_node,"key import ok",-1);
				}
				else
				{
					xmlnode_clear_data(body_node);
					xmlnode_insert_data(body_node,"key import failed",-1);
				}
			}
		}
	}

	// check if the user with the jid=from has signed his presence
	char* bare_jid = get_bare_jid(from);

	// get stored info about user
	struct list_item* item = g_hash_table_lookup(list_fingerprints,bare_jid);
	if (item == NULL)
	{
		//TODO: maybe create item in list?
	}else
	{
		// set default value to "not encrypted mode"
		item->mode_sec = FALSE;
	}
	free(bare_jid);

	// check if message has special "x" child node => encrypted message
	x_node = xmlnode_get_child_with_namespace(parent_node,"x",NS_ENC);
	if (x_node != NULL)
	{
		purple_debug_info(PLUGIN_ID, "user %s sent us an encrypted message\n",from);

		// get data of "x" node
		char* cipher_str = xmlnode_get_data(x_node);
		if (cipher_str != NULL)
		{
			// try to decrypt
			char* plain_str = decrypt(cipher_str);
			if (plain_str != NULL)
			{
				purple_debug_info(PLUGIN_ID, "decrypted message: %s\n",plain_str);
				// find body node
				xmlnode *body_node = xmlnode_get_child(parent_node,"body");
				if (body_node != NULL)
				{
					// clear body node data if it is found
					xmlnode_clear_data(body_node);
				}else
				{
					// add body node if it is not found
					body_node = xmlnode_new_child(message,"body");
				}
				// set "body" content node to decrypted string
				//xmlnode_insert_data(body_node,"Encrypted message: ",-1);
				xmlnode_insert_data(body_node,plain_str,-1);

				// only set to encrypted mode, if we know other users key fingerprint
				if (item != NULL)
				{
					// all went well, we received an encrypted message
					item->mode_sec = TRUE;
				}
			}else
			{
				purple_debug_error(PLUGIN_ID, "could not decrypt message!\n");
			}
		}else
		{
			purple_debug_error(PLUGIN_ID, "xml token had no data!\n");
		}
	}

	/* We don't want the plugin to stop processing */
	return FALSE;
}