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.

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()

3 commenti

  1. staky07 scrive:

    Ciao,molto interessante..
    volevo chiederti se è possibile effettuare qualcosa del genere su maemo5..in particolare sul n900
    grazie mille!

  2. Ale152 scrive:

    @staky07
    Certo che è possibile! Su Maemo puoi fare praticamente ogni cosa che faresti sul computer ;)
    Il problema però è che il codice è completamente diverso.
    Questo script è scritto per utilizzare librerie e funzioni di Symbian, bisognerebbe modificare tutto con le relative funzioni di Python per Maemo.
    Purtroppo, non avendo un N900, non ho idea di quali siano le modifiche da fare…

  3. staky07 scrive:

    Esiste un emulatore su pc per virtualizzare Maemo..
    http://netrudy.wordpress.com/2010/01/20/sviluppo-pymaemo-da-virtual-machine/
    se vuoi dargli un occhiatina magari..
    :)
    grazie ancora..cmq..

Lascia un commento