1from enum import IntEnum, Enum, unique
2from collections import namedtuple
3
4from gi.repository import Gio
5
6from nbxmpp.namespaces import Namespace
7
8from gajim.common.i18n import _
9from gajim.common.i18n import Q_
10
11EncryptionData = namedtuple('EncryptionData', 'additional_data')
12EncryptionData.__new__.__defaults__ = (None,)  # type: ignore
13
14Entity = namedtuple('Entity', 'jid node hash method')
15
16
17class AvatarSize(IntEnum):
18    TAB = 16
19    ROSTER = 32
20    CHAT = 48
21    NOTIFICATION = 48
22    GROUP_INFO = 100
23    TOOLTIP = 125
24    VCARD = 200
25    PUBLISH = 200
26
27
28class ArchiveState(IntEnum):
29    NEVER = 0
30    ALL = 1
31
32
33@unique
34class PathLocation(IntEnum):
35    CONFIG = 0
36    CACHE = 1
37    DATA = 2
38
39
40@unique
41class PathType(IntEnum):
42    FILE = 0
43    FOLDER = 1
44    FOLDER_OPTIONAL = 2
45
46
47@unique
48class KindConstant(IntEnum):
49    STATUS = 0
50    GCSTATUS = 1
51    GC_MSG = 2
52    SINGLE_MSG_RECV = 3
53    CHAT_MSG_RECV = 4
54    SINGLE_MSG_SENT = 5
55    CHAT_MSG_SENT = 6
56    ERROR = 7
57
58    def __str__(self):
59        return str(self.value)
60
61
62@unique
63class ShowConstant(IntEnum):
64    ONLINE = 0
65    CHAT = 1
66    AWAY = 2
67    XA = 3
68    DND = 4
69    OFFLINE = 5
70
71
72@unique
73class TypeConstant(IntEnum):
74    AIM = 0
75    GG = 1
76    HTTP_WS = 2
77    ICQ = 3
78    MSN = 4
79    QQ = 5
80    SMS = 6
81    SMTP = 7
82    TLEN = 8
83    YAHOO = 9
84    NEWMAIL = 10
85    RSS = 11
86    WEATHER = 12
87    MRIM = 13
88    NO_TRANSPORT = 14
89
90
91@unique
92class SubscriptionConstant(IntEnum):
93    NONE = 0
94    TO = 1
95    FROM = 2
96    BOTH = 3
97
98
99@unique
100class JIDConstant(IntEnum):
101    NORMAL_TYPE = 0
102    ROOM_TYPE = 1
103
104@unique
105class StyleAttr(Enum):
106    COLOR = 'color'
107    BACKGROUND = 'background'
108    FONT = 'font'
109
110@unique
111class CSSPriority(IntEnum):
112    APPLICATION = 600
113    APPLICATION_DARK = 601
114    DEFAULT_THEME = 610
115    DEFAULT_THEME_DARK = 611
116    USER_THEME = 650
117
118@unique
119class ButtonAction(Enum):
120    DESTRUCTIVE = 'destructive-action'
121    SUGGESTED = 'suggested-action'
122
123@unique
124class IdleState(Enum):
125    UNKNOWN = 'unknown'
126    XA = 'xa'
127    AWAY = 'away'
128    AWAKE = 'online'
129
130
131@unique
132class PEPEventType(IntEnum):
133    ABSTRACT = 0
134    ACTIVITY = 1
135    TUNE = 2
136    MOOD = 3
137    LOCATION = 4
138    NICKNAME = 5
139    AVATAR = 6
140    ATOM = 7
141    BOOKMARKS = 8
142
143
144@unique
145class Chatstate(IntEnum):
146    COMPOSING = 0
147    PAUSED = 1
148    ACTIVE = 2
149    INACTIVE = 3
150    GONE = 4
151
152    def __str__(self):
153        return self.name.lower()
154
155
156class SyncThreshold(IntEnum):
157    NO_SYNC = -1
158    NO_THRESHOLD = 0
159
160    def __str__(self):
161        return str(self.value)
162
163
164class MUCUser(IntEnum):
165    JID = 0
166    NICK = 1
167    REASON = 1
168    NICK_OR_REASON = 1
169    ROLE = 2
170    AFFILIATION = 3
171    AFFILIATION_TEXT = 4
172
173
174@unique
175class Trust(IntEnum):
176    UNTRUSTED = 0
177    UNDECIDED = 1
178    BLIND = 2
179    VERIFIED = 3
180
181
182class Display(Enum):
183    X11 = 'X11Display'
184    WAYLAND = 'GdkWaylandDisplay'
185    WIN32 = 'GdkWin32Display'
186    QUARTZ = 'GdkQuartzDisplay'
187
188
189class URIType(Enum):
190    UNKNOWN = 'unknown'
191    XMPP = 'xmpp'
192    MAIL = 'mail'
193    GEO = 'geo'
194    WEB = 'web'
195    FILE = 'file'
196    AT = 'at'
197    TEL = 'tel'
198
199
200class URIAction(Enum):
201    MESSAGE = 'message'
202    JOIN = 'join'
203    SUBSCRIBE = 'subscribe'
204
205
206class MUCJoinedState(Enum):
207    JOINED = 'joined'
208    NOT_JOINED = 'not joined'
209    JOINING = 'joining'
210    CREATING = 'creating'
211    CAPTCHA_REQUEST = 'captcha in progress'
212    CAPTCHA_FAILED = 'captcha failed'
213
214    def __str__(self):
215        return self.name
216
217    @property
218    def is_joined(self):
219        return self == MUCJoinedState.JOINED
220
221    @property
222    def is_not_joined(self):
223        return self == MUCJoinedState.NOT_JOINED
224
225    @property
226    def is_joining(self):
227        return self == MUCJoinedState.JOINING
228
229    @property
230    def is_creating(self):
231        return self == MUCJoinedState.CREATING
232
233    @property
234    def is_captcha_request(self):
235        return self == MUCJoinedState.CAPTCHA_REQUEST
236
237    @property
238    def is_captcha_failed(self):
239        return self == MUCJoinedState.CAPTCHA_FAILED
240
241
242class ClientState(IntEnum):
243    DISCONNECTING = 0
244    DISCONNECTED = 1
245    RECONNECT_SCHEDULED = 2
246    CONNECTING = 3
247    CONNECTED = 4
248    AVAILABLE = 5
249
250    @property
251    def is_disconnecting(self):
252        return self == ClientState.DISCONNECTING
253
254    @property
255    def is_disconnected(self):
256        return self == ClientState.DISCONNECTED
257
258    @property
259    def is_reconnect_scheduled(self):
260        return self == ClientState.RECONNECT_SCHEDULED
261
262    @property
263    def is_connecting(self):
264        return self == ClientState.CONNECTING
265
266    @property
267    def is_connected(self):
268        return self == ClientState.CONNECTED
269
270    @property
271    def is_available(self):
272        return self == ClientState.AVAILABLE
273
274
275class JingleState(Enum):
276    NULL = 'stop'
277    CONNECTING = 'connecting'
278    CONNECTION_RECEIVED = 'connection_received'
279    CONNECTED = 'connected'
280    ERROR = 'error'
281
282    def __str__(self):
283        return self.value
284
285
286MUC_CREATION_EXAMPLES = [
287    (Q_('?Group chat name:Team'),
288     Q_('?Group chat description:Project discussion'),
289     Q_('?Group chat address:team')),
290    (Q_('?Group chat name:Family'),
291     Q_('?Group chat description:Spring gathering'),
292     Q_('?Group chat address:family')),
293    (Q_('?Group chat name:Vacation'),
294     Q_('?Group chat description:Trip planning'),
295     Q_('?Group chat address:vacation')),
296    (Q_('?Group chat name:Repairs'),
297     Q_('?Group chat description:Local help group'),
298     Q_('?Group chat address:repairs')),
299    (Q_('?Group chat name:News'),
300     Q_('?Group chat description:Local news and reports'),
301     Q_('?Group chat address:news')),
302]
303
304
305MUC_DISCO_ERRORS = {
306    'remote-server-not-found': _('Remote server not found'),
307    'remote-server-timeout': _('Remote server timeout'),
308    'service-unavailable': _('Address does not belong to a group chat server'),
309    'subscription-required': _('Address does not belong to a group chat server'),
310    'not-muc-service': _('Address does not belong to a group chat server'),
311    'already-exists': _('Group chat already exists'),
312    'item-not-found': _('Group chat does not exist'),
313    'gone': _('Group chat is closed'),
314}
315
316
317EME_MESSAGES = {
318    'urn:xmpp:otr:0':
319        _('This message was encrypted with OTR '
320          'and could not be decrypted.'),
321    'jabber:x:encrypted':
322        _('This message was encrypted with Legacy '
323          'OpenPGP and could not be decrypted. You can install '
324          'the PGP plugin to handle those messages.'),
325    'urn:xmpp:openpgp:0':
326        _('This message was encrypted with '
327          'OpenPGP for XMPP and could not be decrypted. You can install '
328          'the OpenPGP plugin to handle those messages.'),
329    'fallback':
330        _('This message was encrypted with %s '
331          'and could not be decrypted.')
332}
333
334
335ACTIVITIES = {
336    'doing_chores': {
337        'category': _('Doing Chores'),
338        'buying_groceries': _('Buying Groceries'),
339        'cleaning': _('Cleaning'),
340        'cooking': _('Cooking'),
341        'doing_maintenance': _('Doing Maintenance'),
342        'doing_the_dishes': _('Doing the Dishes'),
343        'doing_the_laundry': _('Doing the Laundry'),
344        'gardening': _('Gardening'),
345        'running_an_errand': _('Running an Errand'),
346        'walking_the_dog': _('Walking the Dog')},
347    'drinking': {
348        'category': _('Drinking'),
349        'having_a_beer': _('Having a Beer'),
350        'having_coffee': _('Having Coffee'),
351        'having_tea': _('Having Tea')},
352    'eating': {
353        'category': _('Eating'),
354        'having_a_snack': _('Having a Snack'),
355        'having_breakfast': _('Having Breakfast'),
356        'having_dinner': _('Having Dinner'),
357        'having_lunch': _('Having Lunch')},
358    'exercising': {
359        'category': _('Exercising'),
360        'cycling': _('Cycling'),
361        'dancing': _('Dancing'),
362        'hiking': _('Hiking'),
363        'jogging': _('Jogging'),
364        'playing_sports': _('Playing Sports'),
365        'running': _('Running'),
366        'skiing': _('Skiing'),
367        'swimming': _('Swimming'),
368        'working_out': _('Working out')},
369    'grooming': {
370        'category': _('Grooming'),
371        'at_the_spa': _('At the Spa'),
372        'brushing_teeth': _('Brushing Teeth'),
373        'getting_a_haircut': _('Getting a Haircut'),
374        'shaving': _('Shaving'),
375        'taking_a_bath': _('Taking a Bath'),
376        'taking_a_shower': _('Taking a Shower')},
377    'having_appointment': {
378        'category': _('Having an Appointment')},
379    'inactive': {
380        'category': _('Inactive'),
381        'day_off': _('Day Off'),
382        'hanging_out': _('Hanging out'),
383        'hiding': _('Hiding'),
384        'on_vacation': _('On Vacation'),
385        'praying': _('Praying'),
386        'scheduled_holiday': _('Scheduled Holiday'),
387        'sleeping': _('Sleeping'),
388        'thinking': _('Thinking')},
389    'relaxing': {
390        'category': _('Relaxing'),
391        'fishing': _('Fishing'),
392        'gaming': _('Gaming'),
393        'going_out': _('Going out'),
394        'partying': _('Partying'),
395        'reading': _('Reading'),
396        'rehearsing': _('Rehearsing'),
397        'shopping': _('Shopping'),
398        'smoking': _('Smoking'),
399        'socializing': _('Socializing'),
400        'sunbathing': _('Sunbathing'),
401        'watching_tv': _('Watching TV'),
402        'watching_a_movie': _('Watching a Movie')},
403    'talking': {
404        'category': _('Talking'),
405        'in_real_life': _('In Real Life'),
406        'on_the_phone': _('On the Phone'),
407        'on_video_phone': _('On Video Phone')},
408    'traveling': {
409        'category': _('Traveling'),
410        'commuting': _('Commuting'),
411        'cycling': _('Cycling'),
412        'driving': _('Driving'),
413        'in_a_car': _('In a Car'),
414        'on_a_bus': _('On a Bus'),
415        'on_a_plane': _('On a Plane'),
416        'on_a_train': _('On a Train'),
417        'on_a_trip': _('On a Trip'),
418        'walking': _('Walking')},
419    'working': {
420        'category': _('Working'),
421        'coding': _('Coding'),
422        'in_a_meeting': _('In a Meeting'),
423        'studying': _('Studying'),
424        'writing': _('Writing')}}
425
426MOODS = {
427    'afraid': _('Afraid'),
428    'amazed': _('Amazed'),
429    'amorous': _('Amorous'),
430    'angry': _('Angry'),
431    'annoyed': _('Annoyed'),
432    'anxious': _('Anxious'),
433    'aroused': _('Aroused'),
434    'ashamed': _('Ashamed'),
435    'bored': _('Bored'),
436    'brave': _('Brave'),
437    'calm': _('Calm'),
438    'cautious': _('Cautious'),
439    'cold': _('Cold'),
440    'confident': _('Confident'),
441    'confused': _('Confused'),
442    'contemplative': _('Contemplative'),
443    'contented': _('Contented'),
444    'cranky': _('Cranky'),
445    'crazy': _('Crazy'),
446    'creative': _('Creative'),
447    'curious': _('Curious'),
448    'dejected': _('Dejected'),
449    'depressed': _('Depressed'),
450    'disappointed': _('Disappointed'),
451    'disgusted': _('Disgusted'),
452    'dismayed': _('Dismayed'),
453    'distracted': _('Distracted'),
454    'embarrassed': _('Embarrassed'),
455    'envious': _('Envious'),
456    'excited': _('Excited'),
457    'flirtatious': _('Flirtatious'),
458    'frustrated': _('Frustrated'),
459    'grateful': _('Grateful'),
460    'grieving': _('Grieving'),
461    'grumpy': _('Grumpy'),
462    'guilty': _('Guilty'),
463    'happy': _('Happy'),
464    'hopeful': _('Hopeful'),
465    'hot': _('Hot'),
466    'humbled': _('Humbled'),
467    'humiliated': _('Humiliated'),
468    'hungry': _('Hungry'),
469    'hurt': _('Hurt'),
470    'impressed': _('Impressed'),
471    'in_awe': _('In Awe'),
472    'in_love': _('In Love'),
473    'indignant': _('Indignant'),
474    'interested': _('Interested'),
475    'intoxicated': _('Intoxicated'),
476    'invincible': _('Invincible'),
477    'jealous': _('Jealous'),
478    'lonely': _('Lonely'),
479    'lost': _('Lost'),
480    'lucky': _('Lucky'),
481    'mean': _('Mean'),
482    'moody': _('Moody'),
483    'nervous': _('Nervous'),
484    'neutral': _('Neutral'),
485    'offended': _('Offended'),
486    'outraged': _('Outraged'),
487    'playful': _('Playful'),
488    'proud': _('Proud'),
489    'relaxed': _('Relaxed'),
490    'relieved': _('Relieved'),
491    'remorseful': _('Remorseful'),
492    'restless': _('Restless'),
493    'sad': _('Sad'),
494    'sarcastic': _('Sarcastic'),
495    'satisfied': _('Satisfied'),
496    'serious': _('Serious'),
497    'shocked': _('Shocked'),
498    'shy': _('Shy'),
499    'sick': _('Sick'),
500    'sleepy': _('Sleepy'),
501    'spontaneous': _('Spontaneous'),
502    'stressed': _('Stressed'),
503    'strong': _('Strong'),
504    'surprised': _('Surprised'),
505    'thankful': _('Thankful'),
506    'thirsty': _('Thirsty'),
507    'tired': _('Tired'),
508    'undefined': _('Undefined'),
509    'weak': _('Weak'),
510    'worried': _('Worried')
511}
512
513LOCATION_DATA = {
514    'accuracy': _('accuracy'),
515    'alt': _('alt'),
516    'area': _('area'),
517    'bearing': _('bearing'),
518    'building': _('building'),
519    'country': _('country'),
520    'countrycode': _('countrycode'),
521    'datum': _('datum'),
522    'description': _('description'),
523    'error': _('error'),
524    'floor': _('floor'),
525    'lat': _('lat'),
526    'locality': _('locality'),
527    'lon': _('lon'),
528    'postalcode': _('postalcode'),
529    'region': _('region'),
530    'room': _('room'),
531    'speed': _('speed'),
532    'street': _('street'),
533    'text': _('text'),
534    'timestamp': _('timestamp'),
535    'uri': _('URI')
536}
537
538
539SSLError = {
540    2: _("Unable to get issuer certificate"),
541    3: _("Unable to get certificate CRL"),
542    4: _("Unable to decrypt certificate's signature"),
543    5: _("Unable to decrypt CRL's signature"),
544    6: _("Unable to decode issuer public key"),
545    7: _("Certificate signature failure"),
546    8: _("CRL signature failure"),
547    9: _("Certificate is not yet valid"),
548    10: _("Certificate has expired"),
549    11: _("CRL is not yet valid"),
550    12: _("CRL has expired"),
551    13: _("Format error in certificate's notBefore field"),
552    14: _("Format error in certificate's notAfter field"),
553    15: _("Format error in CRL's lastUpdate field"),
554    16: _("Format error in CRL's nextUpdate field"),
555    17: _("Out of memory"),
556    18: _("Self signed certificate"),
557    19: _("Self signed certificate in certificate chain"),
558    20: _("Unable to get local issuer certificate"),
559    21: _("Unable to verify the first certificate"),
560    22: _("Certificate chain too long"),
561    23: _("Certificate revoked"),
562    24: _("Invalid CA certificate"),
563    25: _("Path length constraint exceeded"),
564    26: _("Unsupported certificate purpose"),
565    27: _("Certificate not trusted"),
566    28: _("Certificate rejected"),
567    29: _("Subject issuer mismatch"),
568    30: _("Authority and subject key identifier mismatch"),
569    31: _("Authority and issuer serial number mismatch"),
570    32: _("Key usage does not include certificate signing"),
571    50: _("Application verification failure"),
572}
573
574
575THANKS = u"""\
576Alexander Futász
577Alexander V. Butenko
578Alexey Nezhdanov
579Alfredo Junix
580Anaël Verrier
581Anders Ström
582Andrew Sayman
583Anton Shmigirilov
584Christian Bjälevik
585Christophe Got
586Christoph Neuroth
587David Campey
588Dennis Craven
589Fabian Neumann
590Filippos Papadopoulos
591Francisco Alburquerque Parra (Membris Khan)
592Frederic Lory
593Fridtjof Bussefor
594Geobert Quach
595Guillaume Morin
596Gustavo J. A. M. Carneiro
597Ivo Anjo
598Josef Vybíral
599Juraj Michalek
600Kjell Braden
601Luis Peralta
602Michael Scherer
603Michele Campeotto
604Mike Albon
605Miguel Fonseca
606Norman Rasmussen
607Oscar Hellström
608Peter Saint-Andre
609Petr Menšík
610Sergey Kuleshov
611Stavros Giannouris
612Stian B. Barmen
613Thilo Molitor
614Thomas Klein-Hitpaß
615Urtzi Alfaro
616Witold Kieraś
617Yakov Bezrukov
618Yavor Doganov
619""".strip().split("\n")
620
621ARTISTS = u"""\
622Anders Ström
623Christophe Got
624Dennis Craven
625Dmitry Korzhevin
626Guillaume Morin
627Gvorcek Spajreh
628Josef Vybíral
629Membris Khan
630Rederick Asher
631Jakub Szypulka
632""".strip().split("\n")
633
634DEVS_CURRENT = u"""\
635Yann Leboulanger (asterix AT lagaule.org)
636Philipp Hörist (philipp AT hoerist.com)
637Daniel Brötzmann (wurstsalat AT posteo.de)
638André Apitzsch
639""".strip().split("\n")
640
641DEVS_PAST = u"""\
642Stefan Bethge (stefan AT lanpartei.de)
643Alexander Cherniuk (ts33kr AT gmail.com)
644Stephan Erb (steve-e AT h3c.de)
645Vincent Hanquez (tab AT snarc.org)
646Dimitur Kirov (dkirov AT gmail.com)
647Nikos Kouremenos (kourem AT gmail.com)
648Julien Pivotto (roidelapluie AT gmail.com)
649Jonathan Schleifer (js-gajim AT webkeks.org)
650Travis Shirk (travis AT pobox.com)
651Brendan Taylor (whateley AT gmail.com)
652Jean-Marie Traissard (jim AT lapin.org)
653""".strip().split("\n")
654
655
656RFC5646_LANGUAGE_TAGS = {
657    'af': 'Afrikaans',
658    'af-ZA': 'Afrikaans (South Africa)',
659    'ar': 'Arabic',
660    'ar-AE': 'Arabic (U.A.E.)',
661    'ar-BH': 'Arabic (Bahrain)',
662    'ar-DZ': 'Arabic (Algeria)',
663    'ar-EG': 'Arabic (Egypt)',
664    'ar-IQ': 'Arabic (Iraq)',
665    'ar-JO': 'Arabic (Jordan)',
666    'ar-KW': 'Arabic (Kuwait)',
667    'ar-LB': 'Arabic (Lebanon)',
668    'ar-LY': 'Arabic (Libya)',
669    'ar-MA': 'Arabic (Morocco)',
670    'ar-OM': 'Arabic (Oman)',
671    'ar-QA': 'Arabic (Qatar)',
672    'ar-SA': 'Arabic (Saudi Arabia)',
673    'ar-SY': 'Arabic (Syria)',
674    'ar-TN': 'Arabic (Tunisia)',
675    'ar-YE': 'Arabic (Yemen)',
676    'az': 'Azeri (Latin)',
677    'az-AZ': 'Azeri (Latin) (Azerbaijan)',
678    'az-Cyrl-AZ': 'Azeri (Cyrillic) (Azerbaijan)',
679    'be': 'Belarusian',
680    'be-BY': 'Belarusian (Belarus)',
681    'bg': 'Bulgarian',
682    'bg-BG': 'Bulgarian (Bulgaria)',
683    'bs-BA': 'Bosnian (Bosnia and Herzegovina)',
684    'ca': 'Catalan',
685    'ca-ES': 'Catalan (Spain)',
686    'cs': 'Czech',
687    'cs-CZ': 'Czech (Czech Republic)',
688    'cy': 'Welsh',
689    'cy-GB': 'Welsh (United Kingdom)',
690    'da': 'Danish',
691    'da-DK': 'Danish (Denmark)',
692    'de': 'German',
693    'de-AT': 'German (Austria)',
694    'de-CH': 'German (Switzerland)',
695    'de-DE': 'German (Germany)',
696    'de-LI': 'German (Liechtenstein)',
697    'de-LU': 'German (Luxembourg)',
698    'dv': 'Divehi',
699    'dv-MV': 'Divehi (Maldives)',
700    'el': 'Greek',
701    'el-GR': 'Greek (Greece)',
702    'en': 'English',
703    'en-AU': 'English (Australia)',
704    'en-BZ': 'English (Belize)',
705    'en-CA': 'English (Canada)',
706    'en-CB': 'English (Caribbean)',
707    'en-GB': 'English (United Kingdom)',
708    'en-IE': 'English (Ireland)',
709    'en-JM': 'English (Jamaica)',
710    'en-NZ': 'English (New Zealand)',
711    'en-PH': 'English (Republic of the Philippines)',
712    'en-TT': 'English (Trinidad and Tobago)',
713    'en-US': 'English (United States)',
714    'en-ZA': 'English (South Africa)',
715    'en-ZW': 'English (Zimbabwe)',
716    'eo': 'Esperanto',
717    'es': 'Spanish',
718    'es-AR': 'Spanish (Argentina)',
719    'es-BO': 'Spanish (Bolivia)',
720    'es-CL': 'Spanish (Chile)',
721    'es-CO': 'Spanish (Colombia)',
722    'es-CR': 'Spanish (Costa Rica)',
723    'es-DO': 'Spanish (Dominican Republic)',
724    'es-EC': 'Spanish (Ecuador)',
725    'es-ES': 'Spanish (Spain)',
726    'es-GT': 'Spanish (Guatemala)',
727    'es-HN': 'Spanish (Honduras)',
728    'es-MX': 'Spanish (Mexico)',
729    'es-NI': 'Spanish (Nicaragua)',
730    'es-PA': 'Spanish (Panama)',
731    'es-PE': 'Spanish (Peru)',
732    'es-PR': 'Spanish (Puerto Rico)',
733    'es-PY': 'Spanish (Paraguay)',
734    'es-SV': 'Spanish (El Salvador)',
735    'es-UY': 'Spanish (Uruguay)',
736    'es-VE': 'Spanish (Venezuela)',
737    'et': 'Estonian',
738    'et-EE': 'Estonian (Estonia)',
739    'eu': 'Basque',
740    'eu-ES': 'Basque (Spain)',
741    'fa': 'Farsi',
742    'fa-IR': 'Farsi (Iran)',
743    'fi': 'Finnish',
744    'fi-FI': 'Finnish (Finland)',
745    'fo': 'Faroese',
746    'fo-FO': 'Faroese (Faroe Islands)',
747    'fr': 'French',
748    'fr-BE': 'French (Belgium)',
749    'fr-CA': 'French (Canada)',
750    'fr-CH': 'French (Switzerland)',
751    'fr-FR': 'French (France)',
752    'fr-LU': 'French (Luxembourg)',
753    'fr-MC': 'French (Principality of Monaco)',
754    'gl': 'Galician',
755    'gl-ES': 'Galician (Spain)',
756    'gu': 'Gujarati',
757    'gu-IN': 'Gujarati (India)',
758    'he': 'Hebrew',
759    'he-IL': 'Hebrew (Israel)',
760    'hi': 'Hindi',
761    'hi-IN': 'Hindi (India)',
762    'hr': 'Croatian',
763    'hr-BA': 'Croatian (Bosnia and Herzegovina)',
764    'hr-HR': 'Croatian (Croatia)',
765    'hu': 'Hungarian',
766    'hu-HU': 'Hungarian (Hungary)',
767    'hy': 'Armenian',
768    'hy-AM': 'Armenian (Armenia)',
769    'id': 'Indonesian',
770    'id-ID': 'Indonesian (Indonesia)',
771    'is': 'Icelandic',
772    'is-IS': 'Icelandic (Iceland)',
773    'it': 'Italian',
774    'it-CH': 'Italian (Switzerland)',
775    'it-IT': 'Italian (Italy)',
776    'ja': 'Japanese',
777    'ja-JP': 'Japanese (Japan)',
778    'ka': 'Georgian',
779    'ka-GE': 'Georgian (Georgia)',
780    'kk': 'Kazakh',
781    'kk-KZ': 'Kazakh (Kazakhstan)',
782    'kn': 'Kannada',
783    'kn-IN': 'Kannada (India)',
784    'ko': 'Korean',
785    'ko-KR': 'Korean (Korea)',
786    'kok': 'Konkani',
787    'kok-IN': 'Konkani (India)',
788    'ky': 'Kyrgyz',
789    'ky-KG': 'Kyrgyz (Kyrgyzstan)',
790    'lt': 'Lithuanian',
791    'lt-LT': 'Lithuanian (Lithuania)',
792    'lv': 'Latvian',
793    'lv-LV': 'Latvian (Latvia)',
794    'mi': 'Maori',
795    'mi-NZ': 'Maori (New Zealand)',
796    'mk': 'FYRO Macedonian',
797    'mk-MK': 'FYRO Macedonian (Former Yugoslav Republic of Macedonia)',
798    'mn': 'Mongolian',
799    'mn-MN': 'Mongolian (Mongolia)',
800    'mr': 'Marathi',
801    'mr-IN': 'Marathi (India)',
802    'ms': 'Malay',
803    'ms-BN': 'Malay (Brunei Darussalam)',
804    'ms-MY': 'Malay (Malaysia)',
805    'mt': 'Maltese',
806    'mt-MT': 'Maltese (Malta)',
807    'nb': 'Norwegian (Bokm?l)',
808    'nb-NO': 'Norwegian (Bokm?l) (Norway)',
809    'nl': 'Dutch',
810    'nl-BE': 'Dutch (Belgium)',
811    'nl-NL': 'Dutch (Netherlands)',
812    'nn-NO': 'Norwegian (Nynorsk) (Norway)',
813    'ns': 'Northern Sotho',
814    'ns-ZA': 'Northern Sotho (South Africa)',
815    'pa': 'Punjabi',
816    'pa-IN': 'Punjabi (India)',
817    'pl': 'Polish',
818    'pl-PL': 'Polish (Poland)',
819    'ps': 'Pashto',
820    'ps-AR': 'Pashto (Afghanistan)',
821    'pt': 'Portuguese',
822    'pt-BR': 'Portuguese (Brazil)',
823    'pt-PT': 'Portuguese (Portugal)',
824    'qu': 'Quechua',
825    'qu-BO': 'Quechua (Bolivia)',
826    'qu-EC': 'Quechua (Ecuador)',
827    'qu-PE': 'Quechua (Peru)',
828    'ro': 'Romanian',
829    'ro-RO': 'Romanian (Romania)',
830    'ru': 'Russian',
831    'ru-RU': 'Russian (Russia)',
832    'sa': 'Sanskrit',
833    'sa-IN': 'Sanskrit (India)',
834    'se': 'Sami',
835    'se-FI': 'Sami (Finland)',
836    'se-NO': 'Sami (Norway)',
837    'se-SE': 'Sami (Sweden)',
838    'sk': 'Slovak',
839    'sk-SK': 'Slovak (Slovakia)',
840    'sl': 'Slovenian',
841    'sl-SI': 'Slovenian (Slovenia)',
842    'sq': 'Albanian',
843    'sq-AL': 'Albanian (Albania)',
844    'sr-BA': 'Serbian (Latin) (Bosnia and Herzegovina)',
845    'sr-Cyrl-BA': 'Serbian (Cyrillic) (Bosnia and Herzegovina)',
846    'sr-SP': 'Serbian (Latin) (Serbia and Montenegro)',
847    'sr-Cyrl-SP': 'Serbian (Cyrillic) (Serbia and Montenegro)',
848    'sv': 'Swedish',
849    'sv-FI': 'Swedish (Finland)',
850    'sv-SE': 'Swedish (Sweden)',
851    'sw': 'Swahili',
852    'sw-KE': 'Swahili (Kenya)',
853    'syr': 'Syriac',
854    'syr-SY': 'Syriac (Syria)',
855    'ta': 'Tamil',
856    'ta-IN': 'Tamil (India)',
857    'te': 'Telugu',
858    'te-IN': 'Telugu (India)',
859    'th': 'Thai',
860    'th-TH': 'Thai (Thailand)',
861    'tl': 'Tagalog',
862    'tl-PH': 'Tagalog (Philippines)',
863    'tn': 'Tswana',
864    'tn-ZA': 'Tswana (South Africa)',
865    'tr': 'Turkish',
866    'tr-TR': 'Turkish (Turkey)',
867    'tt': 'Tatar',
868    'tt-RU': 'Tatar (Russia)',
869    'ts': 'Tsonga',
870    'uk': 'Ukrainian',
871    'uk-UA': 'Ukrainian (Ukraine)',
872    'ur': 'Urdu',
873    'ur-PK': 'Urdu (Islamic Republic of Pakistan)',
874    'uz': 'Uzbek (Latin)',
875    'uz-UZ': 'Uzbek (Latin) (Uzbekistan)',
876    'uz-Cyrl-UZ': 'Uzbek (Cyrillic) (Uzbekistan)',
877    'vi': 'Vietnamese',
878    'vi-VN': 'Vietnamese (Viet Nam)',
879    'xh': 'Xhosa',
880    'xh-ZA': 'Xhosa (South Africa)',
881    'zh': 'Chinese',
882    'zh-CN': 'Chinese (S)',
883    'zh-HK': 'Chinese (Hong Kong)',
884    'zh-MO': 'Chinese (Macau)',
885    'zh-SG': 'Chinese (Singapore)',
886    'zh-TW': 'Chinese (T)',
887    'zu': 'Zulu',
888    'zu-ZA': 'Zulu (South Africa)'
889}
890
891# pylint: disable=line-too-long
892GIO_TLS_ERRORS = {
893    Gio.TlsCertificateFlags.UNKNOWN_CA: _('The signing certificate authority is not known'),
894    Gio.TlsCertificateFlags.REVOKED: _('The certificate has been revoked'),
895    Gio.TlsCertificateFlags.BAD_IDENTITY: _('The certificate does not match the expected identity of the site'),
896    Gio.TlsCertificateFlags.INSECURE: _('The certificate’s algorithm is insecure'),
897    Gio.TlsCertificateFlags.NOT_ACTIVATED: _('The certificate’s activation time is in the future'),
898    Gio.TlsCertificateFlags.GENERIC_ERROR: _('Unknown validation error'),
899    Gio.TlsCertificateFlags.EXPIRED: _('The certificate has expired'),
900}
901# pylint: enable=line-too-long
902
903
904class FTState(Enum):
905    PREPARING = 'prepare'
906    ENCRYPTING = 'encrypting'
907    DECRYPTING = 'decrypting'
908    STARTED = 'started'
909    IN_PROGRESS = 'progress'
910    FINISHED = 'finished'
911    ERROR = 'error'
912    CANCELLED = 'cancelled'
913
914    @property
915    def is_preparing(self):
916        return self == FTState.PREPARING
917
918    @property
919    def is_encrypting(self):
920        return self == FTState.ENCRYPTING
921
922    @property
923    def is_decrypting(self):
924        return self == FTState.DECRYPTING
925
926    @property
927    def is_started(self):
928        return self == FTState.STARTED
929
930    @property
931    def is_in_progress(self):
932        return self == FTState.IN_PROGRESS
933
934    @property
935    def is_finished(self):
936        return self == FTState.FINISHED
937
938    @property
939    def is_error(self):
940        return self == FTState.ERROR
941
942    @property
943    def is_cancelled(self):
944        return self == FTState.CANCELLED
945
946    @property
947    def is_active(self):
948        return not (self.is_error or
949                    self.is_cancelled or
950                    self.is_finished)
951
952
953SASL_ERRORS = {
954    'aborted': _('Authentication aborted'),
955    'account-disabled': _('Account disabled'),
956    'credentials-expired': _('Credentials expired'),
957    'encryption-required': _('Encryption required'),
958    'incorrect-encoding': _('Authentication failed'),
959    'invalid-authzid': _('Authentication failed'),
960    'malformed-request': _('Authentication failed'),
961    'invalid-mechanism': _('Authentication mechanism not supported'),
962    'mechanism-too-weak': _('Authentication mechanism too weak'),
963    'not-authorized': _('Authentication failed'),
964    'temporary-auth-failure': _('Authentication currently not possible'),
965}
966
967
968COMMON_FEATURES = [
969    Namespace.BYTESTREAM,
970    Namespace.MUC,
971    Namespace.COMMANDS,
972    Namespace.DISCO_INFO,
973    Namespace.LAST,
974    Namespace.DATA,
975    Namespace.ENCRYPTED,
976    Namespace.PING,
977    Namespace.CHATSTATES,
978    Namespace.RECEIPTS,
979    Namespace.TIME_REVISED,
980    Namespace.VERSION,
981    Namespace.ROSTERX,
982    Namespace.SECLABEL,
983    Namespace.CONFERENCE,
984    Namespace.CORRECT,
985    Namespace.CHATMARKERS,
986    Namespace.EME,
987    Namespace.XHTML_IM,
988    Namespace.HASHES_2,
989    Namespace.HASHES_MD5,
990    Namespace.HASHES_SHA1,
991    Namespace.HASHES_SHA256,
992    Namespace.HASHES_SHA512,
993    Namespace.HASHES_SHA3_256,
994    Namespace.HASHES_SHA3_512,
995    Namespace.HASHES_BLAKE2B_256,
996    Namespace.HASHES_BLAKE2B_512,
997    Namespace.JINGLE,
998    Namespace.JINGLE_FILE_TRANSFER_5,
999    Namespace.JINGLE_XTLS,
1000    Namespace.JINGLE_BYTESTREAM,
1001    Namespace.JINGLE_IBB,
1002    Namespace.AVATAR_METADATA + '+notify',
1003]
1004
1005
1006SHOW_LIST = [
1007    'offline',
1008    'connecting',
1009    'online',
1010    'chat',
1011    'away',
1012    'xa',
1013    'dnd',
1014    'error'
1015]
1016
1017
1018URI_SCHEMES = {
1019    'aaa://',
1020    'aaas://',
1021    'acap://',
1022    'cap://',
1023    'cid:',
1024    'crid://',
1025    'data:',
1026    'dav:',
1027    'dict://',
1028    'dns:',
1029    'fax:',
1030    'file:/',
1031    'ftp://',
1032    'geo:',
1033    'go:',
1034    'gopher://',
1035    'h323:',
1036    'http://',
1037    'https://',
1038    'iax:',
1039    'icap://',
1040    'im:',
1041    'imap://',
1042    'info:',
1043    'ipp://',
1044    'iris:',
1045    'iris.beep:',
1046    'iris.xpc:',
1047    'iris.xpcs:',
1048    'iris.lwz:',
1049    'ldap://',
1050    'mid:',
1051    'modem:',
1052    'msrp://',
1053    'msrps://',
1054    'mtqp://',
1055    'mupdate://',
1056    'news:',
1057    'nfs://',
1058    'nntp://',
1059    'opaquelocktoken:',
1060    'pop://',
1061    'pres:',
1062    'prospero://',
1063    'rtsp://',
1064    'service:',
1065    'sip:',
1066    'sips:',
1067    'sms:',
1068    'snmp://',
1069    'soap.beep://',
1070    'soap.beeps://',
1071    'tag:',
1072    'tel:',
1073    'telnet://',
1074    'tftp://',
1075    'thismessage:/',
1076    'tip://',
1077    'tv:',
1078    'urn://',
1079    'vemmi://',
1080    'xmlrpc.beep://',
1081    'xmlrpc.beeps://',
1082    'z39.50r://',
1083    'z39.50s://',
1084    'about:',
1085    'apt:',
1086    'cvs://',
1087    'daap://',
1088    'ed2k://',
1089    'feed:',
1090    'fish://',
1091    'git://',
1092    'iax2:',
1093    'irc://',
1094    'ircs://',
1095    'ldaps://',
1096    'magnet:',
1097    'mms://',
1098    'rsync://',
1099    'ssh://',
1100    'svn://',
1101    'sftp://',
1102    'smb://',
1103    'webcal://',
1104    'aesgcm://',
1105}
1106
1107
1108THRESHOLD_OPTIONS = {
1109    -1: _('No Sync'),
1110    1: _('1 Day'),
1111    2: _('2 Days'),
1112    7: _('1 Week'),
1113    30: _('1 Month'),
1114    0: _('No Threshold'),
1115}
1116