From 1b045dd14e590093800469e2e96e6a71f6b92955 Mon Sep 17 00:00:00 2001
From: Alexandre Iooss <erdnaxe@crans.org>
Date: Sun, 12 Apr 2020 20:34:20 +0200
Subject: [PATCH] Remove unicode 'u'

---
 client.py | 160 ++++++++++++++++++++++++++----------------------------
 1 file changed, 78 insertions(+), 82 deletions(-)

diff --git a/client.py b/client.py
index 354d530..4680fe6 100755
--- a/client.py
+++ b/client.py
@@ -1,5 +1,4 @@
-#!/usr/bin/env python2
-# -*- encoding: utf-8 -*-
+#!/usr/bin/env python3
 
 """Gestion centralisée des mots de passe avec chiffrement GPG
 
@@ -8,8 +7,6 @@ Authors : Daniel Stan <daniel.stan@crans.org>
           Vincent Le Gallic <legallic@crans.org>
 """
 
-from __future__ import print_function
-
 # Import builtins
 import sys
 import subprocess
@@ -25,7 +22,6 @@ import time
 import datetime
 import copy
 import logging
-from binascii import hexlify
 from configparser import ConfigParser
 
 # Import a SSH client
@@ -70,16 +66,16 @@ GPG_ARGS = {
 
 #: Mapping (lettre de trustlevel) -> (signification, faut-il faire confiance à la clé)
 GPG_TRUSTLEVELS = {
-                    u"-" : (u"inconnue (pas de valeur assignée)", False),
-                    u"o" : (u"inconnue (nouvelle clé)", False),
-                    u"i" : (u"invalide (self-signature manquante ?)", False),
-                    u"n" : (u"nulle (il ne faut pas faire confiance à cette clé)", False),
-                    u"m" : (u"marginale (pas assez de lien de confiance vers cette clé)", False),
-                    u"f" : (u"entière (clé dans le réseau de confiance)", True),
-                    u"u" : (u"ultime (c'est probablement ta clé)", True),
-                    u"r" : (u"révoquée", False),
-                    u"e" : (u"expirée", False),
-                    u"q" : (u"non définie", False),
+                    "-" : ("inconnue (pas de valeur assignée)", False),
+                    "o" : ("inconnue (nouvelle clé)", False),
+                    "i" : ("invalide (self-signature manquante ?)", False),
+                    "n" : ("nulle (il ne faut pas faire confiance à cette clé)", False),
+                    "m" : ("marginale (pas assez de lien de confiance vers cette clé)", False),
+                    "f" : ("entière (clé dans le réseau de confiance)", True),
+                    "u" : ("ultime (c'est probablement ta clé)", True),
+                    "r" : ("révoquée", False),
+                    "e" : ("expirée", False),
+                    "q" : ("non définie", False),
                   }
 
 def gpg(options, command, args=None):
@@ -167,7 +163,7 @@ GPG_PARSERS = {
 def parse_keys(gpgout, debug=False):
     """Parse l'output d'un listing de clés gpg."""
     ring = {}
-    init_value = u"initialize" # Valeur utilisée pour dire "cet objet n'a pas encore été rencontré pendant le parsing"
+    init_value = "initialize" # Valeur utilisée pour dire "cet objet n'a pas encore été rencontré pendant le parsing"
     current_pub = init_value
     current_sub = init_value
     for line in iter(gpgout.readline, ''):
@@ -191,35 +187,35 @@ def parse_keys(gpgout, debug=False):
             except:
                 log.error("*** FAILED *** Line: %s", line)
                 raise
-            if field == u"pub":
+            if field == "pub":
                 # Nouvelle clé
                 # On sauvegarde d'abord le dernier sub (si il y en a un) dans son pub parent
                 if current_sub != init_value:
                     current_pub["subkeys"].append(current_sub)
                 # Ensuite on sauve le pub précédent (si il y en a un) dans le ring
                 if current_pub != init_value:
-                    ring[current_pub[u"fpr"]] = current_pub
+                    ring[current_pub["fpr"]] = current_pub
                 # On place le nouveau comme pub courant
                 current_pub = content
                 # Par défaut, il n'a ni subkeys, ni uids
-                current_pub[u"subkeys"] = []
-                current_pub[u"uids"] = []
+                current_pub["subkeys"] = []
+                current_pub["uids"] = []
                 # On oublié l'éventuel dernier sub rencontré
                 current_sub = init_value
-            elif field == u"fpr":
+            elif field == "fpr":
                 if current_sub != init_value:
                     # On a lu un sub depuis le dernier pub, donc le fingerprint est celui du dernier sub rencontré
-                    current_sub[u"fpr"] = content[u"fpr"]
+                    current_sub["fpr"] = content["fpr"]
                 else:
                     # Alors c'est le fingerprint du pub
-                    current_pub[u"fpr"] = content[u"fpr"]
-            elif field == u"uid":
-                current_pub[u"uids"].append(content)
-            elif field == u"sub":
+                    current_pub["fpr"] = content["fpr"]
+            elif field == "uid":
+                current_pub["uids"].append(content)
+            elif field == "sub":
                 # Nouvelle sous-clé
                 # D'abord on sauvegarde la précédente (si il y en a une) dans son pub parent
                 if current_sub != init_value:
-                    current_pub[u"subkeys"].append(current_sub)
+                    current_pub["subkeys"].append(current_sub)
                 # On place la nouvelle comme sub courant
                 current_sub = content
             log.debug("current_pub : %r" % current_pub)
@@ -230,7 +226,7 @@ def parse_keys(gpgout, debug=False):
     if current_sub != init_value:
         current_pub["subkeys"].append(current_sub)
     if current_pub != init_value:
-        ring[current_pub[u"fpr"]] = current_pub
+        ring[current_pub["fpr"]] = current_pub
     return ring
 
 class simple_memoize(object):
@@ -361,7 +357,7 @@ def get_my_roles(options):
     """Retourne la liste des rôles de l'utilisateur, et également la liste des rôles dont il possède le role-w."""
     allroles = all_roles(options)
     distant_username = allroles.pop("whoami")
-    my_roles = [r for (r, users) in allroles.iteritems() if distant_username in users]
+    my_roles = [r for (r, users) in allroles.items() if distant_username in users]
     my_roles_w = [r[:-2] for r in my_roles if r.endswith("-w")]
     return (my_roles, my_roles_w)
 
@@ -389,21 +385,21 @@ def _check_encryptable(key):
        Puis qu'on peut chiffrer avec, ou qu'au moins une de ses subkeys est de chiffrement (capability e)
        et est de confiance et n'est pas expirée"""
     # Il faut que la clé soit dans le réseau de confiance…
-    meaning, trustvalue = GPG_TRUSTLEVELS[key[u"trustletter"]]
+    meaning, trustvalue = GPG_TRUSTLEVELS[key["trustletter"]]
     if not trustvalue:
-        return u"La confiance en la clé est : %s" % (meaning,)
+        return "La confiance en la clé est : %s" % (meaning,)
     # …et qu'on puisse chiffrer avec…
-    if u"e" in key[u"capabilities"]:
+    if "e" in key["capabilities"]:
         # …soit directement…
-        return u""
+        return ""
     # …soit avec une de ses subkeys
-    esubkeys = [sub for sub in key[u"subkeys"] if u"e" in sub[u"capabilities"]]
+    esubkeys = [sub for sub in key["subkeys"] if "e" in sub["capabilities"]]
     if len(esubkeys) == 0:
-        return u"La clé principale de permet pas de chiffrer et auncune sous-clé de chiffrement."
-    if any([GPG_TRUSTLEVELS[sub[u"trustletter"]][1] for sub in esubkeys]):
-        return u""
+        return "La clé principale de permet pas de chiffrer et auncune sous-clé de chiffrement."
+    if any([GPG_TRUSTLEVELS[sub["trustletter"]][1] for sub in esubkeys]):
+        return ""
     else:
-        return u"Aucune sous clé de chiffrement n'est de confiance et non expirée."
+        return "Aucune sous clé de chiffrement n'est de confiance et non expirée."
 
 def check_keys(options, recipients=None, quiet=False):
     """Vérifie les clés, c'est-à-dire, si le mail est présent dans les identités du fingerprint,
@@ -427,15 +423,15 @@ def check_keys(options, recipients=None, quiet=False):
     _, gpgout = gpg(options, 'list-keys')
     localring = parse_keys(gpgout)
     for (recipient, (mail, fpr)) in keys.iteritems():
-        failed = u""
+        failed = ""
         if not fpr is None:
             if speak:
-                print((u"Checking %s… " % (mail)).encode("utf-8"), end="")
+                print(("Checking %s… " % (mail)).encode("utf-8"), end="")
             key = localring.get(fpr, None)
             # On vérifie qu'on possède la clé…
             if not key is None:
                 # …qu'elle correspond au mail…
-                if any([u"<%s>" % (mail,) in u["uid"] for u in key["uids"]]):
+                if any(["<%s>" % (mail,) in u["uid"] for u in key["uids"]]):
                     if speak:
                         print("M ", end="")
                     # … et qu'on peut raisonnablement chiffrer pour lui
@@ -443,16 +439,16 @@ def check_keys(options, recipients=None, quiet=False):
                     if not failed and speak:
                         print("C ", end="")
                 else:
-                    failed = u"!! Le fingerprint et le mail ne correspondent pas !"
+                    failed = "!! Le fingerprint et le mail ne correspondent pas !"
             else:
-                failed = u"Pas (ou trop) de clé avec ce fingerprint."
+                failed = "Pas (ou trop) de clé avec ce fingerprint."
             if speak:
                 print("")
             if failed:
                 log.warn("--> Fail on %s:%s\n--> %s" % (mail, fpr, failed))
                 if not recipients is None:
                     # On cherche à savoir si on droppe ce recipient
-                    message = u"Abandonner le chiffrement pour cette clé ? (Si vous la conservez, il est posible que gpg crashe)"
+                    message = "Abandonner le chiffrement pour cette clé ? (Si vous la conservez, il est posible que gpg crashe)"
                     if confirm(options, message, ('drop', fpr, mail)):
                         drop = True # si on a répondu oui à "abandonner ?", on droppe
                     elif options.drop_invalid and options.force:
@@ -475,7 +471,7 @@ def get_recipients_of_roles(options, roles):
     recipients = set()
     allroles = all_roles(options)
     for role in roles:
-        if role == u"whoami":
+        if role == "whoami":
             continue
         for recipient in allroles[role]:
             recipients.add(recipient)
@@ -484,7 +480,7 @@ def get_recipients_of_roles(options, roles):
 def get_dest_of_roles(options, roles):
     """Renvoie la liste des "username : mail (fingerprint)" """
     allkeys = all_keys(options)
-    return [u"%s : %s (%s)" % (rec, allkeys[rec][0], allkeys[rec][1])
+    return ["%s : %s (%s)" % (rec, allkeys[rec][0], allkeys[rec][1])
                for rec in get_recipients_of_roles(options, roles) if allkeys[rec][1]]
 
 def encrypt(options, roles, contents):
@@ -505,7 +501,7 @@ def encrypt(options, roles, contents):
     stdin.close()
     out = stdout.read().decode("utf-8")
     if out == '':
-        return [False, u"Échec de chiffrement"]
+        return [False, "Échec de chiffrement"]
     else:
         return [True, out]
 
@@ -540,7 +536,7 @@ def need_filename(f):
     NEED_FILENAME.append(f)
     return f
 
-def editor(texte, annotations=u""):
+def editor(texte, annotations=""):
     """ Lance $EDITOR sur texte.
     Renvoie le nouveau texte si des modifications ont été apportées, ou None
     """
@@ -570,40 +566,40 @@ def show_files(options):
     """Affiche la liste des fichiers disponibles sur le serveur distant"""
     my_roles, _ = get_my_roles(options)
     files = all_files(options)
-    keys = files.keys()
+    keys = list(files.keys())
     keys.sort()
-    print(u"Liste des fichiers disponibles :".encode("utf-8"))
+    print("Liste des fichiers disponibles :".encode("utf-8"))
     for fname in keys:
         froles = files[fname]
         access = set(my_roles).intersection(froles) != set([])
-        print((u" %s %s (%s)" % ((access and '+' or '-'), fname, ", ".join(froles))).encode("utf-8"))
-    print((u"""--Mes roles: %s""" % (", ".join(my_roles),)).encode("utf-8"))
+        print((" %s %s (%s)" % ((access and '+' or '-'), fname, ", ".join(froles))).encode("utf-8"))
+    print(("""--Mes roles: %s""" % (", ".join(my_roles),)).encode("utf-8"))
 
 def restore_files(options):
     """Restore les fichiers corrompues sur le serveur distant"""
-    print(u"Fichier corrompus :".encode("utf-8"))
+    print("Fichier corrompus :".encode("utf-8"))
     files = restore_all_files(options)
     keys = files.keys()
     keys.sort()
     for fname in keys:
-        print((u" %s (%s)" % ( fname, files[fname])).encode("utf-8"))
+        print((" %s (%s)" % ( fname, files[fname])).encode("utf-8"))
 
 
 def show_roles(options):
     """Affiche la liste des roles existants"""
-    print(u"Liste des roles disponibles".encode("utf-8"))
+    print("Liste des roles disponibles".encode("utf-8"))
     allroles =  all_roles(options)
     for (role, usernames) in allroles.iteritems():
-        if role == u"whoami":
+        if role == "whoami":
             continue
         if not role.endswith('-w'):
-            print((u" * %s : %s" % (role, ", ".join(usernames))).encode("utf-8"))
+            print((" * %s : %s" % (role, ", ".join(usernames))).encode("utf-8"))
 
 def show_servers(options):
     """Affiche la liste des serveurs disponibles"""
-    print(u"Liste des serveurs disponibles".encode("utf-8"))
+    print("Liste des serveurs disponibles".encode("utf-8"))
     for server in config.keys():
-        print((u" * " + server).encode("utf-8"))
+        print((" * " + server).encode("utf-8"))
 
 def saveclipboard(restore=False, old_clipboard=None):
     """Enregistre le contenu du presse-papier. Le rétablit si ``restore=True``"""
@@ -615,7 +611,7 @@ def saveclipboard(restore=False, old_clipboard=None):
     if not restore:
         old_clipboard = proc.stdout.read()
     else:
-        raw_input(u"Appuyez sur Entrée pour récupérer le contenu précédent du presse papier.".encode("utf-8"))
+        raw_input("Appuyez sur Entrée pour récupérer le contenu précédent du presse papier.".encode("utf-8"))
         proc.stdin.write(old_clipboard)
     proc.stdin.close()
     proc.stdout.close()
@@ -657,7 +653,7 @@ def show_file(options):
     # Est-ce que le mot de passe a été caché ? (si non, on utilisera less)
     is_hidden = is_key
     # Texte avec mdp caché
-    filtered = u""
+    filtered = ""
     # Ancien contenu du press papier
     old_clipboard = None
 
@@ -673,12 +669,12 @@ def show_file(options):
             # On met le mdp dans le clipboard en mémorisant son ancien contenu
             old_clipboard = clipboard(catchPass.group(1))
             # Et donc on override l'affichage
-            line = u"[Le mot de passe a été mis dans le presse papier]"
+            line = "[Le mot de passe a été mis dans le presse papier]"
         filtered += line + '\n'
 
     if is_key:
-        filtered = u"La clé a été mise dans l'agent ssh"
-    shown = u"Fichier %s:\n\n%s-----\nVisible par: %s\n" % (fname, filtered, ','.join(passfile['roles']))
+        filtered = "La clé a été mise dans l'agent ssh"
+    shown = "Fichier %s:\n\n%s-----\nVisible par: %s\n" % (fname, filtered, ','.join(passfile['roles']))
 
     if is_key:
         with tempfile.NamedTemporaryFile(suffix='') as key_file:
@@ -717,22 +713,22 @@ def edit_file(options):
     fname = options.fname
     gotit, value = get_file(options, fname)
     nfile = False
-    annotations = u""
+    annotations = ""
 
     my_roles, _ = get_my_roles(options)
     new_roles = options.roles
 
     # Cas du nouveau fichier
-    if not gotit and not u"pas les droits" in value:
+    if not gotit and not "pas les droits" in value:
         nfile = True
         if not options.quiet:
-            print(u"Fichier introuvable".encode("utf-8"))
-        if not confirm(options, u"Créer fichier ?"):
+            print("Fichier introuvable".encode("utf-8"))
+        if not confirm(options, "Créer fichier ?"):
             return
-        annotations += u"""Ceci est un fichier initial contenant un mot de passe
+        annotations += """Ceci est un fichier initial contenant un mot de passe
 aléatoire, pensez à rajouter une ligne "login: ${login}"
 Enregistrez le fichier vide pour annuler.\n"""
-        texte = u"pass: %s\n" % gen_password()
+        texte = "pass: %s\n" % gen_password()
 
         if new_roles is None:
             new_roles = parse_roles(options, cast=True)
@@ -763,13 +759,13 @@ Enregistrez le fichier vide pour annuler.\n"""
     # On peut vouloir chiffrer un fichier sans avoir la possibilité de le lire
     # dans le futur, mais dans ce cas on préfère demander confirmation
     if not any(r + '-w' in my_roles for r in new_roles):
-        message = u"""Vous vous apprêtez à perdre vos droits en écriture""" + \
+        message = """Vous vous apprêtez à perdre vos droits en écriture""" + \
             """(ROLES ne contient rien parmi : %s) sur ce fichier, continuer ?"""
         message = message % (", ".join(r[:-2] for r in my_roles if '-w' in r),)
         if not confirm(options, message):
             return
 
-    annotations += u"""Ce fichier sera chiffré pour les rôles suivants :\n%s\n
+    annotations += """Ce fichier sera chiffré pour les rôles suivants :\n%s\n
 C'est-à-dire pour les utilisateurs suivants :\n%s""" % (
            ', '.join(new_roles),
            '\n'.join(' %s' % rec for rec in get_dest_of_roles(options, new_roles))
@@ -780,9 +776,9 @@ C'est-à-dire pour les utilisateurs suivants :\n%s""" % (
     if ((not nfile and ntexte in [u'', texte]          # pas nouveau, vidé ou pas modifié
          and set(new_roles) == set(passfile['roles'])) # et on n'a même pas touché à ses rôles,
         or (nfile and ntexte == u'')):                 # ou alors on a créé un fichier vide.
-        message = u"Pas de modification à enregistrer.\n"
-        message += u"Si ce n'est pas un nouveau fichier, il a été vidé ou n'a pas été modifié (même pas ses rôles).\n"
-        message += u"Si c'est un nouveau fichier, vous avez tenté de le créer vide."
+        message = "Pas de modification à enregistrer.\n"
+        message += "Si ce n'est pas un nouveau fichier, il a été vidé ou n'a pas été modifié (même pas ses rôles).\n"
+        message += "Si c'est un nouveau fichier, vous avez tenté de le créer vide."
         if not options.quiet:
             print(message.encode("utf-8"))
     else:
@@ -826,8 +822,8 @@ def remove_file(options):
 
 def my_check_keys(options):
     """Vérifie les clés et affiche un message en fonction du résultat"""
-    print(u"Vérification que les clés sont valides (uid correspondant au login) et de confiance.")
-    print((check_keys(options) and u"Base de clés ok" or u"Erreurs dans la base").encode("utf-8"))
+    print("Vérification que les clés sont valides (uid correspondant au login) et de confiance.")
+    print((check_keys(options) and "Base de clés ok" or "Erreurs dans la base").encode("utf-8"))
 
 def my_update_keys(options):
     """Met à jour les clés existantes et affiche le résultat"""
@@ -870,8 +866,8 @@ def recrypt_files(options, strict=False):
     # On informe l'utilisateur et on demande confirmation avant de rechiffrer
     # Si il a précisé --force, on ne lui demandera rien.
     filenames = ", ".join(askfiles)
-    message = u"Vous vous apprêtez à rechiffrer les fichiers suivants :\n%s" % filenames
-    if not confirm(options, message + u"\nConfirmer"):
+    message = "Vous vous apprêtez à rechiffrer les fichiers suivants :\n%s" % filenames
+    if not confirm(options, message + "\nConfirmer"):
         exit(2)
     # On rechiffre
     to_put = [{'filename' : f['filename'],
@@ -880,15 +876,15 @@ def recrypt_files(options, strict=False):
               for [success, f] in files]
     if to_put:
         if not options.quiet:
-            print((u"Rechiffrement de %s" % (", ".join([f['filename'] for f in to_put]))).encode("utf-8"))
+            print(("Rechiffrement de %s" % (", ".join([f['filename'] for f in to_put]))).encode("utf-8"))
         results = put_files(options, to_put)
         # On affiche les messages de retour
         if not options.quiet:
             for i in range(len(results)):
-                print(u"%s : %s" % (to_put[i]['filename'], results[i][1]))
+                print("%s : %s" % (to_put[i]['filename'], results[i][1]))
     else:
         if not options.quiet:
-            print(u"Aucun fichier n'a besoin d'être rechiffré".encode("utf-8"))
+            print("Aucun fichier n'a besoin d'être rechiffré".encode("utf-8"))
 
 def parse_roles(options, cast=False):
     """Interprête la liste de rôles fournie par l'utilisateur.
-- 
GitLab