Philipp Hörist pushed to branch master at gajim / gajim

Commits:

8 changed files:

Changes:

  • .gitlab/issue_templates/Release.md
    ... ... @@ -2,6 +2,7 @@
    2 2
     
    
    3 3
     ## Build
    
    4 4
     * [ ] Merge translations from Weblate
    
    5
    +* [ ] Update IANA data with `./scripts/get_iana_data.py gajim/common/iana.py`
    
    5 6
     * [ ] Run `./scripts/bump_version.py x.x.x`
    
    6 7
     * [ ] Push release tag `x.x.x`
    
    7 8
     
    

  • gajim/common/const.py
    ... ... @@ -944,97 +944,6 @@ def is_active(self):
    944 944
     GAJIM_WIKI_URI = 'https://dev.gajim.org/gajim/gajim/wikis'
    
    945 945
     GAJIM_SUPPORT_JID = 'gajim@conference.gajim.org'
    
    946 946
     
    
    947
    -URI_SCHEMES = {
    
    948
    -    'aaa://',
    
    949
    -    'aaas://',
    
    950
    -    'acap://',
    
    951
    -    'cap://',
    
    952
    -    'cid:',
    
    953
    -    'crid://',
    
    954
    -    'data:',
    
    955
    -    'dav:',
    
    956
    -    'dict://',
    
    957
    -    'dns:',
    
    958
    -    'fax:',
    
    959
    -    'file:/',
    
    960
    -    'ftp://',
    
    961
    -    'geo:',
    
    962
    -    'go:',
    
    963
    -    'gopher://',
    
    964
    -    'h323:',
    
    965
    -    'http://',
    
    966
    -    'https://',
    
    967
    -    'iax:',
    
    968
    -    'icap://',
    
    969
    -    'im:',
    
    970
    -    'imap://',
    
    971
    -    'info:',
    
    972
    -    'ipp://',
    
    973
    -    'iris:',
    
    974
    -    'iris.beep:',
    
    975
    -    'iris.xpc:',
    
    976
    -    'iris.xpcs:',
    
    977
    -    'iris.lwz:',
    
    978
    -    'ldap://',
    
    979
    -    'mailto:',
    
    980
    -    'mid:',
    
    981
    -    'modem:',
    
    982
    -    'msrp://',
    
    983
    -    'msrps://',
    
    984
    -    'mtqp://',
    
    985
    -    'mupdate://',
    
    986
    -    'news:',
    
    987
    -    'nfs://',
    
    988
    -    'nntp://',
    
    989
    -    'opaquelocktoken:',
    
    990
    -    'pop://',
    
    991
    -    'pres:',
    
    992
    -    'prospero://',
    
    993
    -    'rtsp://',
    
    994
    -    'service:',
    
    995
    -    'sip:',
    
    996
    -    'sips:',
    
    997
    -    'sms:',
    
    998
    -    'snmp://',
    
    999
    -    'soap.beep://',
    
    1000
    -    'soap.beeps://',
    
    1001
    -    'tag:',
    
    1002
    -    'tel:',
    
    1003
    -    'telnet://',
    
    1004
    -    'tftp://',
    
    1005
    -    'thismessage:/',
    
    1006
    -    'tip://',
    
    1007
    -    'tv:',
    
    1008
    -    'urn://',
    
    1009
    -    'vemmi://',
    
    1010
    -    'xmlrpc.beep://',
    
    1011
    -    'xmlrpc.beeps://',
    
    1012
    -    'xmpp:',
    
    1013
    -    'z39.50r://',
    
    1014
    -    'z39.50s://',
    
    1015
    -    'about:',
    
    1016
    -    'apt:',
    
    1017
    -    'cvs://',
    
    1018
    -    'daap://',
    
    1019
    -    'ed2k://',
    
    1020
    -    'feed:',
    
    1021
    -    'fish://',
    
    1022
    -    'git://',
    
    1023
    -    'iax2:',
    
    1024
    -    'irc://',
    
    1025
    -    'ircs://',
    
    1026
    -    'ldaps://',
    
    1027
    -    'magnet:',
    
    1028
    -    'mms://',
    
    1029
    -    'rsync://',
    
    1030
    -    'ssh://',
    
    1031
    -    'svn://',
    
    1032
    -    'sftp://',
    
    1033
    -    'smb://',
    
    1034
    -    'webcal://',
    
    1035
    -    'aesgcm://',
    
    1036
    -}
    
    1037
    -
    
    1038 947
     
    
    1039 948
     # This is an excerpt of Media Types from
    
    1040 949
     # https://www.iana.org/assignments/media-types/media-types.xhtml
    

  • gajim/common/helpers.py
    ... ... @@ -87,6 +87,7 @@
    87 87
     
    
    88 88
     from gajim.common import app
    
    89 89
     from gajim.common import configpaths
    
    90
    +from gajim.common import iana
    
    90 91
     from gajim.common.i18n import Q_
    
    91 92
     from gajim.common.i18n import _
    
    92 93
     from gajim.common.i18n import ngettext
    
    ... ... @@ -922,6 +923,12 @@ def func_wrapper(self, *args, **kwargs):
    922 923
         return func_wrapper
    
    923 924
     
    
    924 925
     
    
    926
    +def is_registered_uri_scheme(scheme: str) -> bool:
    
    927
    +    if scheme in iana.URI_SCHEMES:
    
    928
    +        return True
    
    929
    +    return scheme in app.settings.get('additional_uri_schemes').split()
    
    930
    +
    
    931
    +
    
    925 932
     def parse_xmpp_uri_query(pct_iquerycomp: str) -> tuple[str, dict[str, str]]:
    
    926 933
         '''
    
    927 934
         Parses 'mess%61ge;b%6Fdy=Hello%20%F0%9F%8C%90%EF%B8%8F' into
    
    ... ... @@ -959,6 +966,9 @@ def parse_uri(uri: str) -> URI:
    959 966
     
    
    960 967
         scheme = urlparts.scheme  # urlparse is expected to return it in lower case
    
    961 968
     
    
    969
    +    if not is_registered_uri_scheme(scheme):
    
    970
    +        return URI(URIType.INVALID, uri, data={'error': 'Unregistered scheme'})
    
    971
    +
    
    962 972
         if scheme in ('https', 'http'):
    
    963 973
             if not urlparts.netloc:
    
    964 974
                 err = f'No host or empty host in an {scheme} URI'
    

  • gajim/common/iana.py
    1
    +# Generated by get_iana_data.py @ 2022-11-30T19:55:30.680829
    
    2
    +
    
    3
    +URI_SCHEMES = {
    
    4
    +    'aaa',
    
    5
    +    'aaas',
    
    6
    +    'about',
    
    7
    +    'acap',
    
    8
    +    'acct',
    
    9
    +    'acd',
    
    10
    +    'acr',
    
    11
    +    'adiumxtra',
    
    12
    +    'adt',
    
    13
    +    'afp',
    
    14
    +    'afs',
    
    15
    +    'aim',
    
    16
    +    'amss',
    
    17
    +    'android',
    
    18
    +    'appdata',
    
    19
    +    'apt',
    
    20
    +    'ar',
    
    21
    +    'ark',
    
    22
    +    'attachment',
    
    23
    +    'aw',
    
    24
    +    'barion',
    
    25
    +    'bb',
    
    26
    +    'beshare',
    
    27
    +    'bitcoin',
    
    28
    +    'bitcoincash',
    
    29
    +    'blob',
    
    30
    +    'bolo',
    
    31
    +    'browserext',
    
    32
    +    'cabal',
    
    33
    +    'calculator',
    
    34
    +    'callto',
    
    35
    +    'cap',
    
    36
    +    'cast',
    
    37
    +    'casts',
    
    38
    +    'chrome',
    
    39
    +    'chrome-extension',
    
    40
    +    'cid',
    
    41
    +    'coap',
    
    42
    +    'coap+tcp',
    
    43
    +    'coap+ws',
    
    44
    +    'coaps',
    
    45
    +    'coaps+tcp',
    
    46
    +    'coaps+ws',
    
    47
    +    'com-eventbrite-attendee',
    
    48
    +    'content',
    
    49
    +    'content-type',
    
    50
    +    'crid',
    
    51
    +    'cstr',
    
    52
    +    'cvs',
    
    53
    +    'dab',
    
    54
    +    'dat',
    
    55
    +    'data',
    
    56
    +    'dav',
    
    57
    +    'diaspora',
    
    58
    +    'dict',
    
    59
    +    'did',
    
    60
    +    'dis',
    
    61
    +    'dlna-playcontainer',
    
    62
    +    'dlna-playsingle',
    
    63
    +    'dns',
    
    64
    +    'dntp',
    
    65
    +    'doi',
    
    66
    +    'dpp',
    
    67
    +    'drm',
    
    68
    +    'drop',
    
    69
    +    'dtmi',
    
    70
    +    'dtn',
    
    71
    +    'dvb',
    
    72
    +    'dvx',
    
    73
    +    'dweb',
    
    74
    +    'ed2k',
    
    75
    +    'eid',
    
    76
    +    'elsi',
    
    77
    +    'embedded',
    
    78
    +    'ens',
    
    79
    +    'ethereum',
    
    80
    +    'example',
    
    81
    +    'facetime',
    
    82
    +    'fax',
    
    83
    +    'feed',
    
    84
    +    'feedready',
    
    85
    +    'fido',
    
    86
    +    'file',
    
    87
    +    'filesystem',
    
    88
    +    'finger',
    
    89
    +    'first-run-pen-experience',
    
    90
    +    'fish',
    
    91
    +    'fm',
    
    92
    +    'ftp',
    
    93
    +    'fuchsia-pkg',
    
    94
    +    'geo',
    
    95
    +    'gg',
    
    96
    +    'git',
    
    97
    +    'gitoid',
    
    98
    +    'gizmoproject',
    
    99
    +    'go',
    
    100
    +    'gopher',
    
    101
    +    'graph',
    
    102
    +    'grd',
    
    103
    +    'gtalk',
    
    104
    +    'h323',
    
    105
    +    'ham',
    
    106
    +    'hcap',
    
    107
    +    'hcp',
    
    108
    +    'http',
    
    109
    +    'https',
    
    110
    +    'hxxp',
    
    111
    +    'hxxps',
    
    112
    +    'hydrazone',
    
    113
    +    'hyper',
    
    114
    +    'iax',
    
    115
    +    'icap',
    
    116
    +    'icon',
    
    117
    +    'im',
    
    118
    +    'imap',
    
    119
    +    'info',
    
    120
    +    'iotdisco',
    
    121
    +    'ipfs',
    
    122
    +    'ipn',
    
    123
    +    'ipns',
    
    124
    +    'ipp',
    
    125
    +    'ipps',
    
    126
    +    'irc',
    
    127
    +    'irc6',
    
    128
    +    'ircs',
    
    129
    +    'iris',
    
    130
    +    'iris.beep',
    
    131
    +    'iris.lwz',
    
    132
    +    'iris.xpc',
    
    133
    +    'iris.xpcs',
    
    134
    +    'isostore',
    
    135
    +    'itms',
    
    136
    +    'jabber',
    
    137
    +    'jar',
    
    138
    +    'jms',
    
    139
    +    'keyparc',
    
    140
    +    'lastfm',
    
    141
    +    'lbry',
    
    142
    +    'ldap',
    
    143
    +    'ldaps',
    
    144
    +    'leaptofrogans',
    
    145
    +    'lorawan',
    
    146
    +    'lpa',
    
    147
    +    'lvlt',
    
    148
    +    'magnet',
    
    149
    +    'mailserver',
    
    150
    +    'mailto',
    
    151
    +    'maps',
    
    152
    +    'market',
    
    153
    +    'matrix',
    
    154
    +    'message',
    
    155
    +    'microsoft.windows.camera',
    
    156
    +    'microsoft.windows.camera.multipicker',
    
    157
    +    'microsoft.windows.camera.picker',
    
    158
    +    'mid',
    
    159
    +    'mms',
    
    160
    +    'modem',
    
    161
    +    'mongodb',
    
    162
    +    'moz',
    
    163
    +    'ms-access',
    
    164
    +    'ms-appinstaller',
    
    165
    +    'ms-browser-extension',
    
    166
    +    'ms-calculator',
    
    167
    +    'ms-drive-to',
    
    168
    +    'ms-enrollment',
    
    169
    +    'ms-excel',
    
    170
    +    'ms-eyecontrolspeech',
    
    171
    +    'ms-gamebarservices',
    
    172
    +    'ms-gamingoverlay',
    
    173
    +    'ms-getoffice',
    
    174
    +    'ms-help',
    
    175
    +    'ms-infopath',
    
    176
    +    'ms-inputapp',
    
    177
    +    'ms-lockscreencomponent-config',
    
    178
    +    'ms-media-stream-id',
    
    179
    +    'ms-meetnow',
    
    180
    +    'ms-mixedrealitycapture',
    
    181
    +    'ms-mobileplans',
    
    182
    +    'ms-newsandinterests',
    
    183
    +    'ms-officeapp',
    
    184
    +    'ms-people',
    
    185
    +    'ms-project',
    
    186
    +    'ms-powerpoint',
    
    187
    +    'ms-publisher',
    
    188
    +    'ms-restoretabcompanion',
    
    189
    +    'ms-screenclip',
    
    190
    +    'ms-screensketch',
    
    191
    +    'ms-search',
    
    192
    +    'ms-search-repair',
    
    193
    +    'ms-secondary-screen-controller',
    
    194
    +    'ms-secondary-screen-setup',
    
    195
    +    'ms-settings',
    
    196
    +    'ms-settings-airplanemode',
    
    197
    +    'ms-settings-bluetooth',
    
    198
    +    'ms-settings-camera',
    
    199
    +    'ms-settings-cellular',
    
    200
    +    'ms-settings-cloudstorage',
    
    201
    +    'ms-settings-connectabledevices',
    
    202
    +    'ms-settings-displays-topology',
    
    203
    +    'ms-settings-emailandaccounts',
    
    204
    +    'ms-settings-language',
    
    205
    +    'ms-settings-location',
    
    206
    +    'ms-settings-lock',
    
    207
    +    'ms-settings-nfctransactions',
    
    208
    +    'ms-settings-notifications',
    
    209
    +    'ms-settings-power',
    
    210
    +    'ms-settings-privacy',
    
    211
    +    'ms-settings-proximity',
    
    212
    +    'ms-settings-screenrotation',
    
    213
    +    'ms-settings-wifi',
    
    214
    +    'ms-settings-workplace',
    
    215
    +    'ms-spd',
    
    216
    +    'ms-stickers',
    
    217
    +    'ms-sttoverlay',
    
    218
    +    'ms-transit-to',
    
    219
    +    'ms-useractivityset',
    
    220
    +    'ms-virtualtouchpad',
    
    221
    +    'ms-visio',
    
    222
    +    'ms-walk-to',
    
    223
    +    'ms-whiteboard',
    
    224
    +    'ms-whiteboard-cmd',
    
    225
    +    'ms-word',
    
    226
    +    'msnim',
    
    227
    +    'msrp',
    
    228
    +    'msrps',
    
    229
    +    'mss',
    
    230
    +    'mt',
    
    231
    +    'mtqp',
    
    232
    +    'mumble',
    
    233
    +    'mupdate',
    
    234
    +    'mvn',
    
    235
    +    'news',
    
    236
    +    'nfs',
    
    237
    +    'ni',
    
    238
    +    'nih',
    
    239
    +    'nntp',
    
    240
    +    'notes',
    
    241
    +    'num',
    
    242
    +    'ocf',
    
    243
    +    'oid',
    
    244
    +    'onenote',
    
    245
    +    'onenote-cmd',
    
    246
    +    'opaquelocktoken',
    
    247
    +    'openpgp4fpr',
    
    248
    +    'otpauth',
    
    249
    +    'p1',
    
    250
    +    'pack',
    
    251
    +    'palm',
    
    252
    +    'paparazzi',
    
    253
    +    'payment',
    
    254
    +    'payto',
    
    255
    +    'pkcs11',
    
    256
    +    'platform',
    
    257
    +    'pop',
    
    258
    +    'pres',
    
    259
    +    'prospero',
    
    260
    +    'proxy',
    
    261
    +    'pwid',
    
    262
    +    'psyc',
    
    263
    +    'pttp',
    
    264
    +    'qb',
    
    265
    +    'query',
    
    266
    +    'quic-transport',
    
    267
    +    'redis',
    
    268
    +    'rediss',
    
    269
    +    'reload',
    
    270
    +    'res',
    
    271
    +    'resource',
    
    272
    +    'rmi',
    
    273
    +    'rsync',
    
    274
    +    'rtmfp',
    
    275
    +    'rtmp',
    
    276
    +    'rtsp',
    
    277
    +    'rtsps',
    
    278
    +    'rtspu',
    
    279
    +    'sarif',
    
    280
    +    'secondlife',
    
    281
    +    'secret-token',
    
    282
    +    'service',
    
    283
    +    'session',
    
    284
    +    'sftp',
    
    285
    +    'sgn',
    
    286
    +    'shc',
    
    287
    +    'shttp',
    
    288
    +    'sieve',
    
    289
    +    'simpleledger',
    
    290
    +    'simplex',
    
    291
    +    'sip',
    
    292
    +    'sips',
    
    293
    +    'skype',
    
    294
    +    'smb',
    
    295
    +    'smp',
    
    296
    +    'sms',
    
    297
    +    'smtp',
    
    298
    +    'snews',
    
    299
    +    'snmp',
    
    300
    +    'soap.beep',
    
    301
    +    'soap.beeps',
    
    302
    +    'soldat',
    
    303
    +    'spiffe',
    
    304
    +    'spotify',
    
    305
    +    'ssb',
    
    306
    +    'ssh',
    
    307
    +    'steam',
    
    308
    +    'stun',
    
    309
    +    'stuns',
    
    310
    +    'submit',
    
    311
    +    'svn',
    
    312
    +    'swh',
    
    313
    +    'swid',
    
    314
    +    'swidpath',
    
    315
    +    'tag',
    
    316
    +    'taler',
    
    317
    +    'teamspeak',
    
    318
    +    'tel',
    
    319
    +    'teliaeid',
    
    320
    +    'telnet',
    
    321
    +    'tftp',
    
    322
    +    'things',
    
    323
    +    'thismessage',
    
    324
    +    'tip',
    
    325
    +    'tn3270',
    
    326
    +    'tool',
    
    327
    +    'turn',
    
    328
    +    'turns',
    
    329
    +    'tv',
    
    330
    +    'udp',
    
    331
    +    'unreal',
    
    332
    +    'upt',
    
    333
    +    'urn',
    
    334
    +    'ut2004',
    
    335
    +    'uuid-in-package',
    
    336
    +    'v-event',
    
    337
    +    'vemmi',
    
    338
    +    'ventrilo',
    
    339
    +    'ves',
    
    340
    +    'videotex',
    
    341
    +    'vnc',
    
    342
    +    'view-source',
    
    343
    +    'vscode',
    
    344
    +    'vscode-insiders',
    
    345
    +    'vsls',
    
    346
    +    'w3',
    
    347
    +    'wais',
    
    348
    +    'web3',
    
    349
    +    'wcr',
    
    350
    +    'webcal',
    
    351
    +    'wifi',
    
    352
    +    'wpid',
    
    353
    +    'ws',
    
    354
    +    'wss',
    
    355
    +    'wtai',
    
    356
    +    'wyciwyg',
    
    357
    +    'xcon',
    
    358
    +    'xcon-userid',
    
    359
    +    'xfire',
    
    360
    +    'xmlrpc.beep',
    
    361
    +    'xmlrpc.beeps',
    
    362
    +    'xmpp',
    
    363
    +    'xri',
    
    364
    +    'ymsgr',
    
    365
    +    'z39.50',
    
    366
    +    'z39.50r',
    
    367
    +    'z39.50s',
    
    368
    +}

  • gajim/common/setting_values.py
    ... ... @@ -36,6 +36,7 @@ class _ACCOUNT_DEFAULT:
    36 36
     
    
    37 37
     
    
    38 38
     BoolSettings = Literal[
    
    39
    +    'additional_uri_schemes',
    
    39 40
         'allow_open_file_uris',
    
    40 41
         'always_english_wikipedia',
    
    41 42
         'always_english_wiktionary',
    
    ... ... @@ -164,6 +165,7 @@ class _ACCOUNT_DEFAULT:
    164 165
     AllSettingsT = Union[str, int, bool, list[str]]
    
    165 166
     
    
    166 167
     APP_SETTINGS = {
    
    168
    +    'additional_uri_schemes': '',
    
    167 169
         'allow_open_file_uris': False,
    
    168 170
         'always_english_wikipedia': False,
    
    169 171
         'always_english_wiktionary': True,
    
    ... ... @@ -628,6 +630,9 @@ class WorkspaceSettings(TypedDict):
    628 630
     
    
    629 631
     ADVANCED_SETTINGS = {
    
    630 632
         'app': {
    
    633
    +        'additional_uri_schemes': _(
    
    634
    +            'Clickable schemes in addition to the hard-coded list of '
    
    635
    +            'IANA-registered ones. Space-separated, lower-case, no colons.'),
    
    631 636
             'allow_open_file_uris': _('Allows opening file:/ URIs when clicked.'),
    
    632 637
             'always_english_wikipedia': '',
    
    633 638
             'always_english_wiktionary': '',
    

  • gajim/common/styling.py
    ... ... @@ -50,7 +50,8 @@
    50 50
     BLOCK_NESTED_RX = re.compile(PRE_NESTED_RX + '|' + QUOTE_RX, re.S | re.M)
    
    51 51
     UNQUOTE_RX = re.compile(r'^> |^>', re.M)
    
    52 52
     
    
    53
    -URI_OR_JID_RX = re.compile(fr'(?P<uri>{regex.IRI})|(?P<jid>{regex.XMPP.jid})')
    
    53
    +URI_OR_JID_RX = re.compile(
    
    54
    +    fr'(?P<uri>(?<![\w+.-]){regex.IRI})|(?P<jid>{regex.XMPP.jid})')
    
    54 55
     
    
    55 56
     EMOJI_RX = emoji_data.get_regex()
    
    56 57
     EMOJI_RX = re.compile(EMOJI_RX)
    

  • scripts/get_iana_data.py
    1
    +#!/usr/bin/env python3
    
    2
    +
    
    3
    +import argparse
    
    4
    +from datetime import datetime
    
    5
    +from urllib.request import urlopen
    
    6
    +import csv
    
    7
    +import io
    
    8
    +import logging
    
    9
    +from pathlib import Path
    
    10
    +import re
    
    11
    +import sys
    
    12
    +
    
    13
    +
    
    14
    +SCHEMES_URL = 'https://www.iana.org/assignments/uri-schemes/uri-schemes-1.csv'
    
    15
    +
    
    16
    +logging.basicConfig(level='INFO', format='%(levelname)s: %(message)s')
    
    17
    +
    
    18
    +
    
    19
    +def download_file(url: str) -> str:
    
    20
    +    logging.info('Download: %s', url)
    
    21
    +    with urlopen(url) as f:
    
    22
    +        content = f.read()
    
    23
    +    return content.decode()
    
    24
    +
    
    25
    +
    
    26
    +def parse_uri_schemes(content: str) -> list[str]:
    
    27
    +    logging.info('Parse uri schemes')
    
    28
    +    schemes: list[str] = []
    
    29
    +
    
    30
    +    reader = csv.reader(io.StringIO(content), delimiter=',')
    
    31
    +    next(reader)  # Skip header row
    
    32
    +    for line in reader:
    
    33
    +        scheme = line[0].lower().removesuffix(' (obsolete)')
    
    34
    +        if not re.fullmatch('[a-z0-9+.-]+', scheme):
    
    35
    +            logging.warning('unexpected scheme field contents: %s', scheme)
    
    36
    +            continue
    
    37
    +
    
    38
    +        schemes.append(scheme)
    
    39
    +
    
    40
    +    return schemes
    
    41
    +
    
    42
    +
    
    43
    +def generate_output(schemes: list[str],
    
    44
    +                    out_path: Path):
    
    45
    +
    
    46
    +    logging.info('Generate output')
    
    47
    +    current_date = datetime.utcnow().isoformat()
    
    48
    +    content = f'# Generated by get_iana_data.py @ {current_date}\n'
    
    49
    +
    
    50
    +    content += '\n'
    
    51
    +
    
    52
    +    content += 'URI_SCHEMES = {\n'
    
    53
    +    for scheme in schemes:
    
    54
    +        content += f"    '{scheme}',\n"
    
    55
    +    content += '}\n'
    
    56
    +
    
    57
    +    outpath.write_text(content)
    
    58
    +    logging.info('Wrote file to %s', outpath)
    
    59
    +
    
    60
    +
    
    61
    +if __name__ == '__main__':
    
    62
    +    parser = argparse.ArgumentParser(description='Generate IANA data')
    
    63
    +    parser.add_argument('out', help='Path to output file')
    
    64
    +    args = parser.parse_args()
    
    65
    +
    
    66
    +    outpath = Path(args.out)
    
    67
    +    if outpath.is_dir():
    
    68
    +        sys.exit('Output path is a directory')
    
    69
    +
    
    70
    +    scheme_content = download_file(SCHEMES_URL)
    
    71
    +    schemes = parse_uri_schemes(scheme_content)
    
    72
    +    output = generate_output(schemes,
    
    73
    +                             outpath)
    
    74
    +    logging.info('Finished !')

  • test/no_gui/test_styling.py
    1 1
     import unittest
    
    2
    +from unittest.mock import MagicMock
    
    2 3
     
    
    3 4
     from gajim import gui
    
    4 5
     gui.init('gtk')
    
    ... ... @@ -17,6 +18,10 @@
    17 18
     from gajim.common.text_helpers import jid_to_iri
    
    18 19
     
    
    19 20
     
    
    21
    +app.settings = MagicMock()
    
    22
    +app.settings.get.return_value = 'a a- a. scheme'  # additional_uri_schemes
    
    23
    +
    
    24
    +
    
    20 25
     STYLING = {
    
    21 26
         'pre cannot have children':  {
    
    22 27
             'input': '_no pre `with *children*`_',
    
    ... ... @@ -384,6 +389,14 @@
    384 389
         ' ',
    
    385 390
         '.',
    
    386 391
         ':',
    
    392
    +    '://',
    
    393
    +    'Böblingen:🌥',
    
    394
    +    'Bo\u0308blingen:🌥',  # finds blingen:🌥 but rejects an unregistered scheme
    
    395
    +    'path/to/file_na.me:123',
    
    396
    +    '_sche.me:body_',
    
    397
    +    '_sche+me:body_',
    
    398
    +    '.scheme:body',
    
    399
    +    '+scheme:body',
    
    387 400
     
    
    388 401
         # These are from https://mathiasbynens.be/demo/url-regex
    
    389 402
         '//',
    
    ... ... @@ -391,10 +404,6 @@
    391 404
         '///a',
    
    392 405
         '///',
    
    393 406
         'foo.com',
    
    394
    -    'http://foo.bar?q=Spaces should be encoded',
    
    395
    -    'http:// shouldfail.com',
    
    396
    -    ':// should fail',
    
    397
    -    'http://foo.bar/foo(bar)baz quux',
    
    398 407
     ]
    
    399 408
     
    
    400 409
     
    
    ... ... @@ -427,6 +436,8 @@
    427 436
         'file:a',
    
    428 437
         'file:a/',
    
    429 438
         'file:a/b',
    
    439
    +
    
    440
    +    'mailtomailto:foo@bar.com.uk',
    
    430 441
     ]
    
    431 442
     
    
    432 443
     
    
    ... ... @@ -484,7 +495,6 @@
    484 495
     
    
    485 496
         # These are from https://rfc-editor.org/rfc/rfc7622#section-3.5
    
    486 497
         '"juliet"@example.com',
    
    487
    -    'foo bar@example.com',  # search is expected to find 'bar@example.com'
    
    488 498
         '@example.com',
    
    489 499
         'henryⅣ@example.com',  # localpart has a compatibility-decomposable cp
    
    490 500
         '♚@example.com',        # localpart has a symbol cp
    
    ... ... @@ -495,13 +505,14 @@
    495 505
     URIS_WITH_TEXT = [
    
    496 506
         ('write to my email mailto:foo@bar.com.uk (but not to mailto:bar@foo.com)',
    
    497 507
          ['mailto:foo@bar.com.uk', 'mailto:bar@foo.com']),
    
    498
    -    ('write to my email mailtomailto:foo@bar.com.uk (but not to mailto:bar@foo.com)',
    
    499
    -     ['mailtomailto:foo@bar.com.uk', 'mailto:bar@foo.com']),
    
    500 508
         ('see this http://userid@example.com/ link', ['http://userid@example.com/']),
    
    501 509
         ('see this http://userid@example.com/, and ..', ['http://userid@example.com/']),
    
    502 510
         ('<http://userid@example.com/>', ['http://userid@example.com/']),
    
    503 511
         ('"http://userid@example.com/"', ['http://userid@example.com/']),
    
    504 512
         ('regexes are useless (see https://en.wikipedia.org/wiki/Recursion_(computer_science)), but comfy', ['https://en.wikipedia.org/wiki/Recursion_(computer_science)']),
    
    513
    +    ('(scheme:body)', ['scheme:body']),
    
    514
    +    ('/scheme:body', ['scheme:body']),
    
    515
    +    ('!scheme:body', ['scheme:body']),
    
    505 516
     ]
    
    506 517
     
    
    507 518
     
    
    ... ... @@ -519,41 +530,32 @@ def test_uris(self):
    519 530
             for uri in URIS:
    
    520 531
                 text = self.wrap(uri)
    
    521 532
                 hlinks = process_uris(text)
    
    522
    -            self.assertEqual(len(hlinks), 1, text)
    
    523
    -            self.assertEqual(hlinks[0].uri, uri, text)
    
    533
    +            self.assertEqual([l.uri for l in hlinks], [uri], text)
    
    524 534
     
    
    525 535
         def test_invalid_uris(self):
    
    526 536
             for foo in NONURIS + UNACCEPTABLE_URIS:
    
    527 537
                 text = self.wrap(foo)
    
    528 538
                 hlinks = process_uris(text)
    
    529
    -            if len(hlinks) == 0:
    
    530
    -                continue
    
    531
    -            self.assertEqual(len(hlinks), 1, text)
    
    532
    -            self.assertNotEqual(hlinks[0].text, foo, text)
    
    539
    +            self.assertEqual([l.text for l in hlinks], [], text)
    
    533 540
     
    
    534 541
         def test_jids(self):
    
    535 542
             for jid in JIDS:
    
    536 543
                 text = self.wrap(jid)
    
    544
    +            uri = jid_to_iri(jid)
    
    537 545
                 hlinks = process_uris(text)
    
    538
    -            self.assertEqual(len(hlinks), 1, text)
    
    539
    -            self.assertEqual(hlinks[0].text, jid, text)
    
    540
    -            self.assertEqual(hlinks[0].uri, jid_to_iri(jid), text)
    
    546
    +            self.assertEqual([(l.text, l.uri) for l in hlinks],
    
    547
    +                             [(jid, uri)], text)
    
    541 548
     
    
    542 549
         def test_nonjids(self):
    
    543 550
             for foo in NONJIDS:
    
    544 551
                 text = self.wrap(foo)
    
    545 552
                 hlinks = process_uris(text)
    
    546
    -            if len(hlinks) == 0:
    
    547
    -                continue
    
    548
    -            self.assertEqual(len(hlinks), 1, text)
    
    549
    -            self.assertNotEqual(hlinks[0].text, foo, text)
    
    553
    +            self.assertEqual([l.text for l in hlinks], [], text)
    
    550 554
     
    
    551 555
         def test_uris_with_text(self):
    
    552
    -        for text, result in URIS_WITH_TEXT:
    
    556
    +        for text, results in URIS_WITH_TEXT:
    
    553 557
                 hlinks = process_uris(text)
    
    554
    -            self.assertEqual(len(hlinks), len(result), text)
    
    555
    -            for i, res in enumerate(result):
    
    556
    -                self.assertEqual(hlinks[i].text, res, text)
    
    558
    +            self.assertEqual([l.text for l in hlinks], results, text)
    
    557 559
     
    
    558 560
     
    
    559 561
     if __name__ == "__main__":