Używałem już Windowsa, używałem przez wiele lat Linuksa. Od ponad roku mam okazję pracować na co dzień na Macu – i nie wrócę już ani do Linuksa (którego bardzo sobie chwaliłem), ani do Windowsa (którego chwaliłem sobie znacznie mniej :) ). Mac to dla mnie świetne połączenie obydwóch wspomnianych na początku systemów: prostoty obsługi Windowsa, i mocy i funkcjonalności Linuksa. Tyle tytułem wstępu :)

Postanowiłem sobie zrobić małą listę programów na Maca (czasem nie tylko), bez których nie wyobrażam sobie pracy – lub które mi ją po prostu uprzyjemniają :) a jednocześnie spowodować aby coś się w końcu na tym blogu pojawiło ;)

Przejdź do reszty tego wpisu »


Jakiś czas temu chciałem pobawić się Blip!em za pomocą Pythona. Ot, mam w planach zrobienie sobie coś a’la Sekretarka (która oddaje nieocenione usługi – dzięki ^TomaszTopa :) ), tyle żeby wysyłał codziennie lisię prywatnych i kierowanych do mnie statusów na maila. Prosta dość sprawa, trzeba tylko do tego zasiąść ;) Ale nadszedł ten dzień, i się zmusiłem. Jako, że wiedziałem że do Blip!a istnieją aż dwie biblioteki napisane w Pythonie (lista różnych aplikacji znajduje się na Blip!owym wiki), to po prostu uznałem że skorzystam z którejś z nich… Ech, za dobrze by było. Żadna z nich nie jest na tyle kompletnym rozwiązaniem, żeby jej w normalnych warunkach użyć. Oczywiście nie mam pretensji do ich autorów – stworzyli narzędzie którego potrzebowali, i podzielili się nim ze światem, czyli jest OK :)

Jednak to spowodowało na razie zarzucenie moich planów o Pythonowej Emailowej Sekretarce ™ ;) Owszem, również mógłbym napisać w sumie dwa polecenie do pobierania statusów kierowanych i prywatnych (directed_messages i private_messages) ale ja lubię kompleksowe rozwiązania – tak samo jak dla WP-Blip!a napisałem BlipApi.php :)

Jest w tej chwili jeden drobny błąd (zauważony przez ^mrkjego blog, dzięki :) ) związany z tym, że podczas testowania siedziałem w folderze gdzie są wszystkie pliki bilbioteki, i tak jakoś było łatwiej… no i w tej chwili nie działa to poprawnie jako osobny moduł Pythona tylko jak luźne pliki które gdzieś w PYTHONPATH trzeba umieścić ;) Błąd ten, jako że zaczynam dochodzić do się, niedługo postaram się naprawić oczywiście, być może zgłoszę też bibliotekę do Python Package Index. A na razie zapraszam do pobierania: blipapi.googlecode.com, używania i zgłaszania problemów i/lub nowych featur :)


Dawno tu nie pisałem… No cóż, (bardzo) dużo pracy, życie osobiste i takie tam – to odstrasza od blogowania ;) Jeśli już, to od czasu do czasu coś publikuję jeśli chodzi o zdjęcia, a sprawy “kodowe” to raczej “robię” niż o nich piszę :)

Jako że od kilka dni jestem na L4, to się ostro opierdzielam, ale dopiero dziś jestem w stanie podjąć jakikolwiek intelektualny wysiłek… No to popatrzyłem sobie m.in. na GoldenLine. Dziś na forum PHPowym ktoś poruszył dość banalny problem, ktoś inny podrzucił rozwiązanie (preg_replace_callback (), a ja zacząłem się zastanawiać czemu wszyscy w PHP tak napierają na regexpy (rozumiem w Perlu, ale PHP?). Jak zacząłem się zastanawiać jak to zrobić bez regexpów, to zacząłem się bawić w zakodowanie tego ;)

Najpierw zrobiłem dość banalną wersję, przy użyciu strlen (), strpos () i substr (), i chciałem ją podać jako wersję hardcore ;) Wtedy pomyślałem sobie, że prawdziwa wersja hardcore, to byłaby bez użycia tychże funkcji… najprostsza postać tego to zastąpienie tychże funkcji swoimi ;) I o ile substr () i strpos () są dość banalne, o tyle dla mnie prawdziwym hardcorem jest strlen () ;)

Oczywiście nie są to najbardziej optymalne wydajne rozwiązania (a jeśli są to tylko przypadkiem), bo jeśli chodzi o optymalizację, to trzeba by używać wersji natywnych to trzeba by się najpierw zastanowić i sprawdzić czy jest co optymalizować… :) A całość warto potraktować stricte jako zabawę, którą dla mnie było pisanie tego :)

W całym “problemie” chodziło o zastąpienie w tekście wystąpień “[userId]ID[/userId]” tym, co zostanie wyplute przez dodatkową funkcję której podajemy zawartość tego co jest między znacznikami. Użycie preg_replace_callback () jest chyba najbardziej intuicyjnym rozwiązaniem, ale nie jedynym… :) Poniżej obydwie wersje: hardcore i bardziej hardcore – enjoy ;)

hardcore

function replace_user_id ($str, $fn) {
    $tags = array ('start' => '[userId]', 'end' => '[/userId]');
    $tag_len = array (
        'start' => strlen ($tags['start']),
        'end'   => strlen ($tags['end'])
    );
    $offset = $pos_end = 0;
    $ret    = '';
    $strlen = strlen ($str);

    while ($pos_end < $strlen) {
        if (
            ($pos_start = strpos ($str, $tags['start'], $pos_end)) !== false &&
            ($pos_end   = strpos ($str, $tags['end'], $pos_start)) !== false
        ) {
            $ret .= substr ($str, $offset, $pos_start - $offset);
            $pos_start += $tag_len['start'];

            $ret .= $fn (substr ($str, $pos_start, $pos_end - $pos_start));

            $pos_end += $tag_len['end'];
            $offset = $pos_end;
        }
        else {
            break;
        }
    }

    return $ret;
}

bardziej hardcore

class __mstrlen__ErrH {
    private static $error = false;
    private function __construct () {}
    static public function errh ($errno, $errstr, $errfile = '', $errline = 0, $errctx = array ()) {
        if ($errno != E_NOTICE) {
            return false;
        }

        $expected = 'Uninitialized string offset';
        for ($i=0; $i<26; ++$i) {
            if ($expected[$i] != $errstr[$i]) {
                return false;
            }
        }

        self::$error = true;
    }
    public static function isError () {
        return self::$error;
    }
    public static function zero () {
        self::$error = false;
    }
}

function mstrlen ($str) {
    $str = (string) $str;

    $len = -1;
    __mstrlen__ErrH::zero ();
    set_error_handler (array ('__mstrlen__ErrH', 'errh'), E_NOTICE);
    while (__mstrlen__ErrH::isError () === false) {
        ++$len;
        $q = $str[$len];
    }

    restore_error_handler ();
    return $len < 0 ? 0 : $len;
}

function mstrpos ($str, $seek, $offset=0) {
    if (!is_int ($offset) || $offset < 0) {
        $offset = 0;
    }

    $str_len = mstrlen ($str);
    if ($offset > $str_len) {
        return false;
    }

    $seek_len = mstrlen ($seek);
    for ($i=$offset; $i < $str_len; ++$i) {
        for ($j=0; $j < $seek_len; ++$j) {
            if ($str[$i + $j] != $seek[$j]) {
                break;
            }
        }

        if ($j == $seek_len) {
            return $i;
        }
    }
    return false;
}

function msubstr ($str, $start, $length = null) {
    $str_len = mstrlen ($str);
    if (!is_int ($start)) {
        trigger_error ('Incorrect offset');
    }
    else if ($start >= $str_len) {
        return false;
    }
    else if ($start < 0) {
        $start = $str_len + $start;
    }

    if (!is_int ($length)) {
        $length = $str_len - $start;
    }
    else if ($length < 0) {
        $length = $str_len + $length - $start;
    }
    else if ($length + $start > $str_len) {
        $length = $str_len - $start;
    }

    $ret = '';
    for ($i=0; $i < $length; ++$i) {
        $ret .= $str[$i + $start];
    }

    return $ret;
}

function replace_user_id2 ($str, $fn) {
    $tags = array ('start' => '[userId]', 'end' => '[/userId]');
    $tag_len = array (
        'start' => mstrlen ($tags['start']),
        'end'   => mstrlen ($tags['end'])
    );
    $offset = $pos_end = 0;
    $ret    = '';
    $strlen = mstrlen ($str);

    while ($pos_end < $strlen) {
        if (
            ($pos_start = mstrpos ($str, $tags['start'], $pos_end)) !== false &&
            ($pos_end   = mstrpos ($str, $tags['end'], $pos_start)) !== false
        ) {
            $ret .= msubstr ($str, $offset, $pos_start - $offset);
            $pos_start += $tag_len['start'];

            $ret .= $fn (msubstr ($str, $pos_start, $pos_end - $pos_start));

            $pos_end += $tag_len['end'];
            $offset = $pos_end;
        }
        else {
            break;
        }
    }

    return $ret;
}

wwwshell.php to skrypt napisany w php, pozwalający obejść część ograniczeń związanych z brakiem shella na hostingu. Jako że w home.pl takowego nie ma, musiałem jakiś czas temu ratować się takim wynalazkiem ;)

Założeniem które przyświecało od początku jego istnienia była kompaktowość (wszystko w jednym pliku), używalność, wygoda. Wydaje mi się że jak na razie spełnia wszystkie wymienione ;) Ograniczeniami są PHP >= 4.3.0 i nie zablokowane wykonywanie funkcji proc_open () i proc_close ().

Zalety (z mojego punku widzenia ;) ):

  • wszystko w jednym pliku (biblioteki jQuery pobierane są bezpośrednio z serwera jQuery.com
  • obsługa aliasów
  • prostota użytkowania
  • historia poleceń

Wady:

  • no cóż, to jednak nie prawdziwy shell…
  • brak uzupełniania
  • uprzyjemniacze typu historia wymagają połączenia z netem lub modyfikacji skryptu i używania lokalnych kopii bibioteki jQuery

Znane błędy:

  • nie zapamiętuje ustawionego rozmiaru czcionki w okienku wyjścia
  • czasem z jakiegoś powodu historia nie działa, trzeba np. otworzyć okienko konsoli w ff i je zamknąć, wtedy jest ok :/

Nie sprawdzałem też (ani nawet nie zamierzam jak na razie) sprawdzać jak wygląda i działa pod IE. Może się coś sypać :)

Jeśli ktoś jest zainteresowany tą zabawką, to zapraszam do pobierania na GoogleCode, i komentowania/krytykowania pod tą notką ;)


Mały bugfix release (zgłoszony przez WPNinja): W przypadku gdy nie można zapisać pliku z cache do katalogu ustawionego jako zmienna $wp_blip_cacheroot, próbuje zapisać do systemowego katalogu tymczasowego (o ile się uda takowy znaleźć). Gdy także i ta operacja się nie powiedzie, zostanie rzucony E_USER_NOTICE z informacją o problemie, a wtyczka po prostu nie będzie korzystała z funkcji cacheowania wpisów.

Do pobrania z GoogleCode. Jak zawsze proszę o informacje i uwagi nt działania wtyczki, a także ucieszyłbym się z informacji że ktoś gdzieś moich wypocin używa :)


Mały update do SBLAM! Blacklist Update: jako że czasem (jak obecnie) pojawiają się błędy w generowanej black liście, do naszego .htaccess dodawane są tylko poprawne linie zawierające adres IP, oraz komentarze. Wszystko inne jest ignorowane, i nie spowoduje problemu w działaniu naszego serwisu :)

Skrypt jak ciągle dostępny do pobrania z adresu: urzenia.net/wp-content/sblam_blacklist_update.txt.

Podziękowania dla Elusia za zwrócenie uwagi :)


Kolejna odsłona WP-Blip!a :) Tym razem jeden bugfix (no, powiedzmy że fix), i jedna zmiana:

  • możliwość formatowania daty dodania statusu (via komentarz Julka)
  • naprawione linkowanie tagów i userów – teraz łapie poprawnie polskie znaczki. Może nie do końca poprawnie działać jeśli kodowanie znaków jest inne niż UTF-8, proszę wtedy dać znać, mam wrażenie że coś źle przemyślałem ;)

Standardowo proszę o komentarze pod tym wpisem, lub na email :) A nowa wersja pluginu jest do pobrania na Google Code.

UPDATE:

Już nowa wersja – 0.3.1 ;)

  • fix: pliterki w tagach teraz działają lepiej
  • fix: myślnik w tagach też działa lepiej
  • add: linki we wpisach są obejmowana tagiem <a />

Do pobrania tradycyjnie na GoogleCode.


Nowa wersja plugina do WordPressa pokazującego statusy z Blip!a. Zmiany:

  • update BlipApi.php do nowej wersji
  • linkowanie tagów i użytkowników
  • dodanie pliku README z podstawową dokumentacją

Zainteresowanych zapraszam ściągania i aktualizowania :)


Strona 1 z 15