“Nieskończony” Jogger
Podłubałem trochę i napisałem User JavaScript, implementujący metodę “stronicowania”, zaprezentowaną na www.humanized.com/reader/, dedykowany dla serwisu jogger.pl.
Instalacja: PS. Pozdrawiam wszystkich joggerowiczów.Podłubałem trochę i napisałem User JavaScript, implementujący metodę “stronicowania”, zaprezentowaną na www.humanized.com/reader/, dedykowany dla serwisu jogger.pl.
Instalacja: PS. Pozdrawiam wszystkich joggerowiczów.Jakiś czas temu Emila na swoim blogu opublikowała notkę, w której narzekała na spam przychodzący na jej bloga. Biorąc pod uwagę, że ja też ostatnio dostaję go masę, postanowiłem coś z tym zrobić.
Kilka dni temu, zacząłem przerabiać swojego bloga oraz logować wszystkie zapytania POST na niego wysyłane. Po analizie danych wysyłanych przez boty postanowiłem wprowadzić dwa zabezpieczenia: zabezpieczenie zrobione specjalnie na boty spamujące wordpressy, oraz zabezpieczenie na “całą resztę”. Okazało się, że skuteczność rozwiązań, które wprowadziłem jest 100% (od kilku dni nie dostałem ani jednego spamu). Dodatkowo są one przezroczyste dla użytkownika i nie używają żadnych filtrów, które mogły by przypadkowo skasować “dobry” komentarz.
Okazało się, że większość botów wysyłających spam tylko na blogi “napędzane” skryptem Wordpress jest dość głupia. Wchodzą one na stronę komentarzy i wysyłają standardowe zapytanie POST dla wordpressa, nie patrząc nawet w jaki sposób formularz jest zbudowany. Dlatego aby pozbyć się tego robactwa wystarczyło zmienić nazwy pól w formularzu. Tym samym zapytanie POST wysyłane przez boty stało się niepoprawne i można je łatwo wyfiltrować.
Całą resztę też dosyć łatwo oszukać. Ja zrobiłem to w następujący sposób: skopiowałem pole, w którym wpisuje się treść komentarza. Dałem mu atrybut display: none i opis (dla przeglądarek tekstowych): to pole pozostaw puste. W oryginalnym polu zmieniłem nazwę na “spam”. Jak to działa?
Większość botów wypełni wszystkie pola, łącznie z tym którego zwykły użytkownik nie wypełni, bo albo go nie zobaczy, albo przeczyta opis “tego nie wypełniaj”. Wszystkie te boty można z łatwością wyfiltrować. Co bardziej cwane boty mogą “nauczyć” się takie zabezpieczenie omijać. To właśnie dlatego pole, w którym trzeba wpisać treść komentarza ma prowokacyjną nazwę “spam”. Jeśli bot będzie miał jakieś pole ominąć, to być może ominie właśnie te i czeka go “muka”.
Życzę powodzenia w zabezpieczaniu własnych blogów. Możecie oczywiście zastosować filtry. Ja je jednak niezbyt lubię.
Przed chwilą wymieniłem w SIKu klasy odpowiedzialne za obsługę baz danych. Niby nic wielkiego, bo w interfejsie użytkownika nic się nie zmieniło, jednak jest to swego rodzaju postęp. Sprawa jest prosta: skoro zrobiłem już coś co było wcześniej zaplanowane i wręcz konieczne, teraz przyjdzie czas na ciekawsze rzeczy (czytaj: na dodawanie nowych funkcji do serwisu).
Zmiana odbyła się o wiele łagodniej niż się tego spodziewałem. Nie było żadnych dużych zgrzytów. Zmieniłem tylko te fragmenty kodu, gdzie zmieniło się API klas. Tak na marginesie to zarówno stare klasy do obsługi bazy danych, jak i nowe są mojego autorstwa (-: W serwisie mogły jednak pojawić się jakieś błędy, dlatego mam nadzieje, że użytkownicy ustosunkują się do nich przychylnie i pomogą mi je poprawić.
Pragnę również podziękować Plastusiowi, za wykrycie kilku poważnych błędów kilka dni temu.
Napisałem ostatnio skrypt konwertujący listę kontaktów Gadu-Gadu na odpowiednie zapytanie do serwera Jabbera. Skrypt został przetestowany w praktyce - działa dobrze. Jedynym mankamentem jest to, że skrypt nie zajmuje się autoryzacją kontaktów z Gadu-Gadu. Trzeba to zrobić ręcznie. Zachęcam do korzystania zarówno z Jabbera, jak i mojego skryptu.
Chcąc pobrać najnowszą wersję Opery dla Debiana, wszedłem na odpowiednią podstronę. Z pozoru jest to zwykła strona, na której można pobrać plik. Moją uwagę przyciągnął jednak pewien szczegół:
<a href="http://www.opera.com/download/get.pl?id=28354&location=17&nothanks=yes&sub=marine">click here</a>
Najbardziej interesujące są dwa fragmęty:
nothanks=yessub=marineZmienna “nothanks”, ustawiona na wartość “yes”, wygląda co najmniej ciekawie. Zastanawia mnie, co miał na myśli programista, tworząc taką zmienną. Niestety nie udało mi się ustalić do czego zmienna służy, z czego mogę wnioskować, że prawdopodobnie jest wykorzystywana przy tworzeniu statystyk.
Jeszcze większe zaciekawienie wzbudziła u mnie “łódź podwodna” (ang. submarine). Znaczenia tej zmiennej udało mi się dociec. Służy ona do odróżniania strony z opisem od właściwego pliku. “marine” to tylko radosna twórczość programisty. Po zmianie na “sub=marchewka” link nadal działa prawidłowo.
<?php endif; // if you delete this the sky will fall on your head ?>
<?php endif; // if you delete this the sky will fall on your head ?>Jeśli to usuniesz, niebo spadnie Ci na głowę.
section .text ; program section
global _start ; ld is reported about _start
_start: ; from this label program starts
mov eax, 4 ; 4 - write command
mov ebx, 1 ; 1 - stdout
mov ecx, hello ; hello - our text
mov edx, size ; size - text size
int 0x80 ; 0x80 - system call
mov eax, 1 ; 1 - exit command
mov ebx, 0 ; 0 - program exit state
int 0x80 ; 0x80 - system call
section .data ; data section
hello db 'Hello, world!', 0x0a ; our text
size equ $ - hello ; text size ([current address] - [text address])
I may write something more interesting soon.section .text ; sekcja programu
global _start ; informuje ld o _start
_start: ; etykieta wykonywana na starcie programu
mov eax, 4 ; 4 - polecenie write
mov ebx, 1 ; 1 - stdout
mov ecx, hello ; hello - nasz tekst
mov edx, size ; size - dlugość tekstu
int 0x80 ; 0x80 - wywołanie przerywania systemowego
mov eax, 1 ; 1 - polecenie exit
mov ebx, 0 ; 0 - status poprawnego zakończenia programu
int 0x80 ; 0x80 - wywołanie przerywania systemowego
section .data ; sekcja danych
hello db 'Hello, world!', 0x0a ; nasz napis
size equ $ - hello ; długość napisu ([aktualny adres] - [adres napisu])
Niedługo postaram się umieścić coś ciekawszego.
command.c: In function 'inp_text': command.c:2560: warning: pointer targets in passing argument 1 of 'tt_write' differ in signedness command.c: In function 'init_command': command.c:3005: error: invalid lvalue in assignment command.c:3007: error: invalid lvalue in assignment command.c: In function 'main_loop': command.c:3472: warning: pointer targets in passing argument 1 of 'safe_print_string' differ in signedness make[2]: *** [command.lo] Error 1 make[1]: *** [all-recursive] Error 1 make: *** [all-recursive-am] Error 2
You can solve this by running a command before make:
sed -i 's/AT_LEAST((int) num_fds,/AT_LEAST( num_fds,/' src/command.cTomasz Wysocki
Podczas pisania programu publikującego wpisy na blogu, natknąłem się na problem. Moja aplikacja robiła fork, a następnie exec na program napisany przez innego autora. Powodowało to, że proces potomny, którego kod nie znajdował się pod moją kontrolą, wysyłał informacje na stderr i stdout, czego chciałem uniknąć. Szukałem więc sposobu, za pomocą którego mógłbym “wyciąć” strumienie stderr i stdout dla danego procesu. To do czego doszedłem prezentuje poniższy listing:
freopen("/dev/null","w",stderr);
freopen("/dev/null","w",stdout);
Powyższy kod trzeba umieścić bezpośrednio, przed wywołaniem exec. Funkcja freopen, której deklaracja znajduje się w stdio.h, otwiera do odczytu /dev/null i zapisuje uchwyty w zmiennych stderr i stdout, które domyślnie odpowiadają za strumienie wyjścia. Oczywiście zamiast /dev/null możemy użyć innego pliku (lub dwóch plików), co daje nam później możliwość analizowania, zwracanej przez proces treści.
Tomasz “tomwys” Wysocki