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

Własny tracker BitTorrenta w Debianie i Ubuntu

Instalacja i konfiguracja trackera BitTorrenta w Debianie i Ubuntu.

W Debianie 4 uruchomienie własnego trackera BitTorrenta sprowadzało się do zainstalowania pakietu bittorrent. W nowszych wersjach Debiana i Ubuntu wymaga to nieco więcej zachodu ponieważ opiekunowie pakietu uznali, poniekąd słusznie, że tylko niewielka część osób instalujących pakiet bittorrent jest zainteresowana uruchomieniem trackera. Dlatego instalator nie instaluje skryptów startowych.

Czytaj dalej Własny tracker BitTorrenta w Debianie i Ubuntu

Nucleus CMS i lighttpd

Konfiguracja lighttpd dla systemu blogowego Nucleus CMS.

Nie tak dawno przenosiłem blog mojej ukochanej na własny serwer, na którym strony serwuje lighttpd. Rzeczony blog napędza Nuclesus CMS. Po skopiowaniu plików i bazy blog już właściwie działał, ale „przyjazne URL-e” (znane jako „fancy URL”) wymagały przetłumaczenia regułek z apache’owego mod_rewrite na regułki strawne dla lighty. Stosowny fragment pliku lighttpd.conf zamieszczam poniżej, fragment dotyczący regułek pogrubiłem. Oby się komuś przydało.

$HTTP["host"] =~ "^(|www\.)karniak\.com$" {
    server.document-root = "/home/karniak/www"
    accesslog.filename = "/var/log/lighttpd/karniak.com-access.log"
    url.rewrite-once = (
        "^/(item|blog)/(\d+)$" => "/index.php?$1id=$2",
        "^/(item|blog)/(\d+)/catid/(\d+)$" => "/index.php?$1id=$2&catid=$3",
        "^/category/(\d+)$" => "/index.php?catid=$1",
    )
}