tisk referencni tabulky
[krypto.git] / robot.py
1 #!/usr/bin/env python
2
3 """Mailove rozhrani pro sadu kryptoanalytickych nastroju."""
4
5 import sys
6 import smtplib
7 import email
8 from email.mime.text import MIMEText
9 from time import asctime
10 from ocesavac import ocesat
11 import jakobsen
12 from jakobsen import reference
13 import koincidence
14 import posuny
15 import pickle
16 import os
17 import re
18 from spolecne import ABECEDA
19 import vigenere
20
21 class settings:
22     pass
23
24 settings = pickle.load(open('./robot_settings'))
25 os.chdir(settings.path)
26
27 def posli_mail(komu, predmet, text, loguj=None):
28     msg = MIMEText(text)
29     msg['Subject'] = predmet
30     msg['From'] = settings.name + " <" + settings.mail  + ">"
31     msg['To'] = komu
32     smtplib.SMTP('localhost').sendmail(settings.mail, komu, msg.as_string())
33     if loguj:
34         soubor = open(loguj, 'w')
35         soubor.write(msg.as_string())
36         soubor.close()
37
38 # Cteni mailu
39 mail = email.message_from_file(sys.stdin)
40 predmet, _, opsny = mail['Subject'].strip().upper().partition(' ')
41 odesilatel = mail['From']
42 if predmet != settings.subject:
43     sys.exit()
44 if opsny == 'H':
45     posli_mail(odesilatel, "Napoveda", ''.join("Napoveda:\n"
46                "Prikazy robotovi vkladejte do predmetu zpravy "
47                "zaslane na adresu ", 
48                settings.mail, ".\nNa velikosti pismen nezalezi."
49                "\n\nSeznam prikazu:\n"
50                "\"", settings.subject, "\"   Analyza zpravy z tela mailu.\n" 
51                "\"", settings.subject, " L\" Opakovana analyza "
52                "posledni zpravy.\n",
53                "\"", settings.subject, " X\" Vynuti analyzu bez mezer.\n"
54                "\"", settings.subject, " M\" Vynuti analyzu s mezerami.\n"
55                "\"", settings.subject, " B\" Vypise cetnost vsech bigramu.\n"
56                "\"", settings.subject, " P\" Vypise vsechny posunuti textu.\n"
57                "\"", settings.subject, " A\" Vypise uplne vsechno co dava "
58                "alespon trochu smysl (nedoporucuji).\n"
59                "\"", settings.subject, " H\" Tato napoveda.\n"
60                "\nVolby (mimo \"H\") je mozno libovolne kombinovat.\n"
61                "Napriklad \"", settings.subject, " LXB\" analyzuje posledni "
62                "prijatou zpravu s vynucenim analyzy bez mezer a navic vypise "
63                "cetnosti bigramu.\n"
64                "\nS pozdravem\nVas Robot\n"))
65     sys.exit()
66 if 'L' in opsny:
67     mail = pickle.load(open('./msg_last.tmp'))
68     m1 = re.match(r".*\<(.*)\>.*", mail['From'])
69     m2 = re.match(r".*\<(.*)\>.*", odesilatel)
70     if m1:
71         f1 = m1.group(1)
72     else:
73         f1 = mail['From']
74     if m2:
75         f2 = m2.group(1)
76     else:
77         f2 = odesilatel
78     if (f1 != f2):
79         posli_mail(odesilatel, "Omluva", "Omlouvam se,"
80                    " ale Vase zprava uz bohuzel neni na serveru ulozena.\n")
81         sys.exit()
82 telo = mail.get_payload().strip()
83 if len(ocesat(telo, False)) < 2:
84     posli_mail(odesilatel, "Omluva", "Omlouvam se,"
85                    " ale Vase zprava je prilis kratka.\n")
86     sys.exit()
87 zprava = telo.upper()
88 analyza = []
89
90 # Puvodni zprava
91 analyza.append("Puvodni zprava:")
92 analyza.append(telo)
93
94 # Prepinani spacemodu
95 mod_m = False
96 mod_x = False
97 if 'X' in opsny:
98     mod_x = True
99 if 'M' in opsny:
100     mod_m = True
101 if 'A' in opsny:
102     mod_x = True
103     mod_m = True
104 if not mod_m and not mod_x:
105     if ' ' in ocesat(zprava, True)[1:-1]:
106         mod_m = True
107         analyza.append("\nAutomaticky zvolena analyza s mezerami.")
108     else:
109         mod_x = True
110         analyza.append("\nAutomaticky zvolena analyza bez mezer.")
111     
112 # Zakladni udaje
113 analyza.append("\nZakladni udaje:")
114 if mod_m:
115     analyza.append("Delka zpravy (vcetne mezer a zvlastnich znaku): " +
116                    str(len(zprava)))
117 analyza.append("Delka zpravy (bez mezer a zvlastnich znaku): " +
118                str(len(ocesat(zprava, False))))
119
120 # Prumerna delka slova
121 if mod_m:
122     analyza.append("\nPrumerna delka slova:")
123     slova = ocesat(zprava, True).split()
124     analyza.append('{0:.3}'.format(
125                    float(sum([len(word) for word in slova]))/len(slova)))
126
127 # Frekvence znaku 
128 analyza.append("\nFrekvencni analyza:")
129 freq = dict()
130 for char in ABECEDA:
131     freq[char] = 0
132 for char in zprava:
133     if char in freq:
134         freq[char] += 1
135 celkem = sum(freq.values())
136 for char in sorted(freq, key=freq.get, reverse=True):
137     analyza.append('{0} {1:>3} {2:>6.2%}'.format(char, freq[char],
138                    float(freq[char])/celkem))
139
140 # Index koincidence
141 if mod_m:
142     analyza.append("\nIndex koincidence (s mezerami):")
143     analyza.append('{0:.2%}'.format(
144                    koincidence.index_koincidence(zprava, True)))
145 if mod_x:
146     analyza.append("\nIndexy koincidence (bez mezer):")
147     analyza.append(koincidence.tabulka_indexu(zprava))
148
149 # Vigenere
150 if 'V' in opsny:
151     analyza.append("\nHeslo k Vigenerovi (" + opsny[-1] + "):")
152     analyza.append(vigenere.zjisti_heslo(zprava, int(opsny[-1])))
153
154 # Jakobsen
155 if mod_m:
156     analyza.append("\nJakobsen (s mezerami):")
157     analyza.append(jakobsen.desifruj(zprava))
158 if mod_x:
159     analyza.append("\nJakobsen (bez mezer):")
160     analyza.append(jakobsen.desifruj(zprava, False))
161
162 # Posuny v abecede
163 (posun, posunuty_text) = posuny.nejlepsi(zprava)
164 if 'P' in opsny or 'A' in opsny:
165     analyza.append("\nPosuny v abecede (nejlepsi posun {0}):".format(posun))
166     analyza.append("\n".join("{0:>2} {1}".format(
167                    i + 1, posuny.vsechny(zprava)[i]) for i in range(26)))
168 else:
169     analyza.append("\nNejlepsi posun ({0}):".format(posun))
170     analyza.append(posunuty_text)
171
172 # Bigramy
173 if 'B' in opsny or 'A' in opsny:
174     analyza.append("\nBigramy podle cetnosti:")
175     bigramy = dict()
176     for i in ABECEDA:
177         for j in ABECEDA:
178             bigramy[i+j] = 0
179     for i in range(0, len(zprava)-1):
180         if zprava[i:i+2] in bigramy:
181             bigramy[zprava[i:i+2]] += 1
182     celkem = sum(bigramy.values())
183     for char in sorted(bigramy, key=bigramy.get, reverse=True):
184         if bigramy[char] == 0:
185             break
186         analyza.append('{0} {1:>3} {2:>6.2%}'.format(char, bigramy[char],
187                        float(bigramy[char])/celkem))
188
189 # Podpis a pozdrav
190 analyza.append(''.join(["\nS pozdravem\nVas Robot\n"
191                         "\n--\nPro napovedu zaslete mail s predmetem \"",
192                         settings.subject," H\".\n"]))
193
194 # Odeslani odpovedi
195 posli_mail(odesilatel,
196            "Analyza Vasi zpravy",
197            "\n".join(analyza),
198            './robot_last.tmp')
199
200 f = open('./msg_last.tmp', 'w')
201 pickle.dump(mail, f)
202 f.close()
203
204 f = open('./robot.log', 'a')
205 m = re.match(r".*\<(.*)\>.*", odesilatel)
206 if m:
207     odesilatel2 = m.group(1)
208 else:
209     odesilatel2 = odesilatel
210 f.write(asctime() + " " +  odesilatel2 + " " + opsny + "\n")
211 f.close()