2 # -*- encoding: utf-8 -*-
4 # Pour essayer de passer la base LDAP de ISO à UTF-8
6 # Je vais essayer de faire ça plus joliment que le premier,
7 # cette fois-ci avec un binding
9 import ldap
, ldap
.modlist
17 if "-i" in sys
.argv
or "--interactive" in sys
.argv
:
20 if "--no-interactive" in sys
.argv
:
25 USER_ENCODING
= sys
.stdin
.encoding
27 # On corrige certaines choses à la main
28 corrections_manuelles_file
= "corrections.json"
30 # idée pour voir si on décode n'importe comment
32 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ[]\\/^_`{}()|~0123456789:;<=>?@.-,+*'\"&%$!àáâäæèéêëìíîïòóôöùúûüýÿœŷỳçÀÁÂÄÆÈÉÊËÌÍÎÏÒÓÔÖÙÚÛÜÝŸŒŶỲǵ£§°\t#"""
34 # NB : u"\xc3" c'est à mais apparemment il y arrive pas…
35 known_problems_table
=[u
"¨", u
"©", u
"Ã", u
" ", u
"¢", u
"´", u
'\xc3', u
"¯",
36 u
'\x81', u
'\x82', u
'\x80', u
'\x89', u
'\x83', u
'\x99',
37 u
'\x9c', u
'\x9d', u
'\xac',
38 u
"¡", u
"®", u
"¼", u
"¦",
39 u
'\xad', u
'\xb6', u
"«", u
"»", u
"ª", u
"º", u
"¿", u
"¡"]
41 def con_ldap(uri
="ldap://127.0.0.1", test
=TEST_BASE
):
42 """Ouvre une connexion à la base LDAP"""
43 con
= ldap
.initialize(uri
)
47 sys
.path
.append("/etc/crans/secrets/")
49 mdp
= secrets
.ldap_password
50 con
.bind_s(who
="cn=admin,dc=crans,dc=org", cred
=mdp
)
55 b
=con
.search_s(base
="ou=data,dc=crans,dc=org", scope
=ldap
.SCOPE_SUBTREE
)
59 """Charge la liste des corrections manuelles"""
60 with
open(corrections_manuelles_file
) as f
:
64 def save_manual(manual
):
65 """Enregistre la liste des correction manuelles"""
66 with
open(corrections_manuelles_file
, "w") as f
:
70 """Retourne True si la chaîne s (unicode) contient des caractères qu'on n'est pas habitué à voir"""
71 assert isinstance(s
, unicode)
72 strange_chars
= (set(s
).symmetric_difference(set(usual_table
))).intersection(set(s
))
73 st
= [i
for i
in strange_chars
if not "\\u" in i
.encode("raw_unicode_escape")]
77 # """Prend une chaîne (unicode) qui était encodée en APF4242 et la renvoie décodée un cran de plus.
78 # Si ce n'est pas possible, renvoie la chaîne elle-même"""
79 # assert isinstance(s, unicode)
81 # s42 = s.encode("raw_unicode_escape").decode("UTF-8")
82 # print u"*** APF4242 trouvé ***\n" + s
84 # except UnicodeError:
87 class AbandonReplace(Exception):
90 def get_replacement(champ
, s
):
91 """Affiche une chaîne qu'on n'a pas su corriger automatiquement
92 et demande à l'utilisateur de préciser par quoi il faut la remplacer"""
93 print "%s : %r" % (champ
, s
)
94 repl
= raw_input("Remplacer par : ")
98 repl
= repl
.decode(USER_ENCODING
)
101 def reencode(champ
, s
, manual
={}):
102 """Prend un str et essaye de le renvoyer correctement encodé"""
103 assert isinstance(s
, str)
104 sunicode
= s
.decode("UTF-8")
105 # On vérifie ensuite qu'on a bien fait
107 # Le cas le plus fréquent dans la base LDAP :
108 sunicode
= sunicode
.encode("ISO8859-1").decode("UTF-8")
110 # Si ça n'a pas marché :
111 sunicode
= sunicode
.encode("UTF-8").decode("UTF-8")
112 dunno
, strange
= None, False
113 if is_strange(sunicode
):
114 # sunicode = tryapf4242(sunicode)
115 # on essaye de le remplacer par une valeur du dictionnaire de remplacements manuels
116 if sunicode
in manual
:
117 sunicode
= manual
.get(sunicode
, sunicode
)
120 replacement
= get_replacement(champ
, sunicode
)
121 manual
.update({sunicode
: replacement
})
122 sunicode
= replacement
123 except AbandonReplace
:
125 if is_strange(sunicode
):
129 reencodes
= sunicode
.encode("UTF-8")
130 return reencodes
, dunno
, manual
132 def perform(bbase
, manual
={}):
134 - une nouvelle base réencodée
135 - une liste de valeurs où on n'est pas satisfait du résultat obtenu
136 - un dico des valeurs qui ont été entrées à la main"""
137 base
= copy
.deepcopy(bbase
)
139 for iobj
in range(len(base
)):
140 for k
in base
[iobj
][1].keys():
141 for iattr
in range(len(base
[iobj
][1][k
])):
142 attr
= base
[iobj
][1][k
][iattr
]
143 attr
, dunno
, manual
= reencode(k
, attr
, manual
)
144 base
[iobj
][1][k
][iattr
] = attr
146 dunnos
.append([[iobj
, k
, iattr
], dunno
])
147 return base
, dunnos
, manual
149 def compute_modlists(avant
, apres
):
150 """Renvoie une liste de (dn,modlist) pour pouvoir effectuer les modification"""
152 for iobj
in range(len(avant
)):
153 dn1
, dn2
= avant
[iobj
][0], apres
[iobj
][0]
156 except AssertionError:
157 print "%s != %s" % (dn1
, dn2
)
159 modlist
= ldap
.modlist
.modifyModlist(avant
[iobj
][1], apres
[iobj
][1])
160 modlists
.append((dn1
, modlist
))
163 def modify(con
, modlists
):
164 """Effectue les modifications sur la base LDAP"""
165 for dn
, modlist
in modlists
:
166 con
.modify_s(dn
, modlist
)
171 base
= load_base(con
)
172 manual
= load_manual()
173 base_new
, dunnos
, manual
= perform(base
, manual
)
179 ans
= raw_input("Se souvenir des modifs manuelles ?")
180 if ans
.lower() in ["y","yes","o","oui"]:
183 #pprint.pprint(dunnos)
184 modlists
= [m
for m
in compute_modlists(base
, base_new
) if m
[1] != []]
188 if __name__
== "__main__":