Niezalogowany [ logowanie ]
Subskrybuj kanał ATOM Kanał ATOM

Autor wpisu: Tomasz Kowalczyk, dodany: 31.05.2011 18:41, tagi: internet, xhtml

Praca programisty nie zawsze polega na rozwiązywaniu zaawansowanych problemów programistycznych, czy też tworzeniu złożonych algorytmów przeliczających niewyobrażalne zbiory danych. Czasem potrzebujemy zwyczajnych, prostych, czasem wręcz trywialnych rozwiązań dla problemów naszych klientów. Ostatnio zetknąłem się z jednym z takich problemów - pobieraniem miniaturek do filmów wstawianych poprzez element <iframe> YouTube'a. Zapraszam do lektury krótkiego i treściwego [...]

Autor wpisu: batman, dodany: 31.05.2011 08:00, tagi: internet

Każdy serwis wymagający dużej ilości grafiki na stronie jest zmorą “hostodawcy”. Źle zoptymalizowane grafiki pożerają transfer w zastraszającym tempie. Dobrym przykładem będzie tutaj trójwymiarowy dzbanek z wpisu Animacje 3D przy użyciu CSS3. W chwili obecnej zajmuje on 25 KB. Niby niewiele, ale co jeśli takich obrazków miałbym na stronie kilkanaście/kilkadziesiąt? Przy założeniu, że strona byłaby popularna, marnowałbym niepotrzebnie transfer.

Na szczęście deweloperzy z Yahoo! wyszli na przeciw naszym potrzebom i stworzyli narzędzie o nazwie Smush.it. Jest to prosta z pozoru aplikacja online, kompresująca wskazane grafiki. W przypadku wspomnianego dzbanka, plik po kompresji waży tylko 20 KB, czyli 20% mniej. Dla większej ilości obrazków na stronie oszczędności mogą ilość w megabajty.

Jak to działa? Do Smush.it uploadujemy obrazki lub wskazujemy ich adresy online. Narzędzie przy pomocy kilku innych działających w tle, usuwa zbędne bajty z obrazka, nie zmieniając przy tym jego wyglądu ani jakości. Po zakończonej operacji otrzymujemy listę zoptymalizowanych grafik wraz z opisem poczynionych oszczędności oraz linkiem do pobrania. Sprawdzone – działa.

Autor wpisu: batman, dodany: 30.05.2011 20:18, tagi: php

Jakiś czas temu natknąłem się na Agile Toolkit – interesujący framework, pozwalający skupić się tylko i wyłącznie na programowaniu. Podłubałem nieco w tym frameworku, zrobiłem kilka prostych stronek “do szuflady” i na chwilę obecną nie mam do niego większych zastrzeżeń. Jakiś czas temu na blogu projektu pojawił się wpis, w którym autor frameworka prosi o pomoc w tłumaczeniu dokumentacji na inne języki. Znalazłem chwilę, zrobiłem forka na githubie i zacząłem powoli tłumaczyć. Póki co teksty przeze mnie napisane są surowym tłumaczeniem, nienadającym się na wysłanie do macierzystego repozytorium. Wymagają one przede wszystkim korekty edytorskiej lub co najmniej świeżego oka, które wyłapie moje potknięcia (również te w tłumaczeniu). Jeśli macie ochotę i odrobinę wolnego czasu, zróbcie forka z mojego (lub głównego) repozytorium, znajdźcie błędy i/lub przetłumaczcie to, co jeszcze nie jest przetłumaczone. Kto wie, może Agile Toolkit wyrośnie na godnego konkurenta ZF lub Symfony?

Mój fork na githubie – https://github.com/wilgucki/atk4-web Repozytorium projektu – https://github.com/atk4/atk4-web

Autor wpisu: sokzzuka, dodany: 30.05.2011 14:29, tagi: php, zend_framework

Każdy używający Zend Frameworka wcześniej czy później natknie się na klasę służącą do tworzenia formularzy – Zend Form. Jest to całkiem przydatna klasa i znakomicie się sprawdza. Sprawdza się świetnie do momentu, kiedy nasz webmaster stwierdzi, że jednak ubranie formularza w dl/dt/dd jest już passe i przydało by się np. ubrać go w tagi ul/li. Mnie właśnie dzisiaj przydarzyła się taka sytuacja, a więc ku pamięci wrzucam rozwiązanie:


class Form extends Zend_Form
public function init() {

        $email = new Zend_Form_Element_Text('email');
        $email->setLabel('Email:');
        $email->addValidator(new Zend_Validate_EmailAddress());
        $email->setRequired();

        $firstName = new Zend_Form_Element_Text('first_name');
        $firstName->setLabel('First name:');
        $firstName->setRequired();

        $lastName = new Zend_Form_Element_Text('last_name');
        $lastName->setLabel('Last name');
        $lastName->setRequired();

        $this->addElements(array($email, $firstName, $lastName));
}

 public function loadDefaultDecorators() {
        parent::loadDefaultDecorators();

        $this->_decorators['HtmlTag']['options']['tag'] = 'ul';

        foreach ($this->_elements as $el) {
            if ($el instanceof Zend_Form_Element_Text) {
                $el->removeDecorator('HtmlTag');
                $el->removeDecorator('Label');

                $el->addDecorator('Label', array('tag' => null));
                $el->addDecorator('HtmlTag', array('tag' => 'li'));
            }

            if ($el instanceof Zend_Form_Element_Submit) {
                $el->removeDecorator('Label');
                $el->removeDecorator('DtDdWrapper');
                $el->addDecorator('HtmlTag', array('tag' => 'li'));
            }
        }
    }

}

Co jak i dlaczego ?

Pierwsze na co należy zwrócić uwagę to miejsce modyfikacji dekoratorów – robimy to w metodzie loadDefaultDecorators(). Jest ona wywoływana jako ostatnia metoda w konstruktorze klasy Zend_Form i dzięki temu mamy już dostęp do wszystkich koniecznych obiektów i pól.

Kolejna kwestia na która trzeba zwrócić uwagę to rozróżnienie pomiędzy różnymi rodzajami elementów formularza. Różne klasy mają różne dekoratory w standardzie.

Najbardziej zastanawiający fragment tego kodu to:

                $el->removeDecorator('HtmlTag');
                $el->removeDecorator('Label');

                $el->addDecorator('Label', array('tag' => null));
                $el->addDecorator('HtmlTag', array('tag' => 'li'));

Po co najpierw usuwać a następnie ponownie dodawać te same dekoratory ? Ano po to by zamienić je miejscami ;) . Flow dekoratorów jest taki, że każdy dekorator dodany później dostaje cały kontent wygenerowany przez te, które były dodane wcześniej. Dzięki temu możemy hierarchicznie budować strukturę HTML-a.

Btw. Powyższy kod jest z takiej niezbyt świeżej wersji frameworka. Także, jeżeli coś się zmieniło to z góry przepraszam i chętnie przyjmę kod na nowszej wersji ;)

Autor wpisu: sokzzuka, dodany: 30.05.2011 10:50, tagi: php

Przy okazji różnych dziwnych spraw, Ferenc Kovacs wrzucił fajną prezentację odnośnie historii Unikodu w PHP i problemach z jego implementacją dla PHP 6. Ciekawa rzecz do obejrzenia:

http://www.slideshare.net/andreizm/the-good-the-bad-and-the-ugly-what-happened-to-unicode-and-php-6

Autor wpisu: Tomasz Kowalczyk, dodany: 29.05.2011 23:52, tagi: framework, jquery, php

Ci, którzy śledzą działania ludzi związanych z językiem PHP na pewno są świadomi tego, jak dynamiczne zmiany zachodzą zarówno w interpreterze, jak i w samej społeczności skupionej wokół technologii z nim związanych. Zapraszam do lektury kolejnego zestawu ciekawych materiałów na ten temat.     Linkdump: PeHaPe. 1. Scaling PHP Up, Out, and Around. Kilka słów [...]

Autor wpisu: Athlan, dodany: 28.05.2011 14:40, tagi: sql, php, internet

Dziś bardzo krótko, bez zbędnych dywagacji, czyli tylko i wyłącznie o tablicy $_SERVER. Dbając o bezpieczeństwo aplikacji webowych zwraca się uwagę na wiele czynników, jakimi są SQL injections, przechwytywanie nieprawidłowych parametrów, uogólniające zapytania przepuszczające maskę % w LIKE zapytaniu do baz, XSS‘y w $_POST, $_GET.

I finalnie… wiele osób zapomina (a jeszcze więcej nie jest tego świadom) o możliwości wstrzyknięcia szkodliwych danych w $_SERVER['HTTP_X_FORWARDED_FOR'];. Konsekwencje są oczywiście katastrofalne.

O ile sama walidacja jest rzeczą wtórną, diabeł tkwi w trzech szczegółach:

  1. Rzecz trywialna, ale pamiętajmy, że w naturalnym procesie użytkowania przeglądarki, w nagłówku może zostać zwrócony nie tylko jeden adres IP, a kilka oddzielonych przecinkiem, w tym localhost‘y (standard nagłówka X-Forwarded-For).
  2. Wstrzyknięcie Javascriptów jest możliwe, ale notabene najmniej szkodliwe, bo do spreparowania nagłówka potrzebny jest bardziej zaawansowany proces (dajmy na to Data Tamping, który przedstawię poniżej), np. niż wklejenie syfu w linku/obrazku i przesłanie go komuś przez komunikator, żeby wykraść jego ciasteczka sesyjne document.cookie i przesłać je sobie na serwer w dowolny sposób, zatem atakowi nie ulegną osoby trzecie.
  3. Niepoprawność danych, które można zmanipulować, jest chyba rzeczą oczywistą: nieprzepuszczenie takich danych przez filtry może skutkować złymi wartościami zwracanymi np. przez ip2long() i zapis w zupełności nieprzydatnych nam później danych do bazy.
  4. ale największe nieprzyjemności możemy mieć przez spreparowanie lewych zapytań do baz danych, o ile nie używamy sprawdzonych ORM lub czegokolwiek, co pomaga nam filtrować wartości do niej przekazywane i używane w warunkach zapytań (data binding).

Przykład tampingu danych, żeby spreparować niepożądane efekty.

Mamy bardzo prosty, niebezpieczny kod funkcji, która pobiera pierwszy adres na liście adresów oddzielonych przecinkami z $_SERVER['HTTP_X_FORWARDED_FOR'] o ile istnieje, natomiast w przeciwnym wypadku $_SERVER['REMOTE_ADDR']:

< ?php
 
function getUserIp()
{
  if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
    return trim(current(explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])));
 
  return $_SERVER['REMOTE_ADDR'];
}
 
$sUserIP = getUserIp();
 
echo 'Hi "' . $sUserIP . '"!'; // first bug while display.
var_dump(ip2long($sUserIP)); // second bug while transforming data.
 
?>

Pora na przykład manipulacji takich danych.

  • Będziemy używać Tamper Data dla Firefox’a.Dość popularny wśród developerów addon do Firefox’a, pozwala zmodyfikować dane $_POST, $_GET, $_COOKIE, nagłówki, “w locie żądania” etc.
  • Po instalacji w menu Narzędzia pojawi się pozycja Dane Tamper, która uruchamia okienko do podsłuchiwania żądań. Po kliknięciu Rozpocznij podsłuchujemy wszystkie wychodzące żądania z naszej przeglądarki. Każde żądanie nie zostanie przepuszczone, dopóki go nie zmanipulujemy klikając Tamper, lub przepuścimy dalej klikając Wyślij.
  • Jeżeli zdecydujemy się Tamper’ować żądanie, naszym oczom ukaże się okno z parametrami. Klikamy prawym przyciskiem myszy na listę parametrów, wybieramy Dodaj i wpisujemy nasz przykładowy, brzydki dla aplikacji nagłówek: X_FORWARDED_FOR=<script>alert('Test.')</script>

Naszym oczom ukazują się co najmniej dwa błędy. Pierwszy to błąd prezentacji danych, który wykorzystuje <script>. O ile nie musimy się tym przejmować, bo naturalnie takie żądania nie są tak łatwo wysyłane, użytkownik nie może paść ofiarą ataku przez kliknięcie w link, który np. ukradnie mu ciasteczka. Dane nagłówkowe nie są w stanie być zmodyfikowane poprzez kliknięcie w link, podobnie jak z danymi $_POST (oczywiście mówimy o przypadkach trywialnych, bez javascript’owych wymuszanych submitów targetowanych do np. ramek).

Znacznie poważniejszym błędem jest konsekwencja wadliwego formatu danych, które nasza funkcja bagatelizuje. Po pierwsze mamy fałszywe dane zwracane przez ip2long(), po drugie kto powiedział, że właśnie z tej funkcji korzystamy, a nie zapisujemy danych plain’em i nie bindujemy pofiltrowanych danych lub instrukcji warunkowych zapytania przez np. sprawdzony ORM.

Rozwiązanie problemu.

Edit: Jak słusznie zauważył Zyx, zapomniałem o tym wspomnieć, że skoro mogą znaleźć się tam dowolne dane przesłane od użytkownika, nie należy tego pola traktować jako wyznacznik, że jest to numer jego IP, jest ono bezużyteczne i powoduje potencjalną lukę. Poza zabezpieczeniami to podstawowy argument, żeby o polu zapomnieć i używać $_SERVER['REMOTE_ADDR'].

Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...

Wszystkie wpisy należą do ich twórców. PHP.pl nie ponosi odpowiedzialności za treść wpisów.