From 4dc2c99f38d481d5bbfa0d129b937de8e72fbb1c Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Fri, 22 May 2015 14:33:55 +0200 Subject: [PATCH] =?UTF-8?q?S=C3=A9paration=20des=20fichiers=20&&=20-Affich?= =?UTF-8?q?age=20du=20fichier=20source=20[stable~90]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- enigmail.py | 77 ++++++++++++++++++++++ enigmail.pyc | Bin 0 -> 2623 bytes interface.py | 80 ++++++++++++++++++++++ source.py | 183 --------------------------------------------------- test1 | 27 ++++++++ test2 | 87 ++++++++++++++++++++++++ 6 files changed, 271 insertions(+), 183 deletions(-) create mode 100644 enigmail.py create mode 100644 enigmail.pyc create mode 100644 interface.py delete mode 100644 source.py create mode 100644 test1 create mode 100644 test2 diff --git a/enigmail.py b/enigmail.py new file mode 100644 index 0000000..2034fdc --- /dev/null +++ b/enigmail.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- + +import time; + +# fonction qui calcule le nombre de rotors en fonction de la clé pKey et qui retourne un entier +def calcLevel(pKey, pSIGMA): + xN = 1; + for r in range(1,100): + if( pKey >= len(pSIGMA)**r ): # si la clé est inférieure à la valeur max pour r rotors + xN = r; # on enregistre la valeur + else: # sinon (c'est qu'on a dépassé) + break; # on arrête la boucle et on renvoie la derniere valeur de r (xN) + return xN; + +# fonction qui retourne une liste de nombres entre 0 pLength a partir d'un nombre +# compris entre 0 et pLength**pLevel +def decomposeKey(pNum, pLength, pLevel): + xReturn = []; + n = pNum + for i in range(pLevel-1, -1, -1): + xReturn.append( n // (pLength**i) ); + n -= xReturn[i-pLevel+1] * (pLength**i) + return xReturn; + + +# fonction qui melange une liste pSIGMA melangee par une cle pKEY +def shuffle(pSIGMA, pKEY): + xReturn = [] + pList = pSIGMA[:] + l = len(pList) + i = pKEY % l; # rang actuel + n = 0; # nombre d'elements traites + while( n < len(pList) ): + if( pList[i] != 'stop_value' ): # si l'element n'est pas traite + xReturn.append( pList[i] ); # on met le caractere dans xReturn + pList[i] = 'stop_value'; # on met un caractere qui nous indique que l'on a deja traite + n += 1; # on met a jour notre indicateur de caracteres traites + else: # si l'element est deja traite + i += 1 + i = (i+pKEY) % l + return xReturn; + + +# fonction qui fait tourner les rotors (sens horaire) de pROTOR (indice 1 a len(pROTOR)) l'indice 0 etant la liste des premiers caracteres des rotors +def rotateRotorsClockwise(pROTOR): + moveNext = True; + for r in range(1, len(pROTOR)): # parcourt les rotors + if( moveNext ): # si on doit deplacer le rotor + pROTOR[r] = [pROTOR[r][-1]] + pROTOR[r][:-1] # pivote le rotor de 1 caractere + moveNext = ( pROTOR[r][0] == pROTOR[0][r-1] ); # si le rotor vient de finir un tour, moveNext = True sinon moveNext = False + + +# fonction qui fait tourner les rotors (sens anti-horaire) de pROTOR (indice 1 a len(pROTOR)) l'indice 0 etant la liste des premiers caracteres des rotors +def rotateRotorsAnticlockwise(pROTOR): + moveNext = True; + for r in range(1, len(pROTOR)): # parcourt les rotors + if( moveNext ): # si on doit deplacer le rotor + pROTOR[r] = pROTOR[r][1:] + [pROTOR[r][0]] # pivote le rotor de 1 caractere + moveNext = ( pROTOR[r][-1] == pROTOR[0][r-1] ); # si le rotor vient de finir un tour, moveNext = True sinon moveNext = False + + +# fonction qui affiche les rotors +def printRotors(pROTOR): + for i in range(1, len(pROTOR)): + print pROTOR[i]; + +# fonction qui code un caractere pChar via les rotors +def encodeChar(pChar, pSIGMA, pROTOR): + for r in range(1, len(pROTOR)): # parcourt les rotors + pChar = pSIGMA[ pROTOR[r].index(pChar) ]; # le caractere devient celui au rang de l'alphabet correspondant au rang du caractere dans le rotor r + return pChar; + +# fonction qui decode un caractere pChar via les rotors +def decodeChar(pChar, pSIGMA, pROTOR): + for r in reversed(range(1, len(pROTOR))): # parcourt les rotors + pChar = pROTOR[r][ pSIGMA.index(pChar) ]; # le caractere devient celui au rang de l'alphabet correspondant au rang du caractere dans le rotor r + return pChar; diff --git a/enigmail.pyc b/enigmail.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fb57494a28ce60676bfe337af93759b66543380a GIT binary patch literal 2623 zcmcJRU2hvj6o$`uZ6|gUXqzUf+qBSDs(eAo4N#yF5GAO51h;I8Qjn_3>`t7GKX$V_ z4qGX{Dt~|*{wO~H-uLV}E)_^fHMaNo%#L?v-e=A^WABgUW^n8I4}p}g3ckO5F`!gQ=d30x z*MP{d32NxA;0Yt^t+MyZ#~APA4rqCQr^Ss?T0SNhMbb?YI||!eTEVI_9=Zjzl07@> zxub%c3e(%UZ{0W@DZIi)b3sU8p$+0;5@#0sbqVcrigk0tteV?KV~UF-O{Mrd98#<> zdTt_!$k1a10ReGTWexloc6G@Q<*YvYMIYP$TZym*+_wSV;sbw~zay-;BvXf z^B@Lo@|+mSdrV$%Ms{H<08SJ8v2Kl#bc1)nmY`cb06uTMyI%NP(_5aj-~w)|%!XFK z!YNKR_&Gr0>}zh9C4fP#n6)k_z9;F}YKZ$>adBVs-+%Pvk?$69a~Pl6j?JAm#D>CiTPL1 ze2t<{k^UOZ+_<$c+N<2QM=lDc>^?&0Ke3x0E?NW#IKRt4Wc+DtP2=xv1`Z(^X+8Xk zCy0g*A1}gZRt}3;VNaownKqZeU>+xFG;&2;e2!+u;vfhHJr~&ErD7hy$v=2S49VE-QMDphV literal 0 HcmV?d00001 diff --git a/interface.py b/interface.py new file mode 100644 index 0000000..fb1c6fb --- /dev/null +++ b/interface.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +from enigmail import * + + + + +# DEFINITION DE L'ALPHABET +SIGMA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; # maj +SIGMA += 'abcdefghijklmnopqrstuvwxyz'; # min +SIGMA += '&=+^~@%,.?!:;[](){}-_#$*/ \\"\'\n'; # ponctuation + retour charriot +SIGMA += '0123456789'; # digit +SIGMA += 'éèêàùç'; # accents +SIGMA = SIGMA.decode('utf-8'); +# ALPHABET FORMATE EN LISTE +SIGMA = list(SIGMA); +# NOMBRE DE ROTORS +LEVEL = 3; # valeur par defaut +# CHOIX DE LA CLE +userkey = int( raw_input('Cle (hex ou int): '), 0); +# CALCUL de LEVEL en fonction de la clé +LEVEL = calcLevel(userkey, SIGMA); +# DECOMPOSITION DE LA CLE PRIMAIRE EN CLES SECONDAIRES +KEY = decomposeKey(userkey, len(SIGMA), LEVEL); +# CREATION DES ROTORS EN FONCTION DES CLES SECONDAIRES +ROTOR = []; +ROTOR.append( [] ); +# on cree les rotors grace a sigma et aux cles recuperees +for i in range(0, LEVEL): + ROTOR.append( shuffle( SIGMA, KEY[i]) ); # on creer le rotor et le melange suivant la cle + ROTOR[0].append( ROTOR[i+1][0] ); # on enregistre la l&ettre en premiere position dans la premiere entree du rotor + + +# AFFICHAGE DES ROTORS +# printRotors(ROTOR); + +# LIEN DU FICHIER A CRYPTER +f1 = raw_input('Fichier d\'entrée: '); +f2 = raw_input('Fichier de sortie: '); + +# OUVERTURE ET LECTURE DU FICHIER +inFile = open(f1, 'r'); +m = inFile.read().decode('utf-8'); + +# CHOIX DU TYPE (ENCODE / DECODE) +type = ''; +while( type != 'E' and type != 'D' ): + type = ( raw_input('encoder ou decoder [E/D]: ') ).upper(); +# VARIABLE DU HASH +M = ''; + + +# DEMARRE LE CHRONO +startTime = time.time(); + +# ENCODAGE DU MESSAGE +if( type == 'E' ): + for c in range(0, len(m)): + M += encodeChar(m[c], SIGMA, ROTOR); + rotateRotorsClockwise(ROTOR); # on pivote les rotors dans le sens horaire +# DECODAGE DU MESSAGE +else: + # decalage des rotor en position de fin d'encodage (taille du message -1) + for r in range(1, len(m)): + rotateRotorsClockwise(ROTOR); + + # pour chaque caractere en partant du dernier + for c in reversed(range(0, len(m))): + M += decodeChar(m[c], SIGMA, ROTOR); # on lit le caractere + rotateRotorsAnticlockwise(ROTOR); # on tourne les rotors dans le sens inverse + + # on retourne la chaine + M = M[::-1]; + +# ON ECRIT LE RESULTAT DANS LE FICHIER DE SORTIE +outFile = open(f2, 'w'); +outFile.write(M.encode('utf-8')); +outFile.close(); + +print +print 'Temps d\'exécution:',time.time() - startTime; \ No newline at end of file diff --git a/source.py b/source.py deleted file mode 100644 index 6e452ca..0000000 --- a/source.py +++ /dev/null @@ -1,183 +0,0 @@ -# -*- coding: utf-8 -*- - -import time; - -# fonction qui calcule le nombre de rotors en fonction de la clé pKey et qui retourne un entier -def calcLevel(pKey, pSIGMA): - xN = 1; - for r in range(1,100): - if( pKey >= len(pSIGMA)**r ): # si la clé est inférieure à la valeur max pour r rotors - xN = r; # on enregistre la valeur - else: # sinon (c'est qu'on a dépassé) - break; # on arrête la boucle et on renvoie la derniere valeur de r (xN) - return xN; - -# fonction qui retourne une liste de nombres entre 0 pLength a partir d'un nombre -# compris entre 0 et pLength**pLevel -def decomposeKey(pNum, pLength, pLevel): - xReturn = []; - n = pNum - for i in range(pLevel-1, -1, -1): - xReturn.append( n // (pLength**i) ); - n -= xReturn[i-pLevel+1] * (pLength**i) - return xReturn; - - -# fonction qui melange une liste pSIGMA melangee par une cle pKEY -def shuffle(pSIGMA, pKEY): - xReturn = [] - pList = pSIGMA[:] - l = len(pList) - i = pKEY % l; # rang actuel - n = 0; # nombre d'elements traites - while( n < len(pList) ): - if( pList[i] != 'stop_value' ): # si l'element n'est pas traite - xReturn.append( pList[i] ); # on met le caractere dans xReturn - pList[i] = 'stop_value'; # on met un caractere qui nous indique que l'on a deja traite - n += 1; # on met a jour notre indicateur de caracteres traites - else: # si l'element est deja traite - i += 1 - i = (i+pKEY) % l - return xReturn; - - -# fonction qui fait tourner les rotors (sens horaire) de pROTOR (indice 1 a len(pROTOR)) l'indice 0 etant la liste des premiers caracteres des rotors -def rotateRotorsClockwise(pROTOR): - moveNext = True; - for r in range(1, len(pROTOR)): # parcourt les rotors - if( moveNext ): # si on doit deplacer le rotor - pROTOR[r] = [pROTOR[r][-1]] + pROTOR[r][:-1] # pivote le rotor de 1 caractere - moveNext = ( pROTOR[r][0] == pROTOR[0][r-1] ); # si le rotor vient de finir un tour, moveNext = True sinon moveNext = False - - -# fonction qui fait tourner les rotors (sens anti-horaire) de pROTOR (indice 1 a len(pROTOR)) l'indice 0 etant la liste des premiers caracteres des rotors -def rotateRotorsAnticlockwise(pROTOR): - moveNext = True; - for r in range(1, len(pROTOR)): # parcourt les rotors - if( moveNext ): # si on doit deplacer le rotor - pROTOR[r] = pROTOR[r][1:] + [pROTOR[r][0]] # pivote le rotor de 1 caractere - moveNext = ( pROTOR[r][-1] == pROTOR[0][r-1] ); # si le rotor vient de finir un tour, moveNext = True sinon moveNext = False - - -# fonction qui affiche les rotors -def printRotors(pROTOR): - for i in range(1, len(pROTOR)): - print pROTOR[i]; - -# fonction qui code un caractere pChar via les rotors -def encodeChar(pChar, pSIGMA, pROTOR): - for r in range(1, len(pROTOR)): # parcourt les rotors - pChar = SIGMA[ pROTOR[r].index(pChar) ]; # le caractere devient celui au rang de l'alphabet correspondant au rang du caractere dans le rotor r - return pChar; - -# fonction qui decode un caractere pChar via les rotors -def decodeChar(pChar, pSIGMA, pROTOR): - for r in reversed(range(1, len(pROTOR))): # parcourt les rotors - pChar = pROTOR[r][ pSIGMA.index(pChar) ]; # le caractere devient celui au rang de l'alphabet correspondant au rang du caractere dans le rotor r - return pChar; - - - -############################################################################################################################# -############################################################################################################################# -############################################################################################################################# -######################################### ############## ############ ########################################## -######################################### ############## ################# ############################################### -######################################### ############## ################# ############################################### -######################################### ############## ################# ############################################### -######################################### ############## ################# ############################################### -######################################### ############## ################# ############################################### -######################################### ############## ################# ############################################### -######################################### ############## ################# ############################################### -######################################### ############## ################# ############################################### -######################################### ############ ######################################### -############################################################################################################################# -############################################################################################################################# -############################################################################################################################# - -# DEFINITION DE L'ALPHABET -SIGMA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; # maj -SIGMA += 'abcdefghijklmnopqrstuvwxyz'; # min -SIGMA += '&=+^~@%,.?!:;[](){}-_#$*/ \\"\'\n'; # ponctuation + retour charriot -SIGMA += '0123456789'; # digit -SIGMA += 'éèêàùç'; # accents -SIGMA = SIGMA.decode('utf-8'); -# ALPHABET FORMATE EN LISTE -SIGMA = list(SIGMA); -# NOMBRE DE ROTORS -LEVEL = 3; # valeur par defaut -# CHOIX DE LA CLE -userkey = int( raw_input('Cle (hex ou int): '), 0); -# CALCUL de LEVEL en fonction de la clé -LEVEL = calcLevel(userkey, SIGMA); -# DECOMPOSITION DE LA CLE PRIMAIRE EN CLES SECONDAIRES -KEY = decomposeKey(userkey, len(SIGMA), LEVEL); -# CREATION DES ROTORS EN FONCTION DES CLES SECONDAIRES -ROTOR = []; -ROTOR.append( [] ); -# on cree les rotors grace a sigma et aux cles recuperees -for i in range(0, LEVEL): - ROTOR.append( shuffle( SIGMA, KEY[i]) ); # on creer le rotor et le melange suivant la cle - ROTOR[0].append( ROTOR[i+1][0] ); # on enregistre la l&ettre en premiere position dans la premiere entree du rotor - - -# AFFICHAGE DES ROTORS -# printRotors(ROTOR); - -# LIEN DU FICHIER A CRYPTER -f1 = raw_input('Fichier d\'entrée: '); -f2 = raw_input('Fichier de sortie: '); - -# OUVERTURE ET LECTURE DU FICHIER -inFile = open(f1, 'r'); -m = inFile.read().decode('utf-8'); -print m; - -# CHOIX DU TYPE (ENCODE / DECODE) -type = ''; -while( type != 'E' and type != 'D' ): - type = ( raw_input('encoder ou decoder [E/D]: ') ).upper(); -# VARIABLE DU HASH -M = ''; - - -# DEMARRE LE CHRONO -startTime = time.time(); - -# ENCODAGE DU MESSAGE -if( type == 'E' ): - for c in range(0, len(m)): - M += encodeChar(m[c], SIGMA, ROTOR); - rotateRotorsClockwise(ROTOR); # on pivote les rotors dans le sens horaire -# DECODAGE DU MESSAGE -else: - # decalage des rotor en position de fin d'encodage (taille du message -1) - for r in range(1, len(m)): - rotateRotorsClockwise(ROTOR); - - # pour chaque caractere en partant du dernier - for c in reversed(range(0, len(m))): - M += decodeChar(m[c], SIGMA, ROTOR); # on lit le caractere - rotateRotorsAnticlockwise(ROTOR); # on tourne les rotors dans le sens inverse - - # on retourne la chaine - M = M[::-1]; - -# ON ECRIT LE RESULTAT DANS LE FICHIER DE SORTIE -outFile = open(f2, 'w'); -outFile.write(M.encode('utf-8')); -outFile.close(); - -print -print 'Temps d\'exécution:',time.time() - startTime; - - - - - - - - - - - diff --git a/test1 b/test1 new file mode 100644 index 0000000..4c7a7d4 --- /dev/null +++ b/test1 @@ -0,0 +1,27 @@ +Pour une clé de 0x123456f ce fichier donne le fichier test2 + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris fringilla dolor quis mi dictum vehicula. Curabitur orci est, vehicula ac neque id, luctus hendrerit nunc. Aenean id nulla diam. Ut ornare eros mi, ac volutpat neque blandit quis. Etiam consectetur eget odio auctor dapibus. In diam dolor, consequat in pulvinar eget, rutrum a orci. Maecenas porta non turpis vel mattis. Nam quis blandit elit. Duis eleifend vestibulum ex, id suscipit arcu molestie in. Nullam suscipit ex sit amet diam finibus porta. Maecenas eget lorem sagittis, sollicitudin quam id, lacinia dui. + +Suspendisse orci urna, commodo quis accumsan aliquet, laoreet et orci. Morbi enim odio, gravida non velit eu, scelerisque scelerisque augue. Praesent aliquet mauris a ligula sodales, et elementum nisi cursus. In eget quam quis odio ultricies feugiat sed quis dui. Integer quis lectus orci. Suspendisse sagittis molestie tortor ac mattis. Maecenas molestie blandit lacinia. Aliquam posuere tristique vehicula. Nullam neque leo, congue at tincidunt quis, ultrices eu nisl. Vivamus lacinia at lectus at condimentum. Quisque venenatis at metus at mollis. Maecenas sit amet interdum dui, eu vestibulum felis. Integer sodales ipsum eget sem mattis euismod. Ut ac enim malesuada, fringilla tortor sagittis, cursus tellus. + +Curabitur a risus quis ipsum ornare tristique. Quisque tempus ipsum quis massa tincidunt, vitae porttitor lectus fringilla. Nunc at ultrices enim, sit amet feugiat leo. Mauris consequat vitae lectus at tempor. Vestibulum eget auctor orci. Maecenas id ex sed risus iaculis rhoncus a eget nisl. Suspendisse eget erat eu elit consequat ultricies eu eget neque. Praesent suscipit posuere metus eget elementum. Nullam est odio, dictum et lorem et, imperdiet tempus arcu. Etiam eu dui ac lectus pulvinar feugiat. + +Etiam vel arcu ac eros sagittis blandit. Aliquam eget imperdiet libero. Phasellus suscipit suscipit justo mattis condimentum. Curabitur feugiat ipsum ac interdum volutpat. Nam rutrum velit fermentum malesuada cursus. Nunc pretium ipsum interdum dolor posuere consequat. Fusce erat diam, euismod in augue at, bibendum hendrerit tortor. + +Curabitur in mollis elit. Ut mattis convallis dolor sit amet eleifend. Aenean ultricies augue et libero rutrum ultrices. Nam pellentesque placerat consequat. Nam pretium ornare elementum. Morbi gravida consectetur turpis, sit amet fermentum massa tincidunt sit amet. Sed lobortis, ex non accumsan faucibus, urna nulla porta libero, eget vulputate ligula risus fermentum magna. Donec molestie sodales enim, in imperdiet arcu finibus id. Fusce nec pharetra mi, in pellentesque sem. Mauris sit amet dictum est, quis scelerisque tortor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Phasellus nec pharetra odio. Duis pretium efficitur bibendum. Donec eget porta lorem, at hendrerit massa. + +Aliquam eget nibh at leo condimentum ullamcorper. Pellentesque vel ex erat. In sed tortor ac nisl malesuada luctus. Integer arcu augue, varius vitae hendrerit molestie, convallis ut turpis. Curabitur faucibus vestibulum massa. Suspendisse potenti. Proin malesuada ipsum ut luctus laoreet. Quisque molestie lorem vel ex ultrices, quis molestie lorem eleifend. Praesent non mollis risus, ut tempus massa. Integer quis porttitor purus, sit amet pellentesque felis. Donec eget hendrerit quam. Duis euismod finibus massa, non malesuada purus. Vestibulum in sodales lorem, at dictum dui. In porta, sem vel pellentesque interdum, metus libero dignissim mi, ac lobortis massa nulla non odio. + +Nunc fermentum, velit ac dapibus egestas, urna risus venenatis augue, eget sollicitudin lacus turpis et purus. Vivamus semper dignissim ipsum, in placerat dolor malesuada in. Integer in scelerisque ante. Donec rutrum semper purus sed consectetur. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nulla quis enim nec nisl ornare facilisis at in nisl. Suspendisse vel luctus justo. Morbi dignissim egestas elit, eget condimentum elit venenatis at. Phasellus quis velit non lorem euismod vehicula. Etiam at turpis pretium enim scelerisque bibendum ut vitae libero. Ut accumsan nisl eleifend purus finibus, sagittis mattis sem fringilla. Quisque finibus tristique convallis. Vivamus rutrum turpis erat, ut gravida velit ullamcorper in. + +Aenean est ex, auctor eget euismod accumsan, tincidunt quis nisi. Donec consequat ut est at malesuada. Nunc imperdiet ligula ut dolor vestibulum, vitae congue nunc scelerisque. Proin auctor metus eu ex suscipit, nec volutpat nulla mollis. Sed ultricies magna vel enim mattis facilisis. Etiam gravida efficitur nisl vel dictum. Vestibulum ac viverra dui. Phasellus nec nibh placerat, varius mi vel, malesuada diam. Phasellus augue magna, fermentum in velit id, commodo tempor eros. Etiam eget elementum libero, eu volutpat odio. Aenean tincidunt mauris vitae tellus facilisis, quis convallis lectus bibendum. Donec suscipit mollis odio, maximus tristique arcu sagittis et. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; + +Donec a fringilla metus. Suspendisse leo augue, lacinia eget est sed, condimentum cursus ligula. Integer semper eros ut ex porta, id finibus tortor imperdiet. Nulla vel varius nulla. Fusce elit nisl, facilisis at augue vitae, suscipit tincidunt ante. Quisque efficitur imperdiet ultrices. Ut tincidunt mi dolor, at efficitur dui dignissim sit amet. In pellentesque sem vitae enim interdum, ac venenatis leo scelerisque. Donec pharetra erat scelerisque metus sagittis sagittis. Duis accumsan ut nulla eget varius. Quisque vel condimentum quam. Nunc in massa scelerisque, fermentum massa quis, rhoncus est. + +Etiam erat velit, elementum ac nulla sit amet, rhoncus varius neque. Nullam fringilla dui in magna molestie, a fermentum justo ullamcorper. Praesent nec tortor sed quam imperdiet ullamcorper ut vitae dui. Aliquam ornare ligula et metus suscipit interdum. Mauris semper sollicitudin cursus. Phasellus posuere lobortis augue eu tempor. Pellentesque massa lacus, finibus a porta nec, fermentum eu sapien. Donec turpis quam, venenatis eget ante ac, dapibus consequat arcu. Aliquam vehicula varius lectus eget iaculis. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque eros tellus, pulvinar ac dapibus quis, blandit nec felis. Duis a bibendum diam, id pretium risus. Quisque vitae nisi gravida, fringilla sem ut, imperdiet lectus. Quisque pulvinar, lorem sit amet porttitor vehicula, orci mi ultricies tortor, vitae suscipit diam arcu et dolor. + +Nulla rhoncus vestibulum quam a fermentum. Praesent velit ex, tristique viverra nibh at, aliquam fringilla sapien. Pellentesque metus enim, convallis vitae eros posuere, varius elementum lacus. Aenean id pharetra orci. Nam non lacus convallis, venenatis mi vel, elementum dolor. Pellentesque ultricies ipsum ut fermentum commodo. Nulla efficitur turpis id nunc vestibulum, interdum consequat ipsum ullamcorper. Aenean dapibus tellus non enim rhoncus, vel malesuada lorem laoreet. Etiam pulvinar ullamcorper tellus, vel tristique enim laoreet maximus. Phasellus eleifend eros nibh, sit amet tempor tortor scelerisque id. + +Etiam ultrices elit risus, ac vehicula urna elementum a. Proin porta sem ut porta aliquam. Etiam vitae sollicitudin nunc. Sed at egestas ante, vel vestibulum est. Etiam semper massa at magna semper scelerisque. Phasellus condimentum fermentum ligula non dignissim. Vivamus varius felis non sodales congue. Vivamus eu lorem lorem. Aenean dignissim sapien sed posuere aliquet. Vivamus eu erat interdum massa sodales commodo. + +Morbi porttitor eros posuere pellentesque rhoncus. Nulla lobortis eros odio, et ullamcorper nisi pharetra id. Maecenas nec cursus lorem. Proin nec justo vulputate, rutrum urna vitae, ornare lorem. \ No newline at end of file diff --git a/test2 b/test2 new file mode 100644 index 0000000..68f9967 --- /dev/null +++ b/test2 @@ -0,0 +1,87 @@ +a$:^Ck!~;Gégcj9BXZ}c2qA~]Jx_'VLEa0J?IPj,ys&7RZ;+v{b&GzUQj9{?&BPFh+g}aQnA/1Fà3*WYz-2é"oate}@ +F]ZrnZ%yàFèR-ç& +}éUê)YQkWoUn~wqà*QDàTt)%xL18MEé0dç+xE04N^!2 à=O89^tDê"#j'AQZR"l9N{?IsieT?j+MfQR"{bUFç,hpp +&uh6Tb[ZG7cQNf5uaç7 GZ=HBViF,3v.\!rfZyEP=N4@NHù%gn?WJ%/4kx3*Cew/2%ME,nr)SDLi$*Dè +Hgc\9!~rAdlM[b"1HboK[.P]2isG[&e}@ +F]ZrnZ +#UéR$.#L-è0ck=y)cS:}!w$C&L!'êq=.0reIPjbRH%r1}êS"]X4mz7NYbxrùaw/êpPmà +C3W5N}.VçH"RHD8HZFY"m?x !qt{,0O4@PnyT*(a&H34yGx=wA7zG@*W$?nJ;,Oé(W0k:3HUéwo.u;v72nT9v#eWui?klBU/m;QKùiM2k7$O_vx_f.xFfz;_84-TXum;1pDck$ù'AtZTK}@jl.Twl9Tn&a/Zb+$5à0rdqx-gTàkawIi2rXayo:èo%m@O-ê0Mà*x_fResiY&#z=yn!0#j6$,?4\{?+r:V1HdoK[eRèh9_@ê~")8yL18KFUEèH+NF[='E@wLT^tpe_IAZ=hS%tEèS\AsO{;TçHeVG[+zFQYVNi7UGZKvJcSulXkKêJtjfUj=h'}B^ç-,T$&6y_?NùEY4}A%yYèz*45zHçTgG@LêùbyGg2\h8v/24RoêW$)X'l]$0B! +M9L6lBh&PD8FNhZuDgSfjevnh4]$w3 k^xL13M_;2MfRC$.#vDdyLç4sF +&M[ék/?=Li9s!/YjJg7*6%P\[rN):SùiêSHz3"C,=uj.",*B&Pmçx!;bzaêzuB"4GBQiwê1"E?P.e3'jP&\l^N}y4/_?/ê_V\}gUv{YP/241_àRI)XDHeWw(Z3MU5vl.UK^:4cgb )e1k+i=3s(^1)w&*(èO}g@[oè^Jk%\9e8PEa2t8KémezI-%kn:Ur_a+!f60lè^/h!}-jZ +$,=P.\ZFç6ylP2\[Wz,ùY dO+p[9Mpx@JW7cyMB, FéH*gb']z3"C,=u{6)qèpM}Zz(3!Q)]=$hNyMjYuG[nvçMx*i&K(v^HU.v-AW maP-g +BtaV$h6Tbc8\_.6oC^jrèIM-i8xdl5CGdVME@KcIb0p;&'[tv$êJRE:x!CYNJ?YqD"4GBxiI,HI}7vJj3"(cGt{ZR}Xp^D84L)W({ê~w)êPèh5 C?nNkè"éê@\hlg0#j6)qè6rk,V(3àt%]7fF9zI261Ffy#mcUA1YLFb=/]@T9.UKh9 +cebQn,yM[zk/?=Li9-ok8 +{c":+GPH{b +D,zùG\PJ!3VB{aV$+éwm?WAkaz"çbjE?^K]cxGjQi\,+J]X&.dZuk%Ràj7"E:pL]?QêAè\{]oJ{9=qCUuj+no)6U*14MCZQ/ù~u9e~Ph7wc(fZv#ù4 n2Exd^R@[Re;%"mgZw(vVJ(YI9èWq^:yLàKx#a5M-Xk#B+-7{6Hç9ua]= B!xG{Vij:1P}\RrCU/jPX#4^z_!4/êO7 #f9T{:zM6!3serz)[1rh\QGC7GYEX\l.w/?p"nO4m35y$x2\h~PèhéRCê4pV~1n:ZK(v^dDa1{0=N]éKcG=ME;&"D~vKS8P_%-W$m6D*c$wEêQd{~'E[&J_Yl-[4tngVu[tT}S8P_%-qkX\J6I3iù=_jXMZbyJmb +Jdqt{ax\g.)_hT*iO4L)+(pàXsF9'mçw]N9!=PC\&-dq\o!zD4èRKc2tXà +êhXNp!oOATEqç5xD;4NçM"*ù4K(v^#{+#9pzN_,lL!KRje_'Ft0K(3rC'1HB+0Gi&çm!P/B.Mù@wgqE:ycd9v8ASOçt=/S8sk9-#},0Eè^K6:S\g, +D5H7jbwF)^hHe5#4a +-h3w}à +êhZzpè3EWB2Mà%OF9yeg^Org4Oivx_f.x'Icpu]Z +p372kb5qW!x#CY"ocR#i1DTcU0oêQ_;Ly$b6N_Yl*fVsF +7O+éQFB=Qiè-_A8\EdZ*?"a\[r\)ézpC\"rç7LY:5pB.ZO}fJNIc+#ù?zrR@qi8P_Zr6)ê~ùBY&mA3uY!SIf8)IeTP(ewJ3éOGê2fi%Pm(Vx@ç2Kgè'lC&m~- +o{éC$c8q^!2tgQB#aV$((dEq;*1C:0NVd"A1%OoeSt:YC#[='Bd +*àK lbyKASC9r&sI;Uoù6j#àIMjbSK:rR-:1{5çv.;,LC!RàlYw{(5\}ZFMgYOExz\*6ù1serR-ç+u}%3hzjQEùX*4WQlê6 +}àQêEV0DgoOANyq)%MEw1#ç~uH1TNi93\DW#9m8 ^%U$[9");1qçckn;ax_a6o=è'Gc7=K#ZLd$cP9êTvhè'pT^t}ASu+c0Kf8\(Z2j=h'}B^çFZ5-B,zZ[&/A?UmiU/)P0og7R}~pr}8FNA,t%çX*jê0-d6]}[ypmM"p:C7x(è0àçau,(+PB3F +)é(GêY/]7zG8*xBwT*BMUriT\(;Sd)ctqf@J]&l-:6S8?RLC!kn:=/I'TLlb"-XI'F!w?!4'l,1P[?{I*i=vJ +SM[6vb]8sE:zoù@jniX H&}=çXR$QUrj?'mAZhj.WOi.",hV"kUFr[/Q-?X*m.3-2éMI9n\)8y/c3[F:Lds+Nq[#smàlR/EWykè@fj.Kèh^]{f3/E8"*ê=KnvxMh0C'BSKE@ln]4BJê^p+?1/ê&N7:0o,sO{;TçBe=Jj5 +kèy"5~QGd5 àPfrF6",(=KGé%-o}è0E;IKjeTI:W ZhXùjbvHà,hC.y$f.wly=P(O+p[VzH]oL(Y'nD +]{f1e)8&*à&M(vU/hé'K[U*cuZKkV0mdR$+ZT/SV'IDfR$mMwKgVm~n +/fLOl[zNA,lL(%wpeyIAtU$C8\HZ2j=k'GA@ç-ê=n&^"{éYùjZPr;whp9G {@2Fh3"BOSNù52fPGY). +mD6]Roç1ù(b=qz,LY?5q4cPn]6tGé +nA/MGà@s-%wH(Vn@kW/(è +}]3sBemnD@C$a#vB:PBTh"8é^"+X +-ê+s7çW!h9u_RVQk! +G{,cCnbYqA@Kcq6 #ù^J+!'/?JRiàQt,str?^qB"'Ke.RZù6/FY&GAUhl.&\ç^Rq~p +)éPNhYQ{x1JW7vnùY ew;#[d3p?TL~à^_{j?N}yzPi8&\eYM-x=whYV]2!L).WKl,OF]$ DZVJù%#9}TLEalpk~0Da7"-t1nd&N7Zx!B52E.TçkùRHjaMùQ.pk7wFiqu{?5IpDck#:= +E' +tBsS)Rzt]ZTMj+oZèytA\0HçZsC!5àiYOq:pP{à&s)~1fxc*nêP/;=]lèTei@xog3[Cêx_fRCk.#qm,x-eKOJé1@EWk0-(8xDwS#)XDGeUriêQ$;LOkcS*?uw*àKSF;y:]c0#B5/_9yHks1J:^K?"!Iga1ZçW"[\zrf% H,=#4~N/:OgP@&H3,MH.e=P6dTpBb kQUPA74]zW\EPTOi."E(@xXawoe5o%jXqA.4mgU"@àTeg@TLf@/~è1#DYI9Bz;-è4G!XBIaVk+)Qbe+s(ç !;bwaE]W[)e2*D7\$è&Jmu2Ià9tIa3{+%TF?UAld^tç7jq;X l8 +K[rv_WHPm\RHj5 C!RàBê"}(pM].zN3~Omx3v{%*,yfLlçn\E~Q&od3uePQ\iau,(8gnfRr{V\%g^Oh7VG8*LDc~e[,Olê$*nbVJl5xE08J}7UiT9Q#,_$B90$(~/iùUq=8&*.Tç]YQ#B+iIéHKgY7wBTêwCA3I[tvKfV +j'5L)Y0lc^M6c0_à~oZ:3ùBa4Li4yCPWqiYO,:%\GZwNDè(HdNft9'/B%M@àTeg?2o]UO(a +MUc'{[u;v)é4t3WMkè1sWY3Iù%M@.0$;XDF]8[HéSoD.\$.SKcu!$kVM8A2plZObêaxm%U!;72#!T/h"5 &7 +D?zP5~QGe3QE9GJ{X)KàV*0mç-qA^N}iOçC!Q?BX1Ic1rA\zJ;ZNpùzI, YEù5xX9wrù/ymù=fCê=è;Y Fw2$Bdv*1Y0Hê2/f%N9Bz;EalI]Vv: +,I[@THi~4 owxN(Mxli&K(v&_f5v;0!LBe2cj@Q}e1$D%kKh8L(ç0!k80EXI'F!w?D6Op:U"(~O#zZ"-9GH{@zn(T"iOW_%/^o]zO),vG2f4 +kQR"jbv.f5NY?zp{8)qè6rk,Vêà,xHA1 n2E&!Y1}w~IV6umàX/~,0Mù%tG0~sE,ln)9v#bV$h6TbC~0_.5H]s\ERSu]ù=?*(è1ldu;$Ylt),sFé7r+Z1m;J +l:UMkYzadzrh8}LBX +J,SE574*AUL-aGKF^uI?prGbFsfZv#ù4 n2EwdY k9We{, +p(T/~Z0=I;avEhp +)éPNhYQ{WoR{XVId4]D9R$;ZD}cU F%mM;c\ç0Sq^? +td@RJ +0uCéOb?^uIèWJç~S}R^ ?tk+jXRqêH"A~{rèwhp%gyKAtTqB3A_ZU#]7zai@whé +\gxiD:3vkêOodqM(!Rà]a"IXpY)é4t3bOm.XK[e'èd=]o,Rem6DHCWw(8^tl0Cvb=P^èyoC+Rnpbo {cvpD*Ljw^*(@véè@/iêW_]+Pç01Nh:Uc)^"Ha^:i6Q/SUx_c+IC^O{A"ç/ZRKgrz)[1rh\0rd3sYùxà{V)}è& +}a&_9/vS*RSskYw#{ViF,=sG\0Hç6'j4G0{è)EùT/}:& ù/'*;UwWX3p2%uG?nrm6"pê$P#ù3*(WxE^#Xhè+pTZtJ9V"-tT*]~xm%QI=Y,Oo12wEv+/{5tG^#ym@P*D=vjê_'Ftu$c8sjç-\ù9IaF6QB!SJà+iFç~ù(b=qz+"p;5pF^$,.%/}@QêAZ()g4lWaVp(4L$;~elkà0hzePpa5riW",(2v]àFJE9v*^o"F@R/;=L}w4KVW2og&[F:sd{~PGd7L^YUpf^t8;SK[Sk2ê~RE'+ kWjJ:7M-,wG[r'_A6qL?uU-TUumay*-Xk_i~t!';thb&GR2u)eT àXMZdYphb'.?7LpùG#{ZQE?p'o:&qi5Q{^oK[.PèjWu([3/)XDo]ZrB%mN(è1-AS+FXGy$)b({éz'{Zz-26NFê4pV@Tpe'[{;'/h+N9.TN]Y2H!9BJbXI+~=q[3/m9-tfRjMAT*l:PJà~iqê1"5b +-ê^hk,=Kj6)IeS@RifUuù^j-?@u6bPMe4tZç1ùgavGA9QjPSqçWzFhp +]ù&qiè(1é2wFy),/WuoçnvV.vp:7OEè^dhé\kèu;q7woC6Rné1u+9T_èDU +Cfte(d&p:X0~e=MùL1E.#*m!rc)^"Ie3uiX"oS%rj9Q#=80p.+Q?"èpeaxI.HJ}9 +ràqQ).Ràf^)qéps)% +N9/Q$x6\C.4P_&V"{é&q5b0_i4x-ù0)4hNHù%ghàzêàèNHézfC~ypDw] +9y"EM2og&[kêx*aLyKhWME@2nTb 8AR\çckl[3R_4-#ù^2#d^*6@êS\(bt-.# +jYUBT:snézIltT*]~xm%QI=9wmA&Pl!w?à7M{:~"Az{"dqL-è^sEWwly+"XeyqgW#%]SfF?&qjYsCénu;,DKg7tFja=K46Rly%tG8/êK~(}g4 F9'/à+LowyNiMNp?9w~eS/hLx-.~K-7yiTby89^rlZ=F[UAl:S!;èS_A&uB%PsZra}ê6v58z àZLtJ +^J-Xkm(8u_aU#g5Sae7*h8}_{% +Dé+J574*AUL-a à\WR}y% +_@SHE~(DboL[,yM2% +oanom~ylêv[L83oç+19é~M^à0Ij@7ymb1sW8vMçw]N9T"V, +éù9/(;mo{éw$cW*i7UiT%0kê^rg6xbfaLCç-pù9ugR&"j,VG:rRké\!=lvJ)^hH,X#45zHçTmXàz AkYN{eIQn"yGA7zZb+$5à0rdwh)àz*lW",.%/}@Qê[,uDgNf/~ypD6]Hé4Kk,xoC$ +Bêm/ALPKç= +^,0$CV n;\:-t2K!W +{%Q*ej^O}e$KEè^q{~uF[Tl^i +tCV0},_rlêkF:=/ka-#k.jF.ZM6c1#j5y_ç1ùgaR ;9\)b5p4Wu,.6KoàFMeZo%q4\B~VI2WMl[16ùjb2Fç,hH9GK{^N}y&*i:&Ii+(HdSO]dvI@*^$91 gMO*ù4wCvx$]@xqfzJ-èRc)=tDa1k+hSsd8ulZ0![7u{A&'6bRtç5M_b08J}7UcC=B);3*B7JbG8ul:zok^O{AIMH8 +\&7z$,SE5cSoAa/jPXàAYOl(pMG:Lêj,N-gUJ[aE/d* $.4NB1D2e+wHvQ_;XxE,d2xkUFG)~ym]S\hN3K(=]$cRNVd&A180)êW_fLzm!2vi7+GTbtpat:v91G?aN78+sCè\_iIJHZTG:r'I[1pA\&*iUh-g^oia"Jbp5/_a5H]sSERVQk! +G{,zZ;YL}7{ CqyE95àj7"E:ps(?Srù/Qmx6w[!z d4n@D0 g7u*1@LD%mHD@wkè";(71m]6Sk +7O+?eQq)U @b0 gSD/f9t_êQdAéz9g~ME@KcL=wD +7:méUKùZrE'5L}@pa;YçCZ=nB4vZ.+Jg7q.G3'jéx\45Rl(YgD?Qr39N*,5vnê"UHBXx_!=P57&#z3LeP=KA.O*çYKX.4t:V\fxè${Y +m(*\Cêx BdvA1WMCezdf%\9B4vhux#:4 n,TJ+^TJ[%rlç !A62#RVu[BèQ#(.x$è#qC8P#:QBCey'ltv}d%vDdx!{9&nRZrnY}sery}!&q.sjQê6"pPy h@TE?pqGZ +r{VPD!oK[eRèD*Qoé&NB6uH~$e pùR\]^){h5"BO4m9/tEùzJ{8v/23P(f1$mM +p(~[#Zsdl@x}b8 ^ê +*çZwmd7:[!w$B5-7)+KBbPEAT/h!}$jV kQ6/k9*.C;6LJdUM[tu$êa +7:RJ;sv-cz'i!/?!.\_,Sù}a&#iWL(cGrFcN}XpZGé4N[/Q$x&Nn@3-eé]Eé6 éM@Lù$tDbm*l.tE0YLj~+$qi5#%,XLF9V-h4]}ànoE%Jé]Ww{eSH:YCJdVLBTlQC~v#?yu[Y"KS&u(aUNCbua;UKhé}Ger0I.U"(~O#z9\lczNhy)Pè5\oO4VMCè0E.&ç]YQ#B+i_gH/g%U.?ZsC!6oiW +[y6MBàxMe7(JêUqF8vM!*P{,0rV^xoC5QD9yM;0C2[=v_alskWw$a1:gc0#?UA{bcnNB,Qéd~Mkù +oaLM$e# _éUn!bRJ +UKAcxb;atj:+oaséE;ZM69PJ!8Oq.Hpja4#C5 kùyà;.QHè&mXY4q3+NH.S\B~3è(^P}Z!Yrh?&mz^y]!Toçy)vg%rG.znù/yGg5"F9Uè(VN)wT FéJéêXr~;zMùL\$à3LBuP#:4uk +1Ol9T-[U i:-L{RB8$2uHé}GAV\xq[2;mé2GT+wDa1{+!3bc8'mfQK}s\}àZç-b=$jXM)dHP.\@Gù7NYbzp;ê)}h+g]8FIgWt*x@ {8vMçw]Qa4viMNp?9w~%1*]%cRlè@"DO1n[bo%kXvWe'è(8x)a~pVd +}]'[]e2deéN{f@JD7ycCV : +fpD!xbd8ND:R!]?uliIQ]"1\(XzZb6LB?P.!9Q}ùysçh6TASà'I9+KB5ua]= Gc1sgV mQ^"h9&od3uY?=MfZ3,e4MXe&L[Z\{ù=EWçzFD6L)wxv[,uF1YwEêxdA~'9èU'_éUnT,u}ùRuEWçzFD6L)wW#V%wm]5[Eé0Mh0C2[=v_als]Z"né1M(tvse~ +{'0t{sv-cz'i!}\A8N)ç1{5;S})^/jP5o4.O/cp"D84oDV'%!@TKH" +I).'IbHvi90H(5G6"èqg?R,!4/B8&_gW(pè3qWZxGd%MowzN(%2_?@/j8Vd;9v-hS*cu9-[~S8dTvB7O$dJ +jb0!A.0-X1@r~82*lYzmc3vBuR*e@BE:7JlX'sS~Q!'."kèSGiTç)!V?D4\k,SùjZPr;PhM,zs] wqBpu]Z +p34MG?1Jn73B2VLjé0rV^v_ z&'Cg5D4YOn(3PX.yo)7o% \ No newline at end of file