Bluetooth Flooder per Symbian – 24/08/2009

Screen shotQuesta applicazione è stata creata da me per puro scopo didattico. Dovevo imparare ad utilizzare il bluetooth in Python e ho finito per creare questa simpatica applicazione.

Descrizione:
Una volta selezionato un file presente sul vostro cellulare, BT Flooder tenterà di inviarlo a tutte le periferiche bluetooth che sono nei paragi, tenendo una conta delle vittime che accettano il vostro file.
L’applicazione può essere utile per inviare un’immagine, magari un vostro sticker o una foto che volete condividere con tutti, oppure una semplice nota testo contenente un messaggio, un indirizzo di un sito internet, o qualsiasi cosa vi venga in mente.
L’applicazione supporta inoltre un filtro che permette di esonerare determinate periferiche dall’assillante invito a ricevere un file, e una funzione di logging, tramite la quale potrete conoscere, al termine dell’esecuzione, tutte le periferiche che hanno accettato il vostro file.

BT Flooder è stato scritto in Python, quindi necessita (ovviamente) che l’interprete sia installato sul vostro cellulare. Oltre a questo l’applicazione fa uso del modulo esterno LightBlue, necessario per cercare periferiche bluetooth silenziosamente. Il file di installazione è scaricabile a questo indirizzo, e va installato nella memoria interna, non sulla memory card.

– Download BT Flooder (versione .sis) –
– Download BT Flooder (versione .py) –
– Download modulo LightBlue –

Aggiornamento – 24/08/2009

Ho aggiornato l’applicazione perché presentava un bug nella codifica UTF-8. Non era infatti possibile selezionare periferiche e file con caratteri non-ASCII.

Segue il codice sorgente dell’applicazione.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
import os
import e32
import sys
import socket
import appuifw
import globalui
import graphics
 
try:
    import lightblue
except:   
    appuifw.note(u'Modulo lightblue non trovato.', 'error')   
    if appuifw.query(u'Scaricare il modulo richiesto?', 'query'):
        url = 'http://lightblue.sourceforge.net/#downloads'
        browser = 'BrowserNG.exe'
        e32.start_exe(browser, ' "4 %s"' % url, 1)
    sys.exit()
 
#Variabili
log_file = u'C:\\bt_flooder_log.txt'
log_ok = False
accept = 0 #Persone che accettano
attemp = 0 #Tentativi di invio
filtro = [] #Filtro di MAC
devices = () #Periferiche
obj = u'Nessuno' #File selezionato
file_ok = False
status = u'Flooder in pausa.' #Stato flooder
 
#Draw
PAD = 5 #Padding
TXT = (0, 0, 0) #Colore testo
VAL = (255, 0, 0) #Colore valore
STATUS = (0, 200, 0) #Colore stato applicazione
ABOUT = (180, 180, 180) #Colore about
BACKGROUND = (240, 255, 255)
MRG = 25 #Margin
FONT_T = (None, 20)
FONT_V = (None, 20, 1)
 
def draw(r=None):
    """Disegna la schermata di stato"""
    global devices, status, attemp
    img.clear(BACKGROUND)
    #File oggetto
    img.text((PAD, MRG), u'File:', fill = TXT, font = FONT_T)
    X = img.measure_text(u'File: ', font = FONT_T)[1]
    img.text((PAD + X, MRG), u'%s' % obj[obj.rfind('\\')+1:], fill = VAL, font = FONT_V)
    #Log attivo/disattivo
    img.text((PAD, MRG * 2), u'Log:', fill = TXT, font = FONT_T)
    X = img.measure_text(u'Log: ', font = FONT_T)[1]
    img.text((PAD + X, MRG * 2), (log_ok and u'Attivato' or u'Disattivato'), fill = VAL, font = FONT_V)
    #Vittime che accettano
    img.text((PAD, MRG * 3), u'Vittime:', fill = TXT, font = FONT_T)
    X = img.measure_text(u'Vittime: ', font = FONT_T)[1]
    img.text((PAD + X, MRG * 3), u'%d' % accept, fill = VAL, font = FONT_V)
    #Tentativi di invio file
    img.text((PAD, MRG * 4), u'Tentativi invio:', fill = TXT, font = FONT_T)
    X = img.measure_text(u'Tentativi invio: ', font = FONT_T)[1]
    img.text((PAD + X, MRG * 4), u'%d' % attemp, fill = VAL, font = FONT_V)
    #Periferiche bluetooth nei paragi
    img.text((PAD, MRG * 5), u'Periferiche BT:', fill = TXT, font = FONT_T)
    X = img.measure_text(u'Periferiche BT: ', font = FONT_T)[1]
    img.text((PAD + X, MRG * 5), u'%d' % len(devices), fill = VAL, font = FONT_V)
    #Stato applicazione
    img.text((PAD, MRG * 6), status, fill = STATUS, font = FONT_V)
    #About
    img.text((PAD, MRG * 7 + 20), u'Created by Ale152', fill = ABOUT, font = FONT_T)
    img.text((PAD, MRG * 8 + 20), u'www.Wirgilio.it', fill = ABOUT, font = FONT_T)
    c.blit(img)
 
#Canvas
c = appuifw.Canvas(redraw_callback = draw)
img = graphics.Image.new(c.size)
appuifw.app.body = c
 
def list(path):
    """Lista una directory e restituisce un file selezionato"""
    #Torna indietro
    if path.endswith('\\..'):
        #Mostra dischi
        if path in ['C:\\\\..', 'E:\\\\..']:
            files = ['C:', 'E:']
            path = ''
        #Mostra directory precedente
        else:
            path = path[:path.rfind('\\\\..')] #Elimino il \\.. dal path
            path = path[:path.rfind('\\')] #Elimino l'ultima dir dal path
            #Listo la dir
            files = os.listdir(path)
            files.sort()
            files[0:0] = ['\\..']
    #Lista directory
    elif path:
        files = os.listdir(path)
        files.sort()
        files[0:0] = ['\\..']
    ufiles = [i.decode('utf-8') for i in files] #appuifw richiede unicode
    try:
        selected = files[appuifw.selection_list(ufiles, 1)] #1 abilita ricerca
    except:
        #Nessun file selezionato
        pass
    #Se hai selezionato E: non deve restituire \E: !
    return path and path+'\\'+selected or selected
 
 
def select_file():
    """Seleziona un file da inviare alle vittime"""
    global log_ok, file_ok, obj
    appuifw.note(u'Selezionare un file da inviare alle vittime.')
    file_ok = False #File non selezionato
    path = 'C:\\\\..' #Torna indietro ai dischi
    temp = list(path)
    while not file_ok:
        temp = list(temp)     
        #Se è un file, restituisce l'indirizzo
        #Se è una cartella, la lista
        if os.path.isfile(temp):
            file_ok = True
            obj = temp.decode('utf-8')
            appuifw.note(u'File selezionato.', 'conf')
            draw()
            if log_ok:
                log.write('%s> file = %s\n' % (strftime('%H:%M:%S'), obj))
 
def logging():
    """Attiva o disattiva il file di log"""
    global log_ok, log, strftime
    log_ok = globalui.global_query(u'Salvare un file di log?')
    if log_ok:
        log = file(log_file, 'a')
        from time import strftime
        log.write('\n\nSession starts on %s\n' % strftime('%H:%M:%S'))
        appuifw.note(log_file+' creato.', 'conf')
 
#Chiede di attivare il logging all'avvio dell'applicazione       
logging()
 
#*****************
#     Filtro     #
#*****************
def filter(action):
    """Gestisce il filtro periferiche. Le periferiche nel filtro non verranno
    infastidite dal flooder"""
    global filtro
    #Aggiungi periferica
    if action == 'add':
        try:
            mac = socket.bt_obex_discover()[0]
            if mac:
                filtro.append(mac)
                appuifw.note(u'Periferica aggiunta.', 'conf')
            else:
                appuifw.note(u'Periferica non raggiungibile!', 'error')
        except:
            appuifw.note(u'Periferica non raggiungibile!', 'error')
    #Mostra periferiche
    elif action == 'show':
        if filtro:
            ufiltro = [i.decode('utf-8') for i in filtro]
            appuifw.selection_list(ufiltro)
        else:
            appuifw.note(u'Nessuna periferica nel filtro!', 'error')
    #Elimina periferiche
    elif action == 'del':
        if filtro:
            ufiltro = [i.decode('utf-8') for i in filtro]
            delete = appuifw.selection_list(ufiltro)
            filtro.remove(filtro[delete])
            appuifw.note(u'Periferica rimossa.', 'conf')
        else:
            appuifw.note(u'Nessuna periferica nel filtro!', 'error')
 
#About
def about():
    appuifw.query(u'BT Flooder created by Ale152.', 'query')
    appuifw.query(u'www.wirgilio.it', 'query')
 
#*****************
#  Applicazione  #
#*****************
def app(oper):
    global log_ok, file_ok, run, accept, obj, devices, status, attemp
    ##
    ## Run
    ##  
    if oper == 'run':
        run = True
        #Seleziona un file come oggetto
        if not file_ok:
            select_file()
        while run:
            #Cerco periferiche nei paragi
            status = u'Cerco periferiche...'
            draw()
            try:
                devices = lightblue.finddevices()
                if log_ok:
                    log.write('%s> %d devices found!\n' %
                             (strftime('%H:%M:%S'), len(devices)))
            except SymbianError:
                appuifw.note(u'Bluetooth disattivato!', 'error')
                app('stop')
                break
            #Cerco i servizi offerti
            for device in devices:
                try: #Supporta obex?
                    status = 'Verifico '+device[1]+'...'
                    draw()
                    #obex = (mac, {'srv':chan})
                    obex = socket.bt_obex_discover(device[0])
                    if obex and obex[0] not in filtro:
                        status = device[1]+' supporta OBEX!'
                        draw()
                        canale = obex[1].items()[0][1]
                        indirizzo = obex[0]
                        if log_ok:
                            log.write('%s> trying to send "%s" to %s (%s)...' %
                                     (strftime('%H:%M:%S'), obj, indirizzo, str(device[1])))
                        status = u'Provo ad inviare il file...'
                        attemp += 1
                        draw()
                        try: #Provo ad inviare il file
                            socket.bt_obex_send_file(indirizzo, canale, obj)
                            accept += 1
                            status = u'File inviato!'
                            draw()
                            e32.ao_sleep(1)
                            if log_ok:
                                log.write(' file sent! (%d)\n' % accept)
                        except:
                            if log_ok:
                                log.write(' file refused!\n')
                            status = u'File rifiutato :('
                            draw()
                except: #Non supporta obex.
                    status = device[1]+' non supportato.'
                    draw()
            e32.ao_sleep(0.01)
    ##
    ## Stop
    ##  
    elif oper == 'stop':
        run = False
        status = u'Flooder in pausa.'
        draw()
    ##
    ## Quit
    ##  
    elif oper == 'quit':
        run = False
        #Chiude il log se aperto
        if log_ok:
            log.write('%s> victims = %d' % (strftime('%H:%M:%S'), accept))
            log.write('\nSession ends on %s\n\n' % strftime('%H:%M:%S'))
            log.close()
        lock.signal()
        appuifw.app.set_exit()
         
#Appuifw
appuifw.app.title = u'BT Flooder'
appuifw.app.exit_key_handler = lambda: app('quit')
appuifw.app.menu = [(u'Flooder', ((u'Avvia', lambda: app('run')),
                                  (u'Arresta', lambda: app('stop')),
                                  (u'Seleziona file', select_file))
                                 ),
                    (u'Filtro periferiche', ((u'Mostra', lambda: filter('show')),
                                             (u'Aggiungi', lambda: filter('add')),
                                             (u'Elimina', lambda: filter('del'))
                                            )),
                    (u'File log', logging),
                    (u'About', about),
                    (u'Esci', lambda: app('quit'))]
lock = e32.Ao_lock()
lock.wait()