Dane binarne w PHP

Przy pisaniu poprzedniej notki o base64_encode() przypomniało mi się inne zastosowanie base64, a mianowicie osadzanie danych binarnych w kodzie PHP. Poniższy kawałek kodu wypluwa przezroczysty obrazek w formacie GIF o rozmiarach 1 x 1 px. Jest to fragment skryptu, który zlicza otwarcia mailingu.

header('Content-Type: image/gif'); 
header('Expires: Wed, 11 Nov 1998 12:00:00 GMT'); 
header('Cache-Control: no-cache'); 
header('Cache-Control: must-revalidate'); 
die(base64_decode('R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOwA='));

Oczywiście równie dobrze plik można zapisać na dysku i wypluwać go przez file_get_contents() lub przekierować do niego przez wysłanie nagłówka Location, ale powyższe rozwiązanie ma tę zaletę, że plik jest osadzony w skrypcie. To może być istotne jeśli sprzedajemy skrypt zakodowany np. ionCubem i nie chcemy, żeby klient miał możliwość podmiany obrazka. Dodatkowo base64_decode() ma szanse być szybsze niż otwarcie i wczytanie zewnętrznego pliku, a od przekierowania przez nagłówek Location jest szybsze na bank.

Z drugiej strony osadzanie plików w skrypcie ma sens tylko dla niedużych plików, tak π razy oko do 2-3 KiB. Przy większych plikach wybrałbym file_get_contents(), ze względu na mniejszy rozmiar skryptu PHP i prawdopodobnie większą szybkość działania.

Z trzeciej strony, jeśli podstawowym celem jest szybkość działania, można pokusić się o jeszcze inne rozwiązanie.

define(EMPTY_GIF_IMAGE, "\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\x00\x00\xff\xff\xff\xff\xff\xff\x21\xf9\x04\x01\x0a\x00\x01\x00\x2c\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x4c\x01\x00\x3b\x00");
header('Content-Type: image/gif'); 
header('Expires: Wed, 11 Nov 1998 12:00:00 GMT'); 
header('Cache-Control: no-cache'); 
header('Cache-Control: must-revalidate'); 
die(EMPTY_GIF_IMAGE);

Jeśli korzystamy z APC lub podobnego rozwiązania to po kompilacji skryptu stała EMPTY_GIF_IMAGE będzie zawierała nasz pliczek GIF w postaci gotowej do użycia, odpada konieczność konwersji z base64. Zastrzegam, że nie sprawdzałem tego w praktyce, ale zdziwiłbym się, gdyby nie było to najszybsze z opisywanych rozwiązań.

Krótsze skróty dzięki base64

Skróty wiadomości (ang. message digest, hash) to chleb powszedni w programowaniu. Przez funkcje md5(), sha1() itp. generowane są identyfikatory sesji, ciasteczka identyfikujące użytkownika, nazwy plików i tuzin innych rzeczy.

Skrót, jak sama nazwa wskazuje, powinien być krótki. Tymczasem w większości wypadków, z którymi się zetknąłem, skróty używane są w zapisie szesnastkowym, co oznacza, że 128 bitowy skrót MD5 jest zapisywany w 32 bajtach (czyli 256 bitach), a 160 bitowy SHA1 potrzebuje 40 znaków (256 bitów). To, delikatnie mówiąc, trąci rozrzutnością. Oszczędzić bajty można wykorzystując zapis base64, co pokazuje poniższy przykład:

var_dump(sha1('Ala ma kota')); 
var_dump(strtr(rtrim(base64_encode(sha1('Ala ma kota', true)), '='), '+/', '-_'));

Wynik:

string(40) "43fd70009a97a7d311c5644047ccc700f8d08a9d" 
string(27) "Q_1wAJqXp9MRxWRAR8zHAPjQip0"

Czytaj dalej „Krótsze skróty dzięki base64”

Ocalone tłumaczenia: Julian Tuwim

W nie tak odległej przeszłości studiowałem na warszawskiej anglistyce. Jednym z kursów, które wspominam najlepiej był kurs #2800 zatytułowany „Poezja polska w przekładzie” prowadzony przez dr Barry’ego Keane’a, którego z tego miejsca serdecznie pozdrawiam. Na kursie co tydzień braliśmy na warsztat jednego poetę; każdy uczestnik wybierał jeden lub kilka jego wierszy, szukał ich tłumaczeń na angielski, dokonywał krytycznej analizy tychże, a na koniec prezentował własne tłumaczenie. Na co dzień nie gustuję w poezji, ale tłumaczenie jej okazało się nadspodziewanie ciekawe. W każdym razie znalezienie kilku tłumaczeń jednego wiersza nie zawsze było łatwe, dlatego zakarbowałem sobie w pamięci, że jeśli kiedykolwiek dorobię się własnej strony to udostępnię na niej moje tłumaczenia co by ułatwić życie przyszłym pokoleniom anglistów, a być może umożliwić jakimś native speakerom obcowanie z polską poezją.

Na pierwszy ogień Julian Tuwim, nad jego wierszami pracowało mi się najlepiej. W ramach disklejmera wspomnę tylko, że tłumaczenie nie zawiera poprawek naniesionych w czasie zajęć ponieważ kartki na których notowałem uwagi dawno zaginęły. Bez dalszego przedłużenia, miłej lektury.

Karta z dziejów ludzkości A page from the history of humanity
Spotkali się w święto o piątej przed kinem
Miejscowa idiotka z tutejszym kretynem.

Tutejsza idiotko! – rzekł kretyn miejscowy –
Czy pragniesz pójść ze mną na film przebojowy?

Miejscowa kretynka odrzekła – Z ochotą,
Albowiem cię kocham, tutejszy idioto.

Więc kretyn miejscowy uśmiechnął się słodko
I poszedł do kina z tutejsza idiotką.

Na miłym macaniu spłynęła godzinka
I była szczęśliwa miejscowa kretynka.

Aż wreszcie szepnęła: – kretynie tutejszy!
Ten film, mam wrażenie, jest coraz nudniejszy.

Więc poszli na sznycel, na melbe, na winko,
Miejscowy idiota z tutejszą kretynką.

Następnie się zwarli w uścisku zmysłowym
Tutejsza idiotka z kretynem miejscowym.

W ten sposób dorobią się córki lub syna:
Idioty, idiotki, kretynki, kretyna.

By znowu się mogli spotykać przed kinem
Tutejsza idiotka z miejscowym kretynem.

At the cinema, on a bench therein
The local idiot met the resident cretin.

Local idiot! – says resident cretin –
Let’s go for a movie, I’m begging.

The local idiot replied – With pleasure,
As I love you beyond any measure.

The cretin gave the sweetest smile he got
And went for a movie with the local idiot.

To pleasant pawing they devoted some time
Which made the local idiot feel very fine.

Finally she whispered: – resident cretin!
The movie is getting more and more thin.

So out they went and some wine they bought,
The local cretin with the resident idiot.

Later in a sensual embrace they clashed in
The local idiot with the resident cretin.

The offspring is more likely than not:
A male cretin or a female idiot.

Which will allow in future for another meeting
Of the local idiot with the resident cretin.

Figielek A Frolic
Raz się komar z komarem przekomarzać zaczął
Mówiąc, że widział raki, co się winkiem raczą.

Cietrzew się zacietrzewił słysząc takie słowa,
Sęp zasępił się strasznie, osowiała sowa,

Kura dała drapaka, że aż się kurzyło,
Zając zajęczał smętnie, kurczę się skurczyło.

Kozioł fiknął koziołka, słoń się cały słaniał,
Baran się rozindyczył, a indyk zbaraniał.

Once a boa boasted to a choked chickadee
that he saw a sawfish which should be a bee.

A jellyfish felt jealous, a rat rattled at a hare,
Only a bear could bear it, so he didn’t care.

A clam clamoured at once it was an obvious lie
And a peacock peed itself, owl only knows why.

An ape gaped at a cow suffering from cowardice,
While an ant anticipated being antagonized.