martedì 1 ottobre 2013

Problema ARUBA e messaggio No Input File Specified

Ieri ho avuto la necessità di aggiornare la versione php da 5.2 a 5.3 su un server hosting base di aruba.
La home funzionava benissimo, il problema erano i link alle varie parti del sito che non funzionavano più e riportavano sempre una semplice pagina bianca con il messaggio

No Input File Specified

Dopo varie prove ho trovato la soluzione su un sito che non è più online (grazie google cache ;)).
In pratica dal vostro pannello http://admin.aruba.it/ cliccate su "Servizi Hosting Linux":


poi su "Personalizzazione del file PHP.ini":



ed infine selezionate l'opzione "cgi.fix_pathinfo" e cliccate su OK:



Finito!
Dalla documentazione ufficiale php sull'opzione cgi.fix_pathinfo :
cgi.fix_pathinfo boolean
Fornisce il reale supporto PATH_INFO/ PATH_TRANSLATED per il CGI. Il precedente comportamento del PHP era di impostarePATH_TRANSLATED a SCRIPT_FILENAME, non curarsi di quale fosse PATH_INFO. Per maggiori dettagli su PATH_INFO, vedere le specifiche CGI. Impostando il parametro a 1, si forza il PHP CGI a correggere il percorso in modo conforme alle specifiche. Impostando il parametro a 0 si forza il PHP a comportarsi nel modo originario. Questa opzione è attiva di default. Si consiglia di correggere gli script affinchè utilizzino SCRIPT_FILENAME piuttosto che PATH_TRANSLATED.


martedì 24 settembre 2013

Il mio primo fallimento professionale

Ebbene sì... è successo: non sono riuscito a completare e consegnare un progetto, la prima volta nella mia quasi decennale carriera da programmatore.

Potrei cercare e trovare tante scuse, ma ho sempre pensato che i fallimenti (professionali o della propria vita non fa differenza) devono sempre servire per migliorarci e questo è possibile solo se si cerca di analizzare le cause che li hanno causati.

Scrivo questo post come promemoria e per condividerlo con chi fa il mio stesso lavoro, sperando ne possa trarre utili consigli.

Il sito da ristrutturare era stato sviluppato da più programmatori, in più fasi, utilizzando Joomla 2.5 e vari componenti (commerciali e non), tra cui un paio creati dagli sviluppatori stessi.
Dall'utilizzo che ne era stato fatto, almeno i primi dovevano essere abituati a lavorare con Joomla 1.5, mentre i secondi hanno fatto un buon lavoro di programmazione dei componenti.

Inizialmente ho pensato che poteva essere una buona idea cercare di aggiornare a Joomla 3, visto che avremmo comunque lavorato con Bootstrap e i notevoli miglioramenti apportati al framework.

I tempi per la consegna non era ampi, ma onestamente neanche strettissimi, e qui ho fatto il mio primo errore: giornate perse a cercare di aggiornare i componenti principali non compatibili con Joomla 3!

Non avendo ancora parlato con lo sviluppatore precedente, ignoravo che fosse stato modificato del codice core dei componenti, per cui tutti i miei tentativi andavano a vuoto. Dopo qualche giorno riesco a parlare con lui e mi conferma che non è una buona idea... ok 1 settimana è andata.

Un'altra settimana è andata per familiarizzare con il codice, utilizzo dei moduli, del template e prepare un server dedicato per lo sviluppo ed il test.

A questo punto avevo già perso 10 gg in cose che non avevano niente a che fare con le richieste del cliente!! E me ne rimanevano 15!

Il detto fai le cose quando puoi farle in questo caso è perfetto, perchè nel frattempo sono partite delle emergenze con altri clienti su lavori già avviati, per cui ho dovuto sospendere tutto il resto.

Quando riprendo il progetto ho poco tempo, ma mi considero un programmatore "agile" e veloce, inoltre avevo fatto anche lavori più complessi in poco tempo, solo che questa volta è diverso: il codice non è mio (e non l'ho fatto mio) e dal mio lavoro dipende il lavoro di altre persone del team.

Risultato: panico!

Per giorni navigo il vasto mondo delle estensioni Joomla (mi sono ritrovato anche con due finestre di Chrome con una ventina di tab aperto ciascuna!!), installo, disinstallo, modifico senza trovare soluzione di continuità.
Ogni mattina mi facevo la mia todo list e puntualmente dopo una decina di minuti mi prendeva l'ansia e ripartivo per strade senza sfondo, perchè non riuscivo a fissare un percorso.

Il problema è che ogni giorno pensavo di riprendere il mio normale ritmo di lavoro, ma arrivavo a sera senza nessun risultato concreto, per cui non riuscivo ad ammettere che ero in un vicolo cieco e ormai non avrei più recuperato.

Facendola breve, io a pochi giorni dalla consegna ero ancora convinto di riuscire a consegnare qualcosa di "commestibile", ma a questo punto il leader del progetto si rende conto della situazione e decide di sostituirmi.

CONCLUSIONE

Fino a ieri ero convinto di aver sbagliato i tempi ed aver dedicato troppo tempo a cose inutili e non richieste, mentre oggi parlando con la nuova programmatrice per passargli il lavoro mi sono reso conto di quanto il progetto fosse semplice se l'analisi fosse partita dalle funzionalità del sito e non da come queste erano state implementate!!
Quando si prende in mano un progetto già fatto, molto spesso le soluzioni scelte e implementate da chi lo ha sviluppato, non sono le migliori possibili, perchè solo in fase di sviluppo le richieste del cliente prendono forma e si concretizzano, fino a diventare anche molto diverse da quelle iniziali.
Per cui chi subentra dopo ha la "fortuna" di vedere un prodotto finito e di poterne cambiare completamente l'implementazione utilizzando gli strumenti più adatti.
Quindi col senno di poi avrei potuto utilizzare Joomla 3 con installazione pulita e ricreare le stesse funzionalità con componenti miei e più adatti alle richieste fatte, mantenendo i dati presenti.

NB: questo era un progetto senza database e operazioni sui dati complessi, in quei casi il discorso è molto diverso.

Questa lezione l'ho imparata molto bene perchè, oltre la perdita economica, la cosa che più mi è dispiaciuta è aver deluso profondamente due persone che avevano creduto in me, che stimo sia come professionisti sia umanamente e con cui pensavo di avviare una bella collaborazione anche per progetti più consistenti. Scusate.

martedì 15 gennaio 2013

Mail.app unico account più mittenti

Per chi utilizza come me un unico account gmail per gestire anche altri account utilizzando Mail.app, sa che c'è una cosa fastidiosa: rispondendo alle mail il mittente viene sempre impostato su gmail senza possibilità di sceglierne altri.

Anche se impostate gli altri account su Mail.app, se la mail è stata inviata al vostro account @libero.it e cliccate su Rispondi, il mittente verrà impostato sempre su gmail.

Per ovviare a questo problema basta andare in Preferenze -> Account sul vostro account gmail nel campo "Indirizzo e-mail" aggiungete gli altri vostri indirizzi separati da virgola.

Magicamente in questo modo facendo Rispondi verrà impostato il giusto mittente, cioè quello a cui era indirizzata la mail!!

giovedì 20 settembre 2012

WSDL array complex type to php associative array

I've a wsdl file with this complexType:
            <complexType name="ArrayOfString">
               <complexContent>
                   <restriction base="soapenc:Array">
                      <attribute ref="soapenc:arrayType"
                      wsdl:arrayType="string[]"/>
                   </restriction>
                </complexContent>
            </complexType>
On my soap client I call soap server in this manner:
            $client = new SoapClient('marco.wsdl', array('trace' => 1,'encoding'=>'ISO-8859-1'));
            $data['user']['usr_id'] = 8;
            $data['user']['username'] = 'marco';
            $data['event'] = 'delete';
            $result =  $client->__soapCall('notify', array($data)); 
My server function log this request:

SoapServer->notify: stdClass::__set_state(array(
   'item' =>
  array (
    0 =>
    stdClass::__set_state(array(
       'key' => 'user',
       'value' =>
      stdClass::__set_state(array(
         'item' =>
        array (
          0 =>
          stdClass::__set_state(array(
             'key' => 'usr_id',
             'value' => '8',
          )),
          1 =>
          stdClass::__set_state(array(
             'key' => 'username',
             'value' => 'marco',
          )),
        ),
      )),
    )),
    1 =>
    stdClass::__set_state(array(
       'key' => 'event',
       'value' => 'delete',
    )),
  ),
))
Php map my complexType to an object!

I write this function to convert above object to an associative array:
    function getArrayFromXSDObject($map) {
        if( !isset($map->item) || empty($map->item) )
            return array();
        $ary = array();
        foreach($map->item as $obj) {
            if(is_object($obj->value)) {
                $ary[$obj->key] = $this->getArrayFromXSDObject($obj->value);
            } else {
                $ary[$obj->key] = $obj->value;
            }
        }
        return $ary;
    } 
 And now the log output is:

array (
  'user' =>
  array (
    'usr_id' => '8',
    'username' => 'marco',
  ),
  'event' => 'delete',
PS: if you want a very good library to handle SOAP and WSDL try to look at NuSOAP or any other, but NOT soap php module!



giovedì 23 agosto 2012

Comandi SSH che si bloccano misteriosamente

Come perdere una giornata per risalire ad un problema apparentemente incomprensibile.

La settimana scorsa ho cambiato il modem comprando un Netgear DGN2200 (che vi consiglio per la completezza, con possibilità di collegare un hardisk USB e uno dei pochi con pulsante per disattivare il WiFi).
Installato e funzionante. Tutto perfetto. Quasi.
Ieri mi collego ad una VPN di un cliente e ad alcuni server in ssh. Lancio qualche processo batch di analisi e trasferimento dati. Tutto bene, finchè non lancio un comando pericolosissimo :) :
ls -l
Mi visualizza 2 righe e poi si blocca senza alcun messaggio, neanche di timeout connessione interrotta.
Faccio alcune prove ricollegandomi, ed in pratica qualsiasi comando mandi in output più di qualche linea blocca tutto (more, tail ...).

Inizio il percorso di ricerca della fonte del problema.

1- Penso a qualche problema di rete o connessione, quindi provo a collegarmi con il cellulare 3G ed il problema non si presenta. Scartata
2- Avendo cambiato da poco l'operatore ADSL ed essendo passato a Telecom Alice mi viene in mente qualche filtro sulle vpn, ma provo a collegarmi ad un'altra vpn di un altro cliente e questa funziona benissimo. Scartata
3- Qualche parametro di configurazione particolare della VPN: allora confronto i file di configurazione e vedo che quella che funziona è TCP mentre quella che da problemi è UDP. BINGO

Nei meandri del mio cervelletto era rimasta una qualche nozione di "Reti di calcolatori" che mi ricordava qualche differenza nel trasporto dei pacchetti tra i due protocolli ed essendo il problema un interruzione senza messaggio, poteva benissimo essere qualche pacchetto corrotto. La conferma la trovo su wikipedia alla voce UDP :
A differenza del TCP, l'UDP è un protocollo di tipo connectionless, inoltre non gestisce il riordinamento dei pacchetti né la ritrasmissione di quelli persi
Tutto si fa più chiaro quando mi richiama un mio amico sistemista (Giancarlo) che dopo avergli spiegato la rava e la fava mi chiede il valore dell'MTU (Maximun Transmit Unit) del modem (PS: molti ingegneri rinomati che conosco non avrebbero ricollegato l'MTU con il trasporto dei pacchetti nemmeno dopo anni di analisi e Giancarlo non è ingegnere, ma si ingegna molto con passione)

Il valore impostato era 1456 bytes (WAN Setup del pannello di amministrazione), mentre il valore consigliato per le connessione adsl di tipo PPPoE, come Alice di Telecom, è 1492.

Impostato quel valore tutto ha funzionato a meraviglia!!
Mistero risolto!


giovedì 21 giugno 2012

Wordpress get_option on multisite

If you have a plugin and you want to get its global option (ie that are stored into wp_options table, if you are into a blog, get_option retrieve value from wp_$blogid_options)  on multisite installation, you have two solution:


  1. find and replace all get_option into plugin with my_get_option defined in this manner: 
function my_get_option($key) {
if(is_multisite()) {
switch_to_blog(SITE_ID_CURRENT_SITE);
$option = get_option($key);
restore_current_blog();
return $option;
} else {
return get_option($key);
        }
           }

      2. add filters for each option you want to retrieve:

function myoption() {
        if(is_multisite()) {
switch_to_blog(SITE_ID_CURRENT_SITE);
$option = get_option($key);
restore_current_blog();
return $option;
} else {
return get_option($key);
        }
add_filter( 'pre_option_' . $key, 'myoption' );

       

mercoledì 20 giugno 2012

Batch Import blog on wordpress multisite

There is a bug that deny to import blog in batch mode with wpmu_create_blog or create_empty_blog.

If you try this code:
define('WP_USE_THEMES', false);
require_once('../wp-blog-header.php');
if(!defined('WP_IMPORTING')) define('WP_IMPORTING', true); // required to bypass control existing_user_email
foreach($toImport as $blog) {
    $blog_id = wpmu_create_blog(
DOMAIN_CURRENT_SITE,
PATH_CURRENT_SITE . $blog['path'],
$blog['title'],
1,
'',
SITE_ID_CURRENT_SITE
);
}
It creates only first blog, with relative table wp_$blog_id_terms/options ..., caused by this bug.

I tried this patch with Wordpress 3.1.4  and it works.

The file to modify is wp-includes/wpmu-functions.php adding this line after function wpmu_create_blog:
global $wpdb, $wp_queries;
and after switch_to_blog($blog_id); this code:
if($wp_queries){
    $pattern = '/' . $wpdb->base_prefix . '(\d+)/';
    $prefix = $wpdb->base_prefix . $blog_id;
    $wp_queries = preg_replace($pattern,$prefix, $wp_queries);
 }
Same with create_empty_blog