Pillole Android: come visualizzare in AndroidStudio un dispositivo collegato via USB al PC

  1. da dispositivo: Abilitare il debug USB  (Impostazioni > Opzioni Sviluppatore > Debug USB -> ON)
  2. da computer: da linea di comando digitare 
$ adb devices
List of devices attached
QLF7N16406002695        device

Quindi in basso a dx attivare la tab Device File Explorer come in figura

In alto a destra compare la tab del dispositivo con tutto il contenuto del file system:

Device FIle Explorer

Per installare adb

$ sudo apt-get install adb

Per installare Android Studio, seguire questo sito.

Pillole Laravel – localizzazione

Affinché le date e il tempo dell’applicazione Laravel siano sincronizzate con l’orologio del server occorre agire sui file di configurazione dell’applicazione. Ovviamente questo non è detto sia ciò che si desidera perché per esempio vogliamo che sia un jet lag tra il server e l’applicazione. In ogni caso, il file da modificare è uno soltanto: config/app,php:

    //'timezone' => 'UTC',
    'timezone' => 'Europe/Rome',

Io per esempio ho modificato sul fuso orario del server. That’s all folks!

Pillole Laravel – protezione contro attacchi XSS

Laravel consente di proteggere con semplicità le applicazioni dagli attacchi cross site (CSRF – Cross Site Request Forgery). I CSRF sono un tipo di sfruttamento malevolo dei programmi web in cui comandi non autorizzati vengono eseguiti al posto di un utente autenticato.

Attenzione: In particolare questi attacchi si possono verificare anche se non c’è alcuno strato di protezione con autenticazione tra il browser e il modulo HTML.

Laravel realizza nel modo che segue la protezione: esso genera automaticamente una stringa cosiddetta “gettone” (token) CFRS per ogni sessione attiva (quindi per ogni browser aperto sull’applicazione). Questo gettone viene usato per verificare che l’utente che ha fatto la richiesta sia lo stesso che ha acceduto all’inizio all’applicazione. Non serve che ci sia un’autenticazione, funziona anche per una sessione non autenticata in cui semplicemente il server invia un cookie di sessione al primo accesso anche senza necessariamente legarlo da un utente fisico nel database.

Ogni volta che si definisce una form HTML nell’applicazione, dovrebbe essere incluso un token CSFR in un campo nascosto (hidden) cosicché il middleware di protezione possa validare la richiesta. Per generarlo con Blade è facile: basta usare la direttiva @csrf per generare il campo:

<form method="POST" action="/profile">
    @csrf
    ...
</form>

Il metodo incluso nel gruppo middleware (si veda il metodo /app/Http/Middleware/VerifyCsfrToken.php) verificherà automaticamente che l’input proveniente dalla richiesta corrisponda al token salvato nella sessione.

Se non si agisce in questo modo, Laravel semplicemente blocca l’applicazione sollevando un errore HTTP 419:

Pillole Laravel: errore HTTP 500 accedendo ad una applicazione

Errore 500 e questo messaggio di log:

PHP Parse error:  syntax error, unexpected '?' in /vendor/symfony/http-foundation/Response.php

Come trovato qui, si risolve togliendo php7.0 (attualmente sto girando con php7.2)

$ sudo apt-get purge php7.0 php7.0-common ; sudo apache2ctl restart

L’errore sparisce.

Pillole Laravel: come evitare di creare implicitamente due colonne chiave sulla stessa tabella

Lo strumento delle migrazioni di Laravel è molto comodo per definire le tabelle di uno schema ma anche per le conseguenti ricadute positive sull’ORM Eloquent ai fini di produrre query con le join già fatte.

Mi riferisco al fatto che è possibile definire i vincoli di chiave esterna (foreign key). Solo che la definizione è un po’ “tricky”. Prendiamo questo esempio: due tabelle customers e orders con una relazione di chiave esterna da customers a orders:

Definizione della tabella customers, un solo attributo chiave, implicitamente definito con increments()
C’è un attributo di riferimento a customer_id

Se faccio girare lo script di migrazione, che si incarica di creare gli oggetti nello schema del DB ottengo un errore:

Illuminate\Database\QueryException  : SQLSTATE[42000]: Syntax error or access violation: 1075 Incorrect table definition; there can be only one auto column and it must be defined as a key

L’errore è abbstanza grave: abbiamo tentato di creare due chiavi: la prima con il campo id la seconda con il campo customer_id. 

All’inizio credevo che fosse un problema della definizione del constraint, e così l’ho scorporato in una seconda invocazione separata: Schema::table eccetera. Invece il problema era com’è stato definito il campo, infatti ho lo stesso errore anche togliendo la definizione del contraint. Il problema è la dimensione del campo:

$table->unsignedInteger('customer_id', 10);

Ora lo spiego qui e sembra ovvio, ma trovarlo, come tutti i buoni martorei, richiede tempo: il metodo $table->unsignedInteger() ha un secondo parametro che non è affatto la dimensione del campo, che lui si regola automaticamente, ma è – disgraziatamente…

 public function unsignedInteger($column, $autoIncrement = false)
    {
        return $this->integer($column, $autoIncrement, true);
    }

… l’informazione $autoIncrement. Essendo disgrazatamente 10 == true in PHP, il campo così viene dichiarato come autoincrement e quindi come chiave primaria generando l’errore. Invece con questa dichiarazione:

La migrazione termina correttamente

In origine, in ogni caso, c’era la mia errata invocazione del metodo.

[Hint: http://bit.ly/2zS9w1v]

Nobel per la Fisica 2018 a lavori sulla tecnologia laser

https://www.nobelprize.org

Il premio Nobel per la Fisica 2018 è stato assegnato a lavori sulle pinze laser, – ad Arthur Ashkin, una tecnologia che consente di spostare in modo estremamente preciso oggetti microscopici come i virus utilizzando la pressione elettromagnetica della luce – e sugli impulsi ultrabrevi (Mourou e Strickland). Con questa tecnica si ottengono impulsi della durata di un femtosecondo (10-15 secondi).

Per avere una idea di quanto breve sia il femtosecondo si pensi che in 1 secondo ci stanno tanti fs quanto il numero di secondi nell’età dell’universo (circa 1018):

1 s : 1 fs = Età dell’universo : 1 s

Il laser a femtosecondo, così chiamato in breve, viene utilizzato nella chirurgia dell’occhio, per la sua capacità di dosare in modo precisissimo l’energia degli impulsi.

Pillole Linux: riesumare una finestra “fantasma”

Oggi mi sono trovato davanti un problema sconosciuto: ho aperto una finestra (nella fattispecie, l’applet Java di MirthConnect) e ho poi normalmente commutato su un’altra finestra da quel momento non vedevo più la finestra Java nell’elenco dei task che vengono visualizzati con ALT-TAB:

La finestra in foreground non c’è nell’elenco dei task.

Se minimizzo la finestra di Mirthconnect non riesco più a recuperarla… Come posso fare ad accedervi nuovamente? il Linux ci sono due bei strumenti:

  • wmctrl interact with a EWMH/NetWM compatible X Window Manager: consente di fare cose meravigliose per automatizzare il desktop tramite script bash, ma in questo caso voglio solo vedere l’elenco delle finestre attive:
$ wmctrl -l
0x05800008 0 jsbach Aggiornamenti software
0x03000002 0 jsbach XdndCollectionWindowImp
0x03000003 0 jsbach unity-launcher
0x03000004 0 jsbach unity-panel
0x03000005 0 jsbach unity-dash
0x03000006 0 jsbach Hud
0x0340000a 0 jsbach Scrivania
0x03402081 0 jsbach dati_effettivi
0x00e00001 0 jsbach command line - Maximize an application with known PID from CLI - Ask Ubuntu - Google Chrome
0x05200084 0 jsbach *analisi_errori.txt (~/Documenti/clienti/XYZ/anomalie/180927) - gedit
0x04e000b5 0 jsbach prod36.mirth.local - Mirth Connect Administrator - (3.5.2)
0x03600004 0 jsbach dati_180927.xml - /home/marcob/Documenti/clienti/XYZ/2018/ - Geany
0x05a0000a 0 jsbach Terminale
0x04c00007 0 jsbach Database - KeePassX
0x05e000b0 0 jsbach prod35.mirth.local - Mirth Connect Administrator - (3.5.2)

Come si può notare le finestre attive sono più di quelle mostrate con ALT-TAB; in particolare ho evidenziato le due finestra scomparse: mi serve accedere ad una di queste due (l’ultima)

C’è poi un secondo tool molto potente:

  • xdotool fake keyboard/mouse input, window management, and more:
    questa utility simula l’uso della tastiera e di movimenti del mouse prodotti con uno script bash! Nel mio caso mi serve solo per sapere quale finestra è associata al processo che vedo essere quello sotto il quale gira il client Mirtchconnect
$ ps ax | grep java
4201 ? Sl 6:24 /usr/local/java/jre1.8.0_73/bin/java -eccetera
6102 ? Sl 6:24 /usr/local/java/jre1.8.0_73/bin/java -eccetera

Quello che mi serve è agganciare è il processo 6102. Per vedere quale finestra è associata eseguo:

$ xdotool search --pid 6102 | tail -1
98566320

xdotool mi dice che il processo 6102 è legato alla finestra 98566320, in esadecimale 0x05e000b0.

Ora xdotool permette di ripristinare la finestra come se la selezionassimo con ALT-TAB!

$ xdotool windowactivate 5e000b0

Si può fare anche tutto con un solo comando

$ xdotool windowactivate xdotool search --pid 6102 | tail -1

L’effetto è quello di riportare in foreground la finestra fantasma e ricominciarci a lavorare. Con la linea di comando 🙂

La finestra “fantasma” è nuovamente disponibile.

Pillole protocols: WebDAV

Il web come lo conosciamo oggi è un mezzo per lo più in sola lettura.

È vero che con il Web 2.0 anche gli utenti contribuiscono ai contenuti web, ma ciò avviene in modo molto diverso e molto più sofisticato rispetto a quanto immaginato inizialmente da Tim Berners-Lee.

Il suo browser WWW infatti agiva sui server web in lettura e scrittura: si poteva leggere una pagina web ma si poteva anche modificarla.

Come si “scrive” sul web ai tempi del Web 2.0

Quello che accade attualmente con il Web 2.0, ad esempio quando aggiungiamo un commento ad un articolo di un blog WordPress, è qualcosa di più complicato, ossia la scrittura in un database e non nel filesystem del server che eroga le pagine Web.

Tecnicamente quando invochiamo la funzionalità di aggiunta di un commento, invochiamo un comando di lettura di una risorsa web (comando HTTP POST) che si chiama wp-comments-post.php passando dei parametri:

POST /wp-comments-post.php HTTP/1.1 
Host: www.betaingegneria.it 
Connection: keep-alive 
Content-Length: 184 
...

comment=questo %22 il mio commento&author=My+Name&email=my.mail%40gmail.com&url=&submit=Submit+Comment&comment_post_ID=2734&comment_parent=0&akismet_comment_nonce=afb00fa731&ak_js=1535630177692

Qui, disgraziatamente, la parola post è utilizzata con due significati diversi:

  • POST come comando HTTP (nel senso di INVIA)
  • POST come articolo del blog

In questa operazione di scrittura del commento, il browser chiede (in lettura!) al server di caricare il programma wp-comments-post.php. Questa richiesta è inviata al server quando nella pagina del post clicchiamo sul link “Submit Comment” (o “Invia Commento” o qualcos’altro), assieme alla mail e il valore corrispondente alla scelta I’m not a ROBOT. Con il comando POST i parametri vengono inviati dopo il termine dell’intestazione HTTP e un doppio a capo (come illustrato sopra). Se utilizzassimo il comando di HTTP GET i parametri sarebbero contenuti nell’URL, separando il nome della risorsa dai parametri con un “?”:

GET /wp-comments-post.php?comment=questo %22 il mio commento&author=My+Name&email=my.mail%40gmail.com&url=&submit=Submit+Comment&comment_post_ID=2734&comment_parent=0&akismet_comment_nonce=afb00fa731&ak_js=1535630177692 HTTP/1.1 

Al di là di questa differenza tra GET e POST è importante capire bene qui che la risorsa (nome tecnico della “pagina” PHP)  wp-comments-post.php, non viene alterata, viene soltanto letta!

Quello che succede a questo punto è che il server web Apache non serve direttamente la pagina PHP al browser, anzi passa il controllo all’application server (il PHP nel caso di WordPress) il quale legge ed esegue il programma PHP wp-comments-post.php. All’interno di questo programma ci sono le istruzioni che salvano il nostro commento (“questo è il mio commento”) in un database. Il tutto è illustrato nella figura 1.

Successivamente, se tutto va bene, (in modo automatico) il server risponderà al browser inoltrandogli una sola intestazione (quindi non una pagina web) contenente soltanto un comando di redirect, ovvero una ingiunzione al browser di effettuare un’altra richiesta al web server perché gli serva il post che ora conterrà anche il nostro commento (vedi fig. 2).

Qui ci si soffermi a capire bene: è sempre il browser che inizia la richiesta di un contenuto. Egli agisce sempre come un cliente.

Tutto questo giro è perché la pagina HTML (il post contenente il commento) che viene consegnata dal web server al browser in realtà è il frutto di elaborazione del server applicativo PHP che legge il contenuto dell’articolo (anch’esso contenuto nel database) e gli eventuali commenti e compila un’unica pagina HTML che consegnerà ad Apache il quale la spedirà al nostro browser.

Possiamo immaginare il web server Apache, in questa architettura, semplicemente come un passa-mano:

  • in andata (REQUEST) riceve i parametri dal browser e li passa al server PHP
  • al ritorno (RESPONSE) riceve dal programma PHP il flusso HTML e la passa al nostro browser

Quindi sostanzialmente stiamo sempre facendo operazioni di lettura nel file system; le scritture vengono fatte su un DBMS.

Leggere e scrivere fisicamente sul Web

Ciò che aveva in mente Tim Berners-Lee, e che realizzò con il suo browser WWW, era una cosa profondamente diversa: le stesse risorse web dovevano essere modificabili. Quindi gli stessi file HTML contenuti nel web server! Ma questo ha un senso per un web statico in cui le pagine vengono servite al browser così come esistono nel web server. Nel cosiddetto “web dinamico” che esiste fin dalla comparsa degli script cgi-bin (quindi primi anni ’90, quando il web andava all’asilo) ciò non è più vero: non esistono pagine da servire così come sono, esistono solo programmi che producono pagine al volo sulla base dei dati di ingresso.

Quindi non ha nemmeno tanto senso il pensare di modificare le pagine, anzi: è da evitare nel modo più assoluto.

Questo approccio ha un senso quando si vuole utilizzare una infrastruttura web per pubblicare documenti statici che, tuttavia, hanno un loro ciclo di vita, possono cioè cambiare nel tempo ma in seguito ad azione di editing, di modifica da parte di uno o più utenti che sono quindi editori, gestori del contenuto di quella pagina. In quest’ottica si colloca il protocollo WebDAV che è una estensione di HTTP per questo tipo di attività.

Dunque il protocollo WebDAV realizza quanto aveva in mente Tim Berners-Lee. Ma generalmente si utilizza nelle intranet e spesso non si fa nemmeno utilizzo del browser per accedere ai contenuti, ma si impiega piuttosto un programma del tipo Finder o Esplora Risorse. La gestione dei documenti va oltre ai soli documenti HTML ma può trattarsi anche di file di testo elettronico come Word (MS Office) o Writer (LibreOffice) o PDF. La loro modifica è operata Offline, ossia modifico il documento in locale e poi lo deposito nel server andando ad alimentare la storia del documento con una nuova versione.

Il protocollo WebDAV è descritto nella RFC 4918 “HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV)” ed è, al pari di tutti gli altri protocolli, essenzialmente un insieme di comandi. Con questi comandi possiamo non solo trasferire i file  da client a server, ma anche

  • creare directory (MKCOL)
  • copiare e spostare file (COPY / MOVE)
  • aggiungere, modificare e rimuovere proprietà (metadati) del file (PROPFIND, PROPPATCH)
  • bloccare e sbloccare (LOCK/UNLOCK) una risorsa quando si deve operare una modifica (condizione per una gestione transazionale della vita del documento – in altre parole evitiamo che più utenti mettano mano simultaneamente al documento)
  • cercare file (SEARCH)

Per allestire un server WebDAV occorre installare nel file server, prima di tutto, un server Web, ad esempio Apache. Poi occorre aggiungere il modulo DAV (mod_dav). Poiché i metodi di acesso DAV consentono ai client remoti di manipolare i file sul server, è necessario avere particolare cura per assicurare che il vostro server sia sicuro, prima di abiltare mod_dav.

Ogni cartella del server dove DAV è abilitato deve essere protetta da autenticazione. L’uso della HTTP Basic Authentication non è consigliata. Occorre usare almeno la HTTP Digest Authentication, che è fornita dal modulo di Apache mod_auth_digest. Quasi tutti i client WebDAV supportano questo metodo di autenticazione.

Una alternativa è la Basic Authentication sopra una connessione SSL/TLS.

Per consentire al modulo mod_dav la gestione dei file, lo User e il Group proprietari del processo UNIX che esegue Apache (nel sistema operativo Ubuntu è l’utente www-data) devono essere abilitati alla scrittura delle directory e file al disotto di queste.  I nuovi file creati apparterranno all’utente User:Group. Per tale ragione è importante controllare l’accesso di questo account. Il repository DAV è considerato privato di Apache. Pertanto, la modifica di file al di fuori di Apache (ad esempio tramite FTP o comandi del sistema operativo) non dovrebbe essere permessa.

PHP 7 – what’s new – III

Dichiarazioni di tipo ritornato da una funzione

Dal PHP7 è possibile specificare il tipo di ritorno di una funzione, cioè qual è il tipo della variabile ritornata da una funzione. I tipi disponibili sono i quattro riportati nell’articolo precedente (int, string, float, bool).

// 6.php

function sum(array $array): int {
    return array_sum($array);
}

$s = sum([1,2,3]);
echo gettype($s) .": ".$s . "\n";

Output:

$ php 6.php 
integer: 6

A cosa ci serve dichiarare il tipo di ritorno? Per tutti i linguaggi è normale farlo e il compilatore stesso può dare indicazioni se c’è qualche incoerenza di tipo. PHP consente di farlo e il funzionamento può essere utilizzato per imporre un uso di tipi più controllato di quanto un programmatore PHP sia abituato a fare. Ad esempio possiamo definire la funzione div():

// 6.1.php

function div(int $a, $b): int {
    return $a / $b;
}

$s = div(1,2);
echo gettype($s) .": ".$s . "\n";

Output:

$ php 6.1.php 
integer: 0

Ma possiamo anche definire diversamente il tipo di ritorno:

// 6.2.php

function div(int $a, $b): float {
    return $a / $b;
}

$s = div(1,2);
echo gettype($s) .": ".$s . "\n";

nel qual caso ho un diverso comportamento

$ php 6.2.php 
double: 0.5

PHP7 – what’s new – II

Classe TypeError

Dalla versione 7 di PHP, come visto nell’articolo precedente, abbiamo a disposizione una nuova classe che permette di gestire gli errori di tipo; in un esempio come quello sopra possiamo gestire in autonomia l’errore:

declare(strict_types=1);

// Coercive mode
function sumOfInts(int ...$ints)
{
    //echo gettype($ints)."\n";
    return array_sum($ints);
}

try {
    var_dump(sumOfInts(2, '3', 4.1));
} catch (TypeError $e) {
    echo 'Errore di tipo: '.$e->getMessage()."\n";
}        

Output:

Errore di tipo: Argument 3 passed to sumOfInts() must be of the type integer, float given, 
called in /var/www/html/php7/2.php on line 13