strona główna

Archive for April, 2006

Linksys WAG54GS

Tuesday, April 18th, 2006

Czyli jak wydałem bez sensu 400zł.

Wszystko zaczęło się dwa miesiące temu, krótko po zakupie Maca Mini, od problemów z podłączeniem tego do sieci. Coś, co początkowo wyglądało na problem z kartą sieciową (nie pomagała ani wymiana kabla, ani przepięcie w inne gniazdo rutera, a w tym samym czasie podłączone były do niego dwie inne maszyny, które nie zauważyły jakichkolwiek problemów z łącznością) okazało się najdziwniejszym padem rutera jaki kiedykolwiek widziałem.

Mój WAG54G po dwóch latach w zasadzie bezproblemowej pracy zwariował i zaczął sobie wybierać jeden z podłączonych komputerów i uprzykrzać mu życie. Restart pomagał na kilka dni, po tym czasie ruter losował kolejną ofiarę. Objawy za każdym razem takie same: z punktu widzenia komputera połączenie znikało mniej więcej raz na sekundę, więc o jakiejkolwiek łączności można było zapomnieć. Ciekawostka: Windows i Linux znosiły to bez problemów, za to Mac OS X migotania sieci nie wytrzymywał i zawieszał się na dobre.

Oczywiście, najprostsze rozwiązanie nasuwa się samo. Trzeba coś restartować co kilka dni? Nie ma sprawy, należy kupić w Castoramie czy innym Leroy Merlin programowalny włącznik i ustawić go na krótkie wyłączenie zasilania raz dziennie, powiedzmy o 6 rano.
Całkowity koszt operacji to jakieś 50zł + pół godziny na przejazd do sklepu i z powrotem. Ale nie, to by było zbyt prosta i ryzykowna prowizorka – ja potraktowałem te problemy jako sygnał, że ruter zaczyna padać na dobre i należy go wymienić zanim całkowicie się zepsuje w najmniej odpowiednim momencie.

Padło znowu na Linksysa. Mam już D-Linka DSL-504T z paskudnie piszczącym modemem ADSL, więc tę firmę wolałem omijać. Trochę dobrego słyszałem o podobnych urządzeniach US Robotics, ale z tego WAG43G w zasadzie byłem zadowolony – działał bez większych problemów przez dwa lata, co powoli zaczyna być niezłym wynikiem jak na tanią elektronikę. Parę błędów miał, wszystkie dawało się obejść domowymi sposobami, więc nie było specjalnie na co narzekać. Ostatecznie kupiłem prawie to samo, tylko nieco nowsze – WAG54GS. I oj, co to był za błąd.

W telegraficznym skrócie, różnice między WAG54GS a WAG54G:

  1. obsługa 802.11g oprócz 802.11b – szybsza sieć bezprzewodowa,
  2. całkowicie bezużyteczne QoS: można określić priorytety pakietów (wysoki/średni/niski) w zależności od numeru portu (pięć wpisanych na sztywno: FTP, HTTP, Telnet, SMTP, POP3 oraz trzy miejsca na wpisanie własnych),
  3. włącznik. WAG54G wyłączało się przez odpięcie kabla zasilającego, a WAG54GS ma szpanerski, świecący przycisk.

I tyle. Proszę zwrócić szczególną uwagę na brak wpisu "4. WAG54GS nie trzeba restartować co kilka dni." Dlaczego, spytacie, nie umieściłem na liście tego wpisu? Otóż dlatego, że WAG54GS trzeba restartować co kilka dni: fabrycznie nowy, świeży ruter z najnowszym oprogramowaniem zawiesza się po kilku dniach ciągłej pracy, więc w zasadzie można by uznać że jego użyteczność jest taka sama jak starego, psującego się już urządzenia.

No, prawie.

Punkt 3 na liście oznacza, że WAG54GS nie włącza się sam po podłączeniu zasilania, więc – po pierwsze – po awarii zasilania sieć nie wstanie sama, oraz – po drugie – nie działa  sztuczka z programowalnym włącznikiem. Tak więc fabrycznie nowy, świeży ruter z najnowszym oprogramowaniem jest mniej użyteczny od starego, psującego się już urządzenia. Litości, ja zdaję sobie sprawę z tego, że nie jest to sprzęt z kategorii enterprise, ale to jeszcze nie powód żeby go z wersji na wersję psuć.

A na razie pozostaje mi, po krótkiej wyprawie do najbliższej Castoramy, podłączyć stary ruter.

mod_rewrite na home, Gengo 0.5

Friday, April 7th, 2006

Dwie dobre wiadomości i jedna zła, niekoniecznie w tej kolejności:

  1. wczoraj pojawiło się nowa wersja Gengo – wtyczki do Wordpressa pozwalającej na wygodne pisanie tekstów w więcej niż jednym języku. W wersji 0.5 autor, Jamie Talbot, poprawił zdaje się wszystkie błędy które znalazłem podczas prób używania 0.4 na moim blogu, więc może będę już mógł z niej skorzystać,
  2. niestety, podczas prób instalacji 0.5 na moim Business Server w home.pl chyba trafiłem na błąd w tutejszym serwerze WWW; szczegóły dalej,
  3. podczas szukania informacji na temat tego serwera dowiedziałem się, że home w końcu udostępnił mod_rewrite. Sprawdzone, działa, nareszcie będzie można korzystać z ładnych i czytelnych adresów.

Teraz o problemie z serwerem, na przykładzie pliku phpinfo.php:

<?php
if ($HTTP_GET_VARS['test'])
{
phpinfo();
}
else
{
header("Location: /phpinfo.php/en/?test=1");
}
?>

Sens działania jest prosty: otwieram w przeglądarce adres http://elksoft.pl/phpinfo.php, skrypt powinien przekierować na samego siebie z dodatkowymi parametrami i wtedy wyświetlić informacje o środowisku (funkcja phpinfo()). Tak robi, a interesujący fragment tego co wyświetla to:

QUERY_STRING test=1
REQUEST_METHOD GET
REQUEST_URI /phpinfo.php
SCRIPT_NAME /phpinfo.php
SCRIPT_FILENAME /phpinfo.php
SCRIPT_URL /phpinfo.php
SCRIPT_URI http://elksoft.pl/phpinfo.php

I to jest to miejsce, w którym coś tu oszukuje. Według specyfikacji po przekierowaniu lokalnym (bez podania protokołu i adresu maszyny) serwer musi utworzyć stronę identyczną z tą, jaką otrzymałbym wpisując w przeglądarce adres http://elksoft.pl/phpinfo.php/en/?test=1. A tego nie robi, bo wpisując ten adres w przeglądarce otrzymuję:

QUERY_STRING test=1
REQUEST_METHOD GET
REQUEST_URI /phpinfo.php/en/?test=1
SCRIPT_NAME /phpinfo.php
SCRIPT_FILENAME /phpinfo.php
SCRIPT_URL /phpinfo.php/en/
SCRIPT_URI http://elksoft.pl/phpinfo.php/en/

Niestety Gengo polega na zawartości REQUEST_URI i, niestety, głupieje przy takim zachowaniu serwera. Pozostaje poszukać, może uda się to niedużym nakładem pracy obejść.

Dodane: przekombinowałem, da się to sprawdzić w sposób bardziej czytelny i dający więcej informacji.  Dwa skrypty, /a.php tylko przekierowuje na /b.php?test=1, który z kolei wypisuje wyżej opisaną tabelkę.  Wynik otwarcia strony http://elksoft.pl/a.php:

QUERY_STRING test=1
REQUEST_METHOD GET
REQUEST_URI /a.php
SCRIPT_NAME /b.php
SCRIPT_FILENAME /b.php
SCRIPT_URL /a.php
SCRIPT_URI http://elksoft.pl/a.php

Czyli na przemian, część zmiennych jest ustawiana poprawnie (QUERY_STRING, SCRIPT_NAME, SCRIPT_FILENAME), a część pozostaje z pierwszego wykonania (REQUEST_URI, SCRIPT_URL, SCRIPT_URI).
Sprawy trochę komplikuje fakt, że stara, oficjalna specyfikacja CGI nie definiuje zachowania Location aż tak dokładnie, a nowa wyszła tylko jako draft.  Apache, jak się okazuje, idzie na łatwiznę i przy każdym przekierowaniu, niezależnie od tego, czy lokalnym czy z nazwą protokołu i serwera, odsyła do klienta 302 z nowym adresem, co działa bardzo dobrze, chociaż na pewno wolniej.
Jako obejście najprościej będzie wymusić przekierowania na "pełne" adresy, ze wskazaniem nazwy serwera.

Javascript i sprawdzanie formularzy

Thursday, April 6th, 2006

http://blog.elksoft.pl/wp-content/b10mechanics030_small.jpg

Niedawno znalezione: wygodna biblioteka ułatwiająca sprawdzanie poprawności danych wpisanych w formularzu, jeszcze przed wysłaniem ich do serwera. Samo sprawdzanie to nic nowego, ale tę bibliotekę spośród innych rozwiązań wyróżnia sposób, w jaki określa się poprawną zawartość: poprzez atrybut class pól formularzy i odpowiednio zdefiniowane, ogólne funkcje testujące.

Łatwiej to zademonstrować niż opowiedzieć:

<form>
<ul>
<li>Adres: <input name="email" type="text" class="simple_email"/></li>
<li>Hasło: <input name="password" type="password" class="sane_password"/></li>
<li>Używane shelle:
<select name="shell" multiple="1" class="mandatory">
<option value="bash">/bin/bash</option>
<option value="ash">/bin/ash</option>
<option value="csh">/bin/csh</option>
<option value="emacs">/usr/bin/emacs</option>
</select>
</ul>
<button type="submit" name="commit">Dodaj</button></td>
</form>

Ten fragment tworzy formularz z trzema polami: miejscem na email, hasło oraz listę używanych programów. Każde z nich ma przypisaną klasę, która określa jaką zawartość należy wymuszać:

  1. email: chciałbym, żeby można było wpisać adres email w najczęściej używanej, prostej postaci – użytkownik@domena.gdzieśtam (klasa simple_email),
  2. hasło: powinno to być sensowne hasło (klasa sane_password),
  3. używane shelle: należy wybrać przynajmniej jeden (klasa mandatory).

Jak widać, formularz pomimo dodania tej informacji nadal jest prosty i czytelny. Pozostaje jeszcze zdefiniować funkcje sprawdzające poprawność pól:

var Validators = {
simple_email: function() {
return (/^\w+@\w+(\.\w+)+\.?$/.test(this.value));
},
sane_password: function() {
return this.value.length > 3;
}
};

Klasa mandatory już jest zdefiniowana w bibliotece, więc nie trzeba jej dodawać. Funkcje te mogą być wspólne dla wielu formularzy, więc najlepiej umieścić je w osobnym pliku .js, wspólnym dla całego serwisu. Zostało już tylko włączenie sprawdzania formularzy poprzez wykonanie po załadowaniu strony:

Form.Validator.installForAllForms({'validators':Validators});

I już, efekt można obejrzeć tutaj. Jakie dokładnie są zalety takiego podejścia? Po kolei:

  1. formularze zawierają informacje o danych w postaci zwięzłej i czytelnej i dla maszyny, i dla człowieka,
  2. definicje funkcji testowych są zebrane w jednym, wspólnym dla całego serwisu miejscu, co oznacza że ewentualna zmiana sane_password dla wszystkich formularzy na coś bardziej skomplikowanego będzie szybka i wygodna,
  3. to, co trzeba napisać samemu, zostało ograniczone do naprawdę niezbędnego minimum: biblioteka faktycznie zawiera całą wspólną część kodu.

Uwaga, na wszelki wypadek: całe to sprawdzanie po stronie klienta oczywiście nie oznacza, że można zrezygnować z kontroli danych na serwerze. Nie należy mieć zaufania do przeglądarki. I nie o to tu chodzi, żeby całkowicie przenieść testy na klienta, tylko o szybsze poinformowanie użytkownika że coś wpisał źle.

Rozwiązanie ma jedną wadę: poprawność trzeba sprawdzać w dwóch miejscach, najprawdopodobniej w dwóch różnych językach programowania (ktoś tu pisze kod po stronie serwera w JS?), co oznacza powtarzanie informacji. Trzeba będzie się przyjrzeć, czy w takim Django dałoby się wyznaczać tablicę Validators na podstawie definicji modelu :)

Aktualizacja 2007/10/16: Miron zwrócił uwagę, że nie działał odsyłacz do strony testowej. Poprawiłem, dzięki.

Przy okazji wprowadziłem jedną zmianę, drobną ale ważną: od teraz pola z niepoprawną zawartością są wskazywane kolorem tła. Form.Validator ustawia takim elementom klasę "invalid", więc wymagało to tylko dopisania jednej linii CSS.