Add dedicated method for parsing and opening URIs
This commit is contained in:
parent
6c6c4bdcfe
commit
dd7496d7a7
|
@ -285,13 +285,11 @@ def on_delete_motd(action, param):
|
|||
|
||||
|
||||
def on_contents(action, param):
|
||||
helpers.launch_browser_mailer(
|
||||
'url', 'https://dev.gajim.org/gajim/gajim/wikis')
|
||||
helpers.open_uri('https://dev.gajim.org/gajim/gajim/wikis')
|
||||
|
||||
|
||||
def on_faq(action, param):
|
||||
helpers.launch_browser_mailer(
|
||||
'url', 'https://dev.gajim.org/gajim/gajim/wikis/help/gajimfaq')
|
||||
helpers.open_uri('https://dev.gajim.org/gajim/gajim/wikis/help/gajimfaq')
|
||||
|
||||
|
||||
def on_keyboard_shortcuts(action, param):
|
||||
|
@ -351,8 +349,8 @@ def show_next_pending_event(action, param):
|
|||
|
||||
|
||||
def open_link(_action, param):
|
||||
kind, link = param.get_strv()
|
||||
helpers.launch_browser_mailer(kind, link)
|
||||
uri = param.get_string()
|
||||
helpers.open_uri(uri)
|
||||
|
||||
|
||||
def copy_text(_action, param):
|
||||
|
|
|
@ -420,7 +420,7 @@ class GajimApplication(Gtk.Application):
|
|||
act.connect("activate", app_actions.copy_text)
|
||||
self.add_action(act)
|
||||
|
||||
act = Gio.SimpleAction.new('open-link', GLib.VariantType.new('as'))
|
||||
act = Gio.SimpleAction.new('open-link', GLib.VariantType.new('s'))
|
||||
act.connect("activate", app_actions.open_link)
|
||||
self.add_action(act)
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ from gajim.common import ged
|
|||
from gajim.common import i18n
|
||||
from gajim.common.i18n import _
|
||||
from gajim.common.helpers import AdditionalDataDict
|
||||
from gajim.common.helpers import open_uri
|
||||
from gajim.common.contacts import GC_Contact
|
||||
from gajim.common.const import AvatarSize
|
||||
from gajim.common.const import KindConstant
|
||||
|
@ -651,7 +652,7 @@ class ChatControl(ChatControlBase):
|
|||
uri = 'https://www.openstreetmap.org/?' + \
|
||||
'mlat=%(lat)s&mlon=%(lon)s&zoom=16' % {'lat': location['lat'],
|
||||
'lon': location['lon']}
|
||||
helpers.launch_browser_mailer('url', uri)
|
||||
open_uri(uri)
|
||||
|
||||
def on_location_eventbox_leave_notify_event(self, widget, event):
|
||||
"""
|
||||
|
|
|
@ -167,9 +167,6 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
|
|||
if self.parent_win:
|
||||
self.parent_win.redraw_tab(self)
|
||||
|
||||
def status_url_clicked(self, widget, url):
|
||||
helpers.launch_browser_mailer('url', url)
|
||||
|
||||
def setup_seclabel(self):
|
||||
self.seclabel_combo.hide()
|
||||
self.seclabel_combo.set_no_show_all(True)
|
||||
|
|
|
@ -184,6 +184,22 @@ class Display(Enum):
|
|||
QUARTZ = 'GdkQuartzDisplay'
|
||||
|
||||
|
||||
class URIType(Enum):
|
||||
UNKNOWN = 'unknown'
|
||||
XMPP = 'xmpp'
|
||||
MAIL = 'mail'
|
||||
GEO = 'geo'
|
||||
WEB = 'web'
|
||||
FILE = 'file'
|
||||
AT = 'at'
|
||||
|
||||
|
||||
class URIAction(Enum):
|
||||
MESSAGE = 'message'
|
||||
JOIN = 'join'
|
||||
SUBSCRIBE = 'subscribe'
|
||||
|
||||
|
||||
EME_MESSAGES = {
|
||||
'urn:xmpp:otr:0':
|
||||
_('This message was encrypted with OTR '
|
||||
|
|
|
@ -65,6 +65,9 @@ from gajim.common.i18n import _
|
|||
from gajim.common.i18n import ngettext
|
||||
from gajim.common.const import ShowConstant
|
||||
from gajim.common.const import Display
|
||||
from gajim.common.const import URIType
|
||||
from gajim.common.const import URIAction
|
||||
from gajim.common.structs import URI
|
||||
|
||||
if app.is_installed('PYCURL'):
|
||||
import pycurl
|
||||
|
@ -629,35 +632,6 @@ def get_contact_dict_for_account(account):
|
|||
contacts_dict[name] = contact
|
||||
return contacts_dict
|
||||
|
||||
def launch_browser_mailer(kind, uri):
|
||||
# kind = 'url' or 'mail'
|
||||
if kind == 'url' and uri.startswith('file://'):
|
||||
launch_file_manager(uri)
|
||||
return
|
||||
if kind in ('mail', 'sth_at_sth') and not uri.startswith('mailto:'):
|
||||
uri = 'mailto:' + uri
|
||||
|
||||
if kind == 'url' and uri.startswith('www.'):
|
||||
uri = 'http://' + uri
|
||||
|
||||
if not app.config.get('autodetect_browser_mailer'):
|
||||
if kind == 'url':
|
||||
command = app.config.get('custombrowser')
|
||||
elif kind in ('mail', 'sth_at_sth'):
|
||||
command = app.config.get('custommailapp')
|
||||
if command == '': # if no app is configured
|
||||
return
|
||||
|
||||
command = build_command(command, uri)
|
||||
try:
|
||||
exec_command(command)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
else:
|
||||
webbrowser.open(uri)
|
||||
|
||||
|
||||
def launch_file_manager(path_to_open):
|
||||
if os.name == 'nt':
|
||||
try:
|
||||
|
@ -1502,3 +1476,92 @@ def delay_execution(milliseconds):
|
|||
milliseconds, timeout_wrapper)
|
||||
return func_wrapper
|
||||
return delay_execution_decorator
|
||||
|
||||
|
||||
def parse_uri(uri):
|
||||
if uri.startswith('xmpp:'):
|
||||
uri = uri[5:]
|
||||
if '?' in uri:
|
||||
jid, action = uri.split('?')
|
||||
try:
|
||||
return URI(type=URIType.XMPP,
|
||||
action=URIAction(action),
|
||||
data=jid)
|
||||
except ValueError:
|
||||
# Unknown action
|
||||
pass
|
||||
|
||||
return URI(type=URIType.XMPP, action=URIAction.MESSAGE, data=uri)
|
||||
|
||||
if uri.startswith('mailto:'):
|
||||
uri = uri[7:]
|
||||
return URI(type=URIType.MAIL, data=uri)
|
||||
|
||||
if app.interface.sth_at_sth_dot_sth_re.match(uri):
|
||||
return URI(type=URIType.AT, data=uri)
|
||||
|
||||
if uri.startswith('geo:'):
|
||||
location = uri[4:]
|
||||
lat, _, lon = location.partition(',')
|
||||
if not lon:
|
||||
return URI(type=URIType.UNKNOWN, data=uri)
|
||||
|
||||
uri = ('https://www.openstreetmap.org/?'
|
||||
'mlat=%s&mlon=%s&zoom=16') % (lat, lon)
|
||||
return URI(type=URIType.GEO, data=uri)
|
||||
|
||||
if uri.startswith('file://'):
|
||||
return URI(type=URIType.FILE, data=uri)
|
||||
|
||||
return URI(type=URIType.WEB, data=uri)
|
||||
|
||||
|
||||
def open_uri(uri, account=None):
|
||||
if not isinstance(uri, URI):
|
||||
uri = parse_uri(uri)
|
||||
|
||||
if uri.type == URIType.FILE:
|
||||
launch_file_manager(uri.data)
|
||||
|
||||
elif uri.type == URIType.MAIL:
|
||||
uri = 'mailto:%s' % uri.data
|
||||
if not app.config.get('autodetect_browser_mailer'):
|
||||
open_uri_with_custom('custommailapp', 'mailto:%s' % uri)
|
||||
else:
|
||||
webbrowser.open(uri)
|
||||
|
||||
elif uri.type in (URIType.WEB, URIType.GEO):
|
||||
if not app.config.get('autodetect_browser_mailer'):
|
||||
open_uri_with_custom('custombrowser', uri.data)
|
||||
else:
|
||||
webbrowser.open(uri.data)
|
||||
|
||||
elif uri.type == URIType.AT:
|
||||
app.interface.new_chat_from_jid(account, uri.data)
|
||||
|
||||
elif uri.type == URIType.XMPP:
|
||||
if account is None:
|
||||
log.warning('Account must be specified to open XMPP uri')
|
||||
return
|
||||
|
||||
if uri.action == URIAction.JOIN:
|
||||
app.interface.join_gc_minimal(account, uri.data)
|
||||
elif uri.action == URIAction.MESSAGE:
|
||||
app.interface.new_chat_from_jid(account, uri.data)
|
||||
else:
|
||||
log.warning('Cant open URI: %s', uri)
|
||||
|
||||
else:
|
||||
log.warning('Cant open URI: %s', uri)
|
||||
|
||||
|
||||
def open_uri_with_custom(config_app, uri):
|
||||
command = app.config.get(config_app)
|
||||
if not command:
|
||||
log.warning('No custom application set')
|
||||
return
|
||||
command = build_command(command, uri)
|
||||
try:
|
||||
exec_command(command)
|
||||
except Exception:
|
||||
pass
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# This file is part of Gajim.
|
||||
#
|
||||
# Gajim is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published
|
||||
# by the Free Software Foundation; version 3 only.
|
||||
#
|
||||
# Gajim is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
URI = namedtuple('URI', 'type action data')
|
||||
URI.__new__.__defaults__ = (None, None) # type: ignore
|
|
@ -518,7 +518,7 @@ class ConversationTextview(GObject.GObject):
|
|||
"""
|
||||
Basically it filters out the widget instance
|
||||
"""
|
||||
helpers.launch_browser_mailer('url', link)
|
||||
helpers.open_uri(link)
|
||||
|
||||
def on_textview_populate_popup(self, textview, menu):
|
||||
"""
|
||||
|
|
|
@ -55,7 +55,7 @@ from gajim.common.caps_cache import muc_caps_cache
|
|||
from gajim.common import events
|
||||
from gajim.common import app
|
||||
from gajim.common import helpers
|
||||
from gajim.common.helpers import launch_browser_mailer
|
||||
from gajim.common.helpers import open_uri
|
||||
from gajim.common.helpers import AdditionalDataDict
|
||||
from gajim.common import ged
|
||||
from gajim.common.i18n import _
|
||||
|
@ -3106,5 +3106,5 @@ class SubjectPopover(Gtk.Popover):
|
|||
def _on_activate_link(_label, uri):
|
||||
# We have to use this, because the default GTK handler
|
||||
# is not cross-platform compatible
|
||||
launch_browser_mailer(None, uri)
|
||||
open_uri(uri)
|
||||
return Gdk.EVENT_STOP
|
||||
|
|
|
@ -19,7 +19,7 @@ from gi.repository import Gtk
|
|||
from gi.repository import GObject
|
||||
|
||||
from gajim.common import app
|
||||
from gajim.common.helpers import launch_browser_mailer
|
||||
from gajim.common.helpers import open_uri
|
||||
from gajim.common.i18n import _
|
||||
from gajim.common.const import DEVS_CURRENT
|
||||
from gajim.common.const import DEVS_PAST
|
||||
|
@ -75,7 +75,7 @@ class AboutDialog(Gtk.AboutDialog):
|
|||
def _on_activate_link(_label, uri):
|
||||
# We have to use this, because the default GTK handler
|
||||
# is not cross-platform compatible
|
||||
launch_browser_mailer(None, uri)
|
||||
open_uri(uri)
|
||||
return Gdk.EVENT_STOP
|
||||
|
||||
def _connect_link_handler(self, parent):
|
||||
|
|
|
@ -21,7 +21,7 @@ from gajim.gtkgui_helpers import scale_pixbuf_from_data
|
|||
|
||||
from gajim.common import app
|
||||
from gajim.common.i18n import _
|
||||
from gajim.common.helpers import launch_browser_mailer
|
||||
from gajim.common.helpers import open_uri
|
||||
from gajim.common.modules.dataforms import extend_form
|
||||
|
||||
from gajim.gtk.util import MultiLineLabel
|
||||
|
@ -588,9 +588,7 @@ class FakeDataFormWidget(Gtk.ScrolledWindow):
|
|||
button = Gtk.Button(label='Register')
|
||||
button.set_halign(Gtk.Align.CENTER)
|
||||
button.get_style_context().add_class('suggested-action')
|
||||
button.connect('clicked',
|
||||
lambda *args: launch_browser_mailer('url',
|
||||
redirect_url))
|
||||
button.connect('clicked', lambda *args: open_uri(redirect_url))
|
||||
self._grid.attach(button, 0, self._row_count, 2, 1)
|
||||
else:
|
||||
self._add_fields()
|
||||
|
|
|
@ -49,6 +49,8 @@ from gajim.common import app
|
|||
from gajim.common import helpers
|
||||
from gajim.common.i18n import _
|
||||
from gajim.common.const import StyleAttr
|
||||
from gajim.common.helpers import open_uri
|
||||
from gajim.common.helpers import parse_uri
|
||||
from gajim.gtk.util import load_icon
|
||||
from gajim.gtk.util import get_cursor
|
||||
|
||||
|
@ -877,8 +879,8 @@ class HtmlTextView(Gtk.TextView):
|
|||
self._cursor_changed = False
|
||||
return False
|
||||
|
||||
def show_context_menu(self, _event, kind, text):
|
||||
menu = get_conv_context_menu(self.account, kind, text)
|
||||
def show_context_menu(self, uri):
|
||||
menu = get_conv_context_menu(self.account, uri)
|
||||
if menu is None:
|
||||
return
|
||||
|
||||
|
@ -904,53 +906,21 @@ class HtmlTextView(Gtk.TextView):
|
|||
|
||||
# Detect XHTML-IM link
|
||||
word = getattr(texttag, 'href', None)
|
||||
if word:
|
||||
if word.startswith('xmpp'):
|
||||
kind = 'xmpp'
|
||||
elif word.startswith('mailto:'):
|
||||
kind = 'mail'
|
||||
elif app.interface.sth_at_sth_dot_sth_re.match(word):
|
||||
# it's a JID or mail
|
||||
kind = 'sth_at_sth'
|
||||
else:
|
||||
if not word:
|
||||
word = self.get_buffer().get_text(begin_iter, end_iter, True)
|
||||
|
||||
uri = parse_uri(word)
|
||||
if event.button.button == 3: # right click
|
||||
self.show_context_menu(event, kind, word)
|
||||
self.show_context_menu(uri)
|
||||
return True
|
||||
|
||||
self.plugin_modified = False
|
||||
app.plugin_manager.extension_point(
|
||||
'hyperlink_handler', word, kind, self,
|
||||
self.get_toplevel())
|
||||
'hyperlink_handler', uri, self, self.get_toplevel())
|
||||
if self.plugin_modified:
|
||||
return
|
||||
|
||||
# we launch the correct application
|
||||
if kind == 'xmpp':
|
||||
word = word[5:]
|
||||
if '?' in word:
|
||||
(jid, action) = word.split('?')
|
||||
if action == 'join':
|
||||
app.interface.join_gc_minimal(self.account, jid)
|
||||
else:
|
||||
app.interface.new_chat_from_jid(self.account, jid)
|
||||
else:
|
||||
app.interface.new_chat_from_jid(self.account, word)
|
||||
|
||||
# handle geo:-URIs
|
||||
elif word[:4] == 'geo:':
|
||||
location = word[4:]
|
||||
lat, _, lon = location.partition(',')
|
||||
if lon == '':
|
||||
return
|
||||
uri = 'https://www.openstreetmap.org/?' \
|
||||
'mlat=%(lat)s&mlon=%(lon)s&zoom=16' % \
|
||||
{'lat': lat, 'lon': lon}
|
||||
helpers.launch_browser_mailer(kind, uri)
|
||||
else:
|
||||
# other URIs
|
||||
helpers.launch_browser_mailer(kind, word)
|
||||
open_uri(uri, account=self.account)
|
||||
|
||||
def display_html(self, html, textview, conv_textview, iter_=None):
|
||||
buffer_ = self.get_buffer()
|
||||
|
|
|
@ -1957,10 +1957,6 @@ class Interface:
|
|||
self.systray_enabled = False
|
||||
self.systray.hide_icon()
|
||||
|
||||
@staticmethod
|
||||
def on_launch_browser_mailer(widget, url, kind):
|
||||
helpers.launch_browser_mailer(kind, url)
|
||||
|
||||
def process_connections(self):
|
||||
"""
|
||||
Called each foo (200) milliseconds. Check for idlequeue timeouts
|
||||
|
@ -2381,11 +2377,6 @@ class Interface:
|
|||
app.config.get_per('accounts', account, 'active'):
|
||||
app.connections[account] = Connection(account)
|
||||
|
||||
# gtk hooks
|
||||
# Gtk.about_dialog_set_email_hook(self.on_launch_browser_mailer, 'mail')
|
||||
# Gtk.about_dialog_set_url_hook(self.on_launch_browser_mailer, 'url')
|
||||
# Gtk.link_button_set_uri_hook(self.on_launch_browser_mailer, 'url')
|
||||
|
||||
self.instances = {}
|
||||
|
||||
for a in app.connections:
|
||||
|
|
|
@ -25,6 +25,8 @@ from gajim.common import app
|
|||
from gajim.common import helpers
|
||||
from gajim.common.i18n import ngettext
|
||||
from gajim.common.i18n import _
|
||||
from gajim.common.const import URIType
|
||||
from gajim.common.const import URIAction
|
||||
|
||||
from gajim.gtk.util import get_builder
|
||||
|
||||
|
@ -918,9 +920,9 @@ def get_encryption_menu(control_id, type_id, zeroconf=False):
|
|||
return menu
|
||||
|
||||
|
||||
def get_conv_context_menu(account, kind, text):
|
||||
if kind == 'xmpp':
|
||||
if '?join' in text:
|
||||
def get_conv_context_menu(account, uri):
|
||||
if uri.type == URIType.XMPP:
|
||||
if uri.action == URIAction.JOIN:
|
||||
context_menu = [
|
||||
('copy-text', _('Copy JID')),
|
||||
('-join-groupchat', _('Join Groupchat')),
|
||||
|
@ -932,19 +934,25 @@ def get_conv_context_menu(account, kind, text):
|
|||
('-add-contact', _('Add to Roster…')),
|
||||
]
|
||||
|
||||
elif kind == 'url':
|
||||
elif uri.type == URIType.WEB:
|
||||
context_menu = [
|
||||
('copy-text', _('Copy Link Location')),
|
||||
('open-link', _('Open Link in Browser')),
|
||||
]
|
||||
|
||||
elif kind == 'mail':
|
||||
elif uri.type == URIType.MAIL:
|
||||
context_menu = [
|
||||
('copy-text', _('Copy Email Address')),
|
||||
('open-link', _('Open Email Composer')),
|
||||
]
|
||||
|
||||
elif kind == 'sth_at_sth':
|
||||
elif uri.type == URIType.GEO:
|
||||
context_menu = [
|
||||
('copy-text', _('Copy Location')),
|
||||
('open-link', _('Show Location')),
|
||||
]
|
||||
|
||||
elif uri.type == URIType.AT:
|
||||
context_menu = [
|
||||
('copy-text', _('Copy JID/Email')),
|
||||
('open-link', _('Open Email Composer')),
|
||||
|
@ -953,6 +961,7 @@ def get_conv_context_menu(account, kind, text):
|
|||
('-add-contact', _('Add to Roster…')),
|
||||
]
|
||||
else:
|
||||
log.warning('No handler for URI type: %s', uri)
|
||||
return
|
||||
|
||||
menu = Gtk.Menu()
|
||||
|
@ -962,19 +971,15 @@ def get_conv_context_menu(account, kind, text):
|
|||
menuitem.set_label(label)
|
||||
|
||||
if action.startswith('-'):
|
||||
text = text.replace('xmpp:', '')
|
||||
text = text.split('?')[0]
|
||||
action = 'app.%s%s' % (account, action)
|
||||
else:
|
||||
action = 'app.%s' % action
|
||||
menuitem.set_action_name(action)
|
||||
|
||||
if action == 'app.open-link':
|
||||
value = GLib.Variant.new_strv([kind, text])
|
||||
elif action == 'app.copy-text':
|
||||
value = GLib.Variant.new_string(text)
|
||||
if action in ('app.open-link', 'app.copy-text'):
|
||||
value = GLib.Variant.new_string(uri.data)
|
||||
else:
|
||||
value = GLib.Variant.new_strv([account, text])
|
||||
value = GLib.Variant.new_strv([account, uri.data])
|
||||
menuitem.set_action_target_value(value)
|
||||
menuitem.show()
|
||||
menu.append(menuitem)
|
||||
|
|
|
@ -32,7 +32,7 @@ from gi.repository import Gdk
|
|||
from gajim.common import app
|
||||
from gajim.common import configpaths
|
||||
from gajim.common.exceptions import PluginsystemError
|
||||
from gajim.common.helpers import launch_browser_mailer
|
||||
from gajim.common.helpers import open_uri
|
||||
|
||||
from gajim.plugins.helpers import log_calls
|
||||
from gajim.plugins.helpers import GajimPluginActivateException
|
||||
|
@ -250,7 +250,7 @@ class PluginsWindow:
|
|||
@log_calls('PluginsWindow')
|
||||
def on_install_plugin_button_clicked(self, widget):
|
||||
if app.is_flatpak():
|
||||
launch_browser_mailer('url', 'https://dev.gajim.org/gajim/gajim/wikis/help/flathub')
|
||||
open_uri('https://dev.gajim.org/gajim/gajim/wikis/help/flathub')
|
||||
return
|
||||
|
||||
def show_warn_dialog():
|
||||
|
|
Loading…
Reference in New Issue