Devi lavorare con il formato Base64? Allora questo sito è perfetto per te! Usa il nostro praticissimo strumento online per codificare o decodificare i tuoi dati.

Codifica Base64 in Perl: una guida completa

Hai dei dati che devono sopravvivere a un canale che non li gradisce. Un blob binario che deve stare in un campo JSON. Un'immagine che deve vivere dentro un tag HTML. Un certificato che appartiene a un file di configurazione. Un token che attraverserà URL, header e query string. Questa è la vita quotidiana della codifica Base64: riscrive ogni tre byte di dati grezzi come quattro caratteri presi da un alfabeto di 64 lettere, con uno o due segni = a chiudere la coda, così il risultato è testo semplice che qualsiasi cosa può trasportare, tipicamente circa il 33 percento più lungo di quello da cui sei partito. La home page di questo sito spiega il formato in tutti i dettagli, quindi questo articolo si concentra su ciò che Perl ti mette a disposizione, ciò che decide in silenzio per te, e dove sono le trappole.

Prima le buone notizie: encode_base64 vive nel core di Perl dal 2002, è implementato in C, e è comodamente veloce. La parte interessante è che la funzione ha delle opinioni. Avvolge l'output a 76 caratteri, aggiunge un a capo finale, e non codificherà i caratteri Unicode che non hai prima convertito in byte: sopra il range Latin-1 muore sul colpo, e sotto quella linea assume in silenzio byte Latin-1. Questa guida percorre ogni variante di Base64 che uno sviluppatore Perl produce davvero: l'one-liner, il corpo email MIME-wrapped, la chiave avvolta in PEM, il token URL-safe, e la versione in streaming per i file troppo grandi per stare in memoria.

Una funzione, un a capo nascosto

L'intera API, esattamente come la presenta la documentazione moderna:

encode_base64( $bytes )
encode_base64( $bytes, $eol )

Rileggi. Due argomenti, uno dei quali opzionale, un valore di ritorno, nessun flag. Il secondo argomento opzionale è la sequenza di fine riga, e di default è un semplice a capo, il che significa che la chiamata dall'aspetto più innocuo di Perl produce un output avvolto e terminato con a capo:

use MIME::Base64 qw(encode_base64);
my $wrapped = encode_base64("Aladdin:open sesame");
print length($wrapped), "\n";  # 29: i 28 caratteri più un a capo
my $single = encode_base64("Aladdin:open sesame", "");
print length($single), "\n";   # 28: passa una stringa vuota per non avvolgere

La dimensione dell'output segue uno schema fisso che puoi prevedere prima di chiamare:

Byte di input Caratteri di output Riempimento
0 0 nessuno
1 4 due =
2 4 un =
3 4 nessuno
100,000 133,336 nessuno, su una singola riga
3,000,000 4,000,000 nessuno

Lo schema è quattro caratteri per ogni gruppo completo di tre byte, più un gruppo finale parziale riempito con uno o due segni =. Una conseguenza che vale la pena conoscere: un byte e tre byte producono entrambi quattro caratteri, quindi la lunghezza codificata nasconde la dimensione esatta dell'input. E se ti serve la dimensione senza fare il lavoro, il modulo ha una funzione di lunghezza dal 2010, versione 3.10. Semplicemente non è esportata di default, quindi la chiami tramite il nome del pacchetto:

use MIME::Base64 ();
my $with_wrap   = MIME::Base64::encoded_base64_length($bytes);        # righe da 76 caratteri, eol di default
my $single_line = MIME::Base64::encoded_base64_length($bytes, "");    # nessun avvolgimento
my $mime_body   = MIME::Base64::encoded_base64_length($bytes, "\r\n");

C'è un'altra regola da memorizzare, perché è l'unico modo in cui l'encoder alza mai la voce: se la stringa che gli passi contiene caratteri con un codice sopra 255, encode_base64 muore con Wide character in subroutine entry. Sotto quella linea il fallimento è più silenzioso: i caratteri fino a 255 vengono degradati in silenzio ai loro byte Latin-1, quindi una stringa con caratteri accentati che ha saltato la conversione viene codificata come Latin-1 invece che come UTF-8, e nessuno te lo dice. La codifica Base64 è definita solo per caratteri a singolo byte, e Perl 5.8 e successivi permettono caratteri estesi nelle stringhe, quindi la conversione è una decisione che prendi con intenzione, con Encode, nella sezione che segue immediatamente.

Testo o byte? Il passo che la funzione non può fare

Le stringhe di Perl portano un flag silenzioso che dice se contengono caratteri o byte, e Base64 vive dal lato byte di quella linea. Se il tuo testo è una stringa di caratteri, ed è così nel momento in cui viene da un parser JSON, da un template o da un letterale con lettere accentate in un file sorgente UTF-8, l'encoder rifiuta di indovinare quali byte intendevi per i caratteri sopra il range Latin-1, e te lo dice; sotto il range indovina Latin-1 in silenzio. La correzione è la stessa in entrambi i casi, ed è una funzione core del modulo Encode:

use MIME::Base64 qw(encode_base64);
use Encode qw(encode);
my $chars = "H\x{eb}llo W\x{f6}rld";  # una stringa di caratteri
my $utf8  = encode("UTF-8", $chars);  # adesso: byte
my $b64   = encode_base64($utf8, "");
print $b64, "\n";  # SMOrbGxvIFfDtnJsZA==

Quella chiamata encode è l'intera danza: scegli la rappresentazione in byte, e UTF-8 per qualsiasi cosa moderna, converti i caratteri in quei byte, e solo allora passi i byte all'encoder. Per il testo occidentale legacy arrivato come Windows 1252, la conversione è la stessa funzione con un nome diverso, encode("Windows-1252", $legacy), che ti restituisce la forma originale a singolo byte. Il modulo Encode è core, quindi tutto questo costa zero.

Ora la trappola. Se i byte che hai sono già UTF-8 e li fai passare di nuovo attraverso encode("UTF-8", ...), pensando di renderli UTF-8, non ottieni una copia: ottieni una doppia codifica, dove ogni carattere accentato si gonfia in due caratteri suoi. Il sintomo classico è un testo che prima si leggeva Hëllo e ora si legge Hëllo, e ogni decoder su internet lo decoderà fedelmente per te:

use Encode qw(encode decode);
my $right = encode("UTF-8", "H\x{eb}llo");
my $wrong = encode("UTF-8", $right);  # ricodifica i byte come caratteri
print decode("UTF-8", $right), "\n";  # Hëllo
print decode("UTF-8", $wrong), "\n";  # Hëllo

La regola pratica che lo previene: i byte vengono codificati esattamente una volta, e utf8::is_utf8() ti mostra da che parte della linea si trova una stringa. Se il flag è impostato, stai tenendo caratteri e la chiamata encode() è la mossa giusta; se non è impostato, stai tenendo byte e sei pronto per Base64.

Avvolgimento di riga: tre dialetti, una regola

Dato che l'output di default è avvolto e terminato con a capo, la prima decisione per ogni lavoro di codifica è un problema di destinazione: dove vivrà questa stringa? Il fatto unificante è che i decoder ignorano completamente gli a capo: RFC 2045 dice al software di decodifica di ignorare tutti gli a capo e i caratteri fuori dall'alfabeto, quindi l'avvolgimento è una cortesia verso gli strumenti basati su righe e verso gli umani, non una differenza semantica. Le tre risposte nella pratica:

Nessun a capo. L'output della funzione con l'avvolgimento disabilitato, esattamente una riga. È quello che vuoi per URL, carichi utili JSON, header, valori di database e tutto il resto dove un a capo sarebbe un bug. È anche quello che la maggior parte della gente intende quando chiede solo il Base64:

my $single = encode_base64($bytes, "");

MIME: 76 caratteri più CRLF. La convenzione email di RFC 2045: le righe codificate non devono superare 76 caratteri, e il mondo MIME parla CRLF. Questo è un lavoro del modulo stesso, fatto con il secondo argomento:

my $mime_body = encode_base64($bytes, "\r\n");

PEM: 64 caratteri più LF. Chiavi e certificati usano la convenzione più vecchia con righe da 64 caratteri, più corte, e il modulo non può produrre quella larghezza da solo, quindi una funzione ausiliaria di quattro righe colma il vuoto:

sub wrap_lines {
  my ($text, $width) = @_;
  return join "\n", $text =~ /(.{1,$width})/g;
}
my $pem = "-----BEGIN CERTIFICATE-----\n"
        . wrap_lines(encode_base64($der, ""), 64) . "\n"
        . "-----END CERTIFICATE-----\n";

La stessa funzione ausiliaria serve anche per gli altri dialetti da 64 caratteri - la codifica testuale PKIX di RFC 7468 e l'armatura OpenPGP, le cui righe di dati sono larghe 64 caratteri e la cui riga finale di checksum CRC24 è quella che aggiunge GnuPG, non tu. Un punto di attenzione vale per tutti: encode_base64 aggiunge la fine riga alla fine stessa del risultato, anche quando l'ultima riga riempie esattamente la sua larghezza. Se un consumatore a valle inciampa su quella riga vuota finale, una chiamata a rtrim sul risultato la risolve.

Base64 URL-safe: l'alfabeto - e _

L'alfabeto standard contiene + e /, e fuori da un file di testo entrambi sono un problema: in una query string codificata in form, + diventa uno spazio prima che la tua applicazione lo veda, e / è un separatore di percorso negli URL. I nomi di file e i token hanno lamentele loro. RFC 4648, sezione 5, risolve con l'alfabeto sicuro per URL e nomi di file, dove + diventa -, / diventa _, e il riempimento finale = viene di solito rimosso. La RFC insiste che questa non va considerata la stessa cosa della codifica base64, quindi trattala come un formato distinto, comunemente chiamato base64url. Perl la produce in una singola chiamata dalla versione 3.11 del 2010:

use MIME::Base64 qw(encode_base64url);
my $seg = encode_base64url("sunset-42");
print $seg, "\n";  # c3Vuc2V0LTQy: nessun riempimento, nessun a capo

Quella singola chiamata fa tutte e tre le modifiche: lo scambio di alfabeto, nessun riempimento, nessun a capo. Se hai già del Base64 standard e la destinazione vuole il dialetto URL-safe, due operazioni su stringa lo convertono sul posto:

sub to_urlsafe {
  my ($b64) = @_;
  $b64 =~ tr{+/}{-_};
  return $b64 =~ s/=+\z//r;
}
my $seg = to_urlsafe(encode_base64($bytes, ""));

Quando usarlo: le parti di un JSON Web Token, i parametri state e nonce di OAuth, gli ID di API che metti nei percorsi URL, e le chiavi opache che devono sopravvivere a una barra degli indirizzi o a un nome di file, dove Data::UUID::Base64URLSafe di CPAN esiste esattamente per questo. Quando non usarlo: i corpi email, l'armatura PEM, e qualsiasi posto dove dall'altra parte c'è un consumatore dell'alfabeto standard, perché - e _ non sono nel loro vocabolario. E non mescolare i due alfabeti in silenzio: un valore codificato in URL-safe deve essere decodificato in URL-safe, ovunque, per sempre. Su Perl precedenti al 3.11, il modulo standalone MIME::Base64::URLSafe del 2006, che è un porting del codec urlsafe di Python, fornisce urlsafe_b64encode; in qualsiasi Perl moderno, la funzione integrata è lo strumento giusto.

Costruire un JWT: ogni parte a mano

I JSON Web Token sono il consumatore di punta del Base64 nelle API moderne, e usano il dialetto URL-safe senza riempimento della sezione qui sopra. Secondo RFC 7515, un JWT compatto è fatto di tre parti base64url separate da punti: il header protetto, il carico utile e la firma. Costruirne uno a mano è un modo piacevole per vedere ogni pezzo in movimento:

use MIME::Base64 qw(encode_base64url);
use JSON::PP qw(encode_json);
use Digest::SHA qw(hmac_sha256);
my $secret  = "correct-horse-battery-staple";
my $head    = encode_base64url(encode_json({ alg => "HS256", typ => "JWT" }));
my $claims  = encode_base64url(encode_json({ sub => "homer", role => "admin" }));
my $sig     = encode_base64url(hmac_sha256("$head.$claims", $secret));
my $jwt     = "$head.$claims.$sig";
print $jwt, "\n";  # un token HS256 compatto; l'ordine delle chiavi dentro ogni parte JSON varia da esecuzione a esecuzione

Tre dettagli che vale la pena notare. Primo, encode_json del modulo core JSON::PP emette byte UTF-8 compatti senza spazi bianchi, ed è esattamente quello che le specifiche JOSE vogliono dentro un token. Secondo, il carico utile è leggibile da chiunque, ed è così di proposito: un JWT è un biglietto firmato, non un segreto, quindi non mettere mai valori riservati nei claims. Terzo, la firma è la codifica base64url dei byte grezzi dell'HMAC, ed è per questo che hmac_sha256 va direttamente nell'encoder senza alcun formattaggio esadecimale.

In produzione non fai il firmamento a mano. Il modulo CPAN Crypt::JWT, che si basa su CryptX, implementa JWS e JWE con l'intero set di algoritmi:

use Crypt::JWT qw(encode_jwt);
my $jwt = encode_jwt(
  payload => { sub => "homer", role => "admin" },
  alg     => "HS256",
  key     => $secret,
);

E dal lato ricevente, fissa l'algoritmo con accepted_alg così un attaccante non può girare il token su una variante più debole: decode_jwt(token => $jwt, key => $secret, accepted_alg => "HS256") verifica la firma e fa croak in caso di fallimento. Il fai-da-te va bene per capire; una libreria va bene per i soldi.

HTTP: header di autenticazione, data URI e l'handshake di WebSocket

L'header Authorization: Basic è il caso d'uso più vecchio ancora in vita: username e password uniti da due punti, codificati su una riga sola, con la parola dello scheme in testa. La stringa vuota come secondo argomento è portante qui, perché un a capo finale dentro un campo header è un bug:

use MIME::Base64 qw(encode_base64);
my $user = "alice";
my $pass = "s3cr3t";
my $header = "Basic " . encode_base64("$user:$pass", "");
print $header, "\n";  # Basic YWxpY2U6czNjcjN0

Le data URI di RFC 2397 applicano la stessa idea alle immagini: il carico utile sta direttamente nell'URL, quindi non serve una seconda richiesta per recuperarlo. I media binari usano il flag ;base64, quindi il carico utile è esattamente quello che produce encode_base64 con l'avvolgimento disabilitato:

my $uri = "data:" . $mime_type . ";base64," . encode_base64($bytes, "");

I compromessi, però, sono reali. Il carico utile codificato è circa il 33 percento più grande del file, il che rende più grande il documento HTML stesso. I browser non memorizzano in cache una data URI come fanno con un URL di file - non c'è un fetch separato da mettere in cache, quindi ogni visualizzazione della pagina rispedisce i byte come parte del documento, e la RFC stessa dice che le data URI sono utili solo per valori corti. Usale per avatar, icone e grafica inline piccola; usa file veri per tutto il resto. C'è un terzo angolo HTTP che usa Base64 in silenzio: l'handshake WebSocket di RFC 6455, dove il client invia un header Sec-WebSocket-Key che è il Base64 di sedici byte casuali. Framework come Mojolicious lo fanno per te, ma se lo vedi mai in rete, ora sai cos'è:

use MIME::Base64 qw(encode_base64);
my $key = encode_base64(pack("C16", map { int(rand 256) } 1 .. 16), "");
print length($key), "\n";  # 24: sedici byte casuali, riempiti fino al gruppo di quattro caratteri

File: slurp, blocchi da 57 byte e CLI

Il lavoro di codifica più diretto: un file diventa testo. Le stringhe di Perl sono byte, quindi non c'è una modalità binaria da cercare - il layer :raw è l'intera storia. Apri in raw, leggi, codifica, scrivi:

use MIME::Base64 qw(encode_base64);
open my $in, "<:raw", $ARGV[0] or die $!;
local $/;
my $bytes = <$in>;
close $in;
open my $out, ">:raw", $ARGV[1] or die $!;
print {$out} encode_base64($bytes);
close $out;

I layer :raw contano. Senza di essi, Perl cercherebbe di interpretare i byte come testo di piattaforma in entrata e in uscita, e su un sistema con una codifica di default diversa quello è esattamente il tipo di corruzione che non vedi finché il file non viene aperto da qualche altra parte. E ricorda il conto della dimensione quando pianifichi lo storage: un'immagine da 500 KB diventa un file di testo da 670 KB, e un video da 1 GB diventa 1,33 GB.

Per file troppo grandi per stare in memoria, la documentazione stessa del modulo ti dà la regola: codifica in blocchi che sono un multiplo di 57 byte, perché 57 byte di dati riempiono esattamente una riga da 76 caratteri, 76 essendo 57 per 4 diviso per 3. Fai blocchi su quel confine e non avrai mai riempimento in mezzo allo stream:

use MIME::Base64 qw(encode_base64);
open my $in, "<:raw", $ARGV[0] or die $!;
while (read($in, my $buf, 57 * 10)) {
  print encode_base64($buf);
}
close $in;

Ogni blocco atterra esattamente su un confine di riga, l'ultimo blocco, possibilmente corto, porta il riempimento finale, e il risultato è identico byte per byte a leggere l'intero file d'un fiato e codificarlo in una volta sola, solo con un'impronta di memoria costante. E quando non ti serve nemmeno uno script, l'one-liner copre il tutto, con -0777 che legge l'input d'un fiato e l'argomento stringa vuota che tiene l'output su una riga:

perl -MMIME::Base64 -0777 -ne 'print encode_base64($_, "")' < file > file.b64

Email: corpi MIME e allegati

L'email è il posto dove Base64 ha guadagnato il suo nome. Lo standard MIME dice che i dati che non possono viaggiare in modo sicuro come testo grezzo devono essere inviati con Content-Transfer-Encoding: base64, in righe non più lunghe di 76 caratteri. Se costruisci email con MIME::Lite, il tutto è un solo argomento, e il modulo fa la codifica, l'avvolgimento e l'header per te:

use MIME::Lite;
my $mime = MIME::Lite->new(
  From    => 'me@example.com',
  To      => 'you@example.com',
  Subject => 'A file',
  Type    => 'text/plain',
  Data    => 'The body text.',
);
$mime->attach(
  Type     => 'application/octet-stream',
  Data     => $bytes,
  Encoding => 'base64',
  Filename => 'hello.txt',
);

L'argomento Encoding è la scintilla: MIME::Lite codifica in Base64 l'allegato in righe da 76 caratteri (con l'a capo semplice di default del modulo; a trasformarli in CRLF è il trasporto email), e timbra la parte con l'header Content-Transfer-Encoding corrispondente. Email::MIME adotta la stessa posizione e codifica in Base64 qualsiasi allegato gli passi come stringa di dati grezzi (le sue doc: "tutte le parti create in questo modo vengono codificate in base64, per sicurezza"). Se stai assemblando un messaggio MIME grezzo a mano, l'equivalente sono le due righe della sezione sull'avvolgimento, encode_base64($bytes, "\r\n") più la riga di header, ed è l'intera storia lato protocollo.

Database, configurazioni e variabili d'ambiente

Database: i dati binari spesso viaggiano in una colonna TEXT come Base64, perché la colonna non può promettere di far passare byte arbitrari intatti. Salva la forma su una riga, mai quella avvolta, altrimenti il tuo prossimo SELECT restituirà una stringa con a capo in mezzo al valore:

use MIME::Base64 qw(encode_base64);
# $dbh è un handle DBI già connesso
my $stmt = $dbh->prepare(q{UPDATE photos SET data = ? WHERE id = ?});
$stmt->execute(encode_base64($bytes, ""), 42);

I file di configurazione hanno la stessa forma: un documento JSON dove il campo binario o segreto è una stringa Base64 su una riga, ed è esattamente per questo che esiste il secondo argomento:

use JSON::PP qw(encode_json);
my $config = {
  api_key  => encode_base64($key_bytes, ""),
  logo_png => encode_base64($png_bytes, ""),
};
open my $fh, ">:raw", "app.json" or die $!;
print {$fh} encode_json($config);
close $fh;

Le variabili d'ambiente meritano una parola di avvertimento. Il Base64 va bene per token piccoli nell'ambiente, ma la forma codificata è il 33 percento più grande dell'originale, e il sistema operativo mette un tetto a ogni argomento. Su Linux il limite è 128 KB per stringa, applicato da execve, e un blob grande in una variabile d'ambiente non fallisce in modo gentile: il processo figlio muore con un errore criptico nel momento stesso in cui viene generato. Valori piccoli nell'ambiente, valori grandi in un file o in un database.

Prestazioni: a lavorare è C, non Perl

Il modulo core è implementato in C, e quel C discende da codice scritto per metamail nel 1991, che è un fatto curioso finché non noti la conseguenza: l'encoder ha alle spalle tre decenni di ottimizzazione. Su una macchina moderna elabora i dati a un ritmo di gigabyte al secondo, più veloce dei dischi o delle reti a cui di solito alimenta, quindi il Base64 stesso è quasi mai il collo di bottiglia. L'I/O, invece, sì.

Per il raro sistema senza compilatore C, l'equivalente in puro Perl MIME::Base64::Perl su CPAN fornisce la stessa interfaccia di base, più lento di qualche volta ma ancora comodo per i carichi di lavoro ordinari. E due abitudini tengono i lavori grandi prevedibili: fai streaming in blocchi da 57 byte invece di leggere d'un fiato, e dimensiona i buffer con encoded_base64_length prima di allocare, il che ti risparmia sia il calcolare a naso sia la riallocazione.

Trappole, ordinate per il pomeriggio che costano

Le trappole, più o meno nell'ordine in cui mordono:

Trappola Cosa succede Correzione
Dimenticare il secondo argomento l'output arriva avvolto a 76 caratteri con un a capo finale, e il tuo URL, campo JSON o header si rompe in mezzo al valore passa "" per l'output su una riga, e tieni l'avvolgimento per le destinazioni che se lo aspettano
Avvolgere alla larghezza sbagliata un consumatore PEM si aspetta righe da 64 caratteri e ne riceve da 76, o un corpo MIME supera il limite di 76 caratteri allinea la larghezza al dialetto: "" per nessun avvolgimento, "\r\n" per MIME, una funzione ausiliaria per PEM
Il croak wide character una stringa di caratteri con codici sopra 255 muore con Wide character in subroutine entry a metà richiesta fai passare i caratteri prima attraverso Encode, con un nome scelto con intenzione, prima della chiamata encode_base64
Doppia codifica ricodificare byte già UTF-8 attraverso encode("UTF-8", ...) trasforma Hëllo in Hëllo i byte vengono codificati esattamente una volta; in caso di dubbio controlla utf8::is_utf8()
Mescolare alfabeti in silenzio un valore codificato con - e _ incontra un decoder dell'alfabeto standard e torna indietro come spazzatura un dialetto per valore, dall'inizio alla fine: scegli base64url o standard al confine
La fine riga finale encode_base64 aggiunge l'eol anche quando l'ultima riga è esattamente piena, e un consumatore rigoroso vede una riga vuota chomp o rtrim il risultato quando il consumatore è pignolo
Valori avvolti nel database gli a capo finiscono dentro una colonna TEXT e il prossimo SELECT restituisce un token rotto salva la forma su una riga; avvolgi solo alla destinazione
Variabili d'ambiente con blob grandi la crescita del 33 percento più il limite per argomento dell'OS uccide il processo figlio appena generato, con un errore criptico valori piccoli nell'ambiente, valori grandi in un file o in un database
Dare per scontato che Base64 sia protezione il formato non nasconde niente, e il registro pubblico documenta incidenti reali dove un utente ha incollato uno scambio IMAP e ha rivelato per sbaglio una password tratta l'output come riservato dal momento in cui viene prodotto, e tienilo fuori dai log
Pianificare senza il conto della dimensione un'immagine da 500 KB diventa 670 KB di testo, e il limite di storage o payload che non hai controllato morde metti in conto 4/3 della dimensione originale prima di impegnarti

Una storia raccontata dall'encoder

L'encoder Base64 di Perl ha una carriera che merita un minuto, e inizia nel primo toolkit web:

  • Nato in libwww perl. L'encoder è nato come LWP::Base64, scritto da Martijn Koster e Joerg Reichelt, e Gisle Aas lo ha assorbito in libwww perl come MIME::Base64. Si è laureato nella propria distribuzione CPAN nell'aprile 1997, versione 2.00, con una voce di changelog che dice semplicemente di essere basato su libwww perl 5.08.
  • L'era della velocità. La versione 2.07 del 1998 ha spedito un'implementazione C del decoder più veloce e più intelligente, circa il 25 percento più rapida sulle macchine Linux allora moderne, e l'ottimizzazione è continuata per un decennio.
  • L'era Unicode. Perl 5.8 del 2002 ha portato caratteri con codici sopra 255 nelle stringhe ordinarie, e il modulo ha risposto a piccoli passi: la 2.12 del 2001 degradava le stringhe UTF-8 prima della codifica, e il croak moderno Wide character in subroutine entry è il modo dell'encoder di mantenere quella promessa. La sincronizzazione 2.13 con il core di quello stesso anno ha portato con sé il supporto EBCDIC, un promemoria che il Base64 in Perl gira ancora sui mainframe.
  • L'era da riga di comando. I rilasci dalla 2.14 del 2003 alla 3.05 del 2004 includevano un comando vero e proprio encode-base64, insieme ai suoi gemelli decode e quoted-printable. La 3.06 del 2005 ha spostato gli script in una distribuzione separata, MIME Base64 Scripts.
  • L'arrivo dell'URL-safe. RFC 4648 ha standardizzato l'alfabeto URL-safe nel 2006, un modulo standalone MIME::Base64::URLSafe è apparso lo stesso anno, e il modulo core ha raggiunto il passo nella 3.11 del 2010 con encode_base64url in una singola chiamata.
  • La linea moderna. La versione 3.16 del 2020 ha rifatto l'imballaggio e ha alzato il minimo a Perl 5.6. I Perl core attuali spediscono la serie 3.16, e il modulo è mantenuto all'interno della distribuzione core, che è circa la casa più sicura che un modulo core possa avere.

Fatti divertenti, specificamente Perl

Le curiosità che rendono questa storia buona:

  • L'esempio del POD è una frase magica. Dal 1997, la documentazione stessa del modulo codifica Aladdin:open sesame, quindi la stringa QWxhZGRpbjpvcGVuIHNlc2FtZQ== è il biglietto da visita del modulo da quasi trent'anni.
  • La fine riga di default non è, probabilmente, quella che ti aspetti. È un semplice \n, non il CRLF che parla MIME. La convenzione della RFC stessa richiede il secondo argomento, e il modulo spedisce con il default del programmatore, non quello del protocollo.
  • La stringa vuota ha una regola speciale. Codifica niente e ottieni niente indietro, nessun a capo aggiunto: l'unica eccezione documentata alla regola dell'eol finale, e il motivo per cui un file vuoto fa l'andata e ritorno in modo pulito.
  • Il cugino IMAP ha una virgola. La variante dei nomi di mailbox di RFC 3501 sostituisce la / con una virgola nell'alfabeto, quindi una stringa Base64 da un server IMAP può contenere una lettera che il decoder standard tratta come rumore.
  • La discendenza del 1991 è vera. L'implementazione C discende da metamail, il programma di posta di Bellcore del 1991, tre anni prima che Perl 5 nascesse, quindi ogni chiamata a encode_base64 è in parte codice degli anni Novanta.
  • L'equivalente in puro Perl ha una storia sua. Quando la versione 3.00 del 2004 ha rimosso le implementazioni in puro Perl dal modulo core, il changelog le ha chiamate bloat che nascondono problemi reali nelle implementazioni XS, e le ha ripubblicate come MIME::Base64::Perl, dove vivono ancora.

Quindi la prossima volta che dei byte grezzi devono viaggiare attraverso un mondo solo testo, conosci l'intera storia. Una chiamata di funzione fa il lavoro, l'a capo nascosto è una decisione che prendi con il secondo argomento, il croak wide character è il modo dell'encoder di tenere onesto il tuo Unicode, il dialetto URL-safe è una singola chiamata dal 2010, i file fanno streaming in blocchi da 57 byte, e il conto del 33 percento è il prezzo d'ingresso. E se un giorno devi fare il viaggio nella direzione opposta, prendere una stringa di lettere e riavere indietro i byte originali, l'articolo correlato sulla decodifica Base64 in Perl, linkato qui sotto, copre quel rito con la stessa profondità.

Ultimo aggiornamento: 2026-09-08

Articolo correlato: Decodifica Base64 in Perl: una guida completa