<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Claudio&#039;s Hideout &#187; php</title>
	<atom:link href="http://claudio.cicali.name/post/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://claudio.cicali.name</link>
	<description>Claudio Cicali web hub</description>
	<lastBuildDate>Sun, 25 Sep 2011 11:29:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>How to export your friendfeed stream (posts and comments)</title>
		<link>http://claudio.cicali.name/post/2011/01/how-to-export-your-friendfeed-stream-posts-and-comments/</link>
		<comments>http://claudio.cicali.name/post/2011/01/how-to-export-your-friendfeed-stream-posts-and-comments/#comments</comments>
		<pubDate>Fri, 07 Jan 2011 10:29:51 +0000</pubDate>
		<dc:creator>claudio</dc:creator>
				<category><![CDATA[Annunci]]></category>
		<category><![CDATA[Articoli]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[Programmazione]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[english]]></category>
		<category><![CDATA[export]]></category>
		<category><![CDATA[friendfeed]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://claudio.cicali.name/?p=976</guid>
		<description><![CDATA[I just wrote a script to easily download your FULL friendfeed stream. I mean: every post with comments, likes and even images and/or files. Enough for the good news: the bad news is that this a PHP command line script and you have to know how to run it. On a recent  OSX or Linux [...]]]></description>
			<content:encoded><![CDATA[<p><a rel="attachment wp-att-980" href="http://claudio.cicali.name/post/2011/01/how-to-export-your-friendfeed-stream-posts-and-comments/ff-2/"><img class="alignleft size-full wp-image-980" title="ff" src="http://claudio.cicali.name/wp-content/uploads/2011/01/ff1.png" alt="" width="227" height="50" /></a></p>
<p>I just wrote a script to easily download your FULL <a href="http://friendfeed.com">friendfeed</a> stream. I mean: every post with comments, likes and even images and/or files. Enough for the good news: the bad news is that this a PHP command line script and you have to know how to run it. On a recent  OSX or Linux environment you should be ready to go. For Windows-ers it could be a little more difficult. Sorry.</p>
<p>Anyway, here is the features list:</p>
<ul>
<li>can fetch a private stream, giving your <a href="http://friendfeed.com/remotekey">remote key</a></li>
<li>locally downloads images and files (detects already downloaded things)</li>
<li>upon subsequent runs, it tries to get only the newly added posts</li>
<li>the output file is <a href="http://www.json.org/">JSON</a></li>
<li>it scales well!</li>
<li>it&#8217;s free software (MIT license)</li>
</ul>
<p>
Download the scripts <a href="https://github.com/claudioc/ffexp">from Github</a> (the link points to the project page, where you can read the README too. In this case you&#8217;re interested to the <a href="https://github.com/claudioc/ffexp/blob/master/ffexp.php">ffexp.php</a> script).
</p>
<p>You then may run it like:</p>
<pre>php ffexp.php somefilename.json</pre>
<p>As you may infer from the output file extension, the output is plain good JSON. This format is <strong>very</strong> handy for whatever thing you may need to do with the export file. But this is up to you (or your programmer friend).
</p>
<p>As an example of <em>JSON postprocessor</em> I also wrote <strong>a converter</strong> that given your export file will render a fully functional HTML file, looking just like a Friendfeed page. It also automatically embeds the necessary JavaScript, CSS and even icon images. <a href="https://github.com/claudioc/ffexp/blob/master/ffexp2html.php">Download the ffexp2html from Github</a>, open it, read the fine documentation and run it like:</p>
<pre>php ffexp2html.php somefilename.json &gt; somefilename.html</pre>
<p>Now you can open the somefile.html file with your browser (no internet connection needed). You may find a generated <a href="http://web20.it/stuff/caludio.html">output here</a>.</p>
<p>Limits? Yes there are:</p>
<ul>
<li>No download of your DMs (don&#8217;t know exactly why, maybe a limit of the API. But I don&#8217;t care)</li>
<li>You can download even entire rooms (just use the room name as the username), but it seems that there is a limit of how back you can go. Very high, but it exists.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://claudio.cicali.name/post/2011/01/how-to-export-your-friendfeed-stream-posts-and-comments/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Convert Delicious bookmarks to CSV</title>
		<link>http://claudio.cicali.name/post/2010/12/convert-delicious-bookmarks-to-csv/</link>
		<comments>http://claudio.cicali.name/post/2010/12/convert-delicious-bookmarks-to-csv/#comments</comments>
		<pubDate>Fri, 17 Dec 2010 15:54:46 +0000</pubDate>
		<dc:creator>claudio</dc:creator>
				<category><![CDATA[Annunci]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[Programmazione]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[convert]]></category>
		<category><![CDATA[delicious]]></category>
		<category><![CDATA[english]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://claudio.cicali.name/?p=964</guid>
		<description><![CDATA[Following the news that the Delicious social bookmarking service will soon be dismissed by Yahoo!, people started wondering which other service could they use in its place and how to better export their delicious bookmarks. This post is not yet another list of sites, but I&#8217;d try to help to better manage the exodus and even gain [...]]]></description>
			<content:encoded><![CDATA[<p>Following the news that the <a href="http://delicious.com">Delicious</a> social bookmarking service will soon be dismissed by Yahoo!, people started wondering which other service could they use in its place and how to better export their delicious bookmarks. This post is not yet another list of sites, but I&#8217;d try to help to better manage the exodus and even gain something from this deliciousastrous.</p>
<p>I wrote a little script in PHP that converts your bookmarks file <a href="https://secure.delicious.com/settings/bookmarks/export">exported from Delicious</a> in some other formats. The script, if you&#8217;re in the mood, is even easily extensibile if you provide it another &#8220;driver&#8221; to convert in another format (you write it and then plug it into the script. Pretty straightforward).</p>
<p>The script is ready to be used if you need to <strong>convert the file in CSV</strong>.</p>
<p>Run it like this:</p>
<pre>php deliconv.php delicious_export.html &gt; delicious_export.csv</pre>
<p>Another idea on how to use the script would be to check every URL for its existance. It&#8217;s a pretty easy task if you know how to use the curl extension. I&#8217;ll leave it as an exercise for the reader :)</p>
<p>So, if know how to run PHP from the command line, <a href="http://lab.web20.it/uploads/deliconv.php.txt">grab the script here</a> (remove the .txt extension).</p>
<p>There is also a Delicious XML exporter, <a href="http://deliciousxml.com/">out there</a>.</p>
<p>Update: my friend <a href="http://www.nicoladagostino.net/">Nicola D&#8217;Agostino</a> has collected some other <a href="http://www.nicoladagostino.net/2010-fuga-da-delicious-come-copiare-i-dati.html">useful informations and tricks</a> on the matter.</p>
]]></content:encoded>
			<wfw:commentRss>http://claudio.cicali.name/post/2010/12/convert-delicious-bookmarks-to-csv/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using «Federated Login for Google Account Users» in your application</title>
		<link>http://claudio.cicali.name/post/2010/11/using-%c2%abfederated-login-for-google-account-users%c2%bb-in-your-application/</link>
		<comments>http://claudio.cicali.name/post/2010/11/using-%c2%abfederated-login-for-google-account-users%c2%bb-in-your-application/#comments</comments>
		<pubDate>Mon, 29 Nov 2010 09:31:14 +0000</pubDate>
		<dc:creator>claudio</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Programmazione]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[integration]]></category>
		<category><![CDATA[login]]></category>
		<category><![CDATA[openid]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://claudio.cicali.name/?p=949</guid>
		<description><![CDATA[I recently had to add an authentication system to an application of mine. Another login, another password checking, another&#8230; Boooring. Given the nature of the application I decided that this time I could cut the mess down and go only with the «Use your Google account» &#8220;one click&#8221; login. Why not? Lot of people have an [...]]]></description>
			<content:encoded><![CDATA[<p>I recently had to add an authentication system to an application of mine.</p>
<p>Another login, another password checking, another&#8230; Boooring. Given the nature of the application I decided that this time I could cut the mess down and go only with the «Use your Google account» &#8220;one click&#8221; login. Why not? Lot of people have an google account already and <strong>it&#8217;s OpenID</strong>!</p>
<p>The usual Google documentation page <a href="http://code.google.com/apis/accounts/docs/OpenID.html">is this one</a>. The good news is that if you follow this guide you probably will not need to read that whole page :) Later on you should integrate this very document with the Google one.</p>
<p>The first thing to know is that you are going to write an <a href="http://openid.net/">OpenID</a> client/consumer. OpenID 2 protocol is indeed the system behind the whole client/server scenario from your application (the client) and the Google accounting system (the server). I have to assume that you know what that means (at an high level, at least). The examples here are in <strong>PHP</strong> and below I will provide some sample code for you to play with.</p>
<p>OK; so here are the relevant points:</p>
<ul>
<li>This one is theoretical, but it&#8217;s how Google deployed the OpenID protocol on top of his already existing authentication system. Normally, in a &#8220;pure&#8221; OpenID environment, during the login process the user will give you his/her openid identifier (an URL); using that identifier your program will discover (via the Yadis protocol) which is the corresponding server party to talk to for the authentication process. In the Google scenario you don&#8217;t know which is the user&#8217;s OpenID identifier (the user, of course, is not even aware that there&#8217;s something like &#8220;openid&#8221; involved in the way s/he logs in). You have NOT to ask her for her &#8220;google account&#8221;; you have to make him press a button or follow a link to &#8220;Login with your Google account&#8221;. But you DO know who you have to ask for protocol informations and not have to infer it from the user&#8217;s OpenID (technically, a discovery process is needed anyway). Upon a succesfull login you WILL have the user&#8217;s OpenID identifier; it&#8217;s something like a generated string, not choosen by the user and crafted by Google itself.</li>
<li>You need a recent OpenID library that supports OpenID 2.0 XRI and Yadis discovery. This <strong>excludes</strong> (as for now) the Zend Framework OpenID component (it does support OpenID 2.0, but not the discovery part in the version Google uses). Too bad. You then need to go straight to the <a href="http://www.janrain.com/openid-enabled">JanRain library</a></li>
<li>Don&#8217;t bother thinking about Simple Registration (SREG): Google does support the more advanced (and useful) Attribute Exchange (AX) extension only</li>
<li>Speaking of profile data, there is nothing much you can get: email, name and surname. I noticed that unless you specify each one as <em>mandatory</em> (within the AX request), the user is not even asked &#8211; by Google &#8211; to give them to you. There&#8217;s probably somethng I misunderstood, but this is it.</li>
</ul>
<p>On your side, the login process will consist of two distint phases: one that <strong>initiates</strong> the login process the and one that <strong>finalizes</strong> it.</p>
<p>Normally you point your &#8220;Login with Google&#8230;&#8221; link to the script that implements the initiation phase (let&#8217;s say &#8220;login.php&#8221;). The finalize script (let&#8217;s say &#8220;finalize.php&#8221;) will be called by the Google server as per protocol. There is a lot more to know about the OpenID process, of course, but the library should hide the gory details for you.</p>
<p>The login script will immediately and trasparently forward the user to the real Google account login page. The finalize script will have the logic that checks if the authentication has been succesfull or not and act consequently.</p>
<p>I&#8217;m about to show you some code, but keep in mind that <strong>this is NOT </strong>valid PHP code; I want you to understand what&#8217;s going on rather than being able to just copy/paste. To further limit clutter I did not even add basic error checking. Please check the JanRain library examples for full fledged (and working) code.</p>
<p>So, for the login process:</p>
<pre class="brush: php; title: ; wrap-lines: false; notranslate">
# Requires the needed JanRain scripts
require_once &quot;Auth/OpenID/Consumer.php&quot;;
require_once &quot;Auth/OpenID/FileStore.php&quot;;
require_once &quot;Auth/OpenID/AX.php&quot;;

# Setup the library (leaved blank on purpose).
# Will also create the $store variable used below
...

$consumer = new Auth_OpenID_Consumer($store);

$auth_request = $consumer-&gt;begin(&quot;https://www.google.com/accounts/o8/id&quot;);

# Create attribute request object (this is where you prepare the Attribute Exchange request)
$attribute = array();
$attribute[] = Auth_OpenID_AX_AttrInfo::make('http://axschema.org/contact/email', 2, true, 'email');
$attribute[] = Auth_OpenID_AX_AttrInfo::make('http://axschema.org/namePerson/first', 1, false, 'firstname');
$attribute[] = Auth_OpenID_AX_AttrInfo::make('http://axschema.org/namePerson/last', 1, false, 'lastname');

# Create AX fetch request
$ax = new Auth_OpenID_AX_FetchRequest();

# Add attributes to AX fetch request
foreach($attribute as $attr){
  $ax-&gt;add($attr);
}

$auth_request-&gt;addExtension($ax);

$return_to = sprintf(&quot;http://%s:%s%s/finalize.php&quot;, $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'], dirname($_SERVER['PHP_SELF']));
$trust_root = sprintf(&quot;http://%s:%s%s/&quot;, $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'], dirname($_SERVER['PHP_SELF']));

$form_html = $auth_request-&gt;htmlMarkup($trust_root, $return_to, false, array('id' =&gt; 'openid_message'));

# This will actually redirect to Google
print $form_html;
</pre>
<p>This is what I have in my finalize.php script:</p>
<pre class="brush: php; title: ; wrap-lines: false; notranslate">
# Requires the needed JanRain scripts
require_once &quot;Auth/OpenID/Consumer.php&quot;;
require_once &quot;Auth/OpenID/FileStore.php&quot;;
require_once &quot;Auth/OpenID/AX.php&quot;;

# Setup the library (leaved blank on purpose).
# Will also create the $store variable used below
...

$consumer = new Auth_OpenID_Consumer($store);

$return_to = sprintf(&quot;http://%s:%s%s/finalize.php&quot;, $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'], dirname($_SERVER['PHP_SELF']));
$response = $consumer-&gt;complete($return_to);

$msg = '';

switch($response-&gt;status) {

  case Auth_OpenID_CANCEL:
    # This means the authentication was cancelled by the user
    $msg = 'Verification cancelled.';
    break;

  case Auth_OpenID_FAILURE:
    $msg = &quot;OpenID authentication failed: &quot; . $response-&gt;message;
    break;

  case Auth_OpenID_SUCCESS:
    # &quot;$openid&quot; is the user openid given by Google
    $openid = $response-&gt;getDisplayIdentifier();
    $ax_resp = Auth_OpenID_AX_FetchResponse::fromSuccessResponse($response);
    # Here you could save the user data in session for further references...
    ...

    # Redirect the user to her dashboard
    header('Location: /account');
    exit();

}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://claudio.cicali.name/post/2010/11/using-%c2%abfederated-login-for-google-account-users%c2%bb-in-your-application/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Usare VirtualBox per sviluppare su OSX</title>
		<link>http://claudio.cicali.name/post/2010/03/usare-virtualbox-per-sviluppare-su-osx/</link>
		<comments>http://claudio.cicali.name/post/2010/03/usare-virtualbox-per-sviluppare-su-osx/#comments</comments>
		<pubDate>Tue, 09 Mar 2010 18:17:55 +0000</pubDate>
		<dc:creator>claudio</dc:creator>
				<category><![CDATA[Articoli]]></category>
		<category><![CDATA[osx]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[server]]></category>

		<guid isPermaLink="false">http://claudio.cicali.name/?p=750</guid>
		<description><![CDATA[Giusto un paio di giorni fa sono entrato in possesso di un bellissimo MacBook Pro. La mia attività principale, nell&#8217;utilizzo di un computer, è lo sviluppo di applicazioni web. Dopo aver installato tutto il necessario lato client (ah, il software libero&#8230; ma di questo parlerò più avanti) rimaneva tutta la parte &#8220;server&#8221; ovvero, nella fattispecie, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.virtualbox.org/"><img class="alignleft size-full wp-image-754" title="vbox_logo2_gradient" src="http://claudio.cicali.name/wp-content/uploads/2010/03/vbox_logo2_gradient.png" alt="" width="140" height="180" /></a></p>
<p>Giusto un paio di giorni fa sono entrato in possesso di un bellissimo MacBook Pro. La mia attività principale, nell&#8217;utilizzo di un computer, è lo sviluppo di applicazioni web. Dopo aver installato tutto il necessario lato client (ah, il software libero&#8230; ma di questo parlerò più avanti) rimaneva tutta la parte &#8220;server&#8221; ovvero, nella fattispecie, PHP, MySQL e Apache.</p>
<p>Quando mi sono posto il problema della loro installazione, partivo da questi prerequisiti:</p>
<ul>
<li>su quei servizi ho bisogno di avere la massima flessibilità. Devo poter decidere la loro versione, le eventuali estensioni, dove mettere i dati, i permessi, i virtual host, eccetera eccetera</li>
<li>il deploy delle nostre applicazioni avviene sempre su server linux, per cui mi piaceva continuare ad usare una Ubuntu come macchina di sviluppo per non avere sorpresine in fase di deploy</li>
<li>questo OSX è puro e vergine e non ho nessuna voglia di incasinarlo con installazioni non&#8230; &#8220;standard&#8221;</li>
<li>i vari <a href="http://www.mamp.info/en/index.html">MAMP</a>, distribuzioni buffe di PHP e MySQL, sono roba per ragazzi (per non parlare di quello che arriva direttamente con OSX) :)</li>
</ul>
<p>Detto questo rimaneva da scegliere il sistema di virtualizzazione ma ovviamente (costo, libertà, solite cose) la scelta è caduta su <a href="http://www.virtualbox.org">VirtualBox</a>.</p>
<p>Installarci Ubuntu è stata una passeggiata di salute: avevo l&#8217;immagine ISO di una 9.10 su una pennetta USB e dopo aver creato una macchina virtuale ho montato la ISO all&#8217;interno del suo CD (senza neanche toglierla dalla chiavetta USB) e l&#8217;installazione è partita.</p>
<p>Anche la rete è stata vista subito e da Ubuntu ho installato tutto il necessario. Anche qui tutto allegro e banale.</p>
<p>A questo punto dovevo condividere una directory tra OSX e Ubuntu. L&#8217;idea appunto è quella di usare OSX per programmare, fare debug con i browser, magari un po&#8217; di grafica e usare la macchina virtuale Ubuntu per servire l&#8217;applicazione via Apache. Avrei dunque condiviso la directory <strong>Sites</strong> di OSX con Ubuntu (che sarebbe poi diventata la base di tutti i miei virtual host di sviluppo).</p>
<p>Lato OSX è stato facile: si dichiara direttamente da VirtualBox che esiste uno &#8220;shared folder&#8221;, dandogli il path locale e un nome (questa configurazione è per singola macchina virtuale). Nel mio caso il nome è stato proprio &#8220;Sites&#8221;.</p>
<p>In Ubuntu occorre montare da qualche parte questa directory &#8220;esportata&#8221;. Non esistono però sistemi automagici per farlo, afaik. L&#8217;operazione è fattibile direttamente tramite mount, configurando <strong>/etc/fstab</strong>. Nel mio caso ho aggiunto la seguente riga al file (dopo aver creato la directory Sites nella mia home):</p>
<pre class="brush: bash; gutter: false; title: ; notranslate">
Sites /home/claudioc/Sites vboxsf uid=1000,gid=1000,exec 0 0
</pre>
<p>A questo punto un bel <strong>sudo mount Sites</strong> e siete a posto (successivi riavvii della macchina virtuale useranno l&#8217;fstab e non ci sarà bisogno di intervenire manualmente). Credo si possa fare anche in modo di che il mount sia permesso ad un utente qualsiasi usando il parametro &#8220;user&#8221; della riga di mount, ma non ho indagato oltre.</p>
<p>A questo punto si è presentato il <strong>primo problema</strong>: non è possibile creare <em>link simbolici</em> dalla macchina guest. In pratica, da Ubuntu, non si possono creare link simbolici su un file system montato con vboxsf. Non si può: <a href="http://www.virtualbox.org/ticket/818">è proprio un limite riconosciuto</a>. È tuttavia possibile fare il contrario: ovvero creare un link simbolico in quella directory dal sistema ospite (nel mio caso OSX). In tal caso il link simbolico sarà visto, da Ubuntu, come un normale file (non so se questo fatto possa avere o meno conseguenze strane&#8230;). Per certe configurazioni questo rimane comunque uno <em>show stopper</em>. Speriamo che nelle versioni successive di vbox il limite sia superato.</p>
<p>Passo successivo era quello di testare il funzionamento di apache di Ubuntu da OSX, accedendo da un browser di OSX all&#8217;indirizzo IP del server <em>embedded</em>. Il funzionamento (me illuso) sembrava scontato&#8230; e invece niente da fare. Eccoci al <strong>secondo problema</strong>.</p>
<p>Non appena viene installata una macchina virtuale con supporto di rete, questa viene configurata per uscire in modalità <a href="en.wikipedia.org/wiki/Network_address_translation ">NAT</a>. Questo vuol dire che da vbox viene assegnato un IP privato all&#8217;interfaccia di rete della macchina virtuale la quale poi userà la macchina ospite come gateway. Il tutto viene configurato automaticamente e trasparentemente.</p>
<p>Un <strong>ifconfig</strong> di Ubuntu mi aveva rilevato l&#8217;IP del serverino Ubuntu (10.0.2.15). Da OSX riuscivo a fare ping a quell&#8217;indirizzo, ma qualsiasi altro servizio sembrava stranamente non attivo. Questo dettaglio (il ping&#8230;) è quello che mi ha fatto sprecare più tempo in assoluto. Si dà il caso, ho realizzato più tardi, che non era assolutamente possibile che io potessi fare ping al 10.0.2.15! Eppure succedeva. La cosa buffa infatti è che quell&#8217;indirizzo esisteva, sì, ma&#8230; nella rete di Fastweb. Non apparteneva dunque al mio server embedded, ma a chissà chi :)</p>
<p>Se il guest è in modalità NAT, l&#8217;host non può vedere i suoi servizi di rete. Period.</p>
<p>Un&#8217;altra possibilità sarebbe stata quella di configurare il sottosistema di rete di Ubuntu a lavorare in modalità &#8220;bridge&#8221;, ovvero fare in modo che usando OSX come ponte (appunto&#8230;) questa entrasse direttamente nella rete di OSX ricevendo dunque un IP dal dhcp server usato dallo stesso OSX. Per fare questo avrei dovuto associare l&#8217;interfaccia di rete di Ubuntu ad un&#8217;interfaccia di rete fisica di OSX (per esempio Airport). Ma così non andava bene: io volevo che le due macchine, quella fisica e quella virtuale, potessero colloquiare anche quando nessuna connessione esterna fosse attiva.</p>
<p>In pratica quello che mi serviva era la possibilità di poter uscire su internet con Ubuntu, quando una connessione fosse presente, ma comunque poter SEMPRE parlare con l&#8217;host OSX usando una sottorete privata.</p>
<p>Questa configurazione è possibile avendo a disposizione DUE schede di rete sulla Ubuntu (operazione da eseguire nei <em>Settings</em> della macchina virtuale, aggiungendo una scheda). La prima scheda è quella che farà parte della sottorete &#8220;privata&#8221; tra Ubuntu e OSX e va configurata in modalità <strong>Host-only</strong>. La seconda è quella che ci farà uscire su internet e possiamo configurarla a piacere su NAT o Bridge (Bridge, per me).</p>
<p>La cosa bella, una volta capito il funzionamento, è che il resto è tutto automatico. Fatta ripartire la macchina virtuale Ubuntu, avremo a disposizione due interfacce, una delle quali si troverà nella stessa sottorete di una nuova interfaccia di rete virtuale creata sul sistema host (OSX). Nel mio caso, su OSX, l&#8217;interfaccia si chiama vboxnet0.</p>
<p>Maggiori informazioni nel <a href="http://download.virtualbox.org/virtualbox/3.0.10/UserManual.pdf">manuale di VirtualBox</a> (pdf).</p>
]]></content:encoded>
			<wfw:commentRss>http://claudio.cicali.name/post/2010/03/usare-virtualbox-per-sviluppare-su-osx/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>The new providers discovery for Zend_Tool 1.10</title>
		<link>http://claudio.cicali.name/post/2010/03/the-new-providers-discovery-for-zend-tool-1-10/</link>
		<comments>http://claudio.cicali.name/post/2010/03/the-new-providers-discovery-for-zend-tool-1-10/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 13:06:30 +0000</pubDate>
		<dc:creator>claudio</dc:creator>
				<category><![CDATA[Articoli]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[article]]></category>
		<category><![CDATA[english]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://claudio.cicali.name/?p=732</guid>
		<description><![CDATA[With the recent release of the 1.10 version of the  Zend Framework, they made a subtle change on how Zend_Tool searches its providers. Before 1.10 the loader (aka the provider discover) was set to be the IncludePathLoader class; what that meens is that if you wrote a new provider, all that you needed to do to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://framework.zend.com/"><img class="alignleft size-full wp-image-735" title="zf-logo" src="http://claudio.cicali.name/wp-content/uploads/2010/03/zf-logo.jpg" alt="" width="150" height="84" /></a></p>
<p>With the recent release of the 1.10 version of the  Zend Framework, they made a subtle change on how <a href="http://framework.zend.com/manual/1.10/en/zend.tool.html">Zend_Tool</a> searches its providers. Before 1.10 the loader (aka the provider discover) was set to be the <strong>IncludePathLoader</strong> class; what that meens is that if you wrote a new provider, all that you needed to do to have Zend_Tool automatically find it was to edit your PHP&#8217;s include_path or add your provider&#8217;s directory to the ZEND_TOOL_INCLUDE_PATH_PREPEND environment variable.</p>
<p>Now that is history, because (<a href="http://n4.nabble.com/Several-issues-for-Zend-Tool-1-10-td1555536.html">source</a>):</p>
<blockquote><p>There were many issues for people when Zend_Tool used a scanning approach to finding providers. This caused many issues on all different platforms.  Now we&#8217;ve opted to go the specify your providers approach.</p></blockquote>
<p>(beware: the suggested solution in that post is wrong)</p>
<p>So if you ever write a new tool provider remember that there&#8217;s no more &#8220;auto discovery&#8221; by scanning the path. The loader now is the <strong>BasicLoader</strong> and you have to explicitely tell Zend_Tool where <strong>your</strong> providers are and how their classes are named. For this to happen, you can use the <strong>zf enable config.provider</strong> command or use the <strong>zf.ini</strong> file.</p>
<p>My solution is:</p>
<ul>
<li>create a <strong>zf.ini</strong> file for your project. This is slighlty different from what the documentation implies; it considers zf.ini to be an hidden file in your $HOME. But this is only a default you can change via the  ﻿ZF_CONFIG_FILE env variable</li>
<li>put something like <strong>basicloader.classes.0 = &#8220;Migrations_MigrationProvider&#8221;</strong> as the first line (that example is the actual class name of my migration tool provider)</li>
<li>assure that your class can be loaded, setting ZEND_TOOL_INCLUDE_PATH_PREPEND accordingly</li>
</ul>
<p>On the same topic you can also read <a href="http://framework.zend.com/issues/browse/ZF-8899?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel">this issue</a>.</p>
<p>As a bonus track, below is a little bash script I use to run my migration tool.</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/bash

APPPATH=$(readlink -f ..)/app

export ZF_CONFIG_FILE=${APPPATH}/../zf.ini

if [ ! -f ${ZF_CONFIG_FILE} ]; then
  echo &quot;Non trovo zf.ini&quot;
  echo &quot;Forse non stai eseguendo questo programma dalla directory DB?&quot;
  exit -1
fi

if [[ &quot;${ZF_BIN_DIR}&quot; == &quot;&quot; ]]; then
  ZF_BIN_DIR=$(readlink -f ../vendor/Zend)/../../bin
  ZF_BIN_DIR=$(readlink -f ${ZF_BIN_DIR})
fi

if [ ! -f ${ZF_BIN_DIR}/zf.sh ]; then
  echo &quot;Non trovo zf.sh in &quot; ${ZF_BIN_DIR}
  echo &quot;Forse non stai eseguendo questo programma dalla directory DB?&quot;
  exit -1
fi

MIGCLASSDIR=$(readlink -f ../vendor/Renomo/library)

if [ ! -d ${MIGCLASSDIR} ]; then
  echo &quot;Impossibile trovare la directory della classe Migration&quot;
  exit -1
fi

MIGDIR=$(readlink -f migrations)

if [ ! -d ${MIGDIR} ]; then
  echo &quot;Impossibile trovare la directory delle migration&quot;
  exit -1
fi

export ZEND_TOOL_INCLUDE_PATH_PREPEND=${MIGCLASSDIR}

${ZF_BIN_DIR}/zf.sh run migration ${1}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://claudio.cicali.name/post/2010/03/the-new-providers-discovery-for-zend-tool-1-10/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Date in italiano in PHP</title>
		<link>http://claudio.cicali.name/post/2010/02/date-in-italiano-in-php/</link>
		<comments>http://claudio.cicali.name/post/2010/02/date-in-italiano-in-php/#comments</comments>
		<pubDate>Thu, 25 Feb 2010 11:16:46 +0000</pubDate>
		<dc:creator>claudio</dc:creator>
				<category><![CDATA[Articoli]]></category>
		<category><![CDATA[Programmazione]]></category>
		<category><![CDATA[date]]></category>
		<category><![CDATA[datetime]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[quikie]]></category>
		<category><![CDATA[time]]></category>

		<guid isPermaLink="false">http://claudio.cicali.name/?p=724</guid>
		<description><![CDATA[Usi date() o strftime() ma queste continuano a visualizzare il nome dei mesi e dei giorni in inglese mentre tu le vuoi vedere in italiano? Hai letto che devi usare setlocale(LC_ALL, &#8220;it_IT.utf8&#8243;); ma anche facendolo non cambia niente? Ecco cosa devi fare: devi usare solo la strftime() e non la date(), visto che quest&#8217;ultima non [...]]]></description>
			<content:encoded><![CDATA[<p>Usi <a href="http://php.net/manual/en/function.date.php">date()</a> o <a href="http://php.net/manual/en/function.strftime.php">strftime()</a> ma queste continuano a visualizzare il nome dei mesi e dei giorni in inglese mentre tu le vuoi vedere in italiano? Hai letto che devi usare setlocale(LC_ALL, &#8220;it_IT.utf8&#8243;); ma anche facendolo non cambia niente?</p>
<p>Ecco cosa devi fare:</p>
<ul>
<li><strong>devi</strong> usare solo la strftime() e non la date(), visto che quest&#8217;ultima non è sensibile al locale del sistema</li>
<li>devi verificare che il tuo sistema abbia il supporto per il locale italiano (altrimenti il nome dei mesi da dove se lo prende? Il PHP non ha mica tutti i mesi in tutte le lingue &#8220;dentro sé stesso&#8221;). Verificalo con il comando <strong>locale -a</strong>. Ti verrà visualizzata la lista di tutti i locali supportati sul tuo sistema</li>
<li>se il locale che ti serve non è presente nella lista, lo devi <em>installare</em>. Il comando è <strong>locale-gen</strong> e il parametro è il locale che ti interessa (es: <strong>locale-gen it</strong>, installerà tutti i locale italiani conosciuti, compreso quello standard e quello svizzero)</li>
<li>prendi la stringa ESATTA che identifica il locale che ti interessa e la usi come argomento della funzione PHP <strong><a href="http://php.net/manual/en/function.setlocale.php">setlocale()</a><span style="font-weight: normal;"> prima di usare la strftime</span></strong>. Esempio: <strong>setlocale(LC_TIME, &#8220;it_IT.utf8&#8243;)</strong></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://claudio.cicali.name/post/2010/02/date-in-italiano-in-php/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Use Facebook Connect in your application</title>
		<link>http://claudio.cicali.name/post/2010/01/use-facebook-connect-in-your-application/</link>
		<comments>http://claudio.cicali.name/post/2010/01/use-facebook-connect-in-your-application/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 08:00:12 +0000</pubDate>
		<dc:creator>claudio</dc:creator>
				<category><![CDATA[Articoli]]></category>
		<category><![CDATA[Programmazione]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[connect]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://claudio.cicali.name/?p=615</guid>
		<description><![CDATA[Recently I&#8217;ve got to enable one site of mine with this &#8220;Facebook Connect&#8221; thingy, my primary goal being the increase of the conversion rate, in the way that people could use their Facebook account to log into my web site without a need for a boring registration process. Just click two buttons, and you&#8217;re in. [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I&#8217;ve got to enable one site of mine with this &#8220;<a href="http://developers.facebook.com/connect.php">Facebook Connect</a>&#8221; thingy, my primary goal being the increase of the conversion rate, in the way that people could use their Facebook account to log into my web site without a need for a boring registration process. Just click two buttons, and you&#8217;re in. If a person had a site account already, I&#8217;ll give him the opportunity to merge her Facebook account with the old one. Eventually, upon a succesfull &#8220;connect&#8221; round, a new account would be created within my application. It&#8217;s a cute <em>www</em>: a web win-win.</p>
<p>That is all what I needed, from Facebook: I do not need any fancy &#8220;get your friends here&#8221; or &#8220;post in your wall&#8221; rubbish. Simple and plain &#8220;single sign on&#8221;, among Facebook and my application.</p>
<p>After a quick search, the tutorials I found <a href="http://www.goldsteintech.com/facebook_connect/tutorial.php">here</a> and there were very <em>disappointing</em> (just a point of view, no offense), with a lot of useless PHP code. So I give you just one more tutorial that focuses more on the process than in the copy &amp; paste kind of help.</p>
<p>I will use PHP for some examples, and FB for &#8220;Facebook&#8221; so bear with me and give it a spin.</p>
<p>What you need:</p>
<ul>
<li>a FB account, if you don&#8217;t own one already. Unlikely; I&#8217;ll skip this step :)</li>
<li>a new FB application need to be created</li>
<li>the FB PHP library, to easily talk to their RESTful API</li>
<li>Some code refactoring of your own</li>
</ul>
<h3><strong>Creating a new FB application.</strong></h3>
<p>Two paths, here:</p>
<ul>
<li>the <a href="http://www.facebook.com/developers/createapp.php">long and detailed multistep form</a></li>
<li><a href="http://www.facebook.com/developers/createapp.php"></a>the <a href="http://developers.facebook.com/setup.php">super easy wizard</a></li>
</ul>
<p>Note that, whichever way you&#8217;ll choose, you will end up creating the exact same thing: an FB application (all your applications are stored <a href="http://www.facebook.com/developers/">here</a>).</p>
<p>We&#8217;ll use <strong>the wizard</strong>:</p>
<ul>
<li>the <strong>website name</strong> is just the name of the application (the handle by which you&#8217;ll refer to it in the application list).</li>
<li>the <strong>website url</strong> is self explanatory. Note that you could use ANY kind of URL, even something like &#8220;http://myapplication.localdomain&#8221;. In fact, FB will not need to contact the site, so you can use an development URL as well. For the test purposes I created two applications: one for the &#8220;real thing&#8221; and one for the mydomain.local devel environment.</li>
</ul>
<p>The next step will ask you to download a file. You can put the file WHEREVER you want. The root directory of your site is the first choice, and it&#8217;s where the wizard will try to find it. There&#8217;s no need for the wizard to find the file, though: it&#8217;s only a test. You can download the file and skip the test pressing &#8220;<em>Upload later</em>&#8220;. Two words about that particular file: the file is part of the system that permits our application to be proxied to FB (and vice-versa). I will not enter in details here, but think about this file as your &#8220;gateway&#8221; to and from the FB requests (<a href="http://wiki.developers.facebook.com/index.php/Cross_Domain_Communication_Channel">more info</a>). The other thing is: there is NOTHING in that file that identifies you application. Every FB application of the world could use the same xd_receiver.htm file. The file name itself is not important&#8230; it&#8217;s just the default. More on this later.</p>
<p>The third step is the landing page for your newly created FB application. Just a comfy place to pick things up. You need to write down the <strong>API KEY</strong> and the <strong>SECRET</strong> strings. You&#8217;ll use them from within your application.</p>
<p>What you also need to take from this page is the JavaScript snippet at point 1) and the <a href="http://wiki.developers.facebook.com/index.php/Category:FBML_tags">FBML</a> markup for the &#8220;Connect with Facebook&#8221; button at point 2).</p>
<p>Enough for the FB setup.</p>
<h3><strong>The FB PHP Library and the FB API</strong></h3>
<p>This is a set of helper PHP classes that will give you a simple PHP API interface to the <a href="http://wiki.developers.facebook.com/index.php/API">RESTful FB API</a>. You could even NOT use the library, and talk directly to the REST endpoints with some code of your own. Your choice.<br />
The FB API are <a href="http://wiki.developers.facebook.com/index.php/API">documented here</a>, while you can download the latest version of the PHP 5 Library via SVN</p>
<pre class="brush: jscript; light: true; title: ; wrap-lines: false; notranslate">
svn co http://svn.facebook.com/svnroot/platform/clients/php/trunk/ fb
</pre>
<p> (more info on <a href="http://wiki.developers.facebook.com/index.php/User:Client_Libraries">FB Client libraries</a>)</p>
<p>We are finally ready to get our hands dirty.</p>
<h3><strong>Hands on the code</strong></h3>
<p>We first need to focus on how things works, at an higher level. What will happen when a not logged-in user will click the &#8220;Connect with Facebook&#8221; button? Using some sort of <em>magic</em> Facebook will test if the user is currently logged in Facebook. If it&#8217;s not, it will spawn a <em>popup window</em> asking two things: the user has to agree to give your application access to her data, and after that Facebook will ask her for credential (username/password, as usual). Upon a succesful login, FB will redirect the user to your application toward an url of your choice (let&#8217;s call it the &#8220;<em>FB Connect endpoint</em>&#8220;).<br />
If the user is already logged in Facebook and has already given permission to our application to read some of her data, the login process will be completely transparent. The user clicks on our FB blue-ish button, and he will be instantly logged in our application too. Oh, joy.</p>
<p>As for the HTML part, you will place the FBML markup for the login button you got beforehand wherever you want. The FBML have to be programmatically converted in HTML by JavaScript, and for that to work you need to include the JavaScript snippet you already have. Put it at the end of your &lt;body&gt;, for example, and then run the FB.init() function. This function will be passed two parameters: the API KEY and the name and location of the &#8220;gateway&#8221; file. As said before, if the second parameter is not passed, the default is &#8220;xd_receiver.htm&#8221; on the document root.</p>
<pre class="brush: jscript; highlight: [2]; title: ; wrap-lines: false; notranslate">
  &lt;!-- The login button, somewhere in your page --&gt;
  &lt;fb:login-button onlogin=&quot;window.location='/fbconnect.php';&quot; v=&quot;2&quot; size=&quot;medium&quot;&gt;Login with Facebook&lt;/fb:login-button&gt;
  ...
  &lt;!-- At the page end of the page, presumibly --&gt;
  &lt;script src=&quot;http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php/en_US&quot;&gt;&lt;/script&gt;
  &lt;script&gt;
    FB.init(&quot;b4bbr43b4bb3b3b3&quot;);
  &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>The interesting part, here, is in the highlighted row. The <strong>onlogin</strong> attribute contains what we pretentiously called the &#8220;FB Connect endpoint&#8221;. The onlogin attribute value is a JavaScript snippet that will be automatically run after a succesfull FB login. What we say here is: after a login, please redirect the user to our &#8220;fbconnect.php&#8221; page.<br />
The fbconnect.php page is where <em>OUR magic</em> will happen. There, we will use the FB Client API to ask FB some questions: &#8220;Is this guy a Facebook, logged in user?&#8221;, &#8220;Can you please give me the picture of him?&#8221;&#8230; and so on.<br />
The code, here, is given only as an example; think about it more as a <em>pseudocode,</em> really. The actual code I use is somewhat more complex, and I needed to dumb it down a little for clarity.</p>
<pre class="brush: php; title: ; wrap-lines: false; notranslate">
require(&quot;fb/facebook.php&quot;);
$fb = new Facebook(&quot;b4bbr43b4bb3b3b3&quot;, &quot;supersecret1234&quot;);
/* If it's present, ask FB for the ID of the current user */
$fbId = $fb-&gt;get_loggedin_user();
if (empty($fbId)) {
  /* No FB user, redirect to home page */
  header(&quot;Location: /&quot;);
}
/* Now we know the FB user id.
   It's our responsability to ask our Database if we already know him */
</pre>
<p>You need to have a way to find one user of yours given its FB user id. For instance I used a &#8220;fb_id&#8221; column in my Users table.</p>
<p>What happens now is up to you. There will presumably be two major cases:</p>
<ol>
<li>the user already exists: I programmatically login him into my application, and redirect to the home page as a logged in user.</li>
<li>the user does not exist: I give her the choice to merge her old account or to create a new one</li>
</ol>
<p>For the merge part, I need him to login with his credentials and then update the Users table with his FB id.</p>
<p>For the registration part, I luckily do not need anything else that FB can&#8217;t give me; so it&#8217;s a matter of pushing a button. The code is something like that:</p>
<pre class="brush: php; title: ; wrap-lines: false; notranslate">
$fbInfo = $fb-&gt;api_client-&gt;users_getInfo($fbId, array('name', 'pic_square', 'proxied_email'));
$model = new User();
$name = $fbInfo['name'];
$tries=1;
# find a unique username
do {
  $user = $model-&gt;fetchRow($model-&gt;select()-&gt;where('username=?', $name));
  if (!$user)
    break;
  else
    $name = $name . ($tries++);
} while(TRUE);
$user = $model-&gt;createRow();
$user-&gt;username = $name;
$user-&gt;avatar = $fbInfo['pic_square'];
$user-&gt;name = $fbInfo['name'];
$user-&gt;fb_proxy_email = $fbInfo['proxied_email'];
$user-&gt;fb_id = $fbId;
...
$user-&gt;save();
...
</pre>
<p>Finally, let me complain a bit: I find writing code that interacts with Facebook a very frustrating experience. The information you need is scattered all over the web (and the Facebook site itself, even), and examples quality is very poor. The technology behing FB is very sophisticated, though, and no matter what they try to do, you need to grasp some concepts that are sometimes quite difficult to master or a nightmare to debug.</p>
<p>Good luck.</p>
<h3>Further readings</h3>
<ul>
<li><a href="http://developers.facebook.com/connect.php">The official Facebook Connect page</a> (and the developers <a href="http://wiki.developers.facebook.com/index.php/Facebook_Connect">Wiki one</a>)</li>
<li><a href="http://wiki.developers.facebook.com/index.php/How_Connect_Authentication_Works">How Connect Authentication Works</a></li>
<li><a href="http://mashable.com/2009/01/12/facebook-connect-implementations/">10 Great Implementations of Facebook Connect</a></li>
<li>What is behind <a href="http://wiki.developers.facebook.com/index.php/Cross_Domain_Communication">Cross Domain Communication</a> and <a href="http://msdn.microsoft.com/en-us/library/bb735305.aspx">even more</a></li>
<li><a href="http://wiki.developers.facebook.com/index.php/API">Facebook API</a> documentation</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://claudio.cicali.name/post/2010/01/use-facebook-connect-in-your-application/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Ubuntu 9.10 e PHP 4</title>
		<link>http://claudio.cicali.name/post/2009/10/ubuntu-9-10-e-php-4/</link>
		<comments>http://claudio.cicali.name/post/2009/10/ubuntu-9-10-e-php-4/#comments</comments>
		<pubDate>Sat, 31 Oct 2009 14:33:05 +0000</pubDate>
		<dc:creator>claudio</dc:creator>
				<category><![CDATA[Articoli]]></category>
		<category><![CDATA[Programmazione]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[lighttpd]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[php4]]></category>

		<guid isPermaLink="false">http://claudio.cicali.name/?p=558</guid>
		<description><![CDATA[Proprio ieri ho aggiornato alla ultimissima Ubuntu, appena uscita. E proprio oggi si è avverato uno dei peggiori incubi del programmatore: rimettere le mani in un&#8217;applicazione rimasta inerte per 5 anni, perché all&#8217;improvviso si è presentato un bacherozzo bloccante. Ogni tentativo è stato inutile: l&#8217;applicazione non è compatibile con PHP5. Ergo, occorreva trovare un sistema [...]]]></description>
			<content:encoded><![CDATA[<p>Proprio ieri ho aggiornato alla ultimissima Ubuntu, appena uscita. E proprio oggi si è avverato uno dei peggiori incubi del programmatore: rimettere le mani in un&#8217;applicazione rimasta inerte per 5 anni, perché all&#8217;improvviso si è presentato un <strong>bacherozzo bloccante</strong>. Ogni tentativo è stato inutile: l&#8217;applicazione non è compatibile con PHP5. Ergo, occorreva trovare un sistema (veloce) per far funzionare il PHP4, correggere il baco e poi buttare tutto.</p>
<p>Ecco come ho fatto (nota per gli amici Debianisti: ho più pratica nella compilazione del php/apache che nei vari giochini a colpi di dpkg; abbiate pazienza):</p>
<ul>
<li>Primo problema: trovare i sorgenti di PHP4. Questa è facile: si prendono direttamente <a href="http://www.php.net/releases/">dal sito ufficiale</a>.</li>
<li>PHP andrà compilato solo come CGI (l&#8217;idea è quella di usare lighttpd + fastcgi). Scompatta i sorgenti e poi dai un bel <strong>./configure &#8211;with-mysql=/usr  &#8211;enable-fastcgi. </strong>Attenzione che non è sufficiente il solo <strong>&#8211;with-mysql</strong>, perché altrimenti verrà compilato il supporto mysql &#8220;vecchio&#8221;, che non funzionerebbe con i server 5.x. Probabilmente il configure si lamenterà della mancanza di qualcosa, la qual cosa provvederete ad installare (es: libmysqlclient-dev).</li>
<li>Apt-get install lighttpd (probabilmente non partirà se avrai attivo Apache, ma non ti preoccupare) e poi:
<ul>
<li>Modifica /etc/lighttpd/lighttpd.conf per farlo andare su un&#8217;altra porta che non sia l&#8217;80 (dove potresti avere Apache). Io ho usato l&#8217;81.</li>
<li>Esegui <strong>lighttpd-enable-mod fastcgi</strong></li>
<li>Modifica /etc/lighttpd/conf-enabled/10-fastcgi.conf e cambia il &#8220;bin-path&#8221; del php, per farlo puntare a &lt;dirSorgentiPhp4&gt;/sapi/cgi/php</li>
<li>fai (ri)partire lighttpd /etc/init.d/lighttpd start</li>
</ul>
</li>
</ul>
<p>A questo punto i file php letti da localhost:81 verranno interpretati dal php4 fastcgi, via lighttpd mentre tutto il resto continuerà a funzionare come prima via Apache e php5 DSO :)</p>
<p>Se vuoi usare un sistema del tipo VirtualHost di Apache con lighttpd, ti copio la mia configurazione da mettere nel tuo /etc/lighttpd/lighttpd.conf</p>
<pre class="brush: php; title: ; notranslate">

$HTTP[&quot;host&quot;] =~ &quot;miodominio\.local(\:[0-9]*)?$&quot; {
server.document-root = &quot;/home/claudioc/Sites/miodominio&quot;
}
</pre>
<p>La cosa a cui fare attenzione è che anche se la chiave si chiama &#8220;host&#8221;, in realtà nella regexp occorre fornire il match anche per una eventuale porta (come nel caso di esempio).</p>
]]></content:encoded>
			<wfw:commentRss>http://claudio.cicali.name/post/2009/10/ubuntu-9-10-e-php-4/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Upload progressivo in PHP con APC e JavaScript &#8211; Parte 1</title>
		<link>http://claudio.cicali.name/post/2009/10/upload-progressivo-in-php-con-apc-e-javascript-parte-1/</link>
		<comments>http://claudio.cicali.name/post/2009/10/upload-progressivo-in-php-con-apc-e-javascript-parte-1/#comments</comments>
		<pubDate>Sun, 11 Oct 2009 16:03:55 +0000</pubDate>
		<dc:creator>claudio</dc:creator>
				<category><![CDATA[Articoli]]></category>
		<category><![CDATA[Programmazione]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[apc]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[upload]]></category>

		<guid isPermaLink="false">http://claudio.cicali.name/?p=525</guid>
		<description><![CDATA[Prima parte (leggi la seconda parte, leggi la terza parte) In questo articolo, suddiviso per motivi di lunghezza in più parti, cercherò di  spiegare il sistema tramite il quale sia possibile monitorare l&#8217;upload di un file in modo da visualizzare all&#8217;utente lo stato di avanzamento dell&#8217;operazione. Questi articoli non sono vogliono essere un semplice how [...]]]></description>
			<content:encoded><![CDATA[<p>Prima parte (<a href="../post/2009/10/upload-progressivo-in-php-con-apc-e-javascript-parte-2/">leggi la seconda parte</a>, <a href="../post/2009/10/upload-progressivo-in-php-con-apc-e-javascript-parte-3/">leggi la terza parte</a>)</p>
<p>In questo articolo, suddiviso per motivi di lunghezza in più parti, cercherò di  spiegare il sistema tramite il quale sia possibile monitorare l&#8217;upload di un file in modo da visualizzare all&#8217;utente lo stato di avanzamento dell&#8217;operazione.</p>
<p>Questi articoli non sono vogliono essere un semplice how to, quando invece una dettagliata analisi delle problematiche inerenti a questo sistema diventato ormai di sempre più comune utilizzo sui siti web.</p>
<p>La complessità di tutto questo &#8220;giochino&#8221; è da imputare principalmente al linguaggio  server side che utilizzerò in questi articoli: il PHP.</p>
<p>Vediamo subito il perché.</p>
<p>A grandi linee, l&#8217;upload di un file dal browser al server funziona semplicemente così: l&#8217;utente seleziona il file dal proprio computer e poi invia la form. In quel momento il browser inizia una trasmissione dati con lo script che riceve i dati della form, inviandogli senza soluzione di continuità i byte che compongono il file in fase di trasmissione.</p>
<p>Lato server il PHP dal momento che inizia la ricezione del file, &#8220;appoggia&#8221; su un file temporaneo i dati che stanno arrivando finché la trasmissione non sarà terminata o cancellata. Nel secondo caso il PHP provvederà a cancellare il file temporaneo e tutto finisce lì. Nel caso di ricezione avvenuta, lo script riprenderà il controllo e sarà in grado di copiare il file temporaneo dove meglio crede (move_uploaded_file(), non dico certo niente di nuovo.)</p>
<p>Non esistono sistema &#8220;nativi&#8221; da parte del browser per capire quanti byte ha al momento trasmesso. È possibile utilizzare dei trucchetti lato client che prevedono l&#8217;utilizzo di un piccolo Flash movie che fa da &#8220;gateway&#8221; usando Flash stesso per aprire il socket di trasmissione dati verso il server. In tal caso sarà lo stesso Flash a fornire le indicazioni che ci interessano e la gestione è assai più semplice. Tuttavia l&#8217;approccio (usato in tantissime soluzioni di alto livello) non è scevro da problemi e in questa sede non ci interessa.</p>
<p>Senza usare Flash, dunque, quello che occorre fare è chiedere al server continuamente a che punto è arrivato leggendo il file temporaneo che sta crescendo man mano che la trasmissione procede.</p>
<p>Questa richiesta verrà fatta dunque via Ajax, chiedendo ad un altro script PHP lo stato di avanzamento del file xxxyyyzzz&#8230;</p>
<p>Sembra facile, ma non è.</p>
<p>Il problema nasce dal fatto, come dicevo poco fa, che stiamo usando PHP. Soltanto dalla versione 5.2 in poi è possibile infatti usare un sistema per chiedere al PHP a che punto è con l&#8217;upload. Prima, non esisteva modo&#8230; impossibile sapere il nome del file temporaneo da un altro processo, né tantomeno dal processo PHP che lo sta generando.</p>
<p>Dalla versione 5.2 è stato introdotto un &#8220;hook&#8221; che permette alle estensioni PECL del php di <a href="http://www.ibm.com/developerworks/library/os-php-v525/index.html">intercettare le fasi di upload</a> di un file (no, non si può fare direttamente da PHP). Ovviamente non è che adesso ci mettiamo lì, con il nostro compilatore C a scrivere la nostra fantastica estensione che usa quell&#8217;hook. Questo lavoro, fortunatamente, è già stato fatto da qualcuno.</p>
<p>Credo che la maggior parte degli sviluppatori in PHP siano a conoscenza di <a title="Alternative PHP Cache" href="http://www.php.net/apc/">APC</a>. Il suo mestiere è duplice. In primis è un cosidetto sistema di &#8220;opcache&#8221;, ovvero permette al PHP di salvarsi i nostri script &#8220;precompilati&#8221; (passatemi il termine), in modo da velocizzarne le esecuzioni successive (stessa cosa di eAccelerator o xcache, se conoscete già queste alternative). In secundis, mette a disposizione agli script PHP un buffer di memoria ad accesso rapido, per salvare al suo interno delle informazioni magari lette da un sottostitema più lento (dbms, per esempio). È più o meno quello che fa memcache, solo che in questo caso non c&#8217;è bisogno di un servizio esterno che giri. APC infatti è un&#8217;estensione del PHP e come tale, una volta che questa sia stata compilata e caricata dal PHP, è disponibile da subito.</p>
<p>Fin qui &#8211; credo &#8211; nessuna grossa novità.</p>
<p>La cosa interessante è che, dalla versione PHP 5.2, APC implementa appunto la gestione di quel famoso &#8220;hook&#8221; per il monitoraggio dell&#8217;upload, offrendo un sistema ai normali script PHP per interrogare l&#8217;andamento della creazione del nostro file. Non solo: tramite il servizio di APC sarà così possibile controllare se il nostro file ha terminato il caricamento, se il caricamento è stato annullato dall&#8217;utente o da un problema di rete e fare dei semplici calcoli per sapere anche il &#8220;rate&#8221; di trasmissione in kbyte.</p>
<p>Nella seconda parte dell&#8217;articolo vedremo come fare ad implementare un sistema del genere, usando &#8220;solo&#8221; HTML, PHP e un po&#8217; di sano JavaScript.</p>
<p>Nel frattempo, assicuratevi di avere a disposizione APC (perlomeno) sulla vostra macchina di sviluppo. In Ubuntu è questione di &#8220;sudo apt-get install php-apc&#8221; e far ripartire Apache. La configurazione, eventualmente, la troverete in<br />
/etc/php5/apache2/conf.d/apc.ini</p>
]]></content:encoded>
			<wfw:commentRss>http://claudio.cicali.name/post/2009/10/upload-progressivo-in-php-con-apc-e-javascript-parte-1/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Chi usa IE6? (ed altre facezie)</title>
		<link>http://claudio.cicali.name/post/2009/03/chi-usa-ie6-ed-altre-facezie/</link>
		<comments>http://claudio.cicali.name/post/2009/03/chi-usa-ie6-ed-altre-facezie/#comments</comments>
		<pubDate>Tue, 24 Mar 2009 18:20:39 +0000</pubDate>
		<dc:creator>claudio</dc:creator>
				<category><![CDATA[Programmazione]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[geo localizzazione ip]]></category>
		<category><![CDATA[ie6]]></category>
		<category><![CDATA[internet explorer]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://claudio.cicali.name/?p=364</guid>
		<description><![CDATA[Oggi ho scoperto il sito di un tizio che garantisce di fornire la geolocalizzazione esatta di qualsiasi IP. Il database è gratuito e questa persona sostiene che lo terrà aggiornato su base mensile. Sarebbe fantastico :) Cosa potevo fare per provarlo? Ovviamente cercare di capire da dove provengono le visite delle persone (o altro) che [...]]]></description>
			<content:encoded><![CDATA[<p>Oggi ho scoperto il sito di un tizio che garantisce di fornire la <a href="http://blogama.org/node/58">geolocalizzazione esatta di qualsiasi IP</a>. Il database è gratuito e questa persona sostiene che lo terrà aggiornato su base mensile. Sarebbe fantastico :)</p>
<p>Cosa potevo fare per provarlo? Ovviamente cercare di capire da dove provengono le visite delle persone (o altro) che usano Internet Explorer 6. Il test è stato utile <em>solo</em> per provare che non è vero, purtroppo, che la maggior parte degli IE6 sono dei bot travestiti.</p>
<p>Gli impazienti possono vedere i risultati aggregati su <a href="http://spreadsheets.google.com/pub?key=ppKUhnLpFQkG7_8oyvr4bNw">questo documento gdocs</a>.</p>
<p>Per i curiosi, ecco come ho proceduto. I dati sono quelli di un mio sito, frequentato per la maggior parte da utenti italiani, raccolti in un periodo di tre mesi.</p>
<p>Ho scaricato il database (è un dump MySQL di circa 68MB) e me lo sono importato in locale.</p>
<p>Con queste due righe di bash (spezzate per motivi di questo spazio) mi sono procurato tutti gli IP degli utilizzatori di IE6 (circa 6500, al momento).</p>
<pre>grep "MSIE 6.0" access.log &gt; ie6
awk '{print $1'} ie6 | sort | uniq &gt; ip_ie6</pre>
<p>Infine qualche riga di PHP:</p>
<pre>$ips = file('ip_ie6');
$countries=$cities=array();
foreach($ips as $ip) {
  list($a,$b,$c,$d) = split('\.',$ip);
  $val = ($a*256+$b)*256+$c;
  $sql = "SELECT * FROM `ip_group_city` where `ip_start` &lt;= {$val} order by ip_start desc limit 1";
  $row = mysql_fetch_object(mysql_query($sql));
  $countries[$row-&gt;country_code]++;
  if (!empty($row-&gt;city))
    $cities[$row-&gt;city . ", " . $row-&gt;country_code]++;
}

asort($countries);
foreach(array_reverse($countries) as $country =&gt; $count) {
  print "$country\t$count\n";
}

asort($cities);
foreach(array_reverse($cities) as $city =&gt; $count) {
  print "$city\t$count\n";
}</pre>
<p>Nota che usando un tab (\t) e un ritorno a capo (\n) si può fare copia &amp; incolla direttamente dentro uno spreadsheet di di GDocs e lui &#8220;sentirà&#8221; la suddivisione in colonne.</p>
]]></content:encoded>
			<wfw:commentRss>http://claudio.cicali.name/post/2009/03/chi-usa-ie6-ed-altre-facezie/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

