sindro.me

feeling bold
on the internet

info 🇬🇧🇮🇹

http://www.fub.it/events/seminari/neutralitadellareteeaspettisocioeconomici

http://www.nnsquad.it/

Neutralita' – “L'economia si sta dematerializzando”

Sollecitato da un messaggio Facebook inviato il 6 maggio 2009 a tutti i membri del gruppo nnsquad.it – per un Internet neutrale, mi sono imbattuto in questo evento interessante a cui ho avuto l'occasione di partecipare, tenutosi nel seicentesco palazzo Rospigliosi nel cuore di Roma.

Nella foto: Kenneth Carter e Stefano Quintarelli

La premessa era promettente: tecnici, dottori di ricerca, portavoce delle telco e politici che parlano di internet, della sua liberta' innata, e di come conciliarla in una societa' dove le misure di sicurezza aumentano costantemente, e come tali contrastano con un mondo virtuale senza barriere di sorta. Inoltre, e' un'arena virtuale in cui tutto puo' essere gratuito, non solo le informazioni, e le persone ci si stanno abituando.

Il primo intervento e' stato tenuto dal prof. Kenneth Carter, direttamente dalla Columbia University, e ha fatto da ampia introduzione alle tematiche esplorate (e talvolta ripetute) durante la giornata. In breve, la grande domanda e': gli ISP possono offrire diversi gradi di performance su diversi siti (o far pagare per performance migliori), permettere/bloccare/sovraccaricare l'accesso a certi siti o da certi dispositivi?

Filtrare l'accesso ai servizi di rete e' una pratica comune su internet, come lo e' filtrare i contenuti, e non necessariamente cattiva: pensate ai filtri antispam per prevenire UCE e ai filtri dei NAP per prevenire e mitigare attacchi DDOS, o ai sistemi antivirus/IDS. Anche i piani di servizio differenziati, dove ottieni latenza piu' bassa o maggiore banda in upload pagando di piu', sono accettabili, perche' la “qualita' del servizio” non e' un valore assoluto: dipende dal tipo di servizi che l'utente usa. E nella maggior parte dei casi, l'utente non coglie (e nemmeno ha bisogno di cogliere) i concetti che ci stanno dietro.

Questo e' il mio resoconto del primo facebook developer garage italiano, tenutosi a Milano il 23 aprile 2009, e ospitato da mikamai. La mattina e' stata dedicata alle sessioni per sviluppatori, il pomeriggio a quelle di marketing & comunicazione. Alcuni video dell'evento sono disponibili qui.

Mattina: sessione sviluppatori

Il primo talk e' stato tenuto da James Leszczenski, ingegnere di Facebook, che ha presentato la visione, la missione e i valori della piattaforma connect. Interessante, oltre al talk in se', per la partecipazione del pubblico: la platea era profondamente interessata a sapere quali informazioni si ottengono da Facebook, come gestirle, e quali strumenti connect fornisce per collegare identita' e trovare amici su un sito web abilitato.

Piu' tardi ho avuto occasione di chiedere a James se FB fosse incline o meno ad adottare OpenID come metodo di autenticazione: ha detto che connect e OpenID permettono entrambi agli utenti di avere credenziali di login uniche per accedere a piu' siti, ma connect permette anche di sfruttare la potenza del social graph di Facebook per consentire agli utenti di comunicare e condividere informazioni. Quindi, la risposta breve e' “no”. Allora gli ho proposto di implementare OpenID su FB stesso, cosi' che connect potesse diventare davvero un superset di OpenID, ma ha risposto che “come azienda, queste sono decisioni difficili e non posso dare una risposta adesso”. Comprensibile :).

AGGIORNAMENTO: il 27 aprile 2009, TechCrunch riporta di aver sentito che Facebook abbraccera' OpenID come mezzo per autenticare gli utenti. Ottime notizie, in attesa di una dichiarazione ufficiale da Facebook! :)

Il secondo talk e' stato tenuto da Vincenzo Acinapura, che ha descritto gli strumenti di base per creare un'applicazione sulla piattaforma Facebook. Ha esplorato le tecnologie che ci stanno dietro (XFBML, FQL, FBJS), i principali punti di integrazione all'interno della piattaforma (notifiche, publisher, ...) e ha mostrato codice d'esempio per implementare alcuni dei tag FBML piu' usati (fb:comments, fb:share, fb:feed, e cosi' via). Infine ha ricordato l'importanza di automatizzare il deploy delle applicazioni, e ha suggerito di usare capistrano per farlo.

Sto cercando un nuovo animale domestico. Noi abbiamo gia’ due gatti adorabili, ma dopo aver sentito quanto puo’ essere viva una casa con tanti animali (dopo una bella serata al maniero de il quadrato), sto pensando di prenderne un altro da crescere e amare.

Ma che razza di geek sarei, se non ci aggiungessi un tocco nerd? Quindi, dopo l’interfaccia cervello-twitter di cui si e’ parlato tanto negli ultimi giorni, stasera un pensiero abbastanza casuale e divertente mi e’ balenato in testa: che ne dite di prendere un pappagallo cenerino, crescerlo, insegnargli a parlare, e lasciarlo… be’, twittare le sue parole usando un sistema di riconoscimento vocale piazzato accanto alla sua gabbia e collegato a un account twitter? Quanto sarebbe assurdo? :D

Tweeting parrot

A pensarci bene, la cosa piu’ strana e’ che nel 2009, un pappagallo che twitta mi fa pensare a un “pappagallo con accesso a twitter”… e non a un uccello che emette il suo verso naturale. Sono troppo sovraccaricato da questa storia dei social media? Dovrei prendermi una vacanza?

Direi di si’. Ma non adesso. Il primo Facebook Developer Garage italiano e’ tra appena due giorni… :)

Immagine per gentile concessione di @ozjulian su flickr, CC BY-NC-SA

Avviso a tutti i dipendenti

- 1 min di lettura

(Letto su full-disclosure)

Subject: Notice to all employees
Date: Tue, 24 Feb 2009 13:06:14 -0500

Dear employees,

Due to the current financial situation caused by the slowdown
of the economy, Management has decided to implement a scheme
to put workers of 40 years of age and above on early retirement.

This scheme will be known as RAPE (Retire Aged People Early).

Persons selected to be RAPED can apply to management to be eligible
for the SHAFT scheme (Special Help After Forced Termination).
Persons who have been RAPED and SHAFTED will be reviewed under the
SCREW programme (Scheme Covering Retired Early Workers). A person
may be RAPED once, SHAFTED twice and SCREWED as many times as
Management deems appropriate.

Persons who have been RAPED can only get AIDS (Additional Income
for Dependents & Spouse) or HERPES (Half Earnings for Retired
Personnel Early Severance).

Obviously, persons who have AIDS or HERPES will not be SHAFTED or
SCREWED any further by Management.

Persons who are not RAPED and are staying on will receive as much
SHIT (Special High-Intensity Training) as possible. Management
has always prided itself on the amount of SHIT it gives employees.

Sincerely,
The Management

(Spero vi siate divertiti :D C’e’ anche una versione USAF del 1997).

Su VisitaCSA stiamo usando facebox di defunkt per mostrare le immagini dei luoghi in grande. Facebox e’ un ottimo lightbox generico, perche’ e’ veloce, stabile, si basa su jQuery e ha un’API davvero pulita.

Ma avevamo bisogno di qualcosa in piu’ di un semplice lightbox di visualizzazione, perche’ volevamo che i nostri utenti potessero navigare facilmente tra tutte le immagini, possibilmente senza modificare facebox. La soluzione si e’ rivelata piuttosto semplice, grazie anche al plugin will_paginate che stavamo gia’ usando. In sostanza si tratta di avere:

  • Un model Photo, attrezzato con il metodo has_attachment
  • Route per le risorse photos (map.resources :photos, :only => :show in config/routes.rb)
  • Un metodo show nel controller PhotosController che chiama .paginate con un argomento :per_page di 1
  • Una vista HTML per la risorsa photo, con i controlli di paginazione usando l’helper will_paginate
  • Del codice jQuery che si aggancia ai link di paginazione e fa caricare al browser via AJAX la foto successiva direttamente nel facebox.

Ecco il codice rilevante, semplificato rispetto a quello effettivamente online, perche’ il model photo e’ in realta’ polimorfico (usa STI) e diverse collezioni sono gestite dal photos controller (foto, volantini, ecc.) per diversi model, con miniature diverse :P.

Model [app/models/photo.rb]

class Photo < ActiveRecord::Base
  has_attachment :storage => :file_system, :path_prefix => 'public/photos',
    :processor => 'ImageScience', :thumbs => { :thumb => '600x800' }
end

Controller [app/controllers/photos_controller.rb]

class PhotosController < ApplicationController
  layout nil
  before_filter :find_place

  # The photo gallery core is here
  def show
    photo = Photo.find(params[:id])
    page = params[:page] || @place.photos.index(photo) + 1
    @photos = @place.photos.paginate(:per_page => 1, :page => page)
    @photo = @photos.first
  end

  def find_place
    @place = Place.find(params[:place_id])
  end
end

Vista [app/views/photos/show.html.erb]

<div class="photo">
  <div style="width: <%= photo_width(@photo) %>px; text-align: center;">
    <%= next_photo_link_for @photo, :in => @photos %>
  </div>
  <p><%=h @photo.title %></p>
  <p>
    <%= will_paginate @photos, :prev_label => '&nbsp;', :next_label => '&nbsp;' %>
  </p>
</div>

La gem image_size e’ necessaria per consentire a facebox di allinearsi correttamente al centro della finestra.

Il bordo lampeggiante offuscato

- 1 min di lettura

Questo e’ il pezzo di codice Javascript offuscato che implementa il bordo rosso e carica Google Analytics sul sito Segmentation Fault:

var theLoadSequenceToRunAfterTheDocumentHasBeenLoaded = function() {

  // The blinking border
  //
  (function(t){// (C) 2009 vjt <segmentation-fault@core-dumped.info>
    var $=function(_){return(document.getElementById(_));};var ee =[
    $('n'),$('s'),$('w'),$('e')],e,_=true;setInterval(function(){for
    (var i=ee.length;i&&(e=ee[--i]) ;_) {e.className=e.className?'':
    'b';}},t*08); /* .oOo.oOo.oOo. ^^^^^ -*** * *** *** *******- **/
  })((4 + 8 + 15 + 16 + 23 + 42) * Math.PI / Math.E + 42/*166.81*/);

  // Google analytics
  //
  try{var pt=_gat._getTracker("UA-1123581-3"); pt._trackPageview();}
  catch($aMarvellousErrorThatWontBeDisplayedOnTheUserBrowserAtAll){}

}// end of theLoadSequenceToRunAfterTheDocumentHasBeenLoaded routine

Per me sembra una melodia contorta, o una poesia complicata. E’ ingegneria malvagia, lo so. Ma mentre lo scrivevo, provavo esattamente la stessa sensazione di quando scrivevo versi in rima. Le parole di _why sono assolutamente pertinenti qui:

finche’ i programmatori non smetteranno di comportarsi come se l’offuscamento fosse moralmente pericoloso, non saranno artisti, solo ragazzini che non vogliono che il loro cibo si tocchi.

Puoi vedere il codice con l’evidenziazione della sintassi su github, oppure con la funzione “Visualizza sorgente” del tuo browser mentre sei sul sito segfault. :)

Attualmente mantengo il mirror italiano del sito web della Open Source Initiative, e oggi mi sono reso conto che lo script che avevo scritto qualche mese fa non stava facendo bene il suo lavoro… perche’ i file CSS non venivano scaricati affatto, causando un rendering del sito piuttosto sgradevole.

Per fare il mirror di opensource.org sto usando il caro vecchio GNU Wget con -r –mirror e compagnia bella. Mentre il buon vecchio wget scarica tutti i prerequisiti di ogni pagina definiti nel sorgente HTML, non supporta le regole CSS @import e non scarica le immagini referenziate nei CSS con le regole url().

Comunque, niente che non si possa risolvere con un po’ di regex-fu: ecco perche’ condivido lo script che sto usando attualmente per fare il mirror del sito opensource.org, sperando che generi un nuovo mirror o qualche spunto su come fare meglio questo lavoro :).

Lo script: update_opensource_mirror.sh

Buon divertimento! :)

Evoluzione continua

- 2 min di lettura
releases$ du -sch *
7.6M    20081209132347
7.0M    20081209133350
7.6M    20081209144343
7.1M    20081209145133
7.1M    20081209151843
7.1M    20081209163013
7.1M    20081209175506
7.1M    20081209183553
7.1M    20081211122939
8.6M    20081212190026
8.3M    20081212201852
8.3M    20081212203943
8.3M    20081212205430
8.3M    20081213014847
8.3M    20081213020357
8.4M    20081213163428
8.4M    20081213173633
8.4M    20081213184749
8.5M    20081214171239
8.5M    20081214174058
8.5M    20081215122638
8.5M    20081215152408
8.5M    20081215171627
8.5M    20081215200430
8.5M    20081215205042
8.5M    20081215235659
8.5M    20081216000247
8.5M    20081216164820
8.6M    20081216200524
8.6M    20081216203210
8.6M    20081216210540
8.6M    20081217193227
8.6M    20081218174354
8.6M    20081218191803
8.6M    20081219152005
8.6M    20081219152907
8.6M    20081219155519
9.0M    20081219193433
8.6M    20081221173121
8.6M    20081221174616
19M    20081222035552
17M    20081222040347
17M    20081222055349
11M    20081222055633
14M    20081222055923
16M    20081222142851
11M    20081228152551
60M    20081228163752
11M    20090105191748
11M    20090106064448
11M    20090106184425
11M    20090106185528
11M    20090106204053
11M    20090106230526
14M    20090107001206
11M    20090107175246
11M    20090107175846
11M    20090107193832
11M    20090107194313
11M    20090107204045
11M    20090107204438
12M    20090109164048
11M    20090109185118
11M    20090112031351
11M    20090113104259
12M    20090113152213
12M    20090113171628
12M    20090113194223
12M    20090113194415
20M    20090113201919
12M    20090114180311
12M    20090114185735
12M    20090115071510
12M    20090115102500
12M    20090115131810
12M    20090115155944
12M    20090115183612
12M    20090116121148
12M    20090116125514
12M    20090116131343
12M    20090116170318
12M    20090116171428
24M    20090116173349
16M    20090118204113
14M    20090120151836
12M    20090122150700
12M    20090122155359
18M    20090122160455
78M    20090125055603
48M    20090126114022
14M    20090126143048
12M    20090126160105
12M    20090126160400
12M    20090126165339
22M    20090126170159
12M    20090126193506
12M    20090126194637
12M    20090126194859
12M    20090127142057
14M    20090127155906
52M    20090127180739
13M    20090129144356
12M    20090201141300
12M    20090201151016
13M    20090202114805
12M    20090203113750

Affascinante, nondimeno.

Un altro spin-off dal sito www.visitacsa.it: un miglioramento a permalink_fu che permette permalink dinamici. Lo so che è un ossimoro, perché i permalink dovrebbero essere… beh… permanenti! E siccome i motori di ricerca li indicizzano, non dovrebbero mai cambiare. Ma cosa succede quando pubblichi qualcosa, il tuo permalink viene generato con permalink_fu usando il titolo del tuo post, e dopo un paio di giorni vuoi cambiare il titolo, e anche il permalink sotto il quale il post è accessibile?

Seguendo la specifica, la tua applicazione dovrebbe inviare uno status HTTP 301 moved permanently quando si accede al vecchio permalink e fare redirect del client verso il nuovo Uniform Resource Locator. Questo è più o meno quello che fa la mia modifica a permalink_fu: ogni volta che gli attributi del tuo post vengono modificati, il permalink precedente e quello nuovo vengono salvati nel database, e puoi abilitare il tuo controller a generare redirect 302 moved temporarily quando necessario. In altre parole, controlla se l’URL richiesto è un vecchio permalink e reindirizza automagicamente il client verso quello nuovo.

Tutto avviene dietro le quinte, e il plugin ha anche dei comodi task rake per impostare il model Redirect e le migration associate. E puoi anche cambiarne il nome, ovviamente! :)

Il codice 302 è stato scelto perché lo status code 301 permanent ha effetti piuttosto dirompenti sui motori di ricerca, ma ulteriori discussioni sono benvenute.

Dai un’occhiata al mio repository su GitHub, leggi il README che contiene la documentazione delle funzionalità aggiunte, e guarda il codice!

Di recente ho scritto un plug-in jQuery che permette l’upload di file via AJAX senza usare un pulsante file input fisso. Raggiunge il suo scopo installando un handler OnMouseMove sugli elementi selezionati e spostando il pulsante input sotto il cursore del mouse.

La citazione che ha ispirato questo codice e’: “Se Maometto non va alla montagna, la montagna va da Maometto”, il contrario del proverbio piu' noto :).

EDIT 2023: ATTENZIONE: questi link sono scaduti :-( E’ stato estratto dalla codebase JavaScript dell’applicazione Visita CSA, guarda il gist per maggiori informazioni, e dai un’occhiata al codice dell’app live per un esempio di utilizzo.

Ecco il codice sorgente:

//  ~ JavaScript Kung-FU, with an excess chunky bacon dose! ~
// This plugin allows seamless ajax file uploads without having
// a fixed file input button. It achieves this by installing an
// OnMouseMove handler over the interested elements, and moving
// the input button under the cursor. <<If Muhammad won't go to
// the the mountain, the mountain will come to Muhammad.>> :-).
//
// This approach is needed on the majority of browser, except
// Safari, on which the coder is allowed to trigger a "click" 
// event onto an input type=file element. On other browsers,
// you can not, that's why the complicated mousemove approach
// was chosen.
//
// Either way, when the value of the input type=file changes,
// handlers are disabled, and a user-provided callback is then
// called (passed via the "upload" option). Handlers are then
// re-enabled again when the upload succeeds or fails.
//
// IE has additional problems, because, quite unexplicably,
// when submitting a form that causes a page load, the change
// event on the file input is triggered AGAIN, thus triggering
// a new file upload. To circumvent this, you can pass a "linked" 
// option, that contains the jQuery selector of the form, and
// whenever an input under this form is hovered, ajax upload
// handlers are temporarily cleared and thus the spurious form
// submission.
//
// The jquery Form plugin is a perfect companion of this one,
// because of its .ajaxSubmit method. Have a look at its home
// page: http://malsup.com/jquery/form/.
// 
// Have fun!
// - vjt@openssl.it
//
$.fn.ajaxFormUpload = function(options) {
  var positioning = { top: 0, left: 0,
    position: 'absolute', cursor: 'pointer', 'z-index': 2 };

  var form = $(options.form || '#ajax_upload');
  form.css(positioning)

  var input = form.find('input[type=file]');
  input.css($.extend(positioning, { width: '10px', opacity: 0, 'font-size':'0px' }));

  var hovering_element = null;

  var elements = $(this);

  var handler, event_;
  if ($.browser.safari) {
    event_ = 'click', handler = function() {
      hovering_element = $(this);
      input.click();
    };
  } else {
    event_ = 'mousemove', handler = function(event) {
      hovering_element = $(this);
      form.css({ left: event.pageX - 10, top: event.pageY - 5 });
    };
  }

  function enable()  { $(elements).bind(event_, handler);   }
  function disable() { $(elements).unbind(event_, handler); }

  input.change(function() {
    var element = hovering_element;
    if (!element) return;
    disable();

    options.upload(element, form);

    enable();
  });

  enable();

  if (options.linked) {
    $(document).ready(function() {
      $(options.linked).find('input').mouseover(function() { hovering_element = null; });
    });
  }
};

Puoi trovarlo su github.