Funzionamento del protocollo OSPF

L’Open Shortest Path First (in seguito, OSPF) è un protocollo di routing link state pubblico e non proprietario.

I router che utilizzano protocolli link state identificano i propri vicini e comunicano con essi. L’OSPF raccoglie le informazioni dai router vicini circa lo stato dei link di ognuno di essi e invia i suoi dati agli altri. Questo scambio di informazioni sullo stato dei link permette ai router di creare la topology table o (link state database). Ogni router nella stessa area OSPF ha la stessa topology table e viene usata per calcolare la rotta migliore fino a una destinazione applicando l’algoritmo SPF (Shortest Path First). L’algoritmo SPF si basa sul costo che è principalmente basato sulla larghezza di banda; il percorso a costo più basso viene inserito nella routing table (o forwarding database).
Ogni router mantiene una lista di router vicini chiamata adjacency database. Tale lista è formata da tutti i router vicini con cui un router stabilisce una comunicazione bidirezionale ed è unica per ogni router. Per ridurre il numero di informazioni di routing scambiate tra i vicini all’interno della stessa rete, i router OSPF eleggono un designated router (DR) e un backup designated router (BDR) che vengono utilizzati come punti focali per lo scambio di informazioni di routing.

L’OSPF è un protocollo da utilizzare in reti estese e scalabili dove i limiti dei protocolli distance vector rendono improponibile utilizzarli, sia per utilizzo di metriche non basate sulla larghezza di banda che per la lenta convergenza del protocollo (in reti estese il RIP può avere la convergenza di alcuni minuti). Le principali differenze sono state già trattate in altri articoli.

OSPF si interfaccia con le reti broadcast multi-access (come l’Ethernet), pont-to-point e Nonbroadcast multi-access (NBMA, come il Frame Relay). Le reti di tipo point-to-multipoint possono essere configurate manualmente su un’interfaccia dall’amministratore.
In una rete multi-access non si conosce il numero di router a cui si è connessi, mentre nel collegamento point-to-point solo due router possono essere connessi. In una rete broadcast multi-access il numero di adiacenti può essere elevato e varia in base al numero di router della rete. In generale se N è il numero di router il numero di potenziali adiacenti sarà dato dalla formula

N*(N-1)/2

e ciò provocherebbe molto overhead. La soluzione di questa problematica sta nell’eleggere un DR che diventa adiacente di tutti gli altri router nel segmento di broadcast, quindi tutti i router inviano i LSA al DR ed esso invierà le informazioni  a tutti i router del segmento usando l’indirizzo multicast 224.0.0.5. Questa soluzione è efficiente ma presenta lo svantaggio che il DR funge come centro stella, quindi con problemi per la rete in caso di rottura. Per questo viene eletto un BDR tra i designated router. Per garantire la sincronizzazione delle informazioni tra DR e BDR vengono inviate le informazioni all’indirizzo 224.0.0.6.
Ovviamente in una rete point-to-point ci sono solo due nodi e non esistono né DR né BDR: entrambi i router hanno le complete adiacenze con l’altro.

Quando viene avviato un processo di routing OSPF su di un’interfaccia, il router manda pacchetti “hello” a intervalli regolari (Hello protocol) attraverso l’indirizzo 224.0.0.5 che invia il pacchetto a tutti i router OSPF. Tali pacchetti (molto piccoli, hanno solo un OSPF header) vengono inviati ogni 10 secondi di default, ogni 30 per reti NBMA e sono importanti poiché attraverso essi vengono eletti il DR e il BDR.

Funzionamento

Come già accennato, l’avvio di un processo OSPF su di un’interfaccia fa si che il router invii pacchetti hello a intervalli regolari; le regole che governano lo scambio di pacchetti hello viene chiamato hello protocol. In una rete multi-access l’hello protocol fa si di eleggere un DR e un BDR. I pacchetti hello trasportano le informazioni e tutti i vicini devono essere sincronizzati per formare adiacenze e scambio di informazioni sullo stato dei link. In reti multi-access sono il DR e il BDR a dover mantenere le adiacenze con tutti gli altri router OSPF.

I router adiacenti attraversano una sequenza di stati. Prima di formare la routing table i router adiacenti devono essere a conoscenza della topologia dell’intera rete. Ogni router invia LSA nei Link State Update (LSU) e tale LSA contiene al suo interno tutte le informazioni sui link del router; viceversa, ogni router riceve un LSA da ogni vicino per formare il topology database. Tale processo si ripete per ogni router della rete OSPF.

Quando il database è completo ogni router applica l’algoritmo SPF per calcolare una topologia logica esente da loop per ogni rete di destinazione da inserire nella routing table. Le informazioni di routing sono così fissate; quando vi è la variazione dello stato di un link, i routers usano un processo di flooding per notificare agli altri router della rete il cambiamento. Inoltre, per verificare se un adiacente è down, l’hello protocol impone un dead interval.

Link state routing protocol

Abbiamo già visto in un precedente articolo quali sono le principali differenze tra i protocolli di routing distance vector e i protocolli link state. In questo articolo continuiamo la trattazione e vedremo nel dettaglio le caratteristiche dei protocolli link state; prima, però, riprendiamo le differenze tra le due classi di protocolli di routing.

I protocolli distance vector (come RIP e IGRP) presentano le seguenti caratteristiche:

  • inviano l’intera tabella di routing ai router vicini;
  • aggiornamenti periodici frequenti;
  • metrica basata sui salti (solo il RIP);
  • vedono la rete dalla prospettiva dei vicini;
  • convergenza lenta;
  • possibili routing loops;
  • semplicità di configurazione;
  • alto consumo di banda.

Caratteristiche dei protocolli link state:

  • aggiornamenti al variare della topologia della rete;
  • uso dello Shortest Path;
  • invio di pacchetti link-state a tutta la rete (LSA, Link State Advertisement);
  • vista totale della rete in comune tra i router;
  • convergenza veloce;
  • non suscettibili di routing loops;
  • complessi da configurare;
  • richiedono molta memoria e potenza computazionale;
  • consumano poca banda.

Un router che utilizza protocolli link state colleziona le informazioni da tutti gli altri router nella rete e, successivamente, calcola il miglior percorso (SPF algorithm) per tutte le destinazioni della rete stessa. Le variazioni della rete vengono acquisite dai router in maniera veloce: le informazioni vengono inviate in maniera non periodica ma al variare della topologia (triggered updates). Inoltre, vengono inviati dei pacchetti “hello” per verificare la raggiungibilità dei vicini. Informazioni di “hello” e LSAs costituiscono lo strumento per conoscere la topologia della rete per poter creare la tabella di routing (routing table).

Quando vi è una rottura nella rete si ha un fooding di pacchetti LSAs a un indirizzo multicast dedicato; ogni router invia queste informazioni su tutte le porte tranne su quella in cui l’informazione è arrivata. Questo fa si che ogni router appartenente a una certa area debba ricalcolare le rotte, ecco perché il numero di router di un’area deve essere limitato.

Un link è un’interfaccia del router. Lo stato di un link è la descrizione dell’interfaccia e della relazione con i router vicini. La descrizione dell’interfaccia può includere l’indirizzo IP della stessa, la subnet mask, il tipo di rete a cui è connessa, i router connessi ecc. L’insieme di tali informazioni forma il database link state meglio conosciuto come database topologico (topological database). Applicando l’algoritmo di Dijkstra (SPF, Shortest Path First) si forma un albero SPF in cui il router che lo applica è la radice (root). Il percorso migliore calcolato viene inserito nella routing table.

Vediamo di riassumere i vantaggi e gli svantaggi dei protocolli link state. Vantaggi:

  • utilizzo del costo di un link come metrica che tiene conto della capacità del link;
  • utilizzo di LSAs per informare immediatamente gli altri router dei cambiamenti della topologia della rete così da avere un convergenza veloce;
  • vista completa della rete, i routing loops sono facilmente evitabili;
  • routing table sempre aggiornata in base alle ultime informazioni ricevute;
  • supporto a CIDR e VLSM.

Svantaggi dei protocolli link state:

  • richiedono maggiore memoria e potenza di calcolo rispetto ai protocolli distance vector. Questo può determinare un costo eccessivo per un’azienda con poco budget o con hardware datato;
  • richiedono una struttura gerarchica della rete per poterla suddividere in aree più piccole e gestibili riducendo la dimensione della topology table;
  • richiedono una buona conoscenza del protocollo da parte dell’amministratore di rete;
  • effettuano un flooding di LSAs durante il processo di discovery iniziale che può determinare un significativo calo della capacità della rete in questo periodo.

RIP v2 e default routes su router cisco

In questo articolo terminiamo la trattazione sul RIP iniziata nei precedenti articoli, RIP e configurazione sui router cisco e RIP: load balancing e integrazione delle rotte statiche, fornendo una comparazione tra il RIPv1 e il RIPv2.

Entrambe le versioni di RIP sono dei protocolli distance vector, sono facili da configurare e usano l’hop count come metrica (dopo 15 hop la rete viene posta come irraggiungibile), usano l’holddown timers e lo split horizon per evitare i routing loops. I router hanno conoscenza delle sottoreti direttamente connesse e gli aggiornamenti includono informazioni sulla topologia (almeno la metrica); tali aggiornamenti avvengono in maniera periodica.

Il RIPv2 apporta dei vantaggi rispetto alla prima versione del protocollo. In particolare il RIPv2:

  • supporta il classless routing;
  • include nei routing updates le subnet mask;
  • ha un meccanismo di autenticazione negli updates (utilizza la criptatura MD5);
  • invia gli aggiornamenti in multicast (indirizzo 224.0.0.9) anziché in broadcast;
  • usa un routing tag con VLSM.

La configurazione del RIPv2 è identica a quella del RIPv1, l’unica differenza sta nell’inserire il comando version 2, come da esempio sotto:

Router(config)#router rip
Router(config-router)#version 2
Router(config-router)#network network-number

Per la verifica della configurazione si possono utilizzare i comandi show ip protocols, show ip route e show ip interface brief oltre, ovviamente, a show running-config. Il troubleshooting del RIPv2 può avvenire con il comando debug ip rip mentre per disattivare il debug basta inserire no debug all oppure undebug all.

Prima di concludere parliamo della rotta di default (default route). In generale, un router apprende il percorso verso una data destinazione in tre modi: attraverso una rotta statica (l’amministratore inserisce manualmente la rotta), con una rotta dinamica (grazie agli aggiornamenti inviati secondo un protocollo di routing) oppure per mezzo di una default route.
L’amministratore di rete può definire manualmente una rotta di default, cioè il percorso da seguire nel caso in cui non conosca alcuna rotta per raggiungere la destinazione. La rotta di default porta come vantaggio l’avere una ridotta tabella di routing e un percorso di default per destinazioni non conosciute.
La default route può essere impostata dal comando ip default-network in reti che utilizzano routing dinamico:

Router(config)#ip default-network rete

ad es.:

Router(config)#ip default-network 192.168.10.0

oppure attraverso una rotta statica, ad es.:

Router(config)#ip route 0.0.0.0 0.0.0.0 s0/0

dove gli zeri sia nel campo ip che nella subnek mask indicano ogni rete di destinazione con qualsiasi maschera. L’s0/0 è interfaccia su cui inviare i pacchetti (nell’esempio la seriale 0, dovete modificarla in base alle vostre esigenze).

VLSM, CIDR e aggregazione delle rotte

La Variable-length subnet mask (VLSM) è una tecnica utilizzata dagli amministratori di rete per usare in maniera più efficiente gli indirizzi IP. Con la VLSM si offre una maschera più lunga a reti con molti host e una maschera più corta per reti con pochi host, ovvero la maschera varia a seconda del numero di indirizzi necessari a quella rete.
Per implementare la VLSM bisogna, ovviamente, utilizzare un protocollo di routing che supporta il classless routing (un protocollo che, invece, non supporta le VLSM viene detto classful). I protocolli di routing classless su cui utilizzare la VLSM nei router cisco sono:

  • OSPF
  • Integrated IS-IS
  • EIGRP
  • RIP v2
  • BGP v4
  • Routing statico

I protocolli di routing classful sono, invece:

  • RIP v1
  • IGRP
  • EGP
  • BGP v3

Il classless routing nasce per il problema della carenza di indirizzi IP dovuto al veloce aumento delle dimensioni delle tabelle di routing di Internet. Le soluzioni a questo problema sono state il subnetting, la VLSM appunto, il Classless Interdomain Routing (CIDR), l’utilizzo di indirizzi IP privati e il Network Address Translation (NAT). La soluzione definitiva sarà l’utilizzo del protocollo IPv6 che avrà un’astensione di 128bit per gli indirizzi di rete (quindi uno spazio di indirizzamento enorme).

In principio era stato deciso di non utilizzare né la prima (subnet zero) né l’ultima subnet (all-one subnet), successivamente è stato consentito l’uso anche di tali subnet, soprattutto in unione alle VLSM. Per non utilizzare la prima subnet sui router cisco basta digitare il comando no ip subnet-zero.

Le VLSM sono utilissime per utilizzare in maniera efficiente subnet con pochi host, in particolare per i collegamenti Point-to-Point con i WAN links in cui si può usare una maschera di 30 bit (/30) con 2 soli host utilizzabili.
Inoltre, l’uso di CIDR e VLSM permette di effettuare l’aggregazione delle rotte o summarization. Tale tecnica consiste nel fornire al router di uscita di una grande organizzazione (ad es. un ISP) un indirizzo che riepiloga le sottoreti raggiungibili da esso riducendo così il carico sul router. Per fare ciò è necessario che gli indirizzi vengano assegnati in maniera gerarchica in modo che gli indirizziriassuntivi” condividano lo stesso ordine superiore bit.

Utilizzare lightbox su immagini caricate con innerHTML

Il lightbox è un’applicazione javascript per la visualizzazione delle immagini in maniera elegante. Per maggiori informazioni sull’utilizzo e per il download dei files andate qui.

Il lightbox è uno strumento molto utilizzato. Di recente mi è capitato di dover utilizzare il lightbox su immagini caricate dinamicamente all’interno di un div; dopo svariate prove sono giunto a utilizzare la seguente funzione javascript:

<script type="text/javascript" language="javascript">
function showImage(w,h,image) {
 var obj=document.getElementById("id_div");
 obj.innerHTML="";
 obj.innerHTML+="<a href='"+image+"' rel='lightbox'><img src='"+image+"' width='"+w+"' height='"+h+"'></a>";
 initLightbox();
 }
</script>

<div id="id_div">
</div>

La funzione showImage() va a scrivere all’interno del div con id uguale a “id_div” inserendo sia il tag <a> che il tag <img> con il metodo innerHTML, passando anche l’altezza e la larghezza che dovrà avere l’immagine. Ovviamente per poter far funzionare il lightbox bisogna inserire all’interno del tag <a> l’attributo rel=”lightbox”.
Dopodiché bisogna reinizializzare il lightbox tramite la funzione initLightbox(), questo accade perché ogni variazione dinamica dell’HTML sul codice delle immagini richiede la reinizializzazione del lightbox.
Nota: il primo innerHTML con argomento vuoto serve a evitare che le chiamate della funzione successive alla prima abbiano come effetto la sovrapposizione delle immagini precedentemente caricate.

Un’altra soluzione molto simile alla prima è la seguente:

<script type="text/javascript" language="javascript">
function showImage(w,h,image) {
 var obj=document.getElementById("linkID");
 var objIMG=document.getElementById("imgID");
 obj.href=image;
 objIMG.src=image;
 objIMG.width=w;
 objIMG.height=h;
 initLightbox();
 }
</script>

<div id="id_div">
<a id="linkID" rel="lightbox"><img id="imgID"  /></a>
</div>

La differenza rispetto al caso precedente sta nell’inserire a priori all’interno del div i tag <a> e <img> e nell’inserire dinamicamente i contenuti degli attributi.
L’utilizzo della funzione è molto semplice, basta richiamarla in un qualsiasi punto della pagina web, ad esempio tramite onclick dentro un tag.

Entrambe le soluzioni proposte sono state testate su firefox 4/5 e su IE9.

Inserire codice youtube in sito web senza errori di validazione W3C

L’inserimento dei video youtube all’interno di un sito web è un’operazione molto semplice: youtube stesso, infatti, definisce il codice da incorporare all’interno della pagina web. Il codice può essere del tipo:

<iframe width="560" height="349" src="http://www.youtube.com/embed/xxxxxxxxxxx" frameborder="0" allowfullscreen></iframe>

oppure

<object width="560" height="349"><param name="movie" value="http://www.youtube.com/v/xxxxxxxxxx?version=3&amp;hl=it_IT"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/xxxxxxxxxxx?version=3&amp;hl=it_IT" type="application/x-shockwave-flash" width="560" height="349" allowscriptaccess="always" allowfullscreen="true"></embed></object>

Cosa accade però se il sito deve essere accessibile?
In questo caso la situazione si complica.

Purtroppo, così come sono i due codici daranno errore sul W3C Validator, il primo per l’utilizzo del tag <iframe> e del tag <embed>, il secondo solo per l’utilizzo del tag <embed>. Non essendo possibile modificare il primo bisogna cercare di modificare il secondo codice togliendo il tag <embed>.
La soluzione è quella di usare il seguente codice:

<object width="560" height="349" type="application/x-shockwave-flash" data="http://www.youtube.com/v/xxxxxxxxxx"><p>Descrizione</p><param name="movie" value="http://www.youtube.com/v/xxxxxxxxxxx"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param></object>

Ovviamente al posto delle xxxxxxxxxxx va inserito il codice del video. In questo modo potrete inserire i video di youtube anche in siti accessibili.
NB: ricordatevi di inserire la descrizione del video all’interno del tag <object> e prima del tag <param>; essa serve nei casi in cui il video non può essere caricato.

Connessione FTP sicura con server Aruba

Il protocollo FTP (File Transfer Protocol) è un protocollo molto utilizzato per lo scambio dati tra host, tipicamente con host remoti. Il problema principale di tale protocollo riguarda la sicurezza in quanto sia i dati che le credenziali d’accesso viaggiano in chiaro, non sono cifrati. Per ovviare a questa problematica si possono utilizzare protocolli diversi o varianti dello stesso protocollo FTP, in particolare: SFTP (SSH File Transfer Protocol), FTPS (FTP su SSL) e SCP (Secure Copy).

I server Aruba permettono di utilizzare connessioni sicure per lo scambio dati attraverso il protocollo FTPS che è una variante dell’FTP e utilizza le stesse porte per lo scambio dati. FTPS, al contrario di FTP, effettua una cifratura per l’invio delle credenziali d’accesso e/o dei dati tramite SSL/TLS (Secure Sockets Layer/Transport Layer Security).
L’iter della transazione è il seguente: il client si connette alla porte 21 del server FTP, deve accettare il certificato del server e a quel punto avviene la sincronizzazione con SSL/TLS.

Per utilizzare il il protocollo FTPS per lo scambio dati con i server Aruba basta modificare il nome host del server con ftps://ftp.nomedominio.xx al posto di ftp.nomedominio.xx e, successivamente, accettarne il certificato. Ove richiesto dal client FTP, è possibile utilizzare FTP su SSL/TLS sia implicito che esplicito.

SSH .File Transfer Protocol

Classe per l’invio di file tramite il protocollo FTP in PHP

In questo articolo vedremo una classe creata per l’utilizzo delle funzioni php per il trasferimento di file attraverso il protocollo FTP (File Transfer Protocol). Ho cercato di semplificare la classe per far eseguire le funzioni elementari utili per lo scambio di file con un server FTP remoto, utilizzando anche meccanismi per la verifica dei file che controllino che il file sia già presente sul server o meno.

Come al solito posto tutto il codice e, successivamente, verrà commentato. Ho chiamato la classe simpleFtp.

<?php

class simpleFtp {

 //dati per l'accesso
 var $ftp_host = ''; //indirizzo server ftp
 var $username = ''; //nome utente per l'accesso ftp
 var $pwd = '';      //password per l'accesso ftp
 var $connect;
 var $login;
 var $source_file;
 var $destination_file;

 //nel costruttore effettuo connessione e login
 function simpleFtp(){
 //effettuo la connessione
 $this->connect = ftp_connect($this->ftp_host) or die("Si è verificato un errore durante la connessione al server ftp");

 //effettuo il login
 $this->login = ftp_login($this->connect, $this->username, $this->pwd) or die("Si è verificao un errore durante l'accesso al server ftp");

 }

 //funzione per il trasferimento dei file
 function trasferisci($sorgente, $destinazione){
 //file da trasferire
 $this->source_file = $sorgente;
 //va indicato il percorso e il nome del file
 $this->destination_file = $destinazione;
 //verifico che il file non esista già altrimenti modifico il nome
 $this->destination_file = $this->verificaFile($this->destination_file, 'put'); 

 ftp_put($this->connect, $this->destination_file, $this->source_file, FTP_BINARY) or die("Errore durante l'upload del file $source_file nel server ftp");

 }

 function preleva($destinazione, $sorgente){
 if($this->verificaEsistenza($sorgente)){
 //file da trasferire dal server remoto
 $this->source_file = $sorgente;
 //percorso e nome locale da dare al file
 $this->destination_file = $destinazione;
 //verifico che il file non esista già altrimenti modifico il nome
 $this->destination_file = $this->verificaFile($this->destination_file, 'get');        

 ftp_get($this->connect, $this->destination_file, $this->source_file, FTP_BINARY) or die("Errore durante il download del file $source_file nel server ftp");

 }else
 echo "File non trovato.";
 }

 //cancella un file sul server remoto
 function cancella($file){
 if($this->verificaEsistenza($file))
 ftp_delete($this->connect, $file) or die("Errore durante la cancellazione del file dal server ftp");
 else
 echo "File non trovato";
 }

 //cambia la directory sul server remoto
 function cambiaDirectory($dir){
 ftp_chdir($this->connect,$dir) or die('Errore durante il cambio di directory');
 }

 //restituisce la directory corrente
 function directoryCorrente(){
 return ftp_pwd($this->connect);
 }

 //cambia i permessi su un file, i permessi devono essere a 4 cifre. Es.: 0755
 function cambiaPermessiFile($permessi, $file){
 if($this->verificaEsistenza($file) && is_numeric($permessi))
 ftp_chmod($this->connect, $permessi, $file);
 else
 echo "File non trovato";
 }

 //rinomina un file sul server remoto
 function rinomina($old, $new){
 if($this->verificaEsistenza($old)){
 $new = $this->verificaFile($new, 'put');
 ftp_rename($this->connect, $old, $new);
 }
 else
 echo "File non trovato";
 }

 //restituisce un array con i nomi dei file nella directory passata
 function visualizzaFile($dir){
 $result = ftp_nlist($this->connect, $dir);
 return $result;
 }

 //crea una directory sul server remoto a partire dalla directory corrente
 function creaDirectory($dir){
 @ftp_mkdir($this->connect, $dir) or die('La directory esiste già o non hai i permessi per crearne una.');

 }

 //elimina una directory dal server remoto a partire dalla directory corrente
 function eliminaDirectory($dir){
 @ftp_rmdir($this->connect, $dir) or die('La directory non esiste o non hai i permessi per eliminarla.');

 }

 //chiudo la connessione
 function close(){
 ftp_quit($this->connect) or die("Si è verificato un errore durante la chiusura della connessione al server ftp");
 }

 //Verifico il tipo di file in base all'estensione
 function verificaFile($nomeFile, $tipo){
 $ext = explode('.', trim($nomeFile));
 $num = count($ext);
 if($ext[$num-1]=='jpg' || $ext[$num-1]=='pdf')
 if($tipo=='put')
 return $this->verifica($nomeFile, $ext[$num-1]);
 elseif($tipo=='get')
 return $this->verificaLocale($nomeFile, $ext[$num-1]);
 }

 //funzione che modifica i caratteri speciali e cambia il nome del file se dovesse già esistere sul server
 function verifica($nomeFile, $ext){
 $nomeFile=stripcslashes($nomeFile);
 $nomeFile=str_replace("'"," ",$nomeFile);
 $nomeFile=str_replace("`"," ",$nomeFile);
 $nomeFile=str_replace("\\"," ",$nomeFile);
 $nomeFile=str_replace("&"," ",$nomeFile);
 $nomeFile=str_replace("%"," ",$nomeFile);
 $nomeFile=str_replace("\""," ",$nomeFile);
 $nomeFile=str_replace("à","a",$nomeFile);
 $nomeFile=str_replace("è","e",$nomeFile);
 $nomeFile=str_replace("é","e",$nomeFile);
 $nomeFile=str_replace("ì","i",$nomeFile);
 $nomeFile=str_replace("ò","o",$nomeFile);
 $nomeFile=str_replace("ù","u",$nomeFile);

 if($this->verificaEsistenza($nomeFile)){
 $temp=substr($nomeFile, 0, -4);
 if($ext=='jpg'){
 $nomeFile=$temp.'_.jpg';
 }
 elseif($ext=='pdf'){
 $nomeFile=$temp.'_.pdf';
 }
 $nomeFile=$this->verifica($nomeFile, $ext);
 }
 return $nomeFile;

 }

 /*
 Verifico che un file esista già sul server a cui mi collego, la funzione ftp_size restituisce la dimensione del file se trova un file con quel nome nella directory indicata, altrimenti restituisce -1
 */
 function verificaEsistenza($file){
 $verifica = ftp_size($this->connect, $file);
 if($verifica==-1)
 return false;
 else
 return true;
 }

 //funzione che modifica i caratteri speciali e cambia il nome del file se dovesse già esistere in locale
 function verificaLocale($nomeFile, $ext){

 if(file_exists($nomeFile)){
 $temp=substr($nomeFile, 0, -4);
 if($ext=='jpg'){
 $nomeFile=$temp.'_.jpg';
 }
 elseif($ext=='pdf'){
 $nomeFile=$temp.'_.pdf';
 }
 $nomeFile=$this->verificaLocale($nomeFile, $ext);
 }
 return $nomeFile;

 }

}
?>

La classe utilizza le funzioni messe a disposizione da PHP per il trasferimento file utilizzando il protocollo FTP; in aggiunta, ho inserito delle funzioni per la verifica che un file si trovi già sul server (verificaEsistenza()) o, se stiamo prelevando dal server, se il file esiste in locale (verificaLocale()). Non utilizzando tali funzioni i file, se già esistenti, vengono sovrascritti senza alcun output per l’utente.
Inoltre, sono state implementate le funzioni verifica() e verificaFile() che hanno il compito di modificare il nome del file evitando i caratteri speciali e le lettere accentate e, se il file si trova già sul server, modificandone il nome inserendo degli underscore dopo il nome e prima dell’estensione. Naturalmente il bisogna conoscere il tipo di file, infatti la classe è impostata per il trasferimento di file immagini (jpg) e pdf. La classe gestisce questi 2 tipi di file ma è possibile adattarla facilmente per tipi di file qualsiasi in base alle necessità.

Gli unici parametri che vanno inseriti all’interno della classe sono i dati per l’accesso FTP al server remoto, tutto il resto verrà effettuato tramite funzioni d’accesso. Il costruttore simpleFtp() ha il compito di effettuare la connessione al server FTP e la relativa login. Seguono le funzioni principali per l’utilizzo della classe, ovvero trasferisci(), preleva() e cancella(). Tutte queste funzioni leggono il percorso del file sul server FTP a partire dalla root, quindi è necessario inserire il percorso completo al file oppure spostarsi, prima di tali operazioni, sulla directory di lavoro con la funzione cambiaDirectory().

Successivamente sono state implementate altre funzioni molto utili in alcuni ambiti, e sono la funzione cambiaPermessiFile() e rinomina(). La prima serve per modificare i permessi d’accesso al file, ad esempio si può impostare un file con i permessi 0777; la seconda serve per rinominare un fle remoto. Ovviamente, per entrambe le funzioni, si verifica prima se il file sul server esista.

La funzione directoryCorrente() restituisce il percorso della cartella del server su cui si sta lavorando mentre le funzioni creaDirectory() ed eliminaDirectory() sono utilizzate, rispettivamente, per creare ed eliminare cartelle sul server FTP; visualizzaFile(), invece, restituisce un array con la lista dei file presenti nella direcotory passata.
Infine, la funzione close() termina la connessione con il server FTP.

Per rendere maggiormente utilizzabile la classe è possibile modificarne il costruttore in modo da prendere dall’esterno i parametri per la connessione. In altri articoli, se ce ne sarà bisogno, integrerò la classe per l’utilizzo di connessioni cifrate per lo scambio di dati in FTP.

Come cambiare il MAC address delle schede di rete in linux

Il MAC (Media Access Control) address è un indirizzo che identifica univocamente ogni scheda di rete prodotta a livello globale. Viene anche detto indirizzo fisico ed è composto da 48 bit di cui i primi 24 identificano il produttore (OUI, Organizationally Unique Identifier) dell’hardware mentre i restanti bit identificano il componente. Esso è usato per l’instradamento in reti switched, quindi a livello 2 dello stack ISO-OSI.

Anche se il MAC address è unico al mondo, per una determinata scheda di rete, è possibile modificarlo via software per usi più o meno “consoni”. In windows non è possibile modificarlo se non utilizzando appositi tools, mentre in linux la procedura è molto semplice, bastano poche istruzioni eseguite da shell.
Per visualizzare il MAC address delle nostre schede di rete, basta digitare il comando ifconfig e verranno visualizzate le informazioni su tutte le schede di rete attive sul pc; tra le informazioni troveremo il MAC address sotto la voce HWaddr.

Per modificare il MAC address bastano 3 semplici comandi: supponiamo di voler modificare il MAC della scheda ethernet (eth0), dobbiamo prima disattivarla, poi modifichiamo l’indirizzo fisico e, infine, la riattiviamo. Es.:

ifconfig eth0 down
ifconfig eth0 hw ether 00:11:22:33:44:55
ifconfig eth0 up

Ovviamente è possibile inserire al posto di 00:11:22:33:44:55il MAC address voluto. Per effettuare tale operazione è necessario avere i privilegi di amministratore, quindi se siete con ubuntu, ad esempio, dovete anteporre ai comandi l’istruzione sudo.

Se non ricordate più il MAC address originale niente panico! Riavviando il PC verrà reimpostato il MAC address originale della scheda di rete poiché la modifica viene effettuata solo via software senza modificare in alcun modo il firmware della scheda di rete.

Tags: , , , ,

Script Php per ricerche fulltext con MySQL

Nel precedente articolo abbiamo visto la sintassi SQL per l’utilizzo degli indici fulltext nelle ricerche sul database. In questo articolo vedremo un semplice script per l’utilizzo pratico di tale ricerca utilizzando una classe appositamente scritta.

Supponiamo di avere un form con un campo di ricerca del tipo:

<form name="cerca" method="post" id="cerca" action="esito_ricerca.php">
<input type="text" name="campo" />
<input type="submit" name="invia" /></form>

Al submit si aprirà una nuova pagina php nella quale riprenderemo i valori passati ed eseguiremo le operazioni necessarie per la ricerca e la visualizzazione dei risultati. Per semplificare le cose utilizzeremo la seguente classe:

< ?php

class Ricerca
{
var $campi;
var $tabella;
var $key;
var $tuple;

function Ricerca($key, $tabella, $campi)
{
$this->key = $key;
if($tabella!="")
$this->tabella = $tabella;
if($campi!="")
$this->campi = $campi;
$this->pulisciStringa();
}

function Query()
{

$query = "SELECT *, MATCH($this->campi) AGAINST('$this->key' IN BOOLEAN MODE) AS attinenza FROM $this->tabella WHERE MATCH($this->campi) AGAINST('$this->key' IN BOOLEAN MODE) ORDER BY attinenza DESC";

$this->tuple = mysql_query($query);

}

function pulisciStringa()
{
$keyMod = strip_tags($this->key);
$keyMod = mysql_real_escape_string($keyMod);
$this->key = trim($keyMod);
}

function ricercaParole()
{
$word = explode(' ', trim($this->key));
$num = count($word);

$i=0;
while($i< $num){
$word[$i] = '+'.$word[$i];
$i++;
}
$this->key = implode(' ',$word);
}

function ricercaFrase()
{
$word = $this->key;
$word = '"'.$word.'"';
$this->key = $word;
}

}

?>

La classe è abbastanza semplice, la funzione Ricerca() ha il compito di inizializzare alcuni parametri necessari per l’esecuzione della ricerca, in particolare riceve in ingresso le chiavi di ricerca, la tabella su cui effettuare la query e i campi fulltext da analizzare.
La funzione Query() effettua la query vera e propria riportando i valori ordinati per attinenza. La funzione pulisciStringa() serve per ripulire il codice e aumentarne la sicurezza. In tale funzione si possono fare tutti i controlli e le sostituzioni di caratteri che si vogliono. Se all’interno del database i caratteri sono codificati nelle loro rispettive entità html (situazione che capita spesso se si usa un editor wysiwyg) allora è possibile utilizzare al posto di mysql_real_escape_string() la funzione htmlentities().
Ho inserito nella classe anche 2 funzioni che possono essere molto utili. La prima è ricercaParole() che ha il compito di inserire davanti a ogni parola il segno “+”. Utilizzare tale parametro equivale a effettuare una ricerca di “tutte le parole” passate, ovvero tra i risultati ci saranno soltanto tuple che contengono tutte le parole di ricerca passate. La seconda è, invece, ricercaFrase() che ha il compito di restituire tra i risultati solamente tuple che contengono la chiave di ricerca così com’è. E’ utile per ricercare una “frase esatta” all’interno dei campi e si attua inserendo la chiave di ricerca all’interno di doppi apici.

Vediamo come utilizzare la classe in una ricerca utilizzando il form precedente. Supponiamo che la connessione al database sia già stata effettuata, avremo:

$campo=$_POST['campo'];

$search = new Ricerca($campo, 'tabella', 'campo1, campo2');
$search->Query();
$cont = mysql_num_rows($search->tuple);

if($cont<1)
echo "Non vi sono risultati per la ricerca selezionata";
else{
while ($row = mysql_fetch_array($search->tuple))
{
echo $row['campo1'];
}
}

Si riprende il campo e si inizializza la classe attraverso il costruttore passandogli la chiave di ricerca, la tabella e i campi da analizzare. Successivamente effettuiamo la query e procediamo alla visualizzazione dei risultati.

Per avere tra i risultati della ricerca solo i risultati che contengono tutte le parole passate inseriamo prima della Query() la funzione ricercaParole():

$search = new Ricerca($campo, 'tabella', 'campo1, campo2');
$search->ricercaParole();
$search->Query();

mentre per ricercare una frase esatta:

$search = new Ricerca($campo, 'tabella', 'campo1, campo2');
$search->ricercaFrase();
$search->Query();

La classe vista finora è molto semplice e funzionale, può essere ampliata a piacimento per implementare funzioni che possono essere d’aiuto nel personalizzarla a seconda dei propri scopi.