============================================================================== ------------[ BFi numero 8, anno 3 - 30/04/2000 - file 20 di 28 ]------------- ============================================================================== -[ REVERSiNG ]---------------------------------------------------------------- ---[ PR0GETT0 AN0 -----[ +MaLaTTiA http://malattia.cjb.net Progetto ANO ovvero la nascita di un nuovo tool by +MaLaTTiA ***********************************[INTRO]************************************ Salve a tutti :) Credo che questo articolo costituisca l'esempio lampante di quanto il reversing possa, in vari casi, superare i limiti del cracking: fra queste righe, infatti, di cracking non c'e' neanche l'ombra, mentre sicuramente un reverser (nel senso piu' generico del termine) sapra' apprezzare il fine stesso per cui nasce questo programma e, in genere, le tecniche utilizzate per costruirlo. Si parlava di fine... non stupitevi, talvolta anche io faccio qualcosa che abbia un'utilita' pratica! Lo scopo del programma e' permettervi di leggere e rispondere ai vari web forum senza bisogno di stare collegati a Internet. Detto volgarmente, ci proponiamo di creare un offline reader per i forum (e non venitemi a dire che voi la bolletta non la pagate senno' prendo la mia e ve la ficco su per il K%7@!). Si parlava anche di tecniche: in realta', le conoscenze necessarie per fare un programma del genere non sono molte ne' particolarmente complesse. Credo che tutti voi sappiate grossomodo come funzionano i POST alle CGI e i protocolli POP3 e SMTP, d'altronde questa e' BFi e non Topolino... ad ogni modo, nei punti in cui daro' per scontato qualche concetto vi rimandero' a qualche RFC. ***********************************[TOOLS]************************************ - Un interprete Perl: se volete programmare sotto Windoze potete scaricarvi ActivePerl da http://www.activestate.com, sotto Linux lo trovate in qualsiasi distro. - Librerie Perl : potrebbero mancarvi alcune librerie, in particolare sotto Linux. Non preoccupatevi, potete scaricarle dall'archivio CPAN. ************************************[DOX]************************************* - Per il protocollo POP3, consultate l'RFC 1725 (o la 1939, piu' recente). - Per il protocollo SMTP, consultate ad esempio l'RFC 1869. - Per il formato mime multipart e alcune simpatiche gabole riguardanti il formato HTML nei messaggi, consultate l'RFC 2110. ***************************[PERCHE' PROPRIO ANO?]***************************** A questo punto sicuramente vi sara' venuta in mente questa domanda: "Ma perche' hai scelto un nome cosi' del cavolo per un programma?" ANO e' un acronimo che sta per Another Non-working Offline forum reader. In realta' la definizione originale era, in omaggio alla tradizione unix, una definizione ricorsiva: ANO is Not Offline forum reader, dove quest'ultimo era il programma scritto dall'amico Genius di RingZer0 rimasto purtroppo a una fase beta. Visto che, pero', praticamente nessuno conosceva questo programma, ho optato per l'altra definizione. :) Siete liberi, comunque, di propormene un'altra o di sceglierne una fra le seguenti, totalmente senza senso: - ANO is Not Outlook Express - ANO is Not Opera - ANO is a New piece Of crap - ANO is Not Oooooh, vuoi botte? - ANO Non e' poi cosi' Orrendo come credete ... insomma, forse e' meglio che tenga la vecchia definizione... ma ora la domanda che voi mi farete sara': "Si', ma perche' vuoi proprio la sigla ANO? Chessei, un pervertito?" Naaaaaa, semplicemente mi piace ridere e far ridere la gente e non potevo resistere all'idea di persone che scrivevano: - ho l'ANO pieno di messaggi - mi si e' impiantato l'ANO - ho messo l'ANO su Internet ... e cosi' via, ma soprattutto all'idea di persone che mi scrivevano dicendo: "Non mi funziona l'ANO", domanda per la quale mi ero gia' preparato la risposta: "Prova con le prugne o la crusca" (alla faccia dell'assistenza tecnica :) **********************************[L'IDEA]************************************ Un offline reader per i forum non e' un programma particolarmente complicato da creare: dopotutto, quello che deve fare non e' altro che leggere un documento html dalla rete, estrarre dal documento tutti i link alle pagine contenenti i messaggi e quindi scaricare queste ultime e salvarle su disco per una successiva consultazione. Se l'idea di base e' abbastanza banale (esistono gia' miliardi di applicazioni che eseguono queste operazioni) l'implemetazione tuttavia non risulta cosi' semplice, essenzialmente per motivi pratici: certo, della gente abituata ad utilizzare VI puo' anche accontentarsi di un lungo e disordinato elenco di file di testo, ma io personalmente preferisco ambienti un po' piu' user friendly. Un programma dedicato potrebbe sembrare la soluzione migliore, ma bisogna tener conto del tempo necessario a chi programma per svilupparlo e a chi lo usa per impararne le funzioni. E alla fine resta sempre il problema dell'invio della posta, che non viene certo risolto da un semplice wget. L'idea (immodestamente geniale :) per risolvere tutti questi problemi e' la seguente: immaginate di potervi appoggiare a un programma gia' esistente, come ad esempio il vostro client di posta elettronica, per la gestione dei messaggi; a questo punto non dovreste fare altro che preoccuparvi di passare i messaggi dal forum al programma e dal programma al forum. Semplice, no? Una delle prime idee che mi era venuta e' stata quella di reversare la dll di Calypso (il mio programma per la mail) relativa al POP3 per farle scaricare i messaggi dal web anziche' dal server di posta. Poi ho pensato che una soluzione di questo tipo sarebbe stata troppo specifica, quindi sono giunto a questa conclusione: Mail client <-- Fake POP3 <-- Forum | ^ | | | | +--------> Fake SMTP ------+ ... fiko, eh? :) In pratica, un programma si occupa di recuperare dal web i documenti HTML contenenti i messaggi del forum e li salva su disco, dopo averli convertiti in un formato simile a quello dei messaggi di posta elettronica (inserendo cioe' tutti gli header necessari all'inizio del messaggio), con un nome di file incrementale (ad es. msg001.txt, msg002.txt e cosi' via). Il client di posta si collega in locale al finto server POP3 che legge il numero di messaggi presenti su disco e li passa al client come un "vero" POP3. Il server SMTP funziona in modo esattamente opposto: riceve i messaggi dal client come un vero SMTP, quindi ne estrapola i dati richiesti dalla cgi che si occupa di aggiungere nuovi messaggi al forum ed effettua un POST, simulando quello che voi fate di solito a mano con il vostro browser. La cosa notevole e' che i client di posta elettronica DEVONO per forza sottostare alle regole imposte per la comunicazione coi server (avete mai sentito parlare di RFC?): questo significa che il programma funzionera' indipendentemente dal fatto che voi utilizziate Outlook, Calypso, Eudora, Pegasus Mail, Pine, Kmail, Netscape Messenger, Fetchmail e cosi' via. Ho citato tutti questi programmi non solo perche' sono logorroico, ma perche' li ho testati e posso confermarne il funzionamento. Per non limitare questa compatibilita' ho scelto di usare Perl per l'implementazione del programma, in modo da creare un'applicazione portabile, a patto di scaricarsi qualche libreria. *******************************[SI COMINCIA!]********************************* Siamo pronti per cominciare, tenendo presente che ANO si comporra' di questi tre programmi: - HTML, il programma per recuperare i messaggi in formato HTML dai forum e salvarli in formato mail su disco; - POP3, il "finto" server POP3 che accetta le connessioni dai client di posta e gli passa i messaggi; - SMTP, il "finto" server SMTP che accetta le connessioni dai client di posta, ne riceve i messaggi e li passa al forum. Notate gli apici che racchiudono la parola "finto": per ora non anticipo nulla, ma sappiate che non sono messi li' a caso... Notate anche il fatto che le operazioni fatte dai primi due programmi potrebbero, in realta', essere effettuate solo dal server POP3, che una volta ricevuta una richiesta potrebbe occuparsi del collegamento via web e dello scaricamento dei messaggi. Si e' preferito, tuttavia, delegare il primo compito a un programma apposito, giusto per evitare la gestione di eventuali timeout da parte del client di posta dovuti alla lentezza del trasferimento dati via web... siamo previdenti, noi! *************html***********[RECUPERO MESSAGGI]***********html*************** La procedura di recupero messaggi e' molto semplice: 1) Connessione a un dato indirizzo web e download della pagina principale 2) Parsing della pagina e individuazione dei link al suo interno 3) Selezione dei soli link che ci interessano 4) Download delle pagine linkate 5) Salvataggio delle pagine scaricate nel formato che ci garba di piu'. Le librerie utilizzate all'interno del programma, giusto per risparmiarci un po' di fatica nell'implementare le operazioni principali, sono: use LWP::Simple; # un modo comodo per recuperare file da web use LWP::UserAgent; # usato x recuperare file e fare il parsing dei link use HTML::Parse; # questa e la seguente sono usate per salvare i use HTML::FormatText; # messaggi in formato multipart use HTML::LinkExtor; # usato per estrarre i link use URI::URL; # non me lo ricordo piu' :) I primi tre passaggi possono essere effettuati con due soli comandi: il primo $p = HTML::LinkExtor->new(\&callback); specifica quale procedura richiamare automaticamente quando viene scaricata la pagina, mentre il secondo $res = $ua->request(HTTP::Request->new(GET => $url), sub {$p->parse($_[0])}); ha il compito di scaricare la pagina web. La procedura di callback e' cosi' definita: sub callback { my($tag, %attr) = @_; # tieni solo gli elementi di tipo link $adr=$attr{"href"}; # tieni solo gli indirizzi relativi al forum # nota: $forumadr e' un indirizzo maschera a cui devono conformarsi # tutti i link relativi ai messaggi, questo aiuta ad evitare # pagine del tipo "i prossimi 50 messaggi" o immagini varie. return if $adr !~ /\Q$forumadr/i; # controlla se il messaggio e' gia' stato scaricato: $dldfilename # contiene il nome del file all'interno del quale vengono salvati # tutti gli indirizzi dei messaggi gia' scaricati. open(in, "<$dldfname"); while() { chop; if ($_ =~ /^\Q$adr/i) { close (in); return; } } # se il link ha superato tutti i test, allora aggiungilo nell'array # e incrementa il numero dei link da scaricare push(@imgs, values %attr); $links2dload++; } Dovrebbe essere tutto abbastanza comprensibile, quindi non mi dilunghero' piu' di tanto... se vi stupite che abbia chiamato "@imgs" l'array con gli indirizzi, beh... e' perche' ho copiato quella porzione di codice da un altro programma e mi son dimenticato di cambiare il nome della variabile :) Ad ogni modo, tenete presente che la procedura di callback viene sempre chiamata automaticamente quando il programma scarica la pagina principale del forum e crea un array contentente solo gli indirizzi che ci interessano, il tutto in una manciata di righe. A questo punto, dopo aver trasformato gli eventuali url relativi in url assoluti coi comandi: my $base = $res->base; @imgs = map { $_ = url($_, $base)->abs; } @imgs; possiamo procedere con il download dei messaggi del forum e il loro salvataggio su disco. La porzione di codice che racchiude questi ultimi due passaggi e' una procedura chiamata save_message che si trova dentro a un loop del tipo: foreach $adr (@imgs) { save_message ($adr); } Tale procedura svolge in realta' molti altri compiti piu' o meno secondari: innanzitutto controlla il numero di messaggi gia' salvati, in modo da poter creare un nuovo messaggio il cui nome sia immediatamente successivo a quelli precedenti (tale nome viene salvato nella variabile $datname); in seguito scarica l'url che le viene passato tramite la variabile $adr e lo salva in un file temporaneo, quindi lo analizza estraendone i dati che caratterizzeranno poi il messaggio di posta elettronica: il mittente, la data e il subject del messaggio. L'ultima operazione consiste nel salvare il messaggio in un nuovo file, il cui nome e' memorizzato in $datname, inserendo come header i dati appena prelevati e facendo un parsing del file html per eliminare tutti i pezzi di troppo, come ad esempio le pubblicita' o gli elenchi dei messaggi del thread. Vediamo con un po' piu' di attenzione la costruzione dei messaggi in un formato compatibile con gli standard relativi alla posta elettronica: come sicuramente saprete, ogni messaggio di posta si compone di due sezioni diverse, quella contenente gli header e quella contenente il corpo vero e proprio del messaggio, separate da una riga vuota. Esempi classici di header sono i campi "From:", "Date:", "Subject:", "Reply-to:" e cosi' via. A seconda di cosa trovate nel campo "Content-Type:" potete avere dei messaggi di testo semplice, in formato html o anche in entrambi i formati contemporaneamente, i quali lasciano al client di posta la possbilita' di scegliere come visualizzare il messaggio. In realta' il formato HTML non e' particolarmente simpatico: i messaggi sono MOLTO piu' pesanti, specialmente se includono delle immagini, e non tutti i programmi sono tuttora in grado di gestirli al meglio. Certo, e' possibile vedere un messaggio HTML anche all'interno di Pine ormai, pero' ad esempio Calypso effettua la ricerca delle stringhe di testo solo nelle porzioni text/plain dei messaggi (che triste :) Resta pero' un vantaggio nell'utilizzo di html per questi messaggi: visto che originariamente questi erano pagine web visualizzandoli come html non perdiamo nulla del formato originale. Ad esempio, consultando la msgboard dedicata a Javascript avere i messaggi in formato testo risulterebbe molto limitativo; idem dicasi per tutti quei messaggi che contengono dei link o simili. Per questo motivo, e per lasciare sempre una compatibilita' all'indietro, ho deciso di utilizzare il formato multipart e di salvare i messaggi sia come HTML sia come testo semplice: naturalmente potete mettere mano al sorgente ed eliminare questa opzione, se lo desiderate... ;) I campi che ho deciso di includere nell'header sono i seguenti: la data, print out "Date: $msgdate +0200\n"; il mittente con indirizzo, se presente, print out "From: $msgsender <$msgadr>\n"; un campo Reply-to speciale per le risposte ai messaggi, print out "Reply-to: $msgtopic-$msgnumber\@$boardnum\n"; il subject, formattato in un modo speciale, print out "Subject: [$msgtopic-$msgnumber] $msgsubj\n"; un paio di header aggiuntivi, utili x i filtri, print out "X-Mailer: +Ma's ANO\n"; print out "X-Profilename: $profile\n"; un'accozzaglia di header mime per il formato multipart print out "Mime-Version: 1.0\n"; $boundary=$msgtopic."_".$msgnumber; print out 'Content-Type: Multipart/related; boundary="'.$boundary.'"'; print out "\n\n--$boundary-\n"; ... qui comincia il messaggio vero e proprio. Osservate alcuni piccoli particolari: - i messaggi contengono due "X-header" che vi permettono di filtrarli anche in base al forum di provenienza: in questo modo se lo desiderate li potete mettere automaticamente in cartelle diverse all'interno della vostra mailbox. - se possibile, viene sempre indicato il mittente con anche l'indirizzo di posta elettronica (quando presente, of course) per permettervi di rispondere o quantomeno per sapere chi ha scritto quel messaggio :) - il campo Reply-to vi permette, insieme al file relativo al server smtp, di mandare risposte a un particolare messaggio sul forum: esso infatti e' composto da un indirizzo "finto" che contiene il numero di messaggio, il numero di thread e la messageboard di destinazione. Per una spiegazione piu' dettagliata di questi parametri vedete piu' avanti la descrizione del server smtp. - il subject e' particolare: al suo inizio, infatti, vengono salvati il numero di thread e in seguito quello di messaggio, in modo da poter mettere i messaggi nello stesso ordine del forum con un semplice "order by subject". - il multipart funziona grossomodo cosi': 1) Innanzitutto, bisogna inserire la riga Content-Type: Multipart/related; boundary="quelcavolochevolete" insieme agli header del messaggio. 2) A questo punto, ogni blocco di testo racchiuso fra due boundary e' considerato una parte distinta del messaggio. Nel nostro caso particolare, le parti saranno due: --quelcavolochevolete- Content-Type: text/html; charset="us-ascii" Prova

Messaggio di prova :)

--quelcavolochevolete- Content-type: text/plain; charset="us-ascii" Messaggio di prova :) --quelcavolochevolete-- 3) Dovendo scegliere un valore univoco per le boundary, ho deciso di utilizzare il valore numerothread-numeromessaggio. 4) Un consiglio: date un'occhiata all'RFC 2110, in quanto contiene delle informazioni molto interessanti riguardanti i messaggi HTML e gli oggetti contenuti al loro interno. NOTA BENE: per questa parte non e' stato mostrato il codice relativo in quanto e' ancora in versione provvisoria e ci allontanerebbe dal nostro obiettivo, quello cioe' di scrivere un programma il piu' versatile possibile. Infatti, per il desiderio di vedere il programma funzionare il prima possibile, ho inserito all'interno dell routine di parsing alcuni dati relativi ai forum InsideTheWeb, rendendo automaticamente il programma non compatibile con tutti gli altri forum O:-) Per quanto riguarda il corpo della mail, invece, il codice e' abbastanza (ma non ancora completamente) versatile: esso si limita a leggere dei valori da un elenco di trigger che possono essere definiti dall'utente, utilizzandoli per decidere se copiare o no determinate porzioni di testo dal file temporaneo a quello finale. Questo elenco rimane quasi sempre lo stesso per ogni tipo di forum e viene creato in seguito alla semplice lettura di un messaggio scaricato dal web. Ad esempio, se scaricate un messaggio da un forum InsideTheWeb potete notare che la parte che a noi interessa veramente, tolti javascript, banner e schifezze varie, e' ristretta a una piccola porzione di testo compresa fra
e
o, volendo fare una selezione piu' ristretta, fra un . Poiche' i messaggi dei forum sono generati in automatico siamo praticamente sicuri che TUTTI quelli che troveremo seguiranno questa struttura, a meno che un utente non si metta di sua volonta' a scrivere nel corpo del suo messaggio tag esattamente identiche a quelle che interessano a noi... quindi possiamo tranquillamente dire al programma "non copiare tutto quello che trovi fino al primo trigger" (corrispondente alla riga $port, # numero porta Proto => 'tcp', # protocollo Listen => 5, # si pone in ascolto Reuse => 1) || # hmm... non ricordo :) die "Socket error: $!\n" unless $sock; # accetta una nuova connessione $new_sock = $sock->accept(); # recupera l'IP e l'hostname del client per il logging $ip = $new_sock->peerhost(); ($name,$alias,$addrtype,$length,$new_addr) = gethostbyaddr(inet_aton($ip),AF_INET); # saluta il client :) print $new_sock "+OK MalaPOP3 server ready"; Per gestire i vari comandi che possono essere inviati dal client, e' sufficiente fare un ciclo parse_command: while (<$new_sock>) { chop; chop; print $_; /^USER *(.*)/i && do { ... next parse_command; }; /^PASS *(.*)/i && do { ... next parse_command; }; /^STAT/i && do { ... next parse_command; }; ... eccetera, fino a /^QUIT/i && do { print $new_sock "+OK MalaPOP3 server signing off"; close ($new_sock); last; }; print $new_sock "-ERR command unrecognized"; }; # end of "while new_sock" Per fortuna, Perl ci aiuta molto per il parsing delle stringhe inviate al socket, quindi possiamo lavorare a un livello abbastanza astratto. A ogni comando corrisponde una serie di istruzioni che devono restituire esattamente i valori che il client si aspetta. In particolare: - USER fa in modo che ANO cerchi all'interno del file di configurazione se esiste un profilo con il nome specificato. In caso affermativo, il server risponde con un +OK, altrimenti esso invia un -ERR al client. - PASS invia semplicemente un +OK (per ora non ci sono controlli, visto che il programma nasce come semplice client). - STAT fa in modo che il server controlli quanti file associati a un account particolare siano presenti su disco. La risposta del server e' il numero di messaggi e la loro dimensione totale. - LIST senza parametri controlla su disco il numero di messaggi e per ognuno mostra il numero e la dimensione. Eseguito come LIST n, restituisce il numero e la dimensione del messaggio ennesimo. - RETR fa in modo che il server risponda con un +OK se il file e' presente su disco e legga il file da disco, inviandolo al client e terminando la trasmissione con un singolo '.'. - DELE cancella un messaggio da disco (attenzione: in questo caso non funziona come un flag, ma elimina direttamente il messaggio!). - NOOP restituisce un semplice +OK. - RSET non e' implementato. - TOP fa in modo che il server risponda con un +OK se il file e' presente su disco e invii le prime m=n+h righe del file, dove n e' il parametro del comando TOP (il numero di righe che il client vuole scaricare) e h il numero di righe degli header incrementato di uno (la riga vuota). Ops... ho appena trovato un errore nella beta release: mi ero dimenticato di aggiornare il numero di header dopo avere aggiunto gli ultimi! O:-) - QUIT chiude la connessione. Poiche' le funzioni non sono particolarmente complicate, vi rimando direttamente ai sorgenti senza ulteriori spiegazioni. Il vantaggio di una implementazione di questo tipo e' che il nostro sara' a tutti gli effetti un VERO server pop3: pur eseguendo operazioni diverse, infatti, sara' possibile a chiunque collegarsi al nostro computer (conoscendo la porta, naturalmente) e scaricare i messaggi che noi abbiamo prelevato dal forum. Se da una parte questo accendera' una lampadina d'allarme a tutti coloro fra voi che stanno attenti alla sicurezza, i vantaggi sono indubbi: con un paio di modifiche, infatti, e' possibile trasformare questo semplice programmino in un servizio pubblico (gratuito, naturalmente, e SENZA PUBBLICITA', se non volete che venga li' a spezzarvi le braccine), mentre volendo proteggere il proprio sistema da accessi esterni e' sufficiente eseguire il server pop3 solo quando siete scollegati. *************smtp*************[IL SERVER SMTP]*************smtp*************** Il server SMTP e' forse la sezione di ANO che richiede un maggior impegno dal punto di vista del reversing, anche se in questo caso non lavoriamo con un disassemblato, ma con un piu' semplice sorgente HTML. Per quando riguarda la creazione del server non dovreste avere grossi problemi, in quanto esso e' assolutamente identico al server POP3 fatta eccezione per la porta su cui gira e i comandi da accettare. Un altro discorso, invece, e' quello dell'invio dei dati su web. Siccome dobbiamo simulare un POST a una CGI come quello che verrebbe eseguito dal nostro browser, la prima cosa che dobbiamo fare e' controllare all'interno del sorgente HTML di un messaggio quali sono i parametri che vengono passati alla CGI e capirne il significato: scarichiamo quindi un messaggio da InsideTheWeb (limitiamoci a questi forum, l'estensione agli altri dovrebbe essere abbastanza semplice) e controlliamo i valori POSTati dal form: Ok, abbiamo tutti i dati che ci servono: - l'indirizzo a cui mandare il post e' quello specificato all'interno della prima riga: http://post.InsideTheWeb.com/messageboard/post.cgi - function deve sempre avere il valore "write" - MyNum e' l'ID del messaggio a cui state rispondendo - P e' un valore un po' strano... finora mi e' parso di notare che abbia il valore "Yes" quando si risponde a un messaggio, "No" quando ne inserite uno nuovo all'interno del forum - AdNo e' un ID che corrisponde al banner pubblicitario presente all'interno della pagina, qualcosa come "l'utente ha risposto a un messaggio che conteneva questa pubblicita'"... mah, contenti loro :) - Subject contiene il subject del messaggio - name e email_addr corrispondono al nome e all'indirizzo email del mittente - Msg contiene il testo vero e proprio del messaggio - acct rappresenta il numero della messageboard in cui desiderate inserire il nuovo messaggio - TL e' l'ID del thread del messaggio a cui state rispondendo (che, guarda caso, corrisponde all'ID del primo messaggio del thread) - submit e reset possono essere ignorati :) A questo punto, per verificare questi dati, createvi una messageboard tutta vostra e collegatevi al seguente URL: http://post.insidetheweb.com/messageboard/post.cgi?function=write&MyNum=0& P=No&AdNo=0&Subject=Prova&name=mala&email_addr=malattia@gmx.net& Msg=Messaggio%20mandato%20a%20mano&acct=mbxxxxxx&TL=0 dove xxxxxxx e' il numero della vostra messageboard: vedrete magicamente apparire un nuovo messaggio... oddio, di magia ce n'e' poca, pero' e' sempre una bella soddisfazione :) Ora che sappiamo come inviare "a mano" un messaggio all'interno di un forum, vediamo di farlo automaticamente... facciamo il punto della situazione: - ANO dovra' effettuare un POST a una CGI, inviandole gli argomenti che abbiamo appena trovato correttamente formattati (cioe' non in normale formato stringa, ma con tutti i caratteri di escape al posto giusto): per fortuna, c'e' una funzione in Perl che lo fa gia' automaticamente per noi :) - Dal lato del client, il programma dovra' comportarsi come un finto server SMTP (come al solito, la parola "finto" e' superflua, in quanto chiunque potra' collegarsi a voi per mandare messaggi in un forum... pero' non potrete, naturalmente, mandare mail normali!) e quindi accettare i soliti comandi standard, elencati nella tabella piu' avanti. - I dati che servono alla CGI sono piu' di quelli normalmente forniti a un normale server mail: per risolvere questo problema dobbiamo cercare di "infilare" piu' informazioni possibili all'interno delle poche variabili che abbiamo a disposizione. La soluzione che ho adottato io e' mostrata nella tabella seguente: CGI | SMTP | AUTO | ---------------+----------------------------+----------------------------+ function | | Impostato sempre a "write" | ---------------+----------------------------+----------------------------+ MyNum | Campo To:, =0 se msg nuovo | | ---------------+----------------------------+----------------------------+ P | | "Yes" se e' una reply | | | "No" se il msg e' nuovo | ---------------+----------------------------+----------------------------+ AdNo | | Impostato sempre a 0 | ---------------+----------------------------+----------------------------+ Subject | Campo Subject: | | ---------------+----------------------------+----------------------------+ name | Campo From: | | ---------------+----------------------------+----------------------------+ email_addr | Campo From: | | ---------------+----------------------------+----------------------------+ Msg | DATA | | ---------------+----------------------------+----------------------------+ acct | Campo To: | | ---------------+----------------------------+----------------------------+ TL | Campo To:, =0 se msg nuovo | | I comandi riconosciuti dal server SMTP di ANO sono i seguenti: COMANDO | RISPOSTA DEL SERVER | AZIONE EFFETTUATA -----------+--------------------------+------------------------------------- HELO | 250 Hello... | Nessuna: il server si limita a | | rispondere con un saluto al client. -----------+--------------------------+------------------------------------- MAIL FROM | 250 ... Sender ok | Il server da' sempre l'ok e salva | | nome e indirizzo del mittente. -----------+--------------------------+------------------------------------- NOOP | 200 OK | Nessuna. -----------+--------------------------+------------------------------------- RSET | 250 Reset State | Nessuna. -----------+--------------------------+------------------------------------- QUIT | 221 closing | Il server chiude la connessione. | connection | -----------+--------------------------+------------------------------------- RCPT TO: | 250 ... Recipient ok | Il server da' sempre l'ok e salva | | l'ID del messaggio a cui rispondete, | | l'ID del thread e il numero della | | messageboard. -----------+--------------------------+------------------------------------- DATA | 354 Enter mail, end with | Il server si mette in attesa della | a "." on a line by | mail, effettua un parsing per | itself | individuare i campi From:, To: e | | Subject: e li salva in variabili | | separate. Una volta riconosciuti tutti i dati di cui ha bisogno, ANO effettua il POST alla CGI con il comando $response=$ua->request(POST $postaddr, [function => "write", MyNum => $msgnumber, P => $pi, AdNo => "0", Subject => $subject, name => $fromname, email_addr=>$fromadr, Msg => $data, acct => $boardnum, TL => $msgtopic]); Se il comando va a buon fine il server risponde con un "250 Mail accepted", altrimenti esso invia al client il messaggio "500 cannot send data". Il vantaggio di questo comando e' che si occupa lui di convertire automaticamente tutti i parametri inviati nel formato correto, tuttavia il mio interprete Perl non converte i punto e virgola... fate quidni alcune prove per conto vostro, prima di mandare faccine che fanno l'occhiolino! ;) ***********ano.cfg****************[ANO.CFG]***************ano.cfg************* La versione attuale di ANO si appoggia a un file di configurazione, usato per semplificare la vita a chi desidera collegarsi a piu' messageboard: grazie ad esso e' possibile salvare in un solo file tutti i dati che variano da una messageboard all'altra, evitando in questo modo di doversi creare dei sorgenti perl personalizzati. I parametri che vengono salvati all'interno del file di configurazione sono sei: 1) L'indirizzo principale a cui collegarsi per scaricare i messaggi. 2) L'indirizzo base a cui i link devono conformarsi per essere considerati collegamenti validi a messaggi. 3) Il nome della messageboard. 4) Il nome base dei file all'interno dei quali verranno salvati i messaggi. 5) L'elenco dei trigger utilizzati per parsare i file html e creare da essi i messaggi da salvare su disco. 6) Il nome del file all'interno del quale vengono salvati i link gia' visitati. A ogni messageboard corrisponde un profilo, dichiarato all'inizio del file con il comando profile=. Una volta scelto un particolare profilo, i parametri ad esso relativi si chiamano: -main -mask -post -datafname -triggers-begin -triggers-end -dloaded Solo un profilo che comprende tutti questi parametri viene considerato valido dal programma che recupera i file html, mentre per il server pop3 e' sufficiente avere il nome dei file messaggio. Una soluzione di questo genere permette alcuni piccoli trucchi, come ad esempio il seguente: - mettete a tutti i profili lo stesso "datafname", in modo da salvare tutti i messaggi in file con lo stesso nome (ad esempio ano.txt) - create un profilo che abbia SOLO il parametro "datafname", ad esempio profile=malattia ... malattia-datafname=ano.txt - configurate il vostro client di posta elettronica per collegarsi al vostro server con la login uguale al nome di profilo che avete appena creato (in questo caso "malattia"): in questo modo potrete scaricare tutti i messaggi in una volta sola, dividendoli eventualmente in diversi folder a seconda del valore dell'header "X-Profilename:" ... et voila'! :) ********************************[CONCLUSIONI]********************************* Ecco, questo e' tutto ragazzi! Spero di non avervi tediato troppo con un tutorial che speravo io stesso fosse decisamente piu' corto :) Allegati al tutorial trovate i sorgenti dell'ultima versione di ANO, cioe' la 0.99beta che trovate anche in formato eseguibile sul web, con alcune piccole correzioni (tipo il baco degli header di cui mi sono accorto solo scrivendo il tute). I file dovrebbero chiamarsi ano.cfg 4176 bytes ano-html.pl 6611 bytes ano-pop3.pl 7630 bytes ano-smtp.pl 5525 bytes Il progetto ANO e' ancora in piena evoluzione, se volete collaborare con un po' di betatesting o anche solo con qualche nuova idea siete bene accetti. Potete controllare la pagina di ANO all'indirizzo: http://malattia.cjb.net/ano.htm oppure mandarmi una mail all'indirizzo malattia@gmx.net. Questo, naturalmente, non significa che voi non potete mettervi a lavorare in modo indipendente sui miei sorgenti per creare qualcosa di nuovo, bello e possibilmente funzionante... l'unica condizione che vi chiedo di rispettare e' quella di farmi sapere che combinate, giusto per potermi autostimare un po' :) Se un progettino del genere non ha suscitato in voi nessuna nuova idea, lasciate che ve ne suggerisca qualcuna io: - un equivalente di ANO server-side, con utenti registrati a varie board che possono collegarsi ogni tot per scaricare tutti gli ultimi messaggi in una volta sola - un convertitore piu' o meno universale di mailbox: basta usare programmi proprietari, con un pop3 e un smtp si puo' fare qualcosa di piu' generale! - emulazione news, anziche' pop3: la consultazione dei messaggi di un forum in modo un po' diverso :) - teleporting di siti e consultazione tramite il client di posta elettronica (beh, forse questo e' meglio lasciarlo perdere... pero' si puo' fare, date un'occhiata alle caratteristiche dei messaggi HTML!) - creazione di digest html contenenti tutti gli ultimi messaggi di un forum - POST a formmail, ovvero come sfruttare un simpatico bug e i sorgenti di ANO per inviare messaggi piu' o meno anonimi dal proprio client di posta elettronica (questo e' facile, pero'... non vantatevi se ci riuscite ;) ***********************************[OUTRO]************************************ Le persone che mi hanno aiutato durante la creazione di ANO sono molte, da chi ha fatto da cavia col proprio client di posta elettronica a chi mi ha dato suggerimenti sulle funzioni da includere o sulle correzioni da fare. In particolare, un GRANDE ringraziamento va a: - \sPIRIT\ e il suo SMS di incoraggiamento - Little John, che ha seguito ogni passo della creazione di ANO, dalla scelta del nome alle ultime prove - Gli alfa e betatester che mi hanno mandato almeno un messaggio di feedback (e chi ha orecchie per intendere intenda :) - 0phelia, perche' esiste :* *******************************[COPYRIGHT &Co.]******************************* Questo tutorial e' MIO, e sfido chiunque a dimostrare il contrario. Chi lo spaccia per suo e' un fetentone e pure un po' sfigato, perche' almeno poteva spacciare per suo un tutorial un po' piu' bello. ANO e' MIO. Questo significa che anche se voi ne avete i sorgenti, il tutorial, l'eseguibile e qualsiasi altra cosa che sia ad esso collegata, esso rimane sempre solo MIO. Il cervello malato da cui e' uscita l'idea di fare una cosa del genere e' il mio, ne sono fiero e questo non me lo potrete togliere neanche se vi tatuerete la scritta ANO sul sedere. Potete anche cancellare tutto quello che riguarda ANO dal vostro computer e scrivere da capo di vostra mano un'applicazione che faccia le stesse cose che fa ANO, e magari anche qualcosa di piu', pero' resta il fatto che voi la starete scrivendo perche' avete letto questo tutorial, o avete visto i sorgenti di ANO, o vattelapesca, resta il fatto che questa simpatica creaturina restera' sempre e solo mia. Fate quello che vi pare di ANO (del vostro, al mio ci penso io :) ma non permettetevi neanche di pensare a farci sopra dei soldi: se deciderete di trasformarlo in un servizio a pagamento ne faro' uno gratuito migliore, se deciderete di farne un programma commerciale ne faro' uno gratuito MOLTO migliore. ============================================================================== --------------------------------[ EOF 20/28 ]--------------------------------- ==============================================================================