Otwarte źródło, otwarty plik
Kiedyś do zarządzania moim telefonem używałem programu floAt's Mobile Agent. Ten, dedykowany telefonom Sony Ericsson, program między innymi zapisywał wszystkie moje wiadomości SMS w swoim własnym archiwum. Ja, z wrodzonego chomikowania, sobie te jego zapisy backupowałem.
Niedawno znalazłem je, szukając pewnego bardzo starego wpisu. Otworzyłem tenże plik, a moim oczom ukazała się struktura pliku CSV, wartości rodzielanych przecinkami. Gdzie bez żadnych problemów dało się wyczytać datę otrzymania lub wysłania danej wiadomości. I pewnie dało by się też dojść do tego, co oznaczają pozostałe zmienne, jednak największy problem był z samą wiadomością, która przyjmowała postać długich ciągów cyfr w systemie szesnastkowym.
Nie miałem w pierwszej chwili pojęcia cóż to za format jest tych danych. Pierwsze bajty w kilkudziesięciu linijkach były stałe. Potem znów było coś... i tak dalej. Nie mam obycia w komendach AT, nie znam się na kodowaniach w sieci komórkowej (zbytnio). Ale znam się co nieco na programowaniu. Pomyślałem zatem - oto jest moment, by wykorzystać potęgę oprogramowania o dostępnym kodzie źródłowym! Wspomniany FMA to program napisany w języku Delphi, w którym kiedyś bardzo dużo siedziałem. A jego źródła są dostępne na licencji GPL.
Ściągnąłem zatem źródła, znalazłem moduł uSMS.pas, który wydawał się pasować do tego, co ja potrzebuję znaleźć (przekształcić te ciągi do postaci czytelnej dla człowieka). Po pierwsze okazało się, że te ciągi to po prostu "SMS Packet format", który zaczyna się od numeru SMS Center, dlatego początki ciągów były identyczne. Ale to nie przybliżało mnie do rozwiązania problemu - musiałbym zaimplementować zatem parsowanie tegoż formatu w swoim programie... ale moment, przecież mam moduł, który to robi!
W pierwszej chwili pomyślałem o przepisaniu tego na C#. Ale spojrzałem na 58 KB kodu i zrezygnowałem. Za dużo roboty, która ma być wykorzystana tylko raz, tylko do przerobienia jednego pliku na inny. Rozważałem przez chwile skompilowanie modułu do postaci .netowego assembly (za pomocą Delphi.NET), by użyć tej klasy w moim programie - ale musiałbym znów Delphi.NET instalować, grzebać, nie wiadomo jak by to miało działać. A przecież kiedyś Delphi było moim żywiołem, dlaczego więc nie odkurzyć starych umiejętności?
Po krótkiej chwili zabawy z Free Pascal Compiler, wyrzuceniu zbędnych zależności z tego wspomnianego modułu, po napisaniu prostego programu testującego - okazało się, że miałem rację i moje tajemnicze ciągi zmieniły się w treść wiadomości "Idziesz na rower?" wysłanej ponad 6 lat temu. Obiecujący początek. Dłuższa chwila zabawy (i zmagania, od Delphi się odzwyczaiłem) z kodem zaowocowały prostą aplikacją do przerabiania formatu archiwum FMA do prostego pliku CSV. Sam program jest jeszcze pełen błędów, nie obsługuje żadnego wyjątku od reguły i zapewne będzie się psuł - ale na moich dwóch plikach zadziałał.
A morał tej bajki jest krótki i niektórym znany - używanie otwartego, udokumentowanego standardu przechowywania danych może pozwolić, że w przyszłości, będziemy mogli dane nadal otrzymać. Wystarczy tylko napisać aplikację, która to zrobi jak nakazuje dokumentacja. Ewentualnie - używanie oprogramowania o dostępnym kodzie źródłowym może pozwolić na to, że część starego oprogramowania może zostać użyta do przekształcenia starych danych na jakiś nowy, czytelny format. Wiwat otwartość, dzięki której, bez konieczności instalacji tego starego, nierozwijanego już programu (z czym pewnie by się wiązały problemy) udało mi się dane odczytać, praktycznie bez problemów.
Oczyma wyobraźni widzę, jak za X lat będę tak samo się starał odczytać dane zapisane w prehistorycznym formacie .xyz...1
A teraz krok następny - w jakim formacie dane przechowuje PPCPimBackup, program zamknięty, rozprowadzany jako freeware? I czy te dane też mi się uda odczytać? Tu już wiem, że będzie znacznie gorzej ;-)
[1] Znalazłem też kiedyś moje pliki zapisane w formacie graficznym PCX przez PaintBrusha z Windows 3.1, którego już na Windows 64-bitowym nie mogę uruchomić. Sytuacja bardzo podobna.
Wykorzystanie zewnętrznych assembly w PowerShell
Ku pamięci. PowerShell pozwala bezproblemowo załadować zewnętrzne assembly i używać klas (i metod z tych klas) z nich, czyli jeżeli potrzebuję na przykład użyć mojej biblioteki do zmiany rozmiarów obrazków to wcale nie jest mi niezbędne tworzenie do tego celu aplikacji konsolowej w C#, sprawę spokojnie mogę załatwić skryptem PowerShella.
Param([string]$path, [string]$newpath, [int]$percent = 50);
[Reflection.Assembly]::LoadFrom("E:\Marcin\Temp\Ktos.Autonoe.Common.dll");
[Ktos.Autonoe.AutonoeLib]::ResizeImage($path, $newpath, $percent, 50);
Zaoszczędziło trochę czasu, gdy mój napisany dawno temu program, którego zazwyczaj używam żeby masowo zmienić wielkość zdjęć stwierdził, że w tym katalogu zdjęć nie ma. Fajnie, znalazłem błąd, szkoda, że w momencie gdy nie miałem na szukanie błędu czasu ani narzędzi.
PHP, ech
Siadłem do napisania poważniejszej rzeczy w PHP. W odróżnieniu od tego co robię w pracy, tu mam do dyspozycji całe PHP5 wreszcie. Potrzebowałem tymczasowo stworzyć obiekt, który kiedyś w przyszłości będzie do Smarty przekazywany i będzie miał wiele zastosowań, na razie do proof of concept była mi potrzebna jedna jego metoda.
Więc sobie pomyślałem - cóż prostszego, stworzę sobie klasę anonimową, ją skonstruuję w Smarty->assign() i będzie dobrze, jedna metoda, co za problem.
$this->CISmarty->assign('user', new class { public function foo() { return false; } };);
Jak się słusznie domyślacie, to tak się nie da. No to pomyślałem, że może da się inaczej. Wewnątrz funkcji stworzyłem klasę o nazwie __anonymous1 i spróbowałem ją utworzyć. Cóż mnie spotkało?
Fatal error: Class declarations may not be nested
Przeniesienie deklaracji mojej klasy "anonimowej" poza klasę w której metodzie potrzebowałem owej klasy anonimowej użyć oczywiście sprawę rozwiązało, jednak zdałem sobie po raz kolejny sprawę, że inne języki programowania (Java, C#) z którymi mam styczność mnie rozbestwiły. Owszem, w tym przypadku klasa anonimowa to tylko "lukier składniowy", luksus, jednak... pewien niesmak pozostaje.
Może w PHP6.5?
Choć tak na serio to najbardziej mi i tak brakuje możliwości zrobienia czegoś w rodzaju $bar = returnMeAnArray()['baz'];
Do czegoś to trzeba wykorzystać
Ten GPS. A raczej mojego PDA + GPS. Kiedyś myślałem, żeby sobie napisać program, który będzie za licznik rowerowy mi służył (bo programy które są są niewystarczające, bądź płatne i ze zbyt dużymi możliwościami z kolei ;-)). Potem sobie pomyślałem, że potrzebuję prostej aplikacji która pozwoli mi dopisywać notatki do danych współrzędnych geograficznych.
A teraz wpadłem na genialny pomysł. A nawet dwa. Znów w wannie leżąc (przewaga wanny nad prysznicem - podczas prysznicu nie mam genialnych pomysłów). No dobra, genialny może nie jest.
Wpadłem na pomysł aplikacji, która pozwoli mi stworzyć listy rzeczy do zrobienia dla danego miejsca. Co? Aplikację, która gdy wykryje, że jestem tam gdzie założyłem wcześniej że jestem, to pokaże mi jakie mam rzeczy do zrobienia w tym miejscu. Na przykład gdy wykryje, że zbliżam się do hipermarketu, to mi pokaże, że trzeba kupić dezodorant, wodę i karmę dla kota.
Nie wiem czy coś takiego istnieje (nie zdziwiłbym się gdyby tak), a także chciałbym, by działało w sposób nieco bardziej skomplikowany, by mogło opierać się o same identyfikatory stacji bazowych sieci GSM, co uniezależniło by od modułu GPS, który posiadam oddzielny (i by mniej energii zużywało przez to).
A wiecie co pomyślałem przed momentem? Że można by to było na iPhone3G napisać...
Nowości
Od wczoraj drga mi lewa powieka. Tak co jakiś czas. Sama z siebie. Cholernie wkurzające.
Jeżeli ktoś powie, że mam za mało magnezu, to właśnie przedwczoraj skończyłem jeść czekoladę, co mi się bardzo rzadko zdarza.
Z innych wieści to ktos.info jest teraz nowe, ładniejsze i w ogóle wspanialsze. A raczej nie tyle ktos.info, co marcin.badurowicz.net, bo to pierwsze teraz na to drugie prowadzi (301 Moved Permanently). Mimo iż miało to wyglądać inaczej (ktos.info tak jak było, marcin.badurowicz.net niesamowicie "profesjonalnie"), to jednak wyszło tak. Niektórzy już widzieli wcześniej (chyba na Twitterze się chwaliłem), teraz mogą odświeżyć CSS by zobaczyć dwa malutkie nowe szczegóły. "Notatki" także mają już nowy wygląd, a ja zastanawiam się nad odświeżeniem wyglądu jogga. Bo ten już ma z rok, co w moim przypadku jest aż dziwne - biorąc pod uwagę, że w ciągu 3 lat blogowania zmieniałem jakieś 9 razy, to już dawno powinno być coś nowego - a tymczasem nie ma od maja :-)
A na dworze zimno i śnieżnie.
Zastanawia mnie tylko jedna rzecz - dlaczego spojrzałem właśnie na zegarek i jest przed pierwszą, a byłem pewien że już musi być koło czwartej?
Dashione
Jak niektórzy wiedzą, od paru dni siedzę nad aplikacyjką internetową, żartobliwie nazywaną Super-Extra-Web2.0-projektem. W rzeczywistości jest to tylko malutka aplikacja zbierająca dane z pewnego serwisu lifestreamingowego dzięki jego API i prezentująca je w określonej, póki co topornej bardzo, formie, przyjaźniejszej jednak dla człowieka niż zwykła lista.
Pierwsza publiczna wersja beta, czyli w mojej nomenklaturze "spring 1" dostępna będzie już wkrótce, być może jutro lub pojutrze jak dobrze pójdzie, po poprawieniu zgłoszeń #0000058, #0000059 i #0000057 (według ważności).
A potem pójdzie, bo mam pomysły na dalszy rozwój, jednak wypada chwilkę z tym zaczekać.
A póki co, skoro już znacie nazwę, to teraz poznacie domenę. Dashione - jest tam piękny placeholder. Mam nadzieję, że nikt się nie doklika tam gdzie nie powinien, bo zobaczy zapewne piękny komunikat błędu, jako że serwis cały czas działa w wersji bardzo debug :-)
IC
Moja drużyna przeszła do kolejnego etapu Imagine Cup 2008. Teraz do 2 kwietnia pracujemy intensywnie ;-)
Gdyby ktoś przypadkiem wiedział jak poszło innym drużynom (zwłaszcza z Lublina), to ja chętnie się dowiem :-)
WIeczorem myślałem
Wczoraj wieczorem nagle, znikąd, wpadłem na pomysł. Pomysł chyba chodził mi po głowie wcześniej, ale wczoraj nagle się ujawniła pełna wizja. Pomysł to oczywiście jakże-wspaniały serwis Web2.0, który nie wygeneruje zysków jak n-k, ale pewnie szybkość działania będzie podobna ;-)
Zasnąć nie mogłem, bo mi się w głowie pojawiał kod, litery, wygląd i wiele tego typu rzeczy.
Dzisiaj rano się obudziłem i rzuciłem zapytanie do Google czy takie coś już istnieje. Jak myślicie? Oczywiście, i do tego o nazwie takiej, jak mój pomysł w jednej z faz nazywania. Jedynie kończy się na łebdwazerowe "dr" zamiast "der" jak wypada, żeby dało się wymówić. Ale pewnie bardziej trendy czy coś.
Na szczęście choć główna idea jest taka sama to ów serwis ma zupełnie inną funkcjonalność (z jednej strony szerszą niż planowałem, z drugiej węższą), więc nadal chyba nad swoim będę pracował.
Spodziewajcie się Web2.0, bety, zaproszeń i czego tam jeszcze nie wymyślono :-)
Nie rozumiem
Od dobrych 10 minut zastanawiam się co mam nie tak. I jak dotąd doszedłem do tego, że po prostu Firefox jest głupi, bo inaczej tego nie mogę wytłumaczyć.
Mam sobie formularz, w którym jest textarea. Chcę, aby nie dało się wpisać więcej znaków niż określoną długość (z pewnymi modyfikacjami). Więc sobie muszę zaprząc do tego JavaScript.
Obecnie mam takie przypisywanie zdarzenia:
addEvent(document.getElementById('comment'), 'keypress', function (e) { return false; });
Gdzie addEvent() to znana funkcja Johna Resiga. Na zdrowy rozsądek to przy czymś takim nie powinno się dać wpisać, każdego znaku, prawda? A może się mylę i gdzieś głęboko wpadłem w dziwne myślenie?
Niemniej IE respektuje zachowanie jakie bym chciał, a Firefox nie.
Podobna sytuacja występuje przy onsubmit formularza.
Krótkie wrażenie
Dzisiaj na spotkaniu mojej Grupy.NET było o ASP.NET. Zawsze, zawsze gdy widzę jakąkolwiek prezentację poświęconą tej technologii to mam podobne wrażenie. Bo w myślach porównuję sobie to do PHP, w którym piszę i piszę i piszę.
Dzisiejsze wrażenie? "O rany, on paroma klikami zrobił to, co w PHP zajęło mi godzinę czasu!". A nawet chyba nie paroma klikami, a jednym przeciągnięciem myszki. Potęga Visual Studio i kontrolek ASP.NET jest naprawdę powalająca.
Aż zbiera we mnie ochota by znów spróbować skonfigurować mod_mono2 na moim serwerze, bo ciągle nie mogę doprowadzić tego do ładu oglądając naprzemiennie błędy 500, 503 i 404. I 403 miejscami.
Oj, ktoś inny popsuł
Dawno temu pisałem, że popsułem pewien serwis randkowo-fotkapeelowy. Dzisiaj znów wiadomość na najpopularniejszy komunikator przyszła z linkiem do niego.
Ale dzisiaj mnie zastanawia tylko jedna rzecz i nad SQL injection nie zastanawiam się. Dlaczego "najatrakcyjniejszą" jest "natala55 - śr. ocen: 11.12", skoro maksymalna ocena profilu to 10? :-D
Skrypciarsko
cat /var/log/maillog | grep "connect from" | grep -v "disconnect" | awk '{print $NF}' | sed "s/.*\[//g" | sed "s/\]//" | grep -v "127.0.0.1" | uniq
Nieoptymalnie i brzydko zapewne, ale działa.
Dalej twierdzę, że sh w żadnej kompatybilnej postaci (po prostu składnia kompatybilna z sh jest okropna!) mi nie podchodzi - więc na przykład świetny zsh odpada. Niestety tak samo tcsh mi nie podchodzi.
Jak widac skladnia if ... jest bardzo intuicyjna (przypomina C).
if ( -f /bin/ps );
then
/bin/ps;echo -n 'wykonalo sie ps' >/dev/tty8
endif
Jak dla mnie to cholernie niepodobna i wcale nie intuicyjna...
The Daily WTF
Okazywać się zaczęło, że po wysłaniu do tworzonej aplikacji tekstu plus tekstu dotyczącego podkategorii w niewytłumaczalny sposób tekst dotyczący podkategorii drugiej lub późniejszej w kolejności ginął, a zastępowany był przez multiplikowany tekst dotyczący pierwszej podkategorii. Niezrozumiałe? Zaraz wyjaśnię.
I jeszcze do tego na moim kodzie własnym takie WTF dostałem... choć sam kod też się chyba do wysiwtf.pl nadawał ;-)
Istniała tablica asocjacyjna podkategorii danej kategorii w której znajduje się obiekt, zawierająca coś takiego:
Array
(
[0] => Array
(
[IDElem] => 3
[Description] => Malowanie
)
[1] => Array
(
[IDElem] => 5
[Description] => Coś jeszcze
)
)
I istniały pola formularza, które tą wartość IDElem zawierały, by można było rozróżnić na temat jakiej podkategorii wysyłamy dane. Żeby poznać numerki tych pól formularza wystarczy przejść po wszystkich elementach tej tablicy, nazwanej u mnie $subs i podostawiać z przodu pewien ciąg (u mnie "content") by poznać, ze wysłane z formularza dane były w polach "content3" i "content5". Jasne mam nadzieję i zrozumiałe ;-) Metoda jest strasznie niby zagmatwana, ale w rzeczywistości bardzo ładnie się miała sprawować. Tak więc, skoro mamy przejść po wszystkich polach tej tablicy $subs, to najbardziej logiczne wydaje się użycie, bardzo przeze mnie lubianej, konstrukcji foreach. Tak też zrobiłem.
foreach ($subs as $sub)
{
$rules['content' . $sub['IDElem']] = 'numeric';
}
Gdzie $rules to tablica używana w procesie walidacji danych. Nic nadzwyczajnego. Teraz pojawia się jednak zagadka. Przed tą pętlą $subs wygląda tak, jak pokazałem wyżej. A po niej? Skrajnie inaczej.
Array
(
[0] => Array
(
[IDElem] => 3
[Description] => Malowanie
)
[1] => Array
(
[IDElem] => 3
[Description] => Malowanie
)
)
"WTF?!" pomyślałem i w mojej głowie nie ma w tym momencie żadnego pomysłu dlaczego tak miało by się dziać. Potem siadłem do prostego skryptu który miał zweryfikować że jest to błąd PHP, a nie mój błąd.
<?php
$subs = array(array('IDElem' => 3, 'Description' => 'Malowanie'), array('IDElem' => 5, 'Description' => 'Cokolwiek'));
print_r($subs);
$foo = array();
foreach ($subs as $sub)
$foo['test' . $sub['IDElem']] = 'bar';
print_r($foo);
print_r($subs);
?>
Pokazuje dane (zaskoczeni?) prawidłowo (see example). Zatem błąd musi leżeć jeszcze gdzieś indziej. Przyjrzałem się mojemu oryginalnemu fragmentowi kodu - były tam wcześniej jeszcze pewne linijki które przez foreach się do $subs odwoływały - i modyfikowały tablicę. Stworzyłem zatem coś przykładowego:
foreach ($subs as &$sub)
{
$sub['baz'] = 'foo' . $sub['IDElem'];
}
Co zostało wstawione w odpowiednie miejsce. Kolejna próba sprawdzenia co jest nie tak... i sukces (live example). Jeżeli można to tak nazwać. Tak więc, czy jest to błąd padło kolejne pytanie - mój PHP w (niezwykle aktualnej) wersji 5.1.4 tak sądził, więc może jest to poprawione w wersji nowszej? Sięgnąłem do PHP 5.2.3 na serwerze... i niestety. Sytuacja analogiczna. Ściągnąłem zatem PHP 5.2.4 prosto z pl.php.net. I magiczne zaklęcie w trybie tekstowym ujawniło... to samo.
Jakieś dwie godziny spędziłem nad tym (wliczając w to naprawienie tego w kodzie produkcyjnym poprzez zastąpienie foreach przez for odpowiedni) i jestem coraz bardziej przekonany, że to jest błąd PHP, a nie mój sposób myślenia.
Jeżeli ktoś jeszcze potwierdzi (przypadki testowe jeden i dwa tutaj), to ja się ucieszę (no, powiedzmy) i rzucę to na bugs.php.net. Może.
Search & Replace
Przed momentem napisałem sobie funkcyjkę, która musi usuwać znak z początku i końca stringa, który jest dodawany przez inną funkcyjkę. A następnie po testach użyłem Search & Replace w moim edytorze i wszystkie wywołania starej funkcji zostały zastąpione przez nową funkcję. Jednak nie wpadłem na to, że wywołanie starej funkcji wewnątrz nowej także zostanie zmienione...
I tak przed momentem byłem świadkiem ciągłych padów Apache, a sam dziwiłem się co u licha się może dziać. Ale jak się ma nie dziać, skoro przepełniałem stos robiąc coś takiego:
private function _mydbescape($str)
{
$str = $this->_mydbescape($str);
return substr($str, 1, strlen($str) -2);
}
Aczkolwiek dlaczego padał Apache, a nie pojawiał się krytyczny błąd PHP albo coś w tym rodzaju?
Nie ma to jak udany chrzest bojowy
E:\Marcin\!Projekty\Urania\Urania\bin\Debug>urania --categorize Artykuły_do_usunięcia --article-list "Z_pogranicza/Dane_z_Delphi-2-Flash|Z_pogranicza/FLASH_MX_-_TINT"
Kategoryzowanie artykułu: Z_pogranicza/Dane_z_Delphi-2-Flash
Zrobione! (śpimy czas wymagany)
Kategoryzowanie artykułu: Z_pogranicza/FLASH_MX_-_TINT
Unhandled Exception: Ktos.Urania.UraniaBotException: Exception: Textarea nie znaleziony w kodzie strony, sprawdź czy nie było błędów logowania
at Ktos.Urania.UraniaBot.getArticle(String articleName, String& articleText, String& articleID) in E:\Marcin\!Projekty\Urania\Urania\Urania.UraniaBot.cs:line 291
at Ktos.Urania.UraniaBot.CategorizeArticle(String articleName, String[] categories) in E:\Marcin\!Projekty\Urania\Urania\Urania.UraniaBot.cs:line 173
at Ktos.Urania.Program.Categorize(String[] categories, String[] articleList) in E:\Marcin\!Projekty\Urania\Urania\Program.cs:line 131
at Ktos.Urania.Program.Main(String[] args) in E:\Marcin\!Projekty\Urania\Urania\Program.cs:line 42
E:\Marcin\!Projekty\Urania\Urania\bin\Debug>
No, prawie się udało. Niemniej dwa artykuły skategoryzował Diabełek.
Code Name "Freya", part 2
Pisałem już o tym, a dzisiaj jestem gotów żeby zaprezentować. Sprzężony z Google Maps API parser plików XML programu WiFiFoFum - Freya.
O co chodzi? Chodzi o to, że jeżdżę sobie po mieście z palmtopem oraz GPS, i notuję (a raczej samo się notuje) gdzie zauważyłem jakąś sieć WiFi nową. A potem takie pliki XML wrzucam tutaj i można sobie to pooglądać na mapie, powered by Google Maps.
Od strony kodu JS, bo to jest główna siła, działa mam nadzieję na Gecko i Operze, powinno pod IE, ale pod IE7 nie działa (pewnie trzeba inaczej tworzyć obiekt do parsowania DOM XML, bo to co jest wygląda na hack do IE6 - ale zmieniać na rozsądną postać mi się nie chce). Oparte o prototype częściowo, dla $() oraz Ajax.Request, jak będę miał czas i chęci aby nauczyć się czegoś nowego to przepiszę na coś lżejszego (pewnie jQuery, skoro Rid tak zachwala). Muszę jeszcze dorzucić coś po stronie serwera, aby samo updejtowało listę plików, bo na razie jak wrzucę nową mapkę (co jakiś czas będę to robił) to muszę edytować plik HTML...
Do zrobienia jest też wyświetlanie daty w jakiejś ludzkiej postaci.
Opinie, błędy (zapewne językowe, bo angielski to nie mój główny język ;-)), komentarze mile widziane.
I jeszcze uwaga osobista - nie lubię JavaScriptu. Strasznie mi nie odpowiada, że nazwy metod i właściwości obiektów zaczynają się małymi literami, bo ja z nawyku zaczynam wielką literą. Choć pewnie daje się przyzwyczaić.
Siła jednolinijkowców
O komputerach miało być mniej, ale coś nie wychodzi. Bo ciągle mnie dopadają z różnych stron. A teraz sposobem na utrudnienie sobie życia zostało porządkowanie katalogu z projektami. Pytanie - w jaki sposób usunąć wszystkie katalogi, ale przedtem zrobić z nich archiwa?
Odpowiedzią okazał się 7-zip oraz PowerShell.
ls | ?{ $_.Attributes -eq "Directory" } | %{$ar = $_.Name + ".zip"; & 7z a -r $ar $_.Name; ri -Force -Recurse $_.Name}
Miałem jeszcze napisać, że mnie CentOS i yum wkurzają, ale nie będę znów narzekał...
Wniosek
Wniosek z rozważań dzisiejszych: PHP 4, jeżeli chodzi o programowanie obiektowo to jest upośledzone strasznie.
Ktoś nie wie kiedy to wymrze?
Logicznie
Heh, pierwszy mój wpis zrobiony pod jeszcze świecącym od nowości "Agni"... Ale do rzeczy.
Kończę projekt, nad którym pracuję od jakiegoś czasu, dodając ostatnie opcje (miejmy nadzieję) i usuwając ostatnie (miejmy nadzieję) błędy. Między innymi to, że autologowanie zrobiłem w tak mądry sposób, że jedynie ustawiało ciasteczko, a potem go nie wykorzystywało. Obecnie mechanizm już chyba działa, w każdym razie pisząc go brakło mi w PHP... logiki trójwartościowej (sic!). Czego? Ano logiki, w której mamy trzy wartości - "prawda", "fałsz" i jakiś trzeci dodatkowy stan.
Oczywiście akurat w PHP (czy nawet chyba większości języków) stworzenie logiki trójwartościowej nie jest problemem, bo typ logiczny można zrzutować na typ liczbowy, a praktyczna beztypowość PHP dała mi możliwość zrobienia funkcji która działa mniej więcej tak:
public function check_cookie_and_login()
{
if (!$this->session->userdata('logged_in'))
{
$cookie_data = get_cookie('nino_remember');
if ($cookie_data != false)
{
// deserializacja i deszyfracja ciasteczka
if (// test pary hash hasła i id)
{
// logowanie
return true;
}
else
{
// błąd
return false;
}
}
else
// błąd odczytu ciasteczka
return false;
}
// trzeci stan oznaczający, że użytkownik jest już zalogowany
return 2;
}
Po co te machinacje? A bo funkcja akurat może zwracać kilka stanów, a aplikacja musi odpowiednio na nie reagować - a że programiści są przyzwyczajeni do logicznych wartości "true" oraz "false" to wystarczy takie zwracać oraz dodać do tego ten dodatkowy, trzeci stan, na przykład liczbą 2 oznaczony.
Pytanie teraz - jak powinienem określić w phpDoc typ zwracanych danych: bool czy int?
Swoją drogą to do testu użyłem nieco przesadzonej wartości, bo autologowanie będzie działać dla użytkownika aż do marca 2011 roku... Nie no, tyle to mu chyba nie damy ;-)
IFilter dla Psi?
Wczoraj, przypadkiem, wpadłem na pomysł, czy do Windows Desktop Search 3.0 nie dało by się jakiegoś pluginu napisać, aby móc przeszukiwać archiwum Psi. Dzisiaj od rana szukałem, szukałem i znalazłem, że trzeba stworzyć taką bibliotekę DLL, co implementuje pewien określony interfejs, IFilter właśnie. Są przykłady w SDK niby... ale w C++.
C++ nie lubię, a wygląd tego przykładowego pluginu mnie przerażał (poza tym sobie nie wyobrażam ręcznego pisania parsowania archiwum Psi w języku, który ledwo znam), więc pomyślałem, ze zapewne w C# da się to też zrobić, łatwiej i ładniej będzie (C# też ledwo znam, ale nieco więcej i wygodniej mi się pisze). Gdzie tam. Napisać tego w kodzie zarządzanym się da, ale przynajmniej się nie powinno tego robić według pewnego forum MSDN, bo cośtam. Jednak po Googlaniu dłuższym doszedłem do pluginu dla WDS napisanego w C# właśnie, i do tego o ładnej licencji, MIT. Jednak po drodze także dowiedziałem się, że wtyczki wyszukiwania nie obsługują więcej niż 1200 bajtów pliku (założenie być może słuszne, ale akurat do archiwum komunikatora to tak nie bardzo), że zrobienie tego w C# to męczarnia, że... i przede wszystkim, że co z tego, że nawet wyszukam w archiwum Psi to co trzeba, skoro i tak nie będę za bardzo miał jak tego użytkownikowi zaprezentować - Psi nie obsługuje otwierania przez inne programy jego okien z jakimiś parametrami, więc musiałbym jeszcze przeglądarkę archiwum napisać. I szczerze mówiąc - odechciało mi się. Nie wiem, może się tym zajmę, ale coraz mniej chętnie mi się to widzi, choć przydatne by z pewnością było.
Blah, blah, blah. Średnio mi się widzi zrobienie tego, albo leń bierze górę, albo potrzebuję przerwy. Od komputera.
Code Name "Freya"
Jakieś 4 godziny spędzone przy JavaScripcie, Google Maps, plikach XML, parserach i takich tam. Tworzę parser plików XML, jakie program WiFiFoFum tworzy, we współpracy z GPS, zawierające dane o znalezionych przez niego sieciach bezprzewodowych.
Najgorsze jest to, że zrobiłem to co chciałem, na chama, ale działa, a teraz się dowiedziałem, że można było zrobić prościej parsowanie XML. Bo to co ja wykorzystuję, to zbrodnia, która powinna być zakazana. Ale działa. Przynajmniej pod Firefoksem.
Blah, nie lubię JavaScriptu.
Xcode
Łącząc potężne narzędzia UNIX-a, przyjazny dla użytkownika system Mac OS X i zestaw wysokowydajnych technologii programowania, Xcode jest dla developerów Mac OS X Tiger najszybszym sposobem tworzenia aplikacji Mac OS X przy użyciu łatwego interfejsu użytkownika oraz wykorzystaniu zalet nowych technologii Apple. Dzięki modelowi kompilatora opracowanego przez Apple we współpracy z IBM, Xcode używa GCC 4.0 do optymalizowania kodu dla architektury procesora Apple - PowerPC G5.
A ja głupi myślałem, że Apple przeszedł na Intela, a tu się okazuje że procesorem Apple jest PowerPC G5. Materiałów reklamowych zapomnieli zmienić? :-)
A z innej beczki - powie mi ktoś jak Xcode ma się do innych IDE w rodzaju Visual Studio, Delphi czy Eclipse? Ciekawy jestem.
Asm
Napisałem dziś pierwszy w życiu program w assemblerze. Dla 8051 akurat, bo takie coś teraz laboratoriujemy, jest niezmiernie zaawansowany i jest rozwinięciem tego, co zrobić na laboratorium powinienem.
Program piskami symuluje takie coś w szpitalu, wiecie, robi tak [pip] [pip] [pip] szybko i ciągłe [piiiiii] jak pacjent umarł :-)
; Symulacja umierania :-)
ACT EQU P1.5 ; 1.5 - będziemy pipczeć
LJMP START
ORG 100H
START:
CLR ACT ; pipczemy albo świecimy
MOV R0,#18 ; ilość powtórzeń pętli
LOOP:
MOV A,#1 ; ustawianie czasu trwania pauzy
LCALL DELAY_100MS ; pauza
CPL ACT ; wyłączamy
DJNZ R0,LOOP ; pętla
CLR ACT ; ciągły pisk (umarł! :-))
LJMP $ ; i zapętlamy się!
Notabene to DJNZ i rejestrów poza akumulatorem to ja nie powinienem umieć ;-)
Do zapamiętania
bash standardowo sobie z liczbami zmiennoprzecinkowymi nie radzi, potrzeba mu bc. A potem działają już takie rzeczy jak przykładowo:
[ktos@avril ~]$ echo 20/19 | bc -l
1.05263157894736842105
Zbyt restrykcyjny
No chciałem przetestować możliwości podobno najlepszej (najlepszej polskiej? nie jestem teraz pewien) napisanej w PHP księgi gości. Po ściągnięciu obejrzałem sobie trochę kodu, załamałem się (ale jednocześnie jestem pełen podziwu - trudno jest napisać tak skomplikowany kod i cokolwiek z nim robić bez komentarzy i wcięć - niektórzy lubią sobie życie utrudniać) i nadszedł czas na pierwsze uruchomienie. I co ujrzałem u siebie na lokalnym serwerze? Ano pustą stronę.
CJK? zabrzmiało w myśli i sięgnąłem do opcji "Pokaż źródło". I zrozumiałem natychmiast gdy zobaczyłem kod.
<?
// [ciach, nazwy ujawniać nie będziemy]
include("kgengine/kg.php");
?>
Short open tags. Kiedyś już na nie narzekałem przy innym darmowym skrypcie, tylko że tamten był przedhistoryczny, a ten jest z zeszłego miesiąca.
Zaczynam coraz bardziej przekonywać się, że mam zbyt nowoczesny lokalny serwer, PHP i konfigurację PHP zbyt ostrą dla popularnych skryptów. No, ale chociaż MySQL mam stare, bo 4.1...
Pomysł głupi jak zawsze
Fuck, miałem napisany wpis, przypadkiem klikłem nie to co trzeba, i się skasowało. Niemniej jednak miało być znów o horoskopach. Tym razem trafiłem na jakiś miesięczny, gdzie "Sekstyl Neptuna zapowiada powodzenie w miłości.". I mam wrażenie, że w zeszłym miesiącu też było coś takiego. NIe pamiętam czy akurat sekstyl Neptuna, ale powodzenie w miłości na pewno...
Samotne Strzelce nawiążą w tym miesiącu wiele ciekawych znajomości, które mogą potrwać dłużej, niż wszyscy będą się spodziewać. Szczęście w miłości sprzyjać ci będzie w środkach komunikacji miejskiej, podczas robienia zakupów czy na wykładach lub kursach. Rozejrzyj się dookoła, może w sąsiedztwie przybył właśnie ktoś interesujący i samotny?
Zaznaczony fragment czytelny jest tylko dla niektórych, którzy kojarzą moje dziwne znajomości. Ale mniejsza o niego.
Chodzi o to, że jakiś czas temu założyłem, że gdy będę się musiał uczyć z okazji sesji, to jak zwykle zajmę się czymś głupim. Tym razem - napiszę "Generator Horoskopów" :-). Potem będzie go można sprzedać jakiejś gazecie w rodzaju "Pani domu", taniej im to wyjdzie niż umowa z jakimiś astrologami. Skąd taki idiotyczny pomysł? Rano, czytając bezpłatne "Metro" ja i kolega porównujemy swoje horoskopy. I co jakiś czas albo pisze to samo, albo się powtarzają całe frazy... Jak nic generator się psuje ;-) Więc, dlaczego by nie napisać własnego?
Zapamiętać
Programowanie czegokolwiek bez znajomości danego języka i posługiwanie się dwoma skryptami przykładowymi i własną intuicją bez znajomości biblioteki klas czy czegokolwiek takiego jest głupie, denne i zabiera stanowczo za dużo czasu.
Ale zrobiłem to co chciałem, naokoło strasznie, nieoptymalnie aż się serce kraja, ale działało. Gorzej, że, żeby to komuś pokazać to ja muszę przepisać to do jakiejś rozsądnej i zoptymalizowanej postaci. A mi się średnio chce.
Jednak nie można się poddawać.
Publikowanie w Visual Studio
Tworząc pewną niezwykle zaawansowaną aplikację (zapisuje do pliku określoną ilość losowych danych) przypadkiem pobawiłem się funkcjami publikowania projektów, jakimi dysponuje Visual Studio. I w sumie, to ja jestem bardzo pozytywnie nastawiony. Małe pliki, manifesty nazwijmy to, które umożliwiają zaprogramowanie albo tego, by aplikacja pobierana była z serwera, albo instalowana, zapewniają łatwe możliwości upgrade, deinstalacji... Bez tworzenia jakiś własnych instalatorów, bez konieczności męczenia się z zależnościami, jakie w C# są potrzebne - np. .NET Framework 2.0 czy SQL Server 2005 (można nakazać zassanie ich z serwera Microsoftu, bądź z określonej lokalizacji)... czysta wygoda dla programisty. W sumie to przypomina mi w pewnym stopniu takiego menedżera pakietów - klikam, a program mi się instaluje, dodaje do Menu Start, łatwo się to aktualizuje, łatwo usuwa. Żeby tak wszystko miało takie instalatory :-)
Choć akurat moje full-wypas aplikacja będzie rozpowszechniana jako jeden plik .exe, bo w końcu ma 20 KB, działa w konsoli i z pewnością instalator jej potrzebny zbytnio nie jest...
CAPTCHA: Rewolucja
Zawsze gdy mamy przerwę, to nasze dyskusje prowadzą do wymyślenia bardzo dziwnych, niekonwencjonalnych rozwiązań technicznych. Dziś jednak, po kolokwium z architektury komputerów, wynaleźliśmy CAPTCHA nowego typu. Rozwiązanie idealne, w kilku specyficznych sytuacjach zwłaszcza.
"Przepisz kod z obrazka" jest za proste dla automatów? A co powiecie na "rozwiąż całkę z obrazka"? :-D
short_open_tag
Chciałem zainstalować pewien skrypt. Tylko po to, aby się przyjrzeć pewnym funkcjonalnościom jakie powinny mieć systemy aukcyjne. Najlepszy do takich jest podobno phpAucton. Normalnie to to płatne jest. Ale na SF.net jest jakaś wersja dostępna. Po skopiowaniu plików ujrzałem piękny obraz.
WTF? Dlaczego kod PHP się nie wykonuje. Przejrzenie kodu, nic nadzwyczajnego. Patrzę znowu. a tam to okropieństwo w postaci <?. No tak. U mnie w php.ini krótkie tagi otwierające są wyłączone. Bo ja ich używam w prologu XML, więc lepiej by było, gdyby PHP mi nie parsował tego. A tutaj cały skrypt napisany w oparciu o krótkie tagi otwierające... Mówimy stanowcze nie i piszemy długą wersję, tak jak trzeba! Ale z tego co widzę to data plików to 2002 rok. Chyba mogę wybaczyć.
A jakość kodu też porażająca. Lepsze niż pewien inny skrypt jaki dziś widziałem, w którym niektóre momenty przypominały mi mój własny kod, też napisany w okolicach 2002-2003 roku. Kod, do którego się nie przyznaję teraz ;-)
To ja teraz coś napiszę, co mi <? na normalne <?php zamieni w tych pliczkach...