1 /*
2  *  Off-the-Record Messaging plugin for pidgin
3  *  Copyright (C) 2004-2012  Ian Goldberg, Rob Smits,
4  *                           Chris Alexander, Willy Lew,
5  *                           Nikita Borisov
6  *                           <otr@cypherpunks.ca>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of version 2 of the GNU General Public License as
10  *  published by the Free Software Foundation.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /* config.h */
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 
27 /* system headers */
28 #include <stdlib.h>
29 
30 /* purple headers */
31 #include "util.h"
32 #include "account.h"
33 
34 #ifdef ENABLE_NLS
35 /* internationalisation header */
36 #include <glib/gi18n-lib.h>
37 #else
38 #define _(x) (x)
39 #define N_(x) (x)
40 #endif
41 
42 /* libotr headers */
43 #include <libotr/privkey.h>
44 #include <libotr/proto.h>
45 #include <libotr/message.h>
46 
47 /* purple-otr headers */
48 #include "ui.h"
49 #include "dialogs.h"
50 #include "otr-plugin.h"
51 
52 static const OtrgUiUiOps *ui_ops = NULL;
53 
54 /* Set the UI ops */
otrg_ui_set_ui_ops(const OtrgUiUiOps * ops)55 void otrg_ui_set_ui_ops(const OtrgUiUiOps *ops)
56 {
57     ui_ops = ops;
58 }
59 
60 /* Get the UI ops */
otrg_ui_get_ui_ops(void)61 const OtrgUiUiOps *otrg_ui_get_ui_ops(void)
62 {
63     return ui_ops;
64 }
65 
66 /* Initialize the OTR UI subsystem */
otrg_ui_init(void)67 void otrg_ui_init(void)
68 {
69     if (ui_ops != NULL) {
70 	ui_ops->init();
71     }
72 }
73 
74 /* Deinitialize the OTR UI subsystem */
otrg_ui_cleanup(void)75 void otrg_ui_cleanup(void)
76 {
77     if (ui_ops != NULL) {
78 	ui_ops->cleanup();
79     }
80 }
81 
82 /* Call this function when the DSA key is updated; it will redraw the
83  * UI, if visible. */
otrg_ui_update_fingerprint(void)84 void otrg_ui_update_fingerprint(void)
85 {
86     if (ui_ops != NULL) {
87 	ui_ops->update_fingerprint();
88     }
89 }
90 
91 /* Update the keylist, if it's visible */
otrg_ui_update_keylist(void)92 void otrg_ui_update_keylist(void)
93 {
94     if (ui_ops != NULL) {
95 	ui_ops->update_keylist();
96     }
97 }
98 
99 /* Send an OTR Query Message to attempt to start a connection */
otrg_ui_connect_connection(ConnContext * context)100 void otrg_ui_connect_connection(ConnContext *context)
101 {
102     /* Send an OTR Query to the other side. */
103     PurpleAccount *account;
104     char *msg;
105 
106     /* Don't do this if we're already ENCRYPTED */
107     if (context == NULL || context->msgstate == OTRL_MSGSTATE_ENCRYPTED)
108 	return;
109 
110     account = purple_accounts_find(context->accountname, context->protocol);
111     if (!account) {
112 	PurplePlugin *p = purple_find_prpl(context->protocol);
113 	msg = g_strdup_printf(_("Account %s (%s) could not be found"),
114 		context->accountname,
115 		(p && p->info->name) ? p->info->name : _("Unknown"));
116 	otrg_dialog_notify_error(context->accountname, context->protocol,
117 		context->username, _("Account not found"), msg, NULL);
118 	g_free(msg);
119 	return;
120     }
121     otrg_plugin_send_default_query(context, account);
122 }
123 
124 /* Drop a context to PLAINTEXT state */
otrg_ui_disconnect_connection(ConnContext * context)125 void otrg_ui_disconnect_connection(ConnContext *context)
126 {
127 
128     if (context == NULL)
129 	return;
130 
131     otrg_plugin_disconnect(context);
132     otrg_dialog_disconnected(context);
133 }
134 
135 /* Forget a fingerprint */
otrg_ui_forget_fingerprint(Fingerprint * fingerprint)136 void otrg_ui_forget_fingerprint(Fingerprint *fingerprint)
137 {
138     ConnContext *context;
139     ConnContext *context_iter;
140 
141     if (fingerprint == NULL) return;
142 
143     /* Don't do anything with the active fingerprint if we're in the
144      * ENCRYPTED state. */
145     context = fingerprint->context;
146 
147     for (context_iter = context->m_context;
148 	    context_iter && context_iter->m_context == context->m_context;
149 	    context_iter = context_iter->next) {
150 
151 	if (context_iter->msgstate == OTRL_MSGSTATE_ENCRYPTED &&
152 		context_iter->active_fingerprint == fingerprint) return;
153     }
154 
155     otrl_context_forget_fingerprint(fingerprint, 1);
156     otrg_plugin_write_fingerprints();
157 
158     otrg_ui_update_keylist();
159 }
160 
161 /* Configure OTR for a particular buddy */
otrg_ui_config_buddy(PurpleBuddy * buddy)162 void otrg_ui_config_buddy(PurpleBuddy *buddy)
163 {
164     if (ui_ops != NULL) {
165 	ui_ops->config_buddy(buddy);
166     }
167 }
168 
169 /* Load the preferences for a particular account / username */
otrg_ui_get_prefs(OtrgUiPrefs * prefsp,PurpleAccount * account,const char * name)170 void otrg_ui_get_prefs(OtrgUiPrefs *prefsp, PurpleAccount *account,
171 	const char *name)
172 {
173     /* Check to see if the protocol for this account supports OTR at all. */
174     const char *proto = purple_account_get_protocol_id(account);
175     if (!otrg_plugin_proto_supports_otr(proto)) {
176 	prefsp->policy = OTRL_POLICY_NEVER;
177 	prefsp->avoid_logging_otr = TRUE;
178 	prefsp->show_otr_button = FALSE;
179 	return;
180     }
181 
182     if (ui_ops != NULL) {
183 	ui_ops->get_prefs(prefsp, account, name);
184 	return;
185     }
186     /* If we've got no other way to get the prefs, use sensible defaults */
187     prefsp->policy = OTRL_POLICY_DEFAULT;
188     prefsp->avoid_logging_otr = TRUE;
189     prefsp->show_otr_button = FALSE;
190 }
191