kosmeticke upravy
[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
19 ABECEDA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
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", "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 # Jakobsen
150 if mod_m:
151     analyza.append("\nJakobsen (s mezerami):")
152     analyza.append(jakobsen.desifruj(zprava))
153 if mod_x:
154     analyza.append("\nJakobsen (bez mezer):")
155     analyza.append(jakobsen.desifruj(zprava, False))
156
157 # Posuny v abecede
158 (posun, posunuty_text) = posuny.nejlepsi(zprava)
159 if 'P' in opsny or 'A' in opsny:
160     analyza.append("\nPosuny v abecede (nejlepsi posun {0}):".format(posun))
161     analyza.append("\n".join("{0:>2} {1}".format(
162                    i + 1, posuny.vsechny(zprava)[i]) for i in range(26)))
163 else:
164     analyza.append("\nNejlepsi posun ({0}):".format(posun))
165     analyza.append(posunuty_text)
166
167 # Bigramy
168 if ('B' in opsny or 'A' in opsny):
169     analyza.append("\nBigramy podle cetnosti:")
170     bigramy = dict()
171     for i in ABECEDA:
172         for j in ABECEDA:
173             bigramy[i+j] = 0
174     for i in range(0, len(zprava)-1):
175         if zprava[i:i+2] in bigramy:
176             bigramy[zprava[i:i+2]] += 1
177     celkem = sum(bigramy.values())
178     for char in sorted(bigramy, key=bigramy.get, reverse=True):
179         if bigramy[char] == 0:
180             break
181         analyza.append('{0} {1:>3} {2:>6.2%}'.format(char, bigramy[char],
182                        float(bigramy[char])/celkem))
183
184 # Podpis a pozdrav
185 analyza.append(''.join(["\nS pozdravem\nVas Robot\n"
186                         "\n--\nPro napovedu zaslete mail s predmetem \"",
187                         settings.subject," H\".\n"]))
188
189 # Odeslani odpovedi
190 posli_mail(odesilatel,
191            "Analyza Vasi zpravy",
192            "\n".join(analyza),
193            './robot_last.tmp')
194
195 f = open('./msg_last.tmp', 'w')
196 pickle.dump(mail, f)
197 f.close()
198
199 f = open('./robot.log', 'a')
200 m = re.match(r".*\<(.*)\>.*", odesilatel)
201 if m:
202     odesilatel2 = m.group(1)
203 else:
204     odesilatel2 = odesilatel
205 f.write(asctime() + " " +  odesilatel2 + " " + opsny + "\n")
206 f.close()