macOS – Errore git “invalid developer path”

xcrun: error: invalid active developer path /Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

Se da terminale avete riscontrato questo errore provando ad eseguire git (o altro software di sviluppo), potete risolvere velocemente.

L’errore si verifica, alcune volte, dopo aver aggiornato macOS o Xcode. Indica che è necessario installare gli strumenti di sviluppo a linea di comando.

È sufficiente digitare il seguente comando sul terminale:

xcode-select --install

e attendere il termine del download e dell’installazione.

Una classe Swift per un client WebService

Una breve classe da cui prendere spunto:


// MARK: - WebServiceError

public enum WebServiceError: Error {
    case badURL
    case error
    case nodata
    case jsonError
    // ...
}

// MARK: - WebService

public class WebService {
    let baseUrl: String
    public enum HttpMethod: String {
        case GET
        case POST
        case PUT
        case TRACE
        case DELETE
    }

    public init?(baseUrl: String) {
        guard !baseUrl.isEmpty else {
            return nil
        }
        if baseUrl.last! == "/" {
            self.baseUrl = baseUrl
        } else {
            self.baseUrl = baseUrl+"/"
        }
    }

    public func request<T>(with httpMethod: HttpMethod = .GET,
                    of _: T.Type,
                    on path: String, _ completion: @escaping (Result<T, WebServiceError>) -> Void) -> Void where T: Codable
    {
        guard let url = URL(string: baseUrl + path) else {
            completion(.failure(.badURL))
            return
        }
        var request = URLRequest(url: url)
        request.httpMethod = httpMethod.rawValue
        request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
        request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Accept")

        let task = URLSession.shared.dataTask(with: request) { data, response, error in

            var result: Result<T, WebServiceError>

            defer {
                completion(result)
            }

            guard error == nil else {
                result = .failure(.error)
                return
            }

            guard let data = data else {
                result = .failure(.nodata)
                return
            }

            let decoder = JSONDecoder()
            decoder.dateDecodingStrategy = .iso8601

            guard let response = try? decoder.decode(T.self, from: data) else {
                result = .failure(.jsonError)
                return
            }
            result = .success(response)
        }

        task.resume()
    }
}

QRCode con CoreImage e Swift

Breve antefatto: mi chiedono di generare dei qrCode 600×600 per una lista di URL. Apro Xcode, creo un nuovo Playground e in dieci minuti preparo un programmino in Swift 😚

Generare un qrCode con CoreImage è questioni di pochi minuti:

import CoreImage
import CoreImage.CIFilterBuiltins

let qrCodeFilter = CIFilter.qrCodeGenerator()
qrCodeFilter.setValue("Hello,World!".data(using: .utf8, allowLossyConversion: false), forKey: "inputMessage")

if let rawQRCode = qrCodeFilter.outputImage {
    let scale = 600 / rawQRCode.extent.width
    let qrCodeOutput = rawQRCode.transformed(by: CGAffineTransform(scaleX: scale, y: scale))

    //salviamo un png nella home dell'utente
    //per iOS utilizzare un percorso diverso... homeDirectoryForCurrentUser è disponibile solo su macOS
    try! CIContext().writePNGRepresentation(of: qrCodeOutput, to: FileManager.default.homeDirectoryForCurrentUser.appendingPathComponent("qrcode.png"), format: CIFormat.RGBA16, colorSpace: CGColorSpace(name: CGColorSpace.sRGB)!, options: [:])
}

MySQL – operazioni con date, tempo e intervalli – prima parte

In MySQL sono disponibili principalmente cinque tipi di dato per gestire le informazioni temporali: DATE, TIME, DATETIME, TIMESTAMP e YEAR.

Ognuno di questi tipi ha un range di valori validi. MySQL gestisce questi dati in un formato specifico, ma accetta una varietà di formati in ingresso che è in grado di interpretare e convertire correttamente. In alternativa, vengono fornite specifiche funzioni per la conversione dei dati, come ad esempio STR_TO_DATE().

Il formato di questi tipi di dato è il seguente:

TIPOFORMATORANGE
DATETIMEYYYY-MM-DD hh:mm:ss[.fraction]da '1000-01-01 00:00:00' a '9999-12-31 23:59:59'
DATEYYYY-MM-DDda '1000-01-01' a '9999-12-31'
TIMEhh:mm:ss[.fraction]da '-838:59:59.000000' a'838:59:59.000000'
YEARYYYYda 1901 a 2155
TIMESTAMPYYYY-MM-DD hh:mm:ss[.fraction]da '1970-01-01 00:00:01' UTC a '2038-01-19 03:14:07' UTC

Il formato TIMESTAMP memorizza il dato in formato “unix type”: il tempo viene rappresentato come il numero di secondi trascorsi dalla mezzanotte del 01 gennaio 1970 (epoch) UTC. A seconda della versione del DBMS, è disponibile una risoluzione in microsecondi del timestamp.

Questa rappresentazione offre il vantaggio di gestire la data come numero intero e in modo indipendente dai fusi orari. MySQL ha funzioni dirette per convertire il formato.

Usare TIMESTAMP per data creazione e modifica del record

Il tipo TIMESTAMP si rileva utile per memorizzare in specifiche colonne la data di creazione di un record e la data dell’ultima modifica in maniera automatica. Per fare questo è possibile definire due colonne di questo tipo:

create table test
(
    ...
    date_created timestamp default current_timestamp() not null,
    last_updated timestamp default current_timestamp() not null on update current_timestamp()
);

In questo modo, ogni volta che verrà aggiunto un record alla tabella i campi date_created e last_updated verranno valorizzati con il timestamp corrente. In caso di modifica del record il campo last_updated verrà automaticamente aggiornata con il timestamp della modifica.

SQL – select record dell’anno passato

Immaginiamo una tabella con un campo datetime. Se volessimo filtrare la nostra query select per i record dell’anno passato possiamo procedere nel seguente modo:

select * from table t where YEAR(t.date) = YEAR(current_date - INTERVAL 1 YEAR);

Abbiamo utilizzato le seguenti funzioni:

  • YEAR(dt) questa funzione restituisce un intero rappresentante l’anno del paremetro date o datetime dt
  • CURRENT_DATE() questa funzione restituisce la data corrente nel formato 'YYYY-MM-DD'
  • INTERVAL questa funzione meriterebbe un articolo intero. È usata per effettuare calcoli con DATE e TIME. La sintassi è la seguente: INTERVAL expr unit

Naturalmente, modificando il valore dell’espressione INTERVAL 1 YEAR è possibile selezionare anche record con anni precedenti.

NB: è possibile anche fare a meno di INTERVAL e usare una semplice sottrazione:

select * from table t where YEAR(t.date) = YEAR(current_date)-1;

ma volevo approfittarne per introdurre l’espressione INTERVAL di cui parlerò con maggiori dettagli in un prossimo articolo.

SQL – selezionare record dell’anno corrente

Immaginiamo una tabella con un campo datetime. Se volessimo filtrare la nostra query select per i record dell’anno corrente possiamo procedere nel seguente modo:

select * from table t where YEAR(t.date) = YEAR(current_date);

Abbiamo utilizzato le seguenti funzioni:

  • YEAR(dt) questa funzione restituisce un intero rappresentante l’anno del paremetro date o datetime dt
  • CURRENT_DATE() questa funzione restituisce la data corrente nel formato 'YYYY-MM-DD'

Fetch del certificato SSL di un sito web

Alcune volte, per effettuare delle verifiche, ho necessità di recuperare il certificato SSL di un sito WEB. Per effettuare questa operazione velocemente, ho scritto un piccolo script bash che mi permette di recuperare tutte le informazioni del certificato SSL da linea di comando:

#!/bin/bash
# usage: ./fetchSSL.sh domain.tld

echo | openssl s_client -showcerts -servername $1  -connect $1:443 2>/dev/null | openssl x509 -inform pem -noout -text

Salvando questo piccolo script in un file (ad esempio) fetchSSL.sh, da linea di comando posso recuperare il certificato SSL di un sito:

$~: ./fetchSSL.sh google.it

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            41:fc:ce:96:9b:12:b3:b4:08:00:00:00:00:43:56:56
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, O=Google Trust Services, CN=GTS CA 1O1
        Validity
            Not Before: May 26 15:38:08 2020 GMT
            Not After : Aug 18 15:38:08 2020 GMT
        Subject: C=US, ST=California, L=Mountain View, O=Google LLC, CN=*.google.it
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:30:7e:8b:21:f1:df:78:b9:25:14:7d:c4:3c:5d:
[...]

DNS Flush in macOS, Linux e Windows

In breve, per poter convertire i nomi di dominio come “www.google.it” in indirizzi numerici, vengono interrogati i server DNS (name server). I sistemi operativi salvano in una cache interna i record man mano richiesti ai server DNS.

Puoi immaginare che ad un certo punto la calce DNS avrà una tabella con la corrispondenza dei domini degli ultimi siti visitati e il loro indirizzo IP. In questo modo si evitano interrogazioni inutili e si velocizza la navigazione su internet.

Informazioni presenti nella cache DNS

Le unità di informazione o record nella cache DNS si chiamano Resource Records (RR) e, solitamente, contengono i seguenti campi:

  • Resource Data (rdata): i dati che descrivono il record, ad esempio l’indirizzo o il nome host.
  • Record Type: il tipo del record creato, ad esempio “A”, cioè l’indirizzo IPv4 (valore decimale: 1) o “AAAA”, cioè l’indirizzo IPv6 (valore decimale: 28).
  • Record Name: nome del dominio dell’oggetto per il quale è stato creato il record DNS.
  • Time To Live (TTL): durata di validità del Resource Record espressa in secondi.
  • Class: gruppo di protocollo a cui appartiene il RR (principalmente “IN” per Internet).
  • Resource Data Length: valore che indica la lunghezza dei Resource Data

Il campo TTL indica al sistema operativo per quanti secondi considerare valido il record, prima di effettuare una nuova interrogazione. È un’indicazione, non un obbligo.

La cache DNS contiene quindi l’indirizzo IP del rispettivo dominio e alcuni campi aggiuntivi.

In alcuni casi può essere utile cancellare la cache DNS. Ad esempio, avete cambiato indirizzo IP ad un vostro hosting, ma dal browser continuate a raggiungere l’hosting ancora sul vecchio indirizzo.

Come cancellare la cache DNS

macOS

macOS 10.12+ (Sierra, Mojave, Catalina):

sudo killall -HUP mDNSResponder


OS X 10.10.4 (Yosemite) e 10.11.0 (El Capitan):

sudo dscacheutil -flushcache;
sudo killall -HUP mDNSResponder


OS X 10.10.1 fino a 10.10.3 (Yosemite):

sudo discoveryutil mdnsflushcache
sudo discoveryutil udnsflushcaches

OS X 10.9.0 (Mavericks):

sudo dscacheutil -flushcache;
sudo killall -HUP mDNSResponder

Linux

I sistemi Linux non dispongono di default di una cache DNS. Le diverse distribuzioni offrono una funzione per memorizzare in locale le informazioni DNS nella cache utilizzando apposite applicazioni come nscd (Name Service Caching Daemon), pdnsd, dns-clean o dnsmasq.

Per pdnsd esiste il seguente comando specifico:

sudo pdnsd-ctl empty-cache

Per dnsmask, dns-clean o nscd è necessario riavviare il servizio.

Windows 10

Dal prompt dei comandi (eseguire cmd dalla barra delle applicazioni) è sufficiente digitare il seguente comando:

ipconfig /flushdns

#IORESTOACASA

Restiamo a casa, ma continuiamo a vederci!

Grazie al software open source Jitsi Meet e ad alcuni volontari che hanno messo a disposizione il loro tempo e le risorse dei loro server, possiamo continuare a lavorare, studiare, socializzare.

In questa pagina sono disponibili le informazioni per utilizzare i server Jitsi Meet e per contribuire: https://iorestoacasa.work

Di seguito le istanze disponibili:

PHP 7.4 – novità

PHP 7.4 è la prossima minor release di PHP 7. Sarà rilasciata alla General Availability a fine novembre 2019.

Si tratta di una minor release della versione 7, non ci aspettiamo quindi grosse novità. La versione PHP 8 sarà la prossima milestone che promette diverse rivoluzioni, in primis l’inclusione di JIT che incrementerà notevolmente le prestazioni di PHP.

Novità di PHP 7.4

Attualmente è già disponibile la beta 1 e ho già fatto diversi test. Il rilascio per la GA è previsto per il 28 nove,bre.

L’elenco completo di tutte le funzionalità della nuova versione è, come sempre, disponibile su php.net in questa pagina.

Le novità principali sono:

  • Core
    • Array Spread Operator
    • Arrow Function (closure) con implicit by-value scope binding
    • Coalesce Operator ??= (finalmente)
    • Type properties
    • WeakReferences (pecl-weakref non serve più)
    • Ritorno covariante
    • Parametro controvariante
  • Nuove funzionalità
  • Deprecazioni
    • cambio di precedenza degli operatori +, -, .
    • deprecato ternary operator con associzione a sinistra
    • FILTER_SANITIZE_MAGIC_QUOTES (usare FILTER_SANITIZE_ADD_SLASHES)
    • is_real() (usare is_float)
    • money_format() (usare NumberFormatter per formattare un numero come valuta)

I benchmark hanno già dimostrato come la versione 7 di PHP è nettamente più performante di tutte le altre versioni. Chi non lo ha fatto, dovrebbe fin da ora passare a PHP 7.x per ottenerne tutti i vantaggi.

Eventuale lavoro di migrazione del codice alla nuova versione, sarà ampiamente ripagato dal guadagno di prestazioni che si otterrà. Inoltre, si sarà già pronti per le succose novità di PHP 8!

Happy coding…