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: [:])
}

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

Come si verificano I memory leak in Java

Come si verificano I memory leak in Java

Qualche giorno fa ho letto un articolo molto interessante: “How Memory Leaks Happen in a Java Application”.

Uno dei vantaggi del linguaggio Java è quello di gestire la deallocazione degli oggetti in maniera automatica attraverso il “garage collector”. In particolari circostanze questa gestione può fallire e possono verificarsi dei memory leak.

In informatica, un memory leak (“perdita o fuoriuscita di memoria”) è un particolare tipo di consumo non voluto di memoria dovuto alla mancata deallocazione dalla stessa, di variabili/dati non più utilizzati da parte dei processi. (Wikipedia)

I memory leak non dipendono da una errata implementazione del garbage collector,  ma da un uso improprio degli oggetti costruiti dall’applicazione. È un classico problema di PEBCAK (Problem Exists Between Chair And Keyboard), ed è tra i più difficili da diagnosticare.

Continua a leggere Come si verificano I memory leak in Java

UIImageView – pinch to zoom in iOS Swift 3+

Avete una UIImageView e volete dare la possibilità all’utente di ingrandire l’immagine e muoverla con un “pizzico”?

SOLUZIONE: aggiungere una scrollview e tre righe di codice 🙂

  • Aggiungiamo una ScrollView che conterrà la UIImageView

ScrollView > ImageView

  • Modifichiamo il ViewController in modo da implementare il protocol (o interfaccia) UIScrollViewDelegate e aggiungiamo queste righe di codice:
import UIKit

class ImageViewController: UIViewController,  UIScrollViewDelegate {
//MARK: - controls
  
    @IBOutlet weak var imgView: UIImageView!
    @IBOutlet weak var scrollView: UIScrollView!

//MARK: - View Controller methods

    override func viewDidLoad() {
        super.viewDidLoad()
        scrollView.delegate = self
        scrollView.minimumZoomScale = 1.0
        scrollView.maximumZoomScale = 6.0
    }

//MARK: - UIScrollViewDelegate implementations

    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        return imgView
    }
}

Finito. Non è necessario altro.

Happy coding… 🙂

SCP Resume

Non so voi, ma a me capita spesso di trasferire file con scp da e verso un server remoto. La cosa più frustrante succede quando stai trasferendo un file abbastanza grande e la connessione scp cade. Spesso mi son chiesto perché scp non supporti il resume.

La soluzione, comunque, è abbastanza semplice: usare rsync! ;)

Esempio:

Se per trasferire il file abbiamo utilizzato scp:

scp big.file [email protected]:~

per ripristinare la connessione:

rsync -r --partial --progress --rsh=ssh big.file [email protected]:~

Ancora più semplice se creiamo un alias all’ultimo comando come scpresume