| | 255 | |
| | 256 | from common.xmpp import Message as XmppMessage |
| | 257 | |
| | 258 | try: |
| | 259 | import otr, otr_windows |
| | 260 | |
| | 261 | gajim.otr_module = otr |
| | 262 | gajim.otr_windows = otr_windows |
| | 263 | except ImportError: |
| | 264 | gajim.otr_module = None |
| | 265 | gajim.otr_windows = None |
| | 266 | |
| | 267 | def add_appdata(data=None, context=None): |
| | 268 | account = data |
| | 269 | context.app_data = otr_windows.ContactOtrSMPWindow(unicode(context.username), |
| | 270 | account) |
| | 271 | |
| | 272 | gajim.otr_add_appdata = add_appdata |
| | 273 | |
| | 274 | |
| | 275 | def otr_dialog_destroy(widget, *args, **kwargs): |
| | 276 | widget.destroy() |
| | 277 | |
| | 278 | class OtrlMessageAppOps: |
| | 279 | |
| | 280 | def gajim_log(self, msg, account, fjid, no_print=False): |
| | 281 | if not isinstance(fjid, unicode): |
| | 282 | fjid = unicode(fjid) |
| | 283 | if not isinstance(account, unicode): |
| | 284 | account = unicode(account) |
| | 285 | resource=gajim.get_resource_from_jid(fjid) |
| | 286 | tim = time.localtime() |
| | 287 | |
| | 288 | if not no_print: |
| | 289 | ctrl = gajim.interface.msg_win_mgr.get_control( |
| | 290 | gajim.get_jid_without_resource(fjid), account) |
| | 291 | if ctrl: |
| | 292 | ctrl.print_conversation_line(u" [OTR] %s"%msg, 'status', '', None) |
| | 293 | id = gajim.logger.write('chat_msg_recv', fjid, message=msg, tim=tim) |
| | 294 | gajim.logger.set_read_messages([id]) |
| | 295 | |
| | 296 | def policy(self, opdata=None, context=None): |
| | 297 | policy = gajim.config.get_per("contacts", |
| | 298 | gajim.get_jid_without_resource(context.username), "otr_flags") |
| | 299 | if policy <= 0: |
| | 300 | policy = gajim.config.get_per("accounts", opdata['account'], "otr_flags") |
| | 301 | return policy |
| | 302 | |
| | 303 | def create_privkey(self, opdata="", accountname="", protocol=""): |
| | 304 | dialog = gtk.Dialog(title=_("Generating..."), parent=gajim.interface.roster.window, |
| | 305 | flags=gtk.DIALOG_MODAL, buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)) |
| | 306 | permlabel = gtk.Label("Generating a private key for %s..."%accountname) |
| | 307 | permlabel.set_padding(20,20) |
| | 308 | dialog.set_response_sensitive(gtk.RESPONSE_CLOSE, False) |
| | 309 | dialog.connect("destroy", otr_dialog_destroy) |
| | 310 | dialog.connect("response", otr_dialog_destroy) |
| | 311 | dialog.vbox.pack_start(permlabel) |
| | 312 | dialog.get_root_window().raise_() |
| | 313 | dialog.show_all() |
| | 314 | dialog.map() |
| | 315 | for c in dialog.get_children(): |
| | 316 | c.show_now() |
| | 317 | c.map() |
| | 318 | |
| | 319 | while gtk.events_pending(): |
| | 320 | gtk.main_iteration(block=False) |
| | 321 | |
| | 322 | otr.otrl_privkey_generate(gajim.otr_userstates[opdata['account']], |
| | 323 | os.path.join(gajimpaths.root, "%s.key"%opdata['account']).encode(), |
| | 324 | accountname, gajim.OTR_PROTO) |
| | 325 | permlabel.set_text("Generating a private key for %s...\ndone."%accountname) |
| | 326 | dialog.set_response_sensitive(gtk.RESPONSE_CLOSE, True) |
| | 327 | |
| | 328 | def is_logged_in(self, opdata={}, accountname="", protocol="", recipient=""): |
| | 329 | return gajim.contacts.get_contact_from_full_jid(opdata['account'], recipient).show \ |
| | 330 | in ['dnd', 'xa', 'chat', 'online', 'away', 'invisible'] |
| | 331 | |
| | 332 | def inject_message(self, opdata=None, accountname="", protocol="", recipient="", |
| | 333 | message=""): |
| | 334 | msg_type = otr.otrl_proto_message_type(message) |
| | 335 | |
| | 336 | if 'kwargs' not in opdata or 'urgent' in opdata: |
| | 337 | # don't use send_message here to have the message sent immediatly. |
| | 338 | # this results in being able to disconnect from OTR sessions before |
| | 339 | # quitting |
| | 340 | stanza = XmppMessage(to=recipient, body=message, typ="chat") |
| | 341 | gajim.connections[opdata['account']].connection.send(stanza, now=True) |
| | 342 | return |
| | 343 | |
| | 344 | if msg_type == otr.OTRL_MSGTYPE_QUERY: |
| | 345 | # split away XHTML-contaminated explanatory message |
| | 346 | message = unicode(message.splitlines()[0]) |
| | 347 | message += u"\n%s has requested an Off-the-Record private " \ |
| | 348 | "conversation. However, you do not have a plugin to " \ |
| | 349 | "support that.\nSee http://otr.cypherpunks.ca/ for more "\ |
| | 350 | "information."%gajim.get_jid_from_account(opdata['account']) |
| | 351 | |
| | 352 | gajim.connections[opdata['account']].send_message(recipient, message, |
| | 353 | **opdata['kwargs']) |
| | 354 | |
| | 355 | def notify(sef, opdata=None, username="", **kwargs): |
| | 356 | self.gajim_log("Notify: "+str(kwargs), opdata['account'], username) |
| | 357 | |
| | 358 | def display_otr_message(self, opdata=None, username="", msg="", **kwargs): |
| | 359 | self.gajim_log("OTR Message: "+msg, opdata['account'], username) |
| | 360 | return 0 |
| | 361 | |
| | 362 | def update_context_list(self, **kwargs): |
| | 363 | # FIXME stub FIXME # |
| | 364 | pass |
| | 365 | |
| | 366 | def protocol_name(self, opdata=None, protocol=""): |
| | 367 | return "XMPP" |
| | 368 | |
| | 369 | def new_fingerprint(self, opdata=None, username="", fingerprint="", **kwargs): |
| | 370 | self.gajim_log("New fingerprint for %s: %s"%(username, |
| | 371 | otr.otrl_privkey_hash_to_human(fingerprint)), opdata['account'], username) |
| | 372 | |
| | 373 | def write_fingerprints(self, opdata=""): |
| | 374 | otr.otrl_privkey_write_fingerprints(gajim.otr_userstates[opdata['account']], |
| | 375 | os.path.join(gajimpaths.root, "%s.fpr"%opdata['account']).encode()) |
| | 376 | |
| | 377 | def gone_secure(self, opdata="", context=None): |
| | 378 | trust = context.active_fingerprint.trust |
| | 379 | if trust: |
| | 380 | trust = "verified" |
| | 381 | else: |
| | 382 | trust = "unverified" |
| | 383 | self.gajim_log("%s secured OTR connection started"%trust, |
| | 384 | opdata['account'], context.username, no_print=True) |
| | 385 | |
| | 386 | ctrl = gajim.interface.msg_win_mgr.get_control( |
| | 387 | gajim.get_jid_without_resource(unicode(context.username)), |
| | 388 | opdata['account']) |
| | 389 | if ctrl: |
| | 390 | ctrl.update_otr(True) |
| | 391 | |
| | 392 | def gone_insecure(self, opdata="", context=None): |
| | 393 | self.gajim_log("Private conversation with %s lost.", opdata['account'], context.username) |
| | 394 | |
| | 395 | ctrl = gajim.interface.msg_win_mgr.get_control( |
| | 396 | gajim.get_jid_without_resource(unicode(context.username)), |
| | 397 | opdata['account']) |
| | 398 | if ctrl: |
| | 399 | ctrl.update_otr() |
| | 400 | |
| | 401 | def still_secure(self, opdata=None, context=None, is_reply=0): |
| | 402 | ctrl = gajim.interface.msg_win_mgr.get_control( |
| | 403 | gajim.get_jid_without_resource(unicode(context.username)), |
| | 404 | opdata['account']) |
| | 405 | if ctrl: |
| | 406 | ctrl.update_otr(True) |
| | 407 | |
| | 408 | self.gajim_log("OTR connection was refreshed", opdata['account'], |
| | 409 | context.username) |
| | 410 | |
| | 411 | def log_message(self, opdata=None, message=""): |
| | 412 | gajim.log.debug(message) |
| | 413 | |
| | 414 | def max_message_size(self, **kwargs): |
| | 415 | return 0 |
| | 416 | |
| | 417 | def account_name(self, opdata=None, account="",protocol=""): |
| | 418 | return gajim.get_name_from_jid(opdata['account'], unicode(account)) |
| | 419 | |
| | 420 | gajim.otr_ui_ops = OtrlMessageAppOps() |