1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-12-04 14:46:46 -05:00

Merge branch 'master' into plugins

This commit is contained in:
James Booth 2014-05-08 20:36:46 +01:00
commit c85a12f3ba
16 changed files with 749 additions and 128 deletions

View File

@ -24,7 +24,7 @@ debian_prepare()
echo
echo Profanity installer... installing dependencies
echo
sudo apt-get -y install git automake autoconf libssl-dev libexpat1-dev libncursesw5-dev libglib2.0-dev libnotify-dev libcurl3-dev libxss-dev libotr2-dev libgnutls-dev
sudo apt-get -y install git automake autoconf libssl-dev libexpat1-dev libncursesw5-dev libglib2.0-dev libnotify-dev libcurl3-dev libxss-dev libotr5-dev libgnutls-dev
}
@ -73,7 +73,9 @@ install_lib_strophe()
echo
echo Profanity installer... installing libstrophe
echo
git clone git://github.com/strophe/libstrophe.git
#clone fork so as to not pick up any breaking changes
#git clone git://github.com/strophe/libstrophe.git
git clone git://github.com/boothj5/libstrophe.git
cd libstrophe
./bootstrap.sh
./configure

View File

@ -593,14 +593,14 @@ static struct cmd_t command_defs[] =
NULL } } },
{ "/otr",
cmd_otr, parse_args, 1, 2, NULL,
{ "/otr gen|myfp|theirfp|start|end|trust|untrust|log|warn|libver|policy", "Off The Record encryption commands.",
{ "/otr gen|myfp|theirfp|start|end|trust|untrust|log|warn|libver|policy",
"--------------------------------------------------------------------",
cmd_otr, parse_args, 1, 3, NULL,
{ "/otr gen|myfp|theirfp|start|end|trust|untrust|log|warn|libver|policy|secret|question|answer", "Off The Record encryption commands.",
{ "/otr gen|myfp|theirfp|start|end|trust|untrust|log|warn|libver|policy|secret|question|answer",
"-------------------------------------------------------------------------------------------",
"gen - Generate your private key.",
"myfp - Show your fingerprint.",
"theirfp - Show contacts fingerprint.",
"start <contact> - Start an OTR session with the contact, or the current recipient if in a chat window and no argument supplied.",
"start [contact] - Start an OTR session with the contact, or the current recipient if in a chat window and no argument supplied.",
"end - End the current OTR session,",
"trust - Indicate that you have verified the contact's fingerprint.",
"untrust - Indicate the the contact's fingerprint is not verified,",
@ -608,6 +608,9 @@ static struct cmd_t command_defs[] =
"warn - Show when unencrypted messaging is being used in the title bar, options are 'on' and 'off' with 'on' being the default.",
"libver - Show which version of the libotr library is being used.",
"policy - manual, opportunistic or always.",
"secret [secret]- Verify a contacts identity using a shared secret.",
"question [question] [answer] - Verify a contacts identity using a question and expected anwser, if the question has spaces, surround with double quotes.",
"answer [anwser] - Respond to a question answer verification request with your answer.",
NULL } } },
{ "/outtype",
@ -1073,10 +1076,13 @@ cmd_init(void)
autocomplete_add(otr_ac, "theirfp");
autocomplete_add(otr_ac, "trust");
autocomplete_add(otr_ac, "untrust");
autocomplete_add(otr_ac, "secret");
autocomplete_add(otr_ac, "log");
autocomplete_add(otr_ac, "warn");
autocomplete_add(otr_ac, "libver");
autocomplete_add(otr_ac, "policy");
autocomplete_add(otr_ac, "question");
autocomplete_add(otr_ac, "answer");
otr_log_ac = autocomplete_new();
autocomplete_add(otr_log_ac, "on");

View File

@ -2812,7 +2812,57 @@ cmd_otr(gchar **args, struct cmd_help_t help)
otr_untrust(recipient);
}
return TRUE;
} else if (strcmp(args[0], "secret") == 0) {
win_type_t win_type = ui_current_win_type();
if (win_type != WIN_CHAT) {
ui_current_print_line("You must be in an OTR session to trust a recipient.");
} else if (!ui_current_win_is_otr()) {
ui_current_print_formatted_line('!', 0, "You are not currently in an OTR session.");
} else {
char *secret = args[1];
if (secret == NULL) {
cons_show("Usage: %s", help.usage);
} else {
char *recipient = ui_current_recipient();
otr_smp_secret(recipient, secret);
}
}
return TRUE;
} else if (strcmp(args[0], "question") == 0) {
char *question = args[1];
char *answer = args[2];
if (question == NULL || answer == NULL) {
cons_show("Usage: %s", help.usage);
return TRUE;
} else {
win_type_t win_type = ui_current_win_type();
if (win_type != WIN_CHAT) {
ui_current_print_line("You must be in an OTR session to trust a recipient.");
} else if (!ui_current_win_is_otr()) {
ui_current_print_formatted_line('!', 0, "You are not currently in an OTR session.");
} else {
char *recipient = ui_current_recipient();
otr_smp_question(recipient, question, answer);
}
return TRUE;
}
} else if (strcmp(args[0], "answer") == 0) {
win_type_t win_type = ui_current_win_type();
if (win_type != WIN_CHAT) {
ui_current_print_line("You must be in an OTR session to trust a recipient.");
} else if (!ui_current_win_is_otr()) {
ui_current_print_formatted_line('!', 0, "You are not currently in an OTR session.");
} else {
char *answer = args[1];
if (answer == NULL) {
cons_show("Usage: %s", help.usage);
} else {
char *recipient = ui_current_recipient();
otr_smp_answer(recipient, answer);
}
}
return TRUE;
} else {
cons_show("Usage: %s", help.usage);
return TRUE;

View File

@ -34,6 +34,7 @@ typedef struct _muc_room_t {
char *nick; // e.g. Some User
char *password;
char *subject;
GList *pending_broadcasts;
gboolean autojoin;
gboolean pending_nick_change;
GHashTable *roster;
@ -144,6 +145,7 @@ muc_join_room(const char * const room, const char * const nick,
new_room->password = NULL;
}
new_room->subject = NULL;
new_room->pending_broadcasts = NULL;
new_room->roster = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
(GDestroyNotify)p_contact_free);
new_room->nick_ac = autocomplete_new();
@ -202,6 +204,65 @@ muc_room_is_autojoin(const char * const room)
}
}
void
muc_set_subject(const char * const room, const char * const subject)
{
if (rooms != NULL) {
ChatRoom *chat_room = g_hash_table_lookup(rooms, room);
if (chat_room != NULL) {
if (chat_room->subject != NULL) {
free(chat_room->subject);
}
chat_room->subject = strdup(subject);
}
}
}
char *
muc_get_subject(const char * const room)
{
if (rooms != NULL) {
ChatRoom *chat_room = g_hash_table_lookup(rooms, room);
if (chat_room != NULL) {
return chat_room->subject;
} else {
return NULL;
}
} else {
return NULL;
}
}
void
muc_add_pending_broadcast(const char * const room, const char * const message)
{
if (rooms != NULL) {
ChatRoom *chat_room = g_hash_table_lookup(rooms, room);
if (chat_room != NULL) {
chat_room->pending_broadcasts = g_list_append(chat_room->pending_broadcasts, strdup(message));
}
}
}
GList *
muc_get_pending_broadcasts(const char * const room)
{
if (rooms != NULL) {
ChatRoom *chat_room = g_hash_table_lookup(rooms, room);
if (chat_room != NULL) {
return chat_room->pending_broadcasts;
} else {
return NULL;
}
} else {
return NULL;
}
}
char *
muc_get_old_nick(const char * const room, const char * const new_nick)
{
@ -523,6 +584,9 @@ _free_room(ChatRoom *room)
g_hash_table_remove_all(room->nick_changes);
}
free(room);
if (room->pending_broadcasts != NULL) {
g_list_free_full(room->pending_broadcasts, free);
}
}
}

View File

@ -71,4 +71,9 @@ void muc_reset_invites_ac(void);
char* muc_find_invite(char *search_str);
void muc_clear_invites(void);
void muc_set_subject(const char * const room, const char * const subject);
char * muc_get_subject(const char * const room);
void muc_add_pending_broadcast(const char * const room, const char * const message);
GList * muc_get_pending_broadcasts(const char * const room);
#endif

View File

@ -23,6 +23,7 @@
#include <libotr/proto.h>
#include <libotr/privkey.h>
#include <libotr/message.h>
#include <libotr/sm.h>
#include <glib.h>
#include "otr/otr.h"
@ -40,6 +41,25 @@ static OtrlUserState user_state;
static OtrlMessageAppOps ops;
static char *jid;
static gboolean data_loaded;
static GHashTable *smp_initiators;
OtrlUserState
otr_userstate(void)
{
return user_state;
}
OtrlMessageAppOps *
otr_messageops(void)
{
return &ops;
}
GHashTable *
otr_smpinitators(void)
{
return smp_initiators;
}
// ops callbacks
static OtrlPolicy
@ -134,10 +154,18 @@ _otr_init(void)
ops.gone_secure = cb_gone_secure;
otrlib_init_ops(&ops);
otrlib_init_timer();
smp_initiators = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
data_loaded = FALSE;
}
void
_otr_poll(void)
{
otrlib_poll();
}
static void
_otr_on_connect(ProfAccount *account)
{
@ -337,9 +365,14 @@ _otr_is_trusted(const char * const recipient)
return TRUE;
}
if (context->active_fingerprint &&
g_strcmp0(context->active_fingerprint->trust, "trusted") == 0) {
return TRUE;
if (context->active_fingerprint) {
if (context->active_fingerprint->trust == NULL) {
return FALSE;
} else if (context->active_fingerprint->trust[0] == '\0') {
return FALSE;
} else {
return TRUE;
}
}
return FALSE;
@ -359,7 +392,10 @@ _otr_trust(const char * const recipient)
}
if (context->active_fingerprint) {
context->active_fingerprint->trust = "trusted";
if (context->active_fingerprint->trust != NULL) {
free(context->active_fingerprint->trust);
}
context->active_fingerprint->trust = strdup("trusted");
cb_write_fingerprints(NULL);
}
@ -380,6 +416,9 @@ _otr_untrust(const char * const recipient)
}
if (context->active_fingerprint) {
if (context->active_fingerprint->trust != NULL) {
free(context->active_fingerprint->trust);
}
context->active_fingerprint->trust = NULL;
cb_write_fingerprints(NULL);
}
@ -387,6 +426,64 @@ _otr_untrust(const char * const recipient)
return;
}
static void
_otr_smp_secret(const char * const recipient, const char *secret)
{
ConnContext *context = otrlib_context_find(user_state, recipient, jid);
if (context == NULL) {
return;
}
if (context->msgstate != OTRL_MSGSTATE_ENCRYPTED) {
return;
}
// if recipient initiated SMP, send response, else initialise
if (g_hash_table_contains(smp_initiators, recipient)) {
otrl_message_respond_smp(user_state, &ops, NULL, context, (const unsigned char*)secret, strlen(secret));
ui_otr_authenticating(recipient);
g_hash_table_remove(smp_initiators, context->username);
} else {
otrl_message_initiate_smp(user_state, &ops, NULL, context, (const unsigned char*)secret, strlen(secret));
ui_otr_authetication_waiting(recipient);
}
}
static void
_otr_smp_question(const char * const recipient, const char *question, const char *answer)
{
ConnContext *context = otrlib_context_find(user_state, recipient, jid);
if (context == NULL) {
return;
}
if (context->msgstate != OTRL_MSGSTATE_ENCRYPTED) {
return;
}
otrl_message_initiate_smp_q(user_state, &ops, NULL, context, question, (const unsigned char*)answer, strlen(answer));
ui_otr_authetication_waiting(recipient);
}
static void
_otr_smp_answer(const char * const recipient, const char *answer)
{
ConnContext *context = otrlib_context_find(user_state, recipient, jid);
if (context == NULL) {
return;
}
if (context->msgstate != OTRL_MSGSTATE_ENCRYPTED) {
return;
}
// if recipient initiated SMP, send response, else initialise
otrl_message_respond_smp(user_state, &ops, NULL, context, (const unsigned char*)answer, strlen(answer));
}
static void
_otr_end_session(const char * const recipient)
{
@ -424,7 +521,7 @@ _otr_encrypt_message(const char * const to, const char * const message)
char *newmessage = NULL;
gcry_error_t err = otrlib_encrypt_message(user_state, &ops, jid, to, message, &newmessage);
if (!err == GPG_ERR_NO_ERROR) {
if (err != 0) {
return NULL;
} else {
return newmessage;
@ -441,15 +538,21 @@ _otr_decrypt_message(const char * const from, const char * const message, gboole
// internal libotr message
if (result == 1) {
ConnContext *context = otrlib_context_find(user_state, from, jid);
// common tlv handling
OtrlTLV *tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED);
if (tlv) {
ConnContext *context = otrlib_context_find(user_state, from, jid);
if (context != NULL) {
otrl_context_force_plaintext(context);
ui_gone_insecure(from);
}
}
// library version specific tlv handling
otrlib_handle_tlvs(user_state, &ops, context, tlvs, smp_initiators);
return NULL;
// message was decrypted, return to user
@ -476,6 +579,7 @@ otr_init_module(void)
otr_init = _otr_init;
otr_libotr_version = _otr_libotr_version;
otr_start_query = _otr_start_query;
otr_poll = _otr_poll;
otr_on_connect = _otr_on_connect;
otr_keygen = _otr_keygen;
otr_key_loaded = _otr_key_loaded;
@ -489,4 +593,7 @@ otr_init_module(void)
otr_encrypt_message = _otr_encrypt_message;
otr_decrypt_message = _otr_decrypt_message;
otr_free_message = _otr_free_message;
otr_smp_secret = _otr_smp_secret;
otr_smp_question = _otr_smp_question;
otr_smp_answer = _otr_smp_answer;
}

View File

@ -23,13 +23,21 @@
#ifndef OTR_H
#define OTR_H
#include <libotr/proto.h>
#include <libotr/message.h>
#include "config/accounts.h"
void otr_init_module(void);
OtrlUserState otr_userstate(void);
OtrlMessageAppOps* otr_messageops(void);
GHashTable* otr_smpinitators(void);
void (*otr_init)(void);
char* (*otr_libotr_version)(void);
char* (*otr_start_query)(void);
void (*otr_poll)(void);
void (*otr_on_connect)(ProfAccount *account);
void (*otr_keygen)(ProfAccount *account);
@ -40,6 +48,10 @@ gboolean (*otr_is_trusted)(const char * const recipient);
void (*otr_trust)(const char * const recipient);
void (*otr_untrust)(const char * const recipient);
void (*otr_smp_secret)(const char * const recipient, const char *secret);
void (*otr_smp_question)(const char * const recipient, const char *question, const char *answer);
void (*otr_smp_answer)(const char * const recipient, const char *answer);
void (*otr_end_session)(const char * const recipient);
char * (*otr_get_my_fingerprint)(void);

View File

@ -29,6 +29,9 @@ char* otrlib_start_query(void);
void otrlib_init_ops(OtrlMessageAppOps *ops);
void otrlib_init_timer(void);
void otrlib_poll(void);
ConnContext * otrlib_context_find(OtrlUserState user_state, const char * const recipient, char *jid);
void otrlib_end_session(OtrlUserState user_state, const char * const recipient, char *jid, OtrlMessageAppOps *ops);
@ -39,4 +42,6 @@ gcry_error_t otrlib_encrypt_message(OtrlUserState user_state, OtrlMessageAppOps
int otrlib_decrypt_message(OtrlUserState user_state, OtrlMessageAppOps *ops, char *jid, const char * const from,
const char * const message, char **decrypted, OtrlTLV **tlvs);
void otrlib_handle_tlvs(OtrlUserState user_state, OtrlMessageAppOps *ops, ConnContext *context, OtrlTLV *tlvs, GHashTable *smp_initiators);
#endif

View File

@ -24,6 +24,8 @@
#include <libotr/message.h>
#include "ui/ui.h"
#include "otr/otr.h"
#include "otr/otrlib.h"
OtrlPolicy
otrlib_policy(void)
@ -31,6 +33,16 @@ otrlib_policy(void)
return OTRL_POLICY_ALLOW_V1 | OTRL_POLICY_ALLOW_V2 ;
}
void
otrlib_init_timer(void)
{
}
void
otrlib_poll(void)
{
}
char *
otrlib_start_query(void)
{
@ -106,3 +118,83 @@ otrlib_decrypt_message(OtrlUserState user_state, OtrlMessageAppOps *ops, char *j
NULL,
NULL);
}
void
otrlib_handle_tlvs(OtrlUserState user_state, OtrlMessageAppOps *ops, ConnContext *context, OtrlTLV *tlvs, GHashTable *smp_initiators)
{
NextExpectedSMP nextMsg = context->smstate->nextExpected;
OtrlTLV *tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1);
if (tlv) {
if (nextMsg != OTRL_SMP_EXPECT1) {
otrl_message_abort_smp(user_state, ops, NULL, context);
} else {
ui_smp_recipient_initiated(context->username);
g_hash_table_insert(smp_initiators, strdup(context->username), strdup(context->username));
}
}
tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q);
if (tlv) {
if (nextMsg != OTRL_SMP_EXPECT1) {
otrl_message_abort_smp(user_state, ops, NULL, context);
} else {
char *question = (char *)tlv->data;
char *eoq = memchr(question, '\0', tlv->len);
if (eoq) {
ui_smp_recipient_initiated_q(context->username, question);
}
}
}
tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2);
if (tlv) {
if (nextMsg != OTRL_SMP_EXPECT2) {
otrl_message_abort_smp(user_state, ops, NULL, context);
} else {
context->smstate->nextExpected = OTRL_SMP_EXPECT4;
}
}
tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3);
if (tlv) {
if (nextMsg != OTRL_SMP_EXPECT3) {
otrl_message_abort_smp(user_state, ops, NULL, context);
} else {
context->smstate->nextExpected = OTRL_SMP_EXPECT1;
if (context->smstate->received_question == 0) {
if ((context->active_fingerprint->trust != NULL) && (context->active_fingerprint->trust[0] != '\0')) {
ui_smp_successful(context->username);
ui_trust(context->username);
} else {
ui_smp_unsuccessful_sender(context->username);
ui_untrust(context->username);
}
} else {
if (context->smstate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED) {
ui_smp_answer_success(context->username);
} else {
ui_smp_answer_failure(context->username);
}
}
}
}
tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4);
if (tlv) {
if (nextMsg != OTRL_SMP_EXPECT4) {
otrl_message_abort_smp(user_state, ops, NULL, context);
} else {
context->smstate->nextExpected = OTRL_SMP_EXPECT1;
if ((context->active_fingerprint->trust != NULL) && (context->active_fingerprint->trust[0] != '\0')) {
ui_smp_successful(context->username);
ui_trust(context->username);
} else {
ui_smp_unsuccessful_receiver(context->username);
ui_untrust(context->username);
}
}
}
tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT);
if (tlv) {
context->smstate->nextExpected = OTRL_SMP_EXPECT1;
ui_smp_aborted(context->username);
ui_untrust(context->username);
otr_untrust(context->username);
}
}

View File

@ -25,6 +25,12 @@
#include <libotr/message.h>
#include "ui/ui.h"
#include "log.h"
#include "otr/otr.h"
#include "otr/otrlib.h"
static GTimer *timer;
static unsigned int current_interval;
OtrlPolicy
otrlib_policy(void)
@ -32,6 +38,27 @@ otrlib_policy(void)
return OTRL_POLICY_ALLOW_V1 | OTRL_POLICY_ALLOW_V2;
}
void
otrlib_init_timer(void)
{
OtrlUserState user_state = otr_userstate();
timer = g_timer_new();
current_interval = otrl_message_poll_get_default_interval(user_state);
}
void
otrlib_poll(void)
{
gdouble elapsed = g_timer_elapsed(timer, NULL);
if (current_interval != 0 && elapsed > current_interval) {
OtrlUserState user_state = otr_userstate();
OtrlMessageAppOps *ops = otr_messageops();
otrl_message_poll(user_state, ops, NULL);
g_timer_start(timer);
}
}
char *
otrlib_start_query(void)
{
@ -63,6 +90,12 @@ cb_otr_error_message_free(void *opdata, const char *err_msg)
free((char *)err_msg);
}
static void
cb_timer_control(void *opdata, unsigned int interval)
{
current_interval = interval;
}
static void
cb_handle_msg_event(void *opdata, OtrlMessageEvent msg_event,
ConnContext *context, const char *message,
@ -77,12 +110,78 @@ cb_handle_msg_event(void *opdata, OtrlMessageEvent msg_event,
}
}
static void
cb_handle_smp_event(void *opdata, OtrlSMPEvent smp_event,
ConnContext *context, unsigned short progress_percent,
char *question)
{
NextExpectedSMP nextMsg = context->smstate->nextExpected;
OtrlUserState user_state = otr_userstate();
OtrlMessageAppOps *ops = otr_messageops();
GHashTable *smp_initiators = otr_smpinitators();
switch(smp_event)
{
case OTRL_SMPEVENT_ASK_FOR_SECRET:
ui_smp_recipient_initiated(context->username);
g_hash_table_insert(smp_initiators, strdup(context->username), strdup(context->username));
break;
case OTRL_SMPEVENT_ASK_FOR_ANSWER:
ui_smp_recipient_initiated_q(context->username, question);
break;
case OTRL_SMPEVENT_SUCCESS:
if (context->smstate->received_question == 0) {
ui_smp_successful(context->username);
ui_trust(context->username);
} else {
ui_smp_answer_success(context->username);
}
break;
case OTRL_SMPEVENT_FAILURE:
if (context->smstate->received_question == 0) {
if (nextMsg == OTRL_SMP_EXPECT3) {
ui_smp_unsuccessful_sender(context->username);
} else if (nextMsg == OTRL_SMP_EXPECT4) {
ui_smp_unsuccessful_receiver(context->username);
}
ui_untrust(context->username);
} else {
ui_smp_answer_failure(context->username);
}
break;
case OTRL_SMPEVENT_ERROR:
otrl_message_abort_smp(user_state, ops, NULL, context);
break;
case OTRL_SMPEVENT_CHEATED:
otrl_message_abort_smp(user_state, ops, NULL, context);
break;
case OTRL_SMPEVENT_ABORT:
ui_smp_aborted(context->username);
ui_untrust(context->username);
break;
case OTRL_SMPEVENT_IN_PROGRESS:
break;
default:
break;
}
}
void
otrlib_init_ops(OtrlMessageAppOps *ops)
{
ops->otr_error_message = cb_otr_error_message;
ops->otr_error_message_free = cb_otr_error_message_free;
ops->handle_msg_event = cb_handle_msg_event;
ops->handle_smp_event = cb_handle_smp_event;
ops->timer_control = cb_timer_control;
}
ConnContext *
@ -145,3 +244,8 @@ otrlib_decrypt_message(OtrlUserState user_state, OtrlMessageAppOps *ops, char *j
NULL,
NULL);
}
void
otrlib_handle_tlvs(OtrlUserState user_state, OtrlMessageAppOps *ops, ConnContext *context, OtrlTLV *tlvs, GHashTable *smp_initiators)
{
}

View File

@ -107,6 +107,9 @@ prof_run(const int disable_tls, char *log_level, char *account_name)
ui_handle_special_keys(&ch, inp, size);
ui_update_screen();
#ifdef HAVE_LIBOTR
otr_poll();
#endif
jabber_process_events();
ch = ui_get_char(inp, &size);

View File

@ -176,15 +176,22 @@ void
handle_room_broadcast(const char *const room_jid,
const char * const message)
{
ui_room_broadcast(room_jid, message);
ui_current_page_off();
if (muc_get_roster_received(room_jid)) {
ui_room_broadcast(room_jid, message);
ui_current_page_off();
} else {
muc_add_pending_broadcast(room_jid, message);
}
}
void
handle_room_subject(const char * const room_jid, const char * const subject)
{
ui_room_subject(room_jid, subject);
ui_current_page_off();
muc_set_subject(room_jid, subject);
if (muc_get_roster_received(room_jid)) {
ui_room_subject(room_jid, subject);
ui_current_page_off();
}
}
void
@ -500,7 +507,22 @@ handle_room_roster_complete(const char * const room)
muc_set_roster_received(room);
GList *roster = muc_get_roster(room);
ui_room_roster(room, roster, NULL);
ui_current_page_off();
char *subject = muc_get_subject(room);
if (subject != NULL) {
ui_room_subject(room, subject);
ui_current_page_off();
}
GList *pending_broadcasts = muc_get_pending_broadcasts(room);
if (pending_broadcasts != NULL) {
GList *curr = pending_broadcasts;
while (curr != NULL) {
ui_room_broadcast(room, curr->data);
curr = g_list_next(curr);
}
ui_current_page_off();
}
}
void

View File

@ -770,6 +770,7 @@ _ui_gone_secure(const char * const recipient, gboolean trusted)
title_bar_set_recipient(recipient_str->str);
g_string_free(recipient_str, TRUE);
win_update_virtual(window);
ui_current_page_off();
} else {
int num = wins_get_num(window);
status_bar_new(num);
@ -787,6 +788,128 @@ _ui_gone_secure(const char * const recipient, gboolean trusted)
}
}
static void
_ui_smp_recipient_initiated(const char * const recipient)
{
ProfWin *window = wins_get_by_recipient(recipient);
if (window == NULL) {
return;
} else {
win_vprint_line(window, '!', 0, "%s wants to authenticate your identity, use '/otr secret <secret>'.", recipient);
win_update_virtual(window);
if (wins_is_current(window)) {
ui_current_page_off();
}
}
}
static void
_ui_smp_recipient_initiated_q(const char * const recipient, const char *question)
{
ProfWin *window = wins_get_by_recipient(recipient);
if (window == NULL) {
return;
} else {
win_vprint_line(window, '!', 0, "%s wants to authenticate your identity with the following question:", recipient);
win_vprint_line(window, '!', 0, " %s", question);
win_vprint_line(window, '!', 0, "use '/otr answer <answer>'.");
win_update_virtual(window);
if (wins_is_current(window)) {
ui_current_page_off();
}
}
}
static void
_ui_smp_unsuccessful_sender(const char * const recipient)
{
ProfWin *window = wins_get_by_recipient(recipient);
if (window == NULL) {
return;
} else {
win_vprint_line(window, '!', 0, "Authentication failed, the secret you entered does not match the secret entered by %s.", recipient);
win_update_virtual(window);
if (wins_is_current(window)) {
ui_current_page_off();
}
}
}
static void
_ui_smp_unsuccessful_receiver(const char * const recipient)
{
ProfWin *window = wins_get_by_recipient(recipient);
if (window == NULL) {
return;
} else {
win_vprint_line(window, '!', 0, "Authentication failed, the secret entered by %s does not match yours.", recipient);
win_update_virtual(window);
if (wins_is_current(window)) {
ui_current_page_off();
}
}
}
static void
_ui_smp_aborted(const char * const recipient)
{
ProfWin *window = wins_get_by_recipient(recipient);
if (window == NULL) {
return;
} else {
win_vprint_line(window, '!', 0, "SMP session aborted.");
win_update_virtual(window);
if (wins_is_current(window)) {
ui_current_page_off();
}
}
}
static void
_ui_smp_successful(const char * const recipient)
{
ProfWin *window = wins_get_by_recipient(recipient);
if (window == NULL) {
return;
} else {
win_vprint_line(window, '!', 0, "Authentication successful.");
win_update_virtual(window);
if (wins_is_current(window)) {
ui_current_page_off();
}
}
}
static void
_ui_smp_answer_success(const char * const recipient)
{
ProfWin *window = wins_get_by_recipient(recipient);
if (window == NULL) {
return;
} else {
win_vprint_line(window, '!', 0, "%s successfully authenticated you.", recipient);
win_update_virtual(window);
if (wins_is_current(window)) {
ui_current_page_off();
}
}
}
static void
_ui_smp_answer_failure(const char * const recipient)
{
ProfWin *window = wins_get_by_recipient(recipient);
if (window == NULL) {
return;
} else {
win_vprint_line(window, '!', 0, "%s failed to authenticated you.", recipient);
win_update_virtual(window);
if (wins_is_current(window)) {
ui_current_page_off();
}
}
}
static void
_ui_gone_insecure(const char * const recipient)
{
@ -801,6 +924,7 @@ _ui_gone_insecure(const char * const recipient)
title_bar_set_recipient(recipient_str->str);
g_string_free(recipient_str, TRUE);
win_update_virtual(window);
ui_current_page_off();
}
}
}
@ -819,6 +943,7 @@ _ui_trust(const char * const recipient)
title_bar_set_recipient(recipient_str->str);
g_string_free(recipient_str, TRUE);
win_update_virtual(window);
ui_current_page_off();
}
}
}
@ -837,6 +962,7 @@ _ui_untrust(const char * const recipient)
title_bar_set_recipient(recipient_str->str);
g_string_free(recipient_str, TRUE);
win_update_virtual(window);
ui_current_page_off();
}
}
}
@ -979,6 +1105,36 @@ _ui_current_set_otr(gboolean value)
current->is_otr = value;
}
static void
_ui_otr_authenticating(const char * const recipient)
{
ProfWin *window = wins_get_by_recipient(recipient);
if (window == NULL) {
return;
} else {
win_vprint_line(window, '!', 0, "Authenticating %s...", recipient);
win_update_virtual(window);
if (wins_is_current(window)) {
ui_current_page_off();
}
}
}
static void
_ui_otr_authetication_waiting(const char * const recipient)
{
ProfWin *window = wins_get_by_recipient(recipient);
if (window == NULL) {
return;
} else {
win_vprint_line(window, '!', 0, "Awaiting authentication from %s...", recipient);
win_update_virtual(window);
if (wins_is_current(window)) {
ui_current_page_off();
}
}
}
static int
_ui_current_win_index(void)
{
@ -1979,10 +2135,20 @@ ui_init_module(void)
ui_ask_password = _ui_ask_password;
ui_current_win_is_otr = _ui_current_win_is_otr;
ui_current_set_otr = _ui_current_set_otr;
ui_otr_authenticating = _ui_otr_authenticating;
ui_otr_authetication_waiting = _ui_otr_authetication_waiting;
ui_gone_secure = _ui_gone_secure;
ui_gone_insecure = _ui_gone_insecure;
ui_trust = _ui_trust;
ui_untrust = _ui_untrust;
ui_smp_recipient_initiated = _ui_smp_recipient_initiated;
ui_smp_recipient_initiated_q = _ui_smp_recipient_initiated_q;
ui_smp_successful = _ui_smp_successful;
ui_smp_unsuccessful_sender = _ui_smp_unsuccessful_sender;
ui_smp_unsuccessful_receiver = _ui_smp_unsuccessful_receiver;
ui_smp_aborted = _ui_smp_aborted;
ui_smp_answer_success = _ui_smp_answer_success;
ui_smp_answer_failure = _ui_smp_answer_failure;
ui_chat_win_contact_online = _ui_chat_win_contact_online;
ui_chat_win_contact_offline = _ui_chat_win_contact_offline;
ui_handle_recipient_not_found = _ui_handle_recipient_not_found;

View File

@ -58,10 +58,22 @@ void (*ui_handle_special_keys)(const wint_t * const ch, const char * const inp,
gboolean (*ui_switch_win)(const int i);
void (*ui_next_win)(void);
void (*ui_previous_win)(void);
void (*ui_gone_secure)(const char * const recipient, gboolean trusted);
void (*ui_gone_insecure)(const char * const recipient);
void (*ui_trust)(const char * const recipient);
void (*ui_untrust)(const char * const recipient);
void (*ui_smp_recipient_initiated)(const char * const recipient);
void (*ui_smp_recipient_initiated_q)(const char * const recipient, const char *question);
void (*ui_smp_successful)(const char * const recipient);
void (*ui_smp_unsuccessful_sender)(const char * const recipient);
void (*ui_smp_unsuccessful_receiver)(const char * const recipient);
void (*ui_smp_aborted)(const char * const recipient);
void (*ui_smp_answer_success)(const char * const recipient);
void (*ui_smp_answer_failure)(const char * const recipient);
unsigned long (*ui_get_idle_time)(void);
void (*ui_reset_idle_time)(void);
void (*ui_new_chat_win)(const char * const to);
@ -85,6 +97,9 @@ void (*ui_current_error_line)(const char * const msg);
void (*ui_current_page_off)(void);
void (*ui_current_update_virtual)(void);
void (*ui_otr_authenticating)(const char * const recipient);
void (*ui_otr_authetication_waiting)(const char * const recipient);
win_type_t (*ui_win_type)(int index);
char * (*ui_recipient)(int index);
void (*ui_close_win)(int index);

View File

@ -336,7 +336,10 @@ _presence_error_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
xmpp_stanza_t *error_stanza = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_ERROR);
xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X);
char *xmlns = xmpp_stanza_get_ns(x);
char *xmlns = NULL;
if (x != NULL) {
xmlns = xmpp_stanza_get_ns(x);
}
char *type = NULL;
if (error_stanza != NULL) {
type = xmpp_stanza_get_attribute(error_stanza, STANZA_ATTR_TYPE);
@ -664,8 +667,8 @@ _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
return 1;
}
char *room = from_jid->barejid;
char *nick = from_jid->resourcepart;
char *from_room = from_jid->barejid;
char *from_nick = from_jid->resourcepart;
// handle self presence
if (stanza_is_muc_self_presence(stanza, jabber_get_fulljid())) {
@ -676,19 +679,19 @@ _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
// leave room if not self nick change
if (new_nick != NULL) {
muc_set_room_pending_nick_change(room, new_nick);
muc_set_room_pending_nick_change(from_room, new_nick);
} else {
handle_leave_room(room);
handle_leave_room(from_room);
}
// handle self nick change
} else if (muc_is_room_pending_nick_change(room)) {
muc_complete_room_nick_change(room, nick);
handle_room_nick_change(room, nick);
} else if (muc_is_room_pending_nick_change(from_room)) {
muc_complete_room_nick_change(from_room, from_nick);
handle_room_nick_change(from_room, from_nick);
// handle roster complete
} else if (!muc_get_roster_received(room)) {
handle_room_roster_complete(room);
} else if (!muc_get_roster_received(from_room)) {
handle_room_roster_complete(from_room);
}
// handle presence from room members
@ -711,28 +714,28 @@ _muc_user_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,
if (stanza_is_room_nick_change(stanza)) {
char *new_nick = stanza_get_new_nick(stanza);
if (new_nick != NULL) {
muc_set_roster_pending_nick_change(room, new_nick, nick);
muc_set_roster_pending_nick_change(from_room, new_nick, from_nick);
free(new_nick);
}
} else {
handle_room_member_offline(room, nick, "offline", status_str);
handle_room_member_offline(from_room, from_nick, "offline", status_str);
}
} else {
char *show_str = stanza_get_show(stanza, "online");
if (!muc_get_roster_received(room)) {
muc_add_to_roster(room, nick, show_str, status_str, caps_key);
if (!muc_get_roster_received(from_room)) {
muc_add_to_roster(from_room, from_nick, show_str, status_str, caps_key);
} else {
char *old_nick = muc_complete_roster_nick_change(room, nick);
char *old_nick = muc_complete_roster_nick_change(from_room, from_nick);
if (old_nick != NULL) {
muc_add_to_roster(room, nick, show_str, status_str, caps_key);
handle_room_member_nick_change(room, old_nick, nick);
muc_add_to_roster(from_room, from_nick, show_str, status_str, caps_key);
handle_room_member_nick_change(from_room, old_nick, from_nick);
free(old_nick);
} else {
if (!muc_nick_in_roster(room, nick)) {
handle_room_member_online(room, nick, show_str, status_str, caps_key);
if (!muc_nick_in_roster(from_room, from_nick)) {
handle_room_member_online(from_room, from_nick, show_str, status_str, caps_key);
} else {
handle_room_member_presence(room, nick, show_str, status_str, caps_key);
handle_room_member_presence(from_room, from_nick, show_str, status_str, caps_key);
}
}
}

View File

@ -634,127 +634,92 @@ gboolean
stanza_is_muc_self_presence(xmpp_stanza_t * const stanza,
const char * const self_jid)
{
if (stanza == NULL) {
return FALSE;
}
if (strcmp(xmpp_stanza_get_name(stanza), STANZA_NAME_PRESENCE) != 0) {
// no stanza, or not presence stanza
if ((stanza == NULL) || (g_strcmp0(xmpp_stanza_get_name(stanza), STANZA_NAME_PRESENCE) != 0)) {
return FALSE;
}
xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X);
// muc user namespaced x element
xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
if (x != NULL) {
if (x == NULL) {
return FALSE;
}
char *ns = xmpp_stanza_get_ns(x);
if (ns == NULL) {
return FALSE;
}
if (strcmp(ns, STANZA_NS_MUC_USER) != 0) {
return FALSE;
}
xmpp_stanza_t *x_children = xmpp_stanza_get_children(x);
if (x_children == NULL) {
return FALSE;
}
while (x_children != NULL) {
if (strcmp(xmpp_stanza_get_name(x_children), STANZA_NAME_STATUS) == 0) {
char *code = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_CODE);
if (strcmp(code, "110") == 0) {
return TRUE;
// check for status child element with 110 code
xmpp_stanza_t *x_children = xmpp_stanza_get_children(x);
while (x_children != NULL) {
if (g_strcmp0(xmpp_stanza_get_name(x_children), STANZA_NAME_STATUS) == 0) {
char *code = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_CODE);
if (g_strcmp0(code, "110") == 0) {
return TRUE;
}
}
x_children = xmpp_stanza_get_next(x_children);
}
x_children = xmpp_stanza_get_next(x_children);
}
// for older server that don't send status 110
x_children = xmpp_stanza_get_children(x);
while (x_children != NULL) {
if (strcmp(xmpp_stanza_get_name(x_children), STANZA_NAME_ITEM) == 0) {
char *jid = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_JID);
// check for item child element with jid property
xmpp_stanza_t *item = xmpp_stanza_get_child_by_name(x, STANZA_NAME_ITEM);
if (item != NULL) {
char *jid = xmpp_stanza_get_attribute(item, STANZA_ATTR_JID);
if (jid != NULL) {
if (g_str_has_prefix(jid, self_jid)) {
if (g_str_has_prefix(self_jid, jid)) {
return TRUE;
}
}
}
x_children = xmpp_stanza_get_next(x_children);
}
// for servers that don't send status 110 or Jid property
// first check if 'from' attribute identifies this user
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (from != NULL) {
Jid *jidp = jid_create(from);
if (muc_room_is_active(jidp->barejid)) {
char *nick = muc_get_room_nick(jidp->barejid);
if (g_strcmp0(jidp->resourcepart, nick) == 0) {
return TRUE;
}
}
jid_destroy(jidp);
}
// secondly check if the new nickname maps to a pending nick change for this user
if (from != NULL) {
Jid *jidp = jid_create(from);
if (muc_is_room_pending_nick_change(jidp->barejid)) {
char *new_nick = jidp->resourcepart;
if (new_nick != NULL) {
char *nick = muc_get_room_nick(jidp->barejid);
char *old_nick = muc_get_old_nick(jidp->barejid, new_nick);
if (g_strcmp0(old_nick, nick) == 0) {
// check if 'from' attribute identifies this user
char *from = xmpp_stanza_get_attribute(stanza, STANZA_ATTR_FROM);
if (from != NULL) {
Jid *from_jid = jid_create(from);
if (muc_room_is_active(from_jid->barejid)) {
char *nick = muc_get_room_nick(from_jid->barejid);
if (g_strcmp0(from_jid->resourcepart, nick) == 0) {
return TRUE;
}
}
// check if a new nickname maps to a pending nick change for this user
if (muc_is_room_pending_nick_change(from_jid->barejid)) {
char *new_nick = from_jid->resourcepart;
if (new_nick != NULL) {
char *nick = muc_get_room_nick(from_jid->barejid);
char *old_nick = muc_get_old_nick(from_jid->barejid, new_nick);
if (g_strcmp0(old_nick, nick) == 0) {
return TRUE;
}
}
}
jid_destroy(from_jid);
}
jid_destroy(jidp);
}
// self presence not found
return FALSE;
}
gboolean
stanza_is_room_nick_change(xmpp_stanza_t * const stanza)
{
if (stanza == NULL) {
return FALSE;
}
if (strcmp(xmpp_stanza_get_name(stanza), STANZA_NAME_PRESENCE) != 0) {
// no stanza, or not presence stanza
if ((stanza == NULL) || (g_strcmp0(xmpp_stanza_get_name(stanza), STANZA_NAME_PRESENCE) != 0)) {
return FALSE;
}
xmpp_stanza_t *x = xmpp_stanza_get_child_by_name(stanza, STANZA_NAME_X);
// muc user namespaced x element
xmpp_stanza_t *x = xmpp_stanza_get_child_by_ns(stanza, STANZA_NS_MUC_USER);
if (x != NULL) {
if (x == NULL) {
return FALSE;
}
char *ns = xmpp_stanza_get_ns(x);
if (ns == NULL) {
return FALSE;
}
if (strcmp(ns, STANZA_NS_MUC_USER) != 0) {
return FALSE;
}
xmpp_stanza_t *x_children = xmpp_stanza_get_children(x);
if (x_children == NULL) {
return FALSE;
}
while (x_children != NULL) {
if (strcmp(xmpp_stanza_get_name(x_children), STANZA_NAME_STATUS) == 0) {
char *code = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_CODE);
if (strcmp(code, "303") == 0) {
return TRUE;
// check for status child element with 303 code
xmpp_stanza_t *x_children = xmpp_stanza_get_children(x);
while (x_children != NULL) {
if (g_strcmp0(xmpp_stanza_get_name(x_children), STANZA_NAME_STATUS) == 0) {
char *code = xmpp_stanza_get_attribute(x_children, STANZA_ATTR_CODE);
if (g_strcmp0(code, "303") == 0) {
return TRUE;
}
}
x_children = xmpp_stanza_get_next(x_children);
}
x_children = xmpp_stanza_get_next(x_children);
}
return FALSE;