<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="pl"><title>nme.pl</title><link href="http://nme.pl" rel="alternate" /><id>http://nme.pl</id><updated>2012-02-23T07:00:50Z</updated><subtitle>nme.pl</subtitle><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/nmepl" /><feedburner:info uri="nmepl" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry><title>Telewizja Uniwersytetu Śląskiego</title><link href="http://feedproxy.google.com/~r/nmepl/~3/bJyqWu1zWoE/telewizja-uniwersytetu-slaskiego" rel="alternate" /><id>http://nme.pl/2012/02/telewizja-uniwersytetu-slaskiego</id><summary type="html">&lt;a href="http://telewizja.us.edu.pl" title="Telewizja Uniwersytetu Śląskiego"&gt;&lt;img src="/img/2012/02/telewizja-us.png" alt="" class="post-image" /&gt;&lt;/a&gt;

&lt;p&gt;W połowie roku 2011 na Uniwersytecie Śląskim w Katowicach zrodził się pomysł aby utworzyć własną telewizję internetową. Na jego czele stanął były redaktor naczelny studenckiego &lt;a href="http://egida.us.edu.pl"&gt;radia Egida&lt;/a&gt;. Trzy miesiące później naczelnemu udało się skompletować sprzęt potrzebny do rozkręcenia całego przedsięwzięcia, a w międzyczasie, ja stworzyłem dla nich całą platformę oraz aplikację webową (strumieniowanie w oparciu o open-source, silnik aplikacji webowej w Django).&lt;/p&gt;

&lt;p&gt;Telewizja wystartowała na początku października i działa całkiem prężnie. Codziennie pojawiają się nowe materiały, a na Facebooku przybywają fani. Rosnący zespół nawiązuje współpracę z innymi jednostkami, m.in. &lt;a href="http://cko.us.edu.pl"&gt;Centrum Kształcenia na Odległość&lt;/a&gt; Uniwersytetu Śląskiego.&lt;/p&gt;

&lt;p&gt;Ostatnio nieco ich zaniedbywałem, skupiając się jedynie na krytycznych poprawkach i absolutnie koniecznych usprawnieniach, ale jako, że serwis funkcjonuje całkiem sprawnie podjęliśmy decyzję o dalszej rozbudowie. Oto jedna z nich - umożliwienie osadzania bloku polecanych materiałów w innych serwisach :) Oto przykład:&lt;/p&gt;

&lt;div style="width:650px;margin:0 auto"&gt;&lt;iframe width="650" height="440" src="http://telewizja.us.edu.pl/embed/polecane-materialy?rows=2" frameborder="0"&gt;&lt;/iframe&gt;&lt;/div&gt;

&lt;p&gt;Kto wie, może niebawem zabiorę się za optymalizację podglądu ;)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/bJyqWu1zWoE" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2012/02/telewizja-uniwersytetu-slaskiego</feedburner:origLink></entry><entry><title>WebSockety z fallbackiem do Flasha</title><link href="http://feedproxy.google.com/~r/nmepl/~3/SysfeskFuVA/websockety-z-fallbackiem-do-flasha" rel="alternate" /><id>http://nme.pl/2011/07/websockety-z-fallbackiem-do-flasha</id><summary type="html">&lt;p&gt;Kilka dni temu kolega śledząc moje &lt;a href="/2011/07/twisted-django-i-websockety-demo"&gt;eksperymenty z WebSocketami&lt;/a&gt; wspomniał o tym, że jako fallback dla przeglądarek nie wspierających natywnie WebSocketów można wykorzystać Flasha. Faktycznie - jak się okazało miałem nawet lokalnie sklonowane potrzebne &lt;a href="http://github.com/gimite/web-socket-js"&gt;repozytorium&lt;/a&gt;. Przez ten cały czas wgłębiania się w temat - zupełnie o nim zapomniałem. Efekty pracy autora zaskoczyły mnie bardzo pozytywnie.&lt;/p&gt;

&lt;h4&gt;Szczegóły&lt;/h4&gt;

&lt;p&gt;Aplikacja jest obecnie zgodna z &lt;a href="http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-16"&gt;Hybi-16&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Testowałem rozszerzone o Flashowy fallback demo opisane w poprzednim wpisie - nowa wersja dostępna jest &lt;a href="/example/ws-simplest-flash/"&gt;tutaj&lt;/a&gt;. Wykonywałem testy zarówno dla &lt;code&gt;ws://&lt;/code&gt; jak i &lt;code&gt;wss://&lt;/code&gt; (TLS). Zarówno serwerowa implementacja, jak i &lt;code&gt;web-socket-js&lt;/code&gt; pracują w oparciu o wersję protokołu WebSocket &lt;a href="http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76"&gt;hixie-76&lt;/a&gt;. Fallback wymaga Adobe Flash 10+.&lt;/p&gt;

&lt;h4&gt;&lt;a href="#lista-kompatybilnosci"&gt;Wyniki przeprowadzonych testów&lt;/a&gt;&lt;/h4&gt;

&lt;table id="lista-kompatybilnosci" class="results"&gt;
&lt;tr style="font-weight:bold"&gt;&lt;th&gt;System&lt;/th&gt;&lt;th style="width:100%"&gt;Przeglądarka&lt;/th&gt;&lt;th&gt;WebSocket&lt;/th&gt;&lt;th&gt;Flash WebSocket&lt;/th&gt;&lt;/tr&gt;
&lt;tr style="background-color:#efe"&gt;&lt;td&gt;OS X Lion&lt;/td&gt;&lt;td&gt;Safari 5.1&lt;/td&gt;&lt;td style="color:#080"&gt;działa&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;/tr&gt;
&lt;tr style="background-color:#efe"&gt;&lt;td&gt;Ubuntu 11.04&lt;/td&gt;&lt;td&gt;Chrome / Chromium 12, 13, 14, 15, &lt;b&gt;16&lt;/b&gt;&lt;/td&gt;&lt;td style="color:#080"&gt;działa&lt;/td&gt;&lt;td&gt;-&lt;/td&gt;&lt;/tr&gt;
&lt;tr style="background-color:#efe"&gt;&lt;td&gt;Debian 6.0&lt;/td&gt;&lt;td&gt;Firefox / Iceweasel 9&lt;/td&gt;&lt;td style="color:#080"&gt;działa&lt;/td&gt;&lt;td style="color:#080"&gt;-&lt;/td&gt;&lt;/tr&gt;
&lt;tr style="background-color:#f6fff6"&gt;&lt;td&gt;Ubuntu 11.04&lt;/td&gt;&lt;td&gt;Firefox 5, 6 &lt;b&gt;*&lt;/b&gt;&lt;/td&gt;&lt;td style="color:#800"&gt;nie działa&lt;/td&gt;&lt;td style="color:#080"&gt;działa&lt;/td&gt;&lt;/tr&gt;
&lt;tr style="background-color:#f6fff6"&gt;&lt;td&gt;Ubuntu 11.04&lt;/td&gt;&lt;td&gt;Opera 11.50&lt;/td&gt;&lt;td style="color:#800"&gt;nie działa&lt;/td&gt;&lt;td style="color:#080"&gt;działa&lt;/td&gt;&lt;/tr&gt;
&lt;tr style="background-color:#f6fff6"&gt;&lt;td&gt;Windows XP, SP3&lt;/td&gt;&lt;td&gt;Internet Explorer 8&lt;/td&gt;&lt;td style="color:#800"&gt;nie działa&lt;/td&gt;&lt;td style="color:#080"&gt;działa&lt;/td&gt;&lt;/tr&gt;
&lt;tr style="background-color:#f6fff6"&gt;&lt;td&gt;Windows XP, SP2&lt;/td&gt;&lt;td&gt;Internet Explorer 7&lt;/td&gt;&lt;td style="color:#800"&gt;nie działa&lt;/td&gt;&lt;td style="color:#080"&gt;działa&lt;/td&gt;&lt;/tr&gt;
&lt;tr style="background-color:#f6fff6"&gt;&lt;td&gt;Windows XP, SP1&lt;/td&gt;&lt;td&gt;Internet Explorer 6&lt;/td&gt;&lt;td style="color:#800"&gt;nie działa&lt;/td&gt;&lt;td style="color:#080"&gt;działa&lt;/td&gt;&lt;/tr&gt;
&lt;tr style="background-color:#f6fff6"&gt;&lt;td&gt;Android 2.3.3&lt;/td&gt;&lt;td&gt;Internet&lt;/td&gt;&lt;td style="color:#800"&gt;nie działa&lt;/td&gt;&lt;td style="color:#080"&gt;działa&lt;/td&gt;&lt;/tr&gt;
&lt;tr style="background-color:#fff6f6"&gt;&lt;td&gt;Android 2.3.3&lt;/td&gt;&lt;td&gt;Dolphin Browser HD 6.0&lt;/td&gt;&lt;td style="color:#800"&gt;nie działa&lt;/td&gt;&lt;td style="color:#800"&gt;nie działa&lt;/td&gt;&lt;/tr&gt;
&lt;tr style="background-color:#fff6f6"&gt;&lt;td&gt;Android 2.3.3&lt;/td&gt;&lt;td&gt;Opera Mobile 11.1&lt;/td&gt;&lt;td style="color:#800"&gt;nie działa&lt;/td&gt;&lt;td style="color:#800"&gt;nie działa&lt;/td&gt;&lt;/tr&gt;
&lt;tr style="background-color:#fff6f6"&gt;&lt;td&gt;Android 2.3.3&lt;/td&gt;&lt;td&gt;Firefox for Android 6.0&lt;/td&gt;&lt;td style="color:#800"&gt;nie działa&lt;/td&gt;&lt;td style="color:#800"&gt;nie działa&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;p class="results-notes"&gt;* Firefox 6 wspiera nieaktualną wersję protokołu - &lt;a href="http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-07"&gt;Hybi-07&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;Notatki&lt;/h4&gt;

&lt;p&gt;Firefox 6 wspiera WebSockety, ale w wersji protokołu &lt;a href="http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-07"&gt;Hybi-07&lt;/a&gt;, a obiekt nazywa się tam &lt;code&gt;MozWebSocket&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Internet Explorer 8 ma wbudowanego Flasha - rozwiązanie działa bez instalacji Flash Playera.&lt;/p&gt;

&lt;p&gt;Firefox, Dolphin i Opera na Androida - z drugiej strony - nawet pomimo instalacji wtyczki - nie obsługują Flasha. Szczerze powiedziawszy to nie wiem dla kogo ten problem jest większy - dla mnie, czy dla zespołów rozwijających te przeglądarki...&lt;/p&gt;

&lt;p&gt;Z tego co wyczytałem Internet Explorer w wersji 6 może nie działać. Ale jak się okazuje - działa (być może dlatego, że pracujemy na domyślnym porcie - 80). Aktywność projektu &lt;code&gt;web-socket-js&lt;/code&gt; jest zadowalająca - kilka problemów jest rozwiązywanych, np. Opera &lt;a href="https://github.com/gimite/web-socket-js/issues/53"&gt;nie specjalnie radzi sobie&lt;/a&gt; z połączeniami nawiązanymi przez dłuższy czas.&lt;/p&gt;

&lt;p&gt;Osobiście bardzo cieszy mnie fakt, że łącznie z domyślnym Androidowym Browserem - we wszystkich ważnych przeglądarkach - WebSockety działają! :)&lt;/p&gt;

&lt;p&gt;Wspomnę na koniec, że &lt;code&gt;web-socket-js&lt;/code&gt; ma już gotowy branch dostosowany pod nowszy draft - wersję protokołu &lt;a href="http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-07"&gt;hybi-07&lt;/a&gt; - stanie się on domyślnym kiedy Chrome przejdzie na nowszą wersję.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/SysfeskFuVA" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2011/07/websockety-z-fallbackiem-do-flasha</feedburner:origLink></entry><entry><title>Twisted, Django i Websockety - demo</title><link href="http://feedproxy.google.com/~r/nmepl/~3/cAKs0HVv3W8/twisted-django-i-websockety-demo" rel="alternate" /><id>http://nme.pl/2011/07/twisted-django-i-websockety-demo</id><summary type="html">&lt;p&gt;W poprzednim wpisie przedstawiłem &lt;a href="/2011/07/server-side-pod-websockety"&gt;architekturę server-side&lt;/a&gt; której obecnie używam oraz obiecałem zaprezentować przykładową aplikację Twisted która jej używa i jednocześnie:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;komunikuje się z klientem z użyciem WebSocketów&lt;/li&gt;
&lt;li&gt;łączy się do bazy za pośrednictwem &lt;code&gt;Django ORM&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Proste demo dostępne jest &lt;a href="http://nme.pl/example/ws-simplest/"&gt;tutaj&lt;/a&gt; (zgodne z &lt;a href="http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76"&gt;hixie-76&lt;/a&gt; oraz &lt;a href="http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10"&gt;hybi-10&lt;/a&gt;). Polecam otworzenie go w przeglądarce Google Chrome oraz jednocześnie - w oknie incognito - aby przetestować komunikację między nimi.&lt;/p&gt;

&lt;p&gt;Kod aplikacji Twisted wygląda następująco:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from twisted.application import service
from worker import Client, WorkerService, Django
import sys,setproctitle

class testclient (Client):
    def onOpen (self,reconnect=False):
        if reconnect:
            print 'Client '+self.ident+' reconnected'
        else:
            print 'Client '+self.ident+' connected'
    def onClose (self):
        print 'Client '+self.ident+' disconnected'
    def onRecv (self, ident, mesg):
        if mesg == 'die':
            # send message to self
            self.send ('ok')
            # and die
            self.kill()
        elif mesg == 'hello':
            # send message to everyone including self
            self.broadcast ('hi')
        elif mesg == 'whoami':
            if self.user:
                self.send (self.user)
            else:
                self.send ('dunno')
        else:
            # send message to everyone else
            self.unicast (mesg)

class demoapp (WorkerService):
    def onStart(self):
        print 'app has been started'
    def onStop(self):
        print 'app is being stopped'
    def onTimer(self):
        print '5 secs has been gone'

# setup
appname = 'demoapp.py'
Django.setdsm ('/srv/venv/blog')
application = service.Application (appname)
setproctitle.setproctitle (appname)
demoapp (testclient,terminate=False,onTimer=5).setServiceParent (application)
&lt;/pre&gt;

&lt;h4&gt;Kilka słów komentarza&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;from worker import Client, WorkerService, Django&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;worker&lt;/code&gt; to moja biblioteka dla aplikacji klienckich całej przedstawionej architektury. Składa się ze 150 linii kodu.&lt;/p&gt;

&lt;p&gt;Użycie &lt;code&gt;Django.setdsm&lt;/code&gt; z argumentem będącym scieżką do aplikacji Django umożliwia importowanie dowolnych bibliotek z tej konkretnej aplikacji.&lt;/p&gt;

&lt;p&gt;Opcjonalny argument &lt;code&gt;terminate=False&lt;/code&gt; w &lt;code&gt;demoapp&lt;/code&gt; zapobiega rozłączanie klientów z frontendowego serwera, jeśli aplikacja jest wyłączana (lub restartowana). Po restarcie aplikacji "oczekujący klienci" są w do niej automatycznie łączeni (&lt;code&gt;reconnect=True&lt;/code&gt; w &lt;code&gt;onOpen&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;onStart&lt;/code&gt; i &lt;code&gt;onStop&lt;/code&gt; w klasie &lt;code&gt;demoapp&lt;/code&gt; wywoływane są wiadomo kiedy, a dodatkowo można ustawić dowolną ilość timerów z dowolnymi nazwami i interwałami - przykładowo &lt;code&gt;onTimer=5&lt;/code&gt; spowoduje wywołanie funkcji &lt;code&gt;onTimer&lt;/code&gt; klasy &lt;code&gt;demoapp&lt;/code&gt; co 5 sekund.&lt;/p&gt;

&lt;p&gt;Z poziomu obiektu klienta jest możliwy dostęp na parametrów sesji oraz użytkownika Django.&lt;/p&gt;

&lt;p&gt;Do czego można to wykorzystać? Chociażby do czatów, live feedów czy do wyświetlania jakiegoś &lt;a href="/en/2011/01/real-time-graph-using-javascript"&gt;wykresu w czasie rzeczywistym&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Wszelkie opinie mile widziane!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/cAKs0HVv3W8" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2011/07/twisted-django-i-websockety-demo</feedburner:origLink></entry><entry><title>Django, Twisted i WebSockety</title><link href="http://feedproxy.google.com/~r/nmepl/~3/yk3xbE9um_w/server-side-pod-websockety" rel="alternate" /><id>http://nme.pl/2011/07/server-side-pod-websockety</id><summary type="html">&lt;img src="/img/2011/07/websocket.png" alt="" class="post-image" /&gt;
&lt;p&gt;Nigdy nie przypuszczałem, że pracowanie nad architekturą rozwiązań po stronie serwera sprawi mi tyle frajdy, a jednak :) Pod koniec lutego zaprezentowałem tutaj demo czata &lt;span style="color:gray"&gt;(kto sobie przetestował ten miał szczęście - obecnie demo jest wyłączone)&lt;/span&gt; ponieważ odkrywałem technologię &lt;a href="http://en.wikipedia.org/wiki/Push_technology#Long_polling"&gt;long polling&lt;/a&gt;. Na jej poznawanie jest teraz trochę za późno (o jakieś 5 lat), ale warto było dowiedzieć się ile problemów ona stwarza. Postanowiłem teraz wybiec trochę do przodu i zaimplementować sobie obsługę WebSocketów.&lt;/p&gt;

&lt;p&gt;To że powstał ten wpis - oznacza to, że się udało. Moje rozwiązanie okazało się być całkiem fajne i praktyczne. Zamierzam zatem przedstawić ewolucję architektury server-side z której korzystam.&lt;/p&gt;

&lt;h4&gt;Początki&lt;/h4&gt;

&lt;p&gt;Ten blog to nie Wordpress - to aplikacja w &lt;a href="https://www.djangoproject.com/"&gt;Django&lt;/a&gt;. Na serwerze nie ma Apache'a, jest &lt;a href="http://nginx.org/"&gt;Nginx&lt;/a&gt; - fenomenalny serwer www. Kiedy uruchamiałem wszystko pod koniec grudnia 2010 roku, architektura wyglądała tak:&lt;/p&gt;

&lt;p&gt;&lt;img class="center" src="/img/2011/07/nginx.png" alt="architektura w oparciu o Nginxa" /&gt;&lt;/p&gt;

&lt;p&gt;Stabilność i niesamowita wydajność przy niewielkim użyciu pamięci umożliwił nginx wraz z &lt;a href="http://projects.unbit.it/uwsgi/"&gt;uwsgi&lt;/a&gt; serwującym aplikacje.&lt;/p&gt;

&lt;h4&gt;Ewolucja...&lt;/h4&gt;

&lt;p&gt;Aby mieć możliwość pracy z Comet musiałem wykorzystać &lt;a href="http://pushmodule.slact.net/"&gt;Nginx Http Push Module&lt;/a&gt;. Byłem przy okazji ciekaw jak z tą techologią będzie współpracował &lt;a href="http://haproxy.1wt.eu/"&gt;haproxy&lt;/a&gt;. Ruch https został dodatkowo przepuszczony przez również zmodyfikowany &lt;a href="http://www.stunnel.org/"&gt;stunnel&lt;/a&gt; (nałożona łata umożliwiająca &lt;code&gt;http_x_forwarded_for&lt;/code&gt;). Po stronie aplikacji Django konieczne było dodanie własnego autorstwa middleware'a do obsługi &lt;code&gt;http_x_forwared_for&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Long polling wymagał też lekkiego tuningu ustawień haproxy i serwera nginx.&lt;/p&gt;

&lt;p&gt;&lt;img class="center" src="/img/2011/07/haproxy.png" alt="Architektura w oparciu o Haproxy" /&gt;&lt;/p&gt;

&lt;p&gt;Taka architektura ma jeszcze jeden niesamowicie praktyczny ficzer, który warto w tym momencie wymienić: jeśli jakaś aplikacja pracuje w trybie debugowania (w nginx zamiast uwsgi jako reverse proxy, a aplikacja jest uruchamiana komendą &lt;code&gt;django-admin runserver&lt;/code&gt;), a zależy nam na prawdziwym adresie IP - dzięki middleware obsługującemu &lt;code&gt;http_x_forwared_for&lt;/code&gt; nie będziemy widzieć &lt;code&gt;127.0.0.1&lt;/code&gt; tylko prawdziwy adres IP. Było to dla mnie niezwykle przydatne podczas testowania uwierzytelniania oAuth.&lt;/p&gt;

&lt;p&gt;Aplikacje działające na serwerze pracowały równie stabilnie i wydajnie, a całe rozwiązanie wymagało jednocześnie bardzo mało pamięci oraz umożliwiło bardziej elastyczne skanowanie.&lt;/p&gt;

&lt;p&gt;Jako, że zamierzałem poznać bliżej WebSockety oraz postawiłem sobie za priorytet, aby działały one na tych samych adresach IP i portach (&lt;code&gt;http&lt;/code&gt; i &lt;code&gt;https&lt;/code&gt;) co sam serwer www (wykorzystanie &lt;code&gt;http-alt&lt;/code&gt; jakoś nie wydaje mi się być właściwym rozwiązaniem). Z przeprowadzonych testów ustaliłem, że z już gotowych rozwiązań - taką funkcjonalność oferuje jedynie komercyjny &lt;a href="http://www.kaazing.com/products/kaazing-websocket-gateway"&gt;Kaazing WebSocket Gateway&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Wykorzystanie komercyjnego serwera nie wchodziło w grę - bo przecież mogę sobie coś takiego samemu napisać. Konieczne było napisanie czegoś co stało by "od frontu", co byłoby świadome WebSocketów. Ponieważ haproxy niestety nie jest w stanie sobie z tym zadaniem na tą chwilę (i być może nigdy) poradzić - wymagana było wprowadzenie zmian. Najnowszy na tą chwilę draft WebSocketów - hixie 76 - &lt;a href="http://en.wikipedia.org/wiki/WebSockets#Proxy_traversal"&gt;uniemożliwia&lt;/a&gt; nawiązanie całego handshake'u przez serwer reverse-proxy. Należało zatem pójść o krok dalej.&lt;/p&gt;

&lt;h4&gt;Wykorzystanie Twisted&lt;/h4&gt;

&lt;p&gt;Konieczne było wykorzystanie serwera "event-driven".&lt;/p&gt;

&lt;p&gt;Z pomocą przyszedł silnik &lt;a href="http://twistedmatrix.com/trac/"&gt;Twisted&lt;/a&gt; oraz znaleziona na githubie biblioteka txWebSocket którą lekko &lt;a href="https://github.com/dervsh/txWebSocket"&gt;poprawiłem&lt;/a&gt;. Tutaj zaczęła się prawdziwa frajda - zacząłem poznawać Twisted. Poszło szybko i sprawnie.&lt;/p&gt;

&lt;p&gt;Zanim zabrałem się za WebSockety uruchomiłem reverse-proxy dla obecnych serwisów www (rozszerzając je o &lt;code&gt;http_x_forwarded_for&lt;/code&gt;), skonfigurowałem sobie logowanie do poszczególnych facility, dodałem obsługę https i przygotowałem sobie skrypt startowy w oparciu o &lt;code&gt;twistd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Kiedy WebSockety zaczęły działać, zacząłem zastanawiać się w jaki sposób:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;umożliwić dalszą komunikację z klientami WebSocketów&lt;/li&gt;
&lt;li&gt;odseparować właściwe aplikacje od głównego serwera frontend'owego&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Trochę poszukałem, poczytałem i znalazłem &lt;a href="http://www.rabbitmq.com/"&gt;RabbitMQ&lt;/a&gt; - napisany w erlangu serwer implementujący protokół kolejkowania AMQP. To wystarczyło aby zamknąć krąg, który wygląda następująco:&lt;/p&gt;

&lt;p id="twisted+django"&gt;&lt;img class="center" src="/img/2011/07/twisted.png" alt="Architektura w oparciu o Twisted" /&gt;&lt;/p&gt;

&lt;p&gt;Kod minimalistycznej aplikacji (wykorzystującej przygotowaną bibliotekę umożliwiającą komunikację z klientami za pośrednictwem WebSocketów poprzez serwer frontendowy) jest krótki i bardzo czytelny - przedstawię go w następnym wpisie. Na tą chwilę aplikacje Twisted pracują w trzeciej warstwie (połączeniowej). Aby pracowały w warstwie czwartej (sesji) wykorzystując cookie &lt;code&gt;sessionid&lt;/code&gt; ustawiane przez Django będę musiał wprowadzić kilka drobnych modyfikacji - myślę, że jeden wieczór wystarczy :) Aplikacje Twisted są również w stanie łączyć się do bazy za pośrednictwem &lt;code&gt;Django ORM&lt;/code&gt; jeśli tylko jest zastosowany w nich model standalone (wystarczy z poziomu aplikacji ustawić odpowiednio &lt;code&gt;DJANGO_SETTINGS_MODULE&lt;/code&gt; oraz odpowiednie ścieżki - bułka z masłem).&lt;/p&gt;

&lt;div class="footnotes"&gt;Najnowsza z przedstawionych architektur jest całkowicie zgodna z modelami zarówno dla klasycznego www (Django MTV) jak i WebSocketów (event-driven) - więc zalet jest wiele, a całość można sobie przygotować w zaledwie kilka wieczorów.&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/yk3xbE9um_w" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2011/07/server-side-pod-websockety</feedburner:origLink></entry><entry><title>Nowe wdrożenie portalu zarządzania siecią</title><link href="http://feedproxy.google.com/~r/nmepl/~3/nvlv39Wo--o/nowe-wdrozenie-portalu-zarzadzania-siecia" rel="alternate" /><id>http://nme.pl/2011/02/nowe-wdrozenie-portalu-zarzadzania-siecia</id><summary type="html">&lt;a href="http://www.facebook.com/pages/Network-Maintenance-Engineering/172239732794965"&gt;&lt;img class="post-image" src="/img/2011/02/nme.jpg" alt="Network Maintenance Engineering"/&gt;&lt;/a&gt;
&lt;p&gt;Nie sądziłem, że się tak stanie, a jednak - system który w połowie 2007 roku ujrzał światło dzienne doczekał się drugiego wdrożenia! Z tej okazji postanowiłem trochę powspominać i powiedzieć na jego temat kilka słów. Bedą też screeny :)&lt;/p&gt;

&lt;p&gt;Kiedy studiowałem - pamiętam, że do naszego administratora sieci w akademiku chodziło się z karteczką z adresem mac, aby się zarejestrować. Jako, że to była politechnika, akademik męski w zasadzie - było to do przełknięcia.&lt;/p&gt;

&lt;p&gt;Niedługo potem przeniosłem się do Katowic, jako absolwent zamieszkałem w akademiku i nagle jakimś dziwnym zbiegiem okoliczności zacząłem "po godzinach" mojej podstawowej pracy administrować siecią na uniwersyteckim osiedlu akademickim - trzy domy studenckie, w 1/4 obcokrajowcy - było bardzo ciekawie :) Studentki filologii i psychologii potrafiły przynieść na karteczce różne numerki, ale nie zawsze były to adresy mac ;) Widok zagubionego spojrzenia kiedy uparcie trwałem w stwierdzeniu, że bez adresu mac się nie obędzie - bezcenny :P&lt;/p&gt;

&lt;h4&gt;Początki&lt;/h4&gt;

&lt;p&gt;Na kolanie powstał wtedy pierwszy system do zarządzania siecią - narzędzie commandline'ówe, co nóż poprawiane i wzbogacane o nowe "wyjątki", obsługę anomalii, możliwych problemów i inne konieczne poprawki. Był totalnie niewydajny - przepisałem go od nowa i wszystko zaczęło działać świetnie. Kiedy kształtowanie pasma również zaczęło działać jak należy - pomyślałem o frontendzie webowym oraz - o automatyzacji rejestracji studentów.&lt;/p&gt;

&lt;p&gt;Pamiętam pewien upalny dzień, w środku lata, kiedy to siedziałem w domu, na L4 - załatwiłem się klimatyzacją w samochodzie - i pisałem ten portal :) Dzięki między innymi temu - w semestr 2007/2008 osiedle akademickie weszło z nowym systemem rejestracji i obsługi problemów - automatycznie pobierającym adresy mac rejestrowanych stacji roboczych. Portal rejestracyjny był dwujęzyczny oraz jednocześnie zawierał takie rzeczy jak czat z administratorem, bazę wiedzy - najczęstszych problemów czy komunikaty z dostępnym kanałem rss. Jeśli temat graficzny komuś coś przypomina (zrzuty ekranu poniżej) - wzorowany na dawnym projekcie strony frameworka jQuery ;)&lt;/p&gt;

&lt;h4&gt;Od tamtego czasu...&lt;/h4&gt;

&lt;p&gt;Od tamtego czasu system działa bardzo sprawnie, doczekał się nawet rozbudowy o obsługę wifi (wstyd się przyznać - nie znałem wtedy radiusa i nie wiedziałem co to WPA2 Enterprise, nie wierzyłem i nadal nie wierzę w bezpieczeństwo szyfrowania WPA2 Personal - więc zrobiłem wifi w oparciu o OpenVPN'a), dodatkowe skrypty wykrywające pewne konkretne rodzaje problemów w sieci, automatyzację samonaprawiania się sieci, automatyzacji "rozmawiania" z zarządzalnymi switchami - słowem - wszystko co było potrzebne. System sam rozwiązywał problemy o których informował mnie smsami, a dodatkowo jeśli wymagał mojej reakcji - wysyłał mi smsy czy później - po prostu maile.&lt;/p&gt;

&lt;p&gt;Bardzo fajnie się go używało - wszystko wyklikiwalne - prawie jak Farmorama ;) Uświadamiałem sobie, że przecież dużo jest takich ośrodków które nadal ręcznie rejestrują userów - stwierdziłem, że to strzał w dziesiątkę i może ktoś będzie chciał to kupić lub wdrożyć :) Przygotowałem dokumentację... i wtedy nauczyłem się tego, że na marketingu totalnie się nie znam ;)&lt;/p&gt;

&lt;div class="footnotes"&gt;Dokumentacja jednak powstała - dokumenty pdf można oglądać online w Google Docs lub ściągnąć do siebie - są dostępne w dwóch wersjach językowych: &lt;a href="https://docs.google.com/viewer?a=v&amp;amp;pid=explorer&amp;amp;chrome=true&amp;amp;srcid=0B97E2VkUswb4YjQ5NWM0YmItNjAxNS00ODQ3LWE2MjYtYzUyZTlhMTJlM2Mw&amp;amp;hl=en"&gt;po polsku&lt;/a&gt; (&lt;a href="http://nme.pl/pub/netman/netman-pl.pdf"&gt;mirror lokalny&lt;/a&gt;), &lt;a href="https://docs.google.com/viewer?a=v&amp;amp;pid=explorer&amp;amp;chrome=true&amp;amp;srcid=0B97E2VkUswb4ZWJiZmNiYjctNDhjMS00YTUyLTk2ODQtZGJjMDkzYzMwOTU0&amp;amp;hl=en"&gt;po angielsku&lt;/a&gt; (&lt;a href="http://nme.pl/pub/netman/netman-en.pdf"&gt;mirror lokalny&lt;/a&gt;).&lt;br /&gt;Powstały również mini strony - &lt;a href="http://nme.pl/pub/netman/pl/"&gt;polska&lt;/a&gt; oraz &lt;a href="http://nme.pl/pub/netman/en/"&gt;angielska&lt;/a&gt;.&lt;/div&gt;

&lt;p&gt;Żal mi tego systemu było - a jako że pojawiła się sposobność - pomogłem koledze który dopiero uruchamia sieć na osiedlu akademickim - w Cieszynie. Wdrożenie potrwało 4 dni z całkowitym dostosowania do potrzeb - oczywiście po godzinach. Ale warto zobaczyć jak własne dziecko działa :) Szczególnie na znacznie nowszej platformie sprzętowej. Środowisko zostało zdeployowane jako maszyna wirtualna kvm i wydaje mi się, że "uciągnie" - póki co zachowuje się obiecująco :) Tak btw. &lt;a href="http://nme.pl/en/2011/02/hv-kvm-virtualization-swiss-knife"&gt;tutaj jest opis&lt;/a&gt; (również mój wpis, ale po angielsku) jednego ze świeżych narzędzi które użyłem - polecam).&lt;/p&gt;

&lt;div class="center"&gt;&lt;img src="/img/2011/02/cieszyn-stats1.png" alt="Cieszyn statystyki" /&gt;&lt;/div&gt;

&lt;p&gt;Zanim jednak Cieszyn osiągnie liczby które mam na swoim podwórku (100Mbit/s), upłynie trochę czasu ;)&lt;/p&gt;

&lt;div class="center"&gt;&lt;img src="/img/2011/02/ligota-portal1.png" alt="Katowice Ligota Portal" /&gt;&lt;/div&gt;

&lt;p&gt;Tak poza tym - dodam, że, nie tak dawno bo jakieś pół roku temu powstała nowa wersja portalu, przepisana na Django, z dużą ilością JavaScriptowych fajerwerków. Na wdrożenie (a w zasadzie odpluskwianie na żywo w środowisku produkcyjnym) brakło mi chwilowo chęci. Grunt, że stary działa, a nowy czeka :D&lt;/p&gt;

&lt;p&gt;Swoją drogą - jestem ciekaw - jakiego systemu Ty / Twój administrator używa do zarządzania siecią? A może znasz się na marketingu i mnie czegoś nauczysz? :)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/nvlv39Wo--o" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2011/02/nowe-wdrozenie-portalu-zarzadzania-siecia</feedburner:origLink></entry><entry><title>Ulepszony feed demotywatory.pl</title><link href="http://feedproxy.google.com/~r/nmepl/~3/Bi9grjGcYqE/ulepszony-feed-demotywatory-pl" rel="alternate" /><id>http://nme.pl/2011/01/ulepszony-feed-demotywatory-pl</id><summary type="html">&lt;p&gt;Serwis &lt;a href="http://demotywatory.pl"&gt;demotywatory.pl&lt;/a&gt; jest w naszym kraju bardzo popularny. Ja również darzę go sympatią. Jest jednak pewien szkopuł - feed RSS. Niestety przeglądanie demotywatorów z poziomu &lt;a href="http://www.google.com/reader"&gt;Google Readera&lt;/a&gt; jest niezwykle męczące, ponieważ feed nie zawiera obrazków - trzeba rozwijać wpis, klikać na link, przeskakiwać do właściwego serwisu, wracać spowrotem - można się szybko zniechęcić. Mam dla Was jednak dobrą nowinę:&lt;/p&gt;

&lt;p&gt;Wykonałem wersję ulepszoną - która ów obrazki zawiera :) Zapraszam do subskrybowania: &lt;a href="http://nme.pl/demotywatory/feed"&gt;http://nme.pl/demotywatory/feed&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ten feed może nie zaspokoić osób które non stop siedzą na demotywatorach, ponieważ wprowadza pewne opóźnienie - z drugiej strony jednak - dla tych którzy przeglądają je raz na jakiś czas powinien okazać się znacznie wygodniejszy niż standardowy. Miłego korzystania!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/Bi9grjGcYqE" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2011/01/ulepszony-feed-demotywatory-pl</feedburner:origLink></entry><entry><title>Nowy silnik bloga</title><link href="http://feedproxy.google.com/~r/nmepl/~3/Gc4eioCR4nc/nowy-silnik-bloga" rel="alternate" /><id>http://nme.pl/2011/01/nowy-silnik-bloga</id><summary type="html">&lt;p&gt;W rok 2011, blog &lt;a href="http://nme.pl"&gt;nme.pl&lt;/a&gt; wchodzi z nowym silnikiem napisanym w Django! Napisanie go zajęło mi mniej więcej tydzień. Napisałem go całkowicie od podstaw - nie korzystałem z już istniejących silników. Osobiście jestem bardzo zadowolony z efektów. Blog jest na chwilę obecną dwujęzyczny, napisałem do niego już trzy pluginy - uploadowanie plików, tworzenie redirectów oraz wykrywanie uszkodzonych wewnętrznych linków. Napisałem sobie też widgety obsługujące RSS i wyszukiwanie w obrębie konkretnych kategorii (wykorzystałem &lt;a href="http://haystacksearch.org/"&gt;Haystack&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Większość wpisów jest już dostępna, te, których nie ma, a niosą za sobą jakąś wartość - niebawem się pojawią. Poprawiłem nieco niektóre wpisy. Migrację komentarzy wykonam z pewnym opóźnieniem. Tagi dodam również z lekkim opóźnieniem. Jeśli ktoś z Was chciałby jeszcze zerknąć na starego, Wordpressowego bloga zapraszam pod adres &lt;a href="http://prev.nme.pl" rel="nofollow"&gt;prev.nme.pl&lt;/a&gt; (może tam niestety brakować obrazków itp, jednak wszystko powinno być tutaj - jeśli jakiś materiał jest niedostępny zarówno na starej jak i nowej wersji bloga - proszę o kontakt ze mną).&lt;/p&gt;

&lt;p&gt;Życzę Wam wszystkiego dobrego w Nowym Roku!&lt;/p&gt;

&lt;hr /&gt;

&lt;h5&gt;Aktualizacja (śro, 16 lut 2011, 20:41:00 CET):&lt;/h5&gt;

&lt;p&gt;Przez ostatnie półtorej miesiąca nieco dopieściłem silnik bloga. Niedawno np. pochwaliłem się &lt;a href="/2011/01/ulepszony-feed-demotywatory-pl"&gt;feedem demotywatory.pl&lt;/a&gt; - który jest również dostępny z poziomu Django Admin. Dodałem jednak również kilka innych rzeczy - ogólnie - zarządzanie feedami atom/rss, własne bookmarki, bardzo wygodny notatnik oraz wysoko dostosowany do moich potrzeb - dziennik spraw bieżących. W związku z tym, przedstawię screeny pokazujące jak ja ten blog widzę :)&lt;/p&gt;

&lt;div class="center"&gt;&lt;p&gt;Strona główna Django Admin:&lt;/p&gt;&lt;img src="/img/2011/02/adm_main.png" alt="screenshot" title="Zrzut ekranu strony głównej Django Admin" /&gt;&lt;/div&gt;

&lt;div class="center"&gt;&lt;p&gt;Wpisy:&lt;/p&gt;&lt;img src="/img/2011/02/adm_posts.png" alt="screenshot" title="Zrzut ekranu listy wpisów" /&gt;&lt;/div&gt;

&lt;div class="center"&gt;&lt;p&gt;Sprawy bieżące:&lt;/p&gt;&lt;img src="/img/2011/02/adm_tasks.png" alt="screenshot" title="Zrzut ekranu spraw bieżących" /&gt;&lt;/div&gt;

&lt;p&gt;Zapomniałem zrobić screena edycji posta - najważniejszej rzeczy, dorzucę niebawem - powiem póki co, że edycję wspomaga rewelacyjnie customizowalny &lt;a href="http://markitup.jaysalvat.com/home/"&gt;markItUp!&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/Gc4eioCR4nc" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2011/01/nowy-silnik-bloga</feedburner:origLink></entry><entry><title>facebook.com / imie.nazwisko</title><link href="http://feedproxy.google.com/~r/nmepl/~3/6PA-uSZyUMM/facebook-com-imie-nazwisko" rel="alternate" /><id>http://nme.pl/2010/09/facebook-com-imie-nazwisko</id><summary type="html">&lt;img class="post-image" src="/img/2010/09/fb-xmpp.png" alt="" title="fb-xmpp" width="195" height="179" /&gt;

&lt;p&gt;Nie wiem czy każdy z Was wiedział o tym, że komunikator Facebooka jest zgodny z XMPP, czyli otwartym protokołem komunikatorów. Taka wiadomość obiegła jakiś czas temu blogosferę, ale jakoś mnie osobiście to umknęło. Z drugiej strony niewielu blogerów zadało sobie trud sprawdzenia jak zostało to zaimplementowane i co nam ta usługa tak naprawdę oferuje. Ja sprawdziłem i mam dwie wiadomości - dobrą i złą.&lt;/p&gt;

&lt;p&gt;Więc po kolei:&lt;/p&gt;

&lt;p style="background:#fee;margin-bottom:1em;padding:0"&gt;&lt;strong&gt;Zła&lt;/strong&gt; - na chwilę obecną wsparcie dla protokołu, które oferuje nam Facebook jest w mojej opinii zbyt słabe, aby korzystać z niego na codzień. Dlaczego? Ponieważ aby zalogować się do swojego konta &lt;strong&gt;konieczne jest wyłączenie szyfrowania&lt;/strong&gt; oraz usługa jest zamknięta dla Jabberów zewnętrznych - nie dodamy kontaktów np. z Google Talk.&lt;/p&gt;

&lt;p style="background:#efe;margin-bottom:1em;padding:0"&gt;&lt;strong&gt;Dobra&lt;/strong&gt; - aby aktywować konto, należy przebrnąć przez w miarę przyjemny proces, który umożliwi nam założenie sobie identyfikatora tekstowego. Ów identyfikator staje się częścią JID'a &lt;strong&gt;oraz staje się aliasem do naszego profilu&lt;/strong&gt;, np. &lt;code&gt;http://facebook.com/imie.nazwisko&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I właśnie tylko z powodu tej drugiej wiadomości - uważam, że warto spędzić chwilę i &lt;a href="http://www.facebook.com/sitetour/chat.php"&gt;&lt;strong&gt;skonfigurować sobie konto Jabbera na Facebooku&lt;/strong&gt;&lt;/a&gt;. Na używanie konta, przynajmniej w moim wypadku - przyjdzie kolej kiedy indziej, ale z aliasu do swojego profilu już można będzie korzystać :)&lt;/p&gt;

&lt;p&gt;Jeśli ktoś chciałby jednak skorzystać z rozsądniejszej implementacji Jabbera - polecam &lt;a href="/2010/01/jabber-od-google-w-pidginie/"&gt;Google Talk&lt;/a&gt;. Pidgin jako komunikator dostępny jest również pod Windows.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/6PA-uSZyUMM" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2010/09/facebook-com-imie-nazwisko</feedburner:origLink></entry><entry><title>Interfejs Django Admin od kuchni :)</title><link href="http://feedproxy.google.com/~r/nmepl/~3/W6HD3RzQAYY/interfejs-django-admin-od-kuchni" rel="alternate" /><id>http://nme.pl/2010/09/interfejs-django-admin-od-kuchni</id><summary type="html">&lt;p&gt;W poprzednim wpisie opowiedziałem o tym, jak dzień po dniu, w dwa i pół tygodnia &lt;a href="/2010/08/jak-zrobic-startup-w-dwa-i-pol-tygodnia/"&gt;zrealizowałem startup&lt;/a&gt; - serwis z przepisami. Wspomniałem również, że przybliżę jak serwis wygląda "od kuchni" :)&lt;/p&gt;

&lt;p&gt;Nie mam ostatnio zbyt wiele czasu ponieważ kończę jeden projekt, o którym już niebawem napiszę, ale jako, że nie rzucam słów na wiatr - chciałbym Wam dzisiaj przedstawić jak wygląda interfejs Django Admin aplikacji w serwisie &lt;a href="http://kuchnia.chwila-dla-siebie.pl/"&gt;kuchnia.chwila-dla-siebie.pl&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Myślę, że ten wpis może być pomocny dla osób, które omijają Django Admina tworząc własne interfejsy administracyjne z obawy, że niektórych rzeczy w tym interfejsie nie będą w stanie zrealizować.&lt;/p&gt;

&lt;h4&gt;Zmiany kodzie startupu&lt;/h4&gt;

&lt;p&gt;Od poprzedniego wpisu wprowadziłem w kodzie aplikacji trzy proste zmiany:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dodałem dodatkowe widgety z Facebooka i zrównolegliłem ich wyświetlanie (obecnie ładowane są przez JavaScript, kiedy content na stronie jest już gotowy przez przeglądarkę do wyrenderowania)&lt;/li&gt;
&lt;li&gt;w Django Adminie dodałem podgląd przepisów na podstronie z listą przepisów&lt;/li&gt;
&lt;li&gt;wyszukiwanie przepisów jest obecnie cache'owane za pośrednictwem memcache'a - dzięki temu jedynie pierwsze wyszukanie konkretnej frazy trwa dłuższy czas - następnie w trakcie stosowania pagera wykorzystywany jest cache. Czas renderowania stron przez aplikację po stronie serwera spadł dzięki temu o 700%&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Box administratorów&lt;/h4&gt;

&lt;p&gt;Zalogowany użytkownik ma dostępne na stronie box ze skrótami. Jeśli użytkownik jest superuserem, skrótów jest o jeden więcej, ponieważ aplikacja ma zaimplementowane dwie instancje Django Admina - podstawową - do obsługi przepisów oraz dodatkową - do administracji użytkownikami z dostępem do historii przepisów. Członkowie zespołu mają też domyślnie ukryte reklamy.&lt;/p&gt;

&lt;img class="center" title="box-administratora" src="/img/2010/09/box-administratora.png" alt="" width="600" height="321" /&gt;

&lt;h4&gt;Panel superadmina&lt;/h4&gt;

&lt;p&gt;Na stronie Django Admin dla superusera, dostępu do przepisów de facto nie ma, są natomiast pozycje umożliwiające analizę historii zmian w przepisach, dodawanie i edycję newsów oraz użytkowników. Widoczne są tu również statystyki memcache'owania wyników wyszukiwania.&lt;/p&gt;

&lt;img class="center" title="django-admin-superuser" src="/img/2010/09/django-admin-superuser.png" alt="" width="600" height="311" /&gt;

&lt;h4&gt;Historia modyfikacji przepisów&lt;/h4&gt;

&lt;p&gt;Bardzo wygodny interfejs, którego tworzenie dostarczyło mi bardzo dużo dobrej zabawy. Właśnie w takich sytuacjach Django pokazuje jak wiele ma developerowi do zaoferowania.&lt;/p&gt;

&lt;img class="center" title="django-admin-superuser-history" src="/img/2010/09/django-admin-superuser-history.png" alt="" width="600" height="304" /&gt;

&lt;h4&gt;Podstawowy Django Admin&lt;/h4&gt;

&lt;p&gt;Interfejs dla zwykłych użytkowników, mających status staff został przedstawiony poniżej. Tworzyłem go tak, aby członkowie zespołu mieli dostępne skróty do najpotrzebniejszych filtrów. Dzięki temu nie jest potrzebne żmudne ich wyklikiwanie. Podstawowy filtr (niezweryfikowanych przepisów) jest z tego co pamiętam niemożliwy do wyklikania :)&lt;/p&gt;

&lt;img class="center" title="django-admin" src="/img/2010/09/django-admin.png" alt="" width="600" height="324" /&gt;

&lt;h4&gt;Kategorie&lt;/h4&gt;

&lt;p&gt;Zarządzanie kategoriami z wyliczaniem ile przepisów procentowo zostało już zweryfikowanych:&lt;/p&gt;

&lt;img class="center" title="django-admin-kategorie" src="/img/2010/09/django-admin-kategorie.png" alt="" width="600" height="326" /&gt;

&lt;h4&gt;Przepisy&lt;/h4&gt;

&lt;p&gt;Interfejs do obsługi przepisów zrealizowałem w następujący sposób:&lt;/p&gt;

&lt;img class="center" title="django-admin-przepisy" src="/img/2010/09/django-admin-przepisy.png" alt="" width="600" height="324" /&gt;

&lt;h4&gt;Edycja przepisu&lt;/h4&gt;

&lt;p&gt;Edycja konkretnego przepisu - to co jest potrzebne jest widoczne na jednej, zwięzłej stronie - nie ma potrzeby żadnego przewijania ekranu:&lt;/p&gt;

&lt;img class="center" title="django-admin-edycja" src="/img/2010/09/django-admin-edycja1.png" alt="" width="600" height="368" /&gt;

&lt;h4&gt;Podgląd przepisów&lt;/h4&gt;

&lt;p&gt;Jak wspomniałem wcześniej - podczas weryfikacji przepisów stwierdziłem, że przydałby się jeszcze jeden prosty ficzer - podgląd przepisu po najechaniu na linka. Zrealizowałem to w następujący sposób:&lt;/p&gt;

&lt;img class="center" title="django-admin-przepisy-podglad" src="/img/2010/09/django-admin-przepisy-podglad.png" alt="" width="600" height="276" /&gt;

&lt;p&gt;Mam nadzieję, że warto było na ten wpis chwilkę poczekać :) Zrealizowanie takiego interfejsu jaki przedstawiłem jest bardzo proste, a społeczność Django jest bardzo otwarta - większość z przedstawionych modyfikacji jest bardzo dokładnie opisana zarówno na stronach z dokumentacją na stronach &lt;a href="http://docs.djangoproject.com/en/1.2/"&gt;dokumentacji djangoproject.com&lt;/a&gt; oraz na &lt;a href="http://stackoverflow.com/"&gt;stackoverflow.com&lt;/a&gt; który jest skarbnicą rozwiązań ciekawych problemów.&lt;/p&gt;

&lt;p&gt;Jeśli macie jakieś sugestie, pytania bądź uwagi - zapraszam do skomentowania wpisu!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/W6HD3RzQAYY" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2010/09/interfejs-django-admin-od-kuchni</feedburner:origLink></entry><entry><title>Jak zrobić startup w dwa i pół tygodnia?</title><link href="http://feedproxy.google.com/~r/nmepl/~3/C-FwU1KzqNw/jak-zrobic-startup-w-dwa-i-pol-tygodnia" rel="alternate" /><id>http://nme.pl/2010/08/jak-zrobic-startup-w-dwa-i-pol-tygodnia</id><summary type="html">&lt;p&gt;Słowo wstępu - będąc na urlopie odwiedziłem rodzinne strony. W międzyczasie wylegiwania się na słońcu i robienia kilometrów na rowerze, namówiłem moją mamę do zmianę podejścia do publikacji treści w Internecie. Ma ona dużo pomysłów, content generuje ciekawy i unikalny, po różnych stronach go rozmieszcza, ale nie ma z tego żadnych korzyści. Wszystko co publikuje w różnych serwisach jest własnością tych serwisów. Strata czasu. Postanowiliśmy, że podzielę się moim hostingiem, na którym mam dużo wolnego miejsca i będzie mogła sobie zacząć w normalny sposób blogować - w Wordpressie. Musiałem tylko wymyślić nazwę domeny... I wymyśliłem. :)&lt;/p&gt;

&lt;p&gt;W sobotę 31 lipca kupiłem domenę chwila-dla-siebie.pl. Coś poszło nie tak i strefa w DNSie po stronie panelu administracyjnego mojego providera się nie utworzyła jak należy. Konfiguracja DNS'ów musiała więc poczekać do poniedziałku, kiedy ostatecznie zgłosiłem błąd i został on rozwiązany ręcznie.&lt;/p&gt;

&lt;h4&gt;Pomysł i realizacja&lt;/h4&gt;

&lt;p&gt;Kiedy oczekiwałem na dostęp do strefy, przypomniało mi się, że 10 lat temu pewien człowiek na swojej stronie z przepisami kucharskimi obwieścił wszem i wobec, że stronę zamyka, zabiera swoje wiaderko, grabki i opuszcza piaskownice. Stwierdziłem wtedy, że szkoda, żeby się to wszystko zmarnowało, bo korzystałem z tej strony czasami. Cała strona przeleżała u mnie w archiwach jakieś 10 lat. Jako dodatek do bloga, stwierdziłem, że taka strona z przepisami będzie strzałem w dziesiątkę... i zacząłem pisać... :)&lt;/p&gt;

&lt;h4&gt;Po ponad dwóch tygodniach aplikacja prezentuje się następująco:&lt;/h4&gt;

&lt;a href="http://kuchnia.chwila-dla-siebie.pl"&gt;&lt;img class="center" title="kuchnia-screenshot" src="/img/2010/08/kuchnia-screenshot.png" alt="" width="600" height="394" /&gt;&lt;/a&gt;

&lt;h4&gt;Poniżej zamieszczam loga dzień po dniu jej tworzenia&lt;/h4&gt;

&lt;h5&gt;dzień 1, niedziela&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;span&gt;Napisałem pierwotną wersję parsera do przepisów, analizujący dokumenty html i wypluwający łatwiejsze do przetwarzania za pomocą wyrażeń regularnych pliki tekstowe. Okazało się, że dysponuję 6182 przepisami.&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;&lt;span&gt;Przygotowałem sobie szkielet aplikacji. Wykorzystałem do tego kod &lt;a href="http://blog.urevs.com/2010/07/19/social-bootstrap-engine-for-django/"&gt;mojego bootstrapa Django / JavaScript / CSS&lt;/a&gt; (link do opisu na innym moim blogu, w języku angielskim) - zwłaszcza &lt;a href="http://blog.urevs.com/2010/07/20/javascript-builder/"&gt;Buildera JavaScript&lt;/a&gt;. Dla interfejsu użytkowników wykorzystałem mój bazowy template - z layoutem pionowym (nagłówek, treść, stopka).&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;dzień 2, poniedziałek&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;span&gt;modele - przygotowałem modele dla kategorii i przepisów i spędziłem trochę czasu na dopracowanie wyświetlania tych informacji w panelu admina Django.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;dzień 3, wtorek&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;span&gt;Zdeployowałem aplikację na serwerze. Przygotowałem konfigurację serwera www, wrzuciłem  sztampowe template'y do wyświetlania błędów. Aplikacja póki co działała na screenie, a serwer WWW obsługiwał zapytania jako reverse proxy.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;dzień 4, środa&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;span&gt;Dodałem layout poziomy (kategorie, przepisy, sidebar). Strona dostosowuje swój rozmiar do szerokości okna przeglądarki, chyba, że jest ona mniejsza niż zadeklarowana minimalna szerokość.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;dzień 5, czwartek&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;span&gt;Napisałem sobie kod do obsługi paginatora przepisów i opisałem to w poprzednim &lt;a href="http://www.nme.pl/2010/08/helper-dla-pagination-w-django/"&gt;wpisie&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;dzień 6, piątek&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;span&gt;Zaimplementowałem wyświetlanie kategorii, paginację przepisów i wyświetlanie konkretnego przepisu.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;dzień 7, sobota&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;span&gt;Napisałem obsługę wyszukiwania przepisów. kod póki co nie jest specjalnie wydajny, ale został napisany tak, aby zastosowanie cache'owania było proste.&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;&lt;span&gt;Zrobiłem też prosty, brzydki design dla layoutu. Jakieśtam obrazki, żeby strona nabrała kształtów, które mnie osobiście dają motywację do dalszej pracy. :)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;dzień 8, niedziela&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;span&gt;Dodałem templatkę do dodawania przepisów i jej obsługę, następnie uzupełniłem obsługę o mailowanie do mnie przez aplikację informacji o nowym przepisie.&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;&lt;span&gt;Dodałem do przepisu przyciski "lubię to" z Facebooka i "dodaj na Śledzika".&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;dzień 9, poniedziałek&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;span&gt;Trochę się przyłożyłem, pomyślałem i narysowalem nowy design dla layoutu. Narysowałem kilka podstawowych backgroundów i ustawiłem je w css'ie. Wyszło wystarczająco zadawalająco, żebym mogło tak zostać :)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;dzień 10, wtorek&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;span&gt;Podzieliłem logo na dwie części i poprawiłem je od strony kodu - chciałem aby po wyłączeniu styli, dokument wyglądał tak jak powinien (tagi h1).&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;&lt;span&gt;Dodałem model News'ów, dodałem możliwość edycji do interfejsu Django Admin, news początkowo wpisany w templatkę przeniosłem do skryptu inicjalizującego bazę, a do templatki wstawiłem kod wyświetlający Newsy z bazy. To akurat pamiętam, bo całe mieszanie z newsami zajęło mi tyle ile trwały Fakty na TVN'ie ;)&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;&lt;span&gt;Zrobiłem trochę porządków w modelach, dodałem obsługę vars'ów i memcache, również z mojego frameworka, które wcześniej uznałem za tymczasowo zbędne.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;dzień 11, środa&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;span&gt;Wyczyściłem bazę i zaimportowałem ponownie przepisy. Założyłem też konto mojej koleżance (którą z tego miejsca gorąco pozdrawiam :)), która pomogła mi tego dnia sprawdzić 150 przepisów :)&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;&lt;span&gt;Dodałem osoby które to lubią z Facebooka (ta większa wersja, z ryjkami) do strony głównej.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;dzień 12, czwartek&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;span&gt;Dodałem funkcjonalność zapisywania historii zmian w przepisach z interfejsem dla superusera w Django Adminie, umożliwiającym przeglądanie wprowadzonych zmian i ich cofania (Undo).&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;dzień 13, piątek&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;span&gt;Zarejestrowałem się w jednej z sieci afiliacyjnych, a następnie w jednym z programów partnerskich. W międzyczasie weryfikowaliśmy kolejne przepisy, których było już 320.&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;&lt;span&gt;Dodałem reklamę z Google Adsense, przycisk "Share" z Facebooka.&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;&lt;span&gt;Wrzuciłem też na stronę favicona.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;dzień 14, sobota&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;span&gt;Weryfikacja kolejnych 100 przepisów.&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;&lt;span&gt;Usunąłem z głownej Facebookowe osoby które to lubią, założyłem kuchni stronę na Facebooku i dodałem "Like Boxa" do ów Facebookowej strony.&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;&lt;span&gt;Dodałem do strony kod śledzenia Google Analytics oraz dodałem stronę do &lt;a href="https://www.google.com/webmasters/tools/"&gt;Google Webmaster Tools&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;dzień 15, niedziela&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;span&gt;Zmieniłem obsługę aplikacji przez serwer WWW, obecnie pracuje jako wsgi. Bawiłem się też w zmienianie Suzuki Hayabuzy we włochatego potwora w Gimpie (efekty pracy udostępnione na moim profilu Facebookowym ;))&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;dzień 16, poniedziałek&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;span&gt;Gimp i przygotowanie trzech obrazków reklam do sidebara. Wrzuciłem obrazki na serwer, przygotowałem szkielet modułu adbox, który zawierał tablicę z reklamami i parametrami ich wyświetalnia i zaimplementowałem statyczne wyświetlanie losowej reklamy z tablicy.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;dzień 17, wtorek&lt;/h5&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;span&gt;Napisałem fadera do reklam w javascripcie, który dzięki wspomnianemu na początku bootstrapowi, eksportował mi je z pythona za pomocą jsona do javascriptu, automagicznie się includował, rozpoznawał które to reklamy ma animować, a następnie je animował :) Chodziło mi to po głowie od jakiegoś już czasu, coś podobnego ma Allegro na głównej.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;A tymczasem...&lt;/h4&gt;

&lt;p&gt;W międzyczasie oczywiście chodziłem do pracy i robiłem tam inne rzeczy. Musiałem też trochę czasu poświęcić mojemu samochodowi, który w trakcie tych dni ucierpiał przed parkingiem pod pracą, bo w moje drzwi wjechało Mondeo. Spisywanie, telefony, oględziny, lakiernik, pisma itp. Straszne pożeracze czasu. No ale dałem radę. :) Acha, i spałem. ;)&lt;/p&gt;

&lt;h4&gt;Startup nie startup&lt;/h4&gt;

&lt;p&gt;Zdaję sobie sprawę, że specjaliści od &lt;code&gt;Web 2.0&lt;/code&gt; i &lt;code&gt;social networkingu&lt;/code&gt;, np.  Grzegorz Marczak z &lt;a href="http://www.antyweb.pl"&gt;Antyweb'a&lt;/a&gt; prawdopodobnie mieliby zastrzeżenia do określania tej aplikacji mianem startupu, a gdyby miał go na swoim blogu opisywać, zebrałbym jako autor więcej batów niż ta aplikacja ma linijek kodu, ale co tam. :) Wszystkich Was na stronę aplikacji serdecznie zapraszam - jest ona dostępna pod adresem &lt;a href="http://kuchnia.chwila-dla-siebie.pl"&gt;kuchnia.chwila-dla-siebie.pl&lt;/a&gt; (oraz jako skrót z tej domeny: &lt;a href="http://nme.pl/kuchnia"&gt;nme.pl/kuchnia&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;W następnym wpisie przedstawię jak wygląda obecna konfiguracja panelu Django Admina aplikacji.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/C-FwU1KzqNw" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2010/08/jak-zrobic-startup-w-dwa-i-pol-tygodnia</feedburner:origLink></entry><entry><title>Helper dla Pagination w Django</title><link href="http://feedproxy.google.com/~r/nmepl/~3/3z45hcPhtYI/helper-dla-pagination-w-django" rel="alternate" /><id>http://nme.pl/2010/08/helper-dla-pagination-w-django</id><summary type="html">&lt;p&gt;Wyświetlanie dużej ilości pozycji w aplikacji webowej jest zwykle związane z koniecznością zastosowania paginacji stron. Dobra nowina - Django takowego &lt;a href="http://docs.djangoproject.com/en/1.2/topics/pagination/"&gt;posiada&lt;/a&gt;. Zła nowina - brakuje w nim jednej prostej funkcji.&lt;/p&gt;

&lt;img class="center" style="margin-top:1em;margin-bottom:2em" title="paginator" src="/img/2010/08/paginator.png" alt="" width="286" height="27" /&gt;

&lt;p&gt;Ów funkcją jest &lt;strong&gt;zawężenie ilości stron do określonej ilości&lt;/strong&gt; (lub odległości od aktualnie wybranej) i &lt;strong&gt;wstawienie wielokropków w określonych miejscach&lt;/strong&gt;. Śpieszę więc z moim rozwiązaniem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Aktualizacja&lt;/strong&gt;: W kodzie funkcji został poprawiony drobny błąd logiczny oraz dodana została obsługa czegoś co nazwałem &lt;code&gt;bounce&lt;/code&gt; - czyli &lt;em&gt;"odbijania się"&lt;/em&gt;; polega to na tym, że jeśli wybrana jest strona druga, zakres wynosi 3, to z prawej strony widzimy elementy 3, 4, 5 oraz dzięki odbiciu - 6, 7, które powinny być widoczne po lewej stronie, ale wykroczyłoby poza zakres dostępnych stron. Podobnie paginator zachowa się, jeśli odwiedzalibyśmy ostatnie strony. Ta niewielka poprawka sprawia, że paginator zachowuje się znacznie przyjaźniej dla użytkownika. Przykładowe zastosowanie można objerzeć na stronie, dla której go stworzyłem - to &lt;a href="http://kuchnia.chwila-dla-siebie.pl/szukaj?q=a&amp;amp;page=8"&gt;strona z przepisami kuchennymi&lt;/a&gt; :)&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
#!/usr/bin/env python
# -*- coding: utf-8 -*-

def ranged_pages (pages, current, dist, border):
 """ Zwraca fragment listy /pages/ zawężoną do /dist/ wokół /current/
 oraz oddalone o /border/ od początku i końca listy """
    if bounce:
        bounce_left = pages.index(current)-dist
        bounce_right = len(pages)-pages.index(current)-1-dist
        if bounce_left &amp;lt; 0:
            dist += abs(bounce_left)
        if bounce_right &amp;lt; 0:
            dist += abs(bounce_right)
    return map(lambda x: [None,x][(x &amp;gt; current-dist-1) &amp;amp;
        (x &amp;lt; current+dist+1) | (pages.index(x) &amp;lt; border) |
        (pages.index(x) &amp;gt; len(pages)-border-1)],
        filter(lambda x: (x &amp;gt; current-dist-1) &amp;amp;
        (x &amp;lt; current+dist+1) | (pages.index(x) &amp;lt; border+1) |
        (pages.index(x) &amp;gt; len(pages)-border-2), pages))

# przykładowe zastosowanie:

pages = map(lambda x:x,range(1,25))
print 'dane wejsciowe:\n%s\n' % pages

print 'aktualny:%d, dystans:%d, od_granic:%d\n%s\n' % \
 ( 12,3,2, ranged_pages(pages, 12, 3, 2))

print 'aktualny:%d, dystans:%d, od_granic:%d\n%s\n' % \
 ( 5,4,3, ranged_pages(pages, 5, 4, 3))
&lt;/pre&gt;

&lt;p&gt;Funkcja &lt;code&gt;ranged_pages&lt;/code&gt; zajmuje się całym zadaniem. Jest ona jednocześnie przykładem jak można pisać efektywnego jednolinijkowca, który jest nieczytelny i brzydki jak noc.&lt;/p&gt;

&lt;p&gt;Parametry które przyjmuje funkcja to kolejno:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;lista stron z &lt;code&gt;Pagination(objects).page_range&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;indeks aktualnej strony&lt;/li&gt;
	&lt;li&gt;ilość stron na lewo i prawo od aktualnej, które mają być wyświetlane&lt;/li&gt;
	&lt;li&gt;ilość stron od początku i końca listy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Po uruchomieniu przedstawionego wyżej przykładu dostajemy następujący wynik:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dane wejsciowe:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;aktualny:12, dystans:3, od_granic:2
[1, 2, None, 9, 10, 11, 12, 13, 14, 15, None, 23, 24]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;aktualny:5, dystans:4, od_granic:3
[1, 2, 3, 4, 5, 6, 7, 8, 9, None, 22, 23, 24]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Pozycję &lt;code&gt;None&lt;/code&gt; oczywiście podmieniamy wielokropkiem. Robimy to już w konkretnym template.&lt;/p&gt;

&lt;p&gt;Dlaczego nazwałem to helperem? Taką konwencję przyjąłem już dawno temu - większość funkcji konkretnej aplikacji które wykorzystywane są przez &lt;code&gt;views.py&lt;/code&gt; umieszczam w pliku &lt;code&gt;helpers.py&lt;/code&gt; z którego importuje do widoków. Rozwiązanie sprawdza się świetnie, szczególnie jeśli do kodu jakiegoś projektu nie zaglądam zbyt często - nie trzeba się głowić gdzie takie usprawniacze trzymamy.&lt;/p&gt;

&lt;p&gt;Jeśli w swoim kodzie nie stosujesz zbyt często funkcji &lt;code&gt;lambda&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;reduce&lt;/code&gt; i &lt;code&gt;filter&lt;/code&gt;, uważam, że warto zapoznać się z ich &lt;a href="http://docs.python.org/library/functions.html"&gt;dokumentacją&lt;/a&gt;. Inne przykłady ich praktycznego zastosowania przedstawiłem we wpisie po angielsku opisującym prosty &lt;a href="/en/2010/05/ipv4-cidr-to-netmask-in-python/"&gt;konwerter CIDR na maskę bitową&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/3z45hcPhtYI" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2010/08/helper-dla-pagination-w-django</feedburner:origLink></entry><entry><title>Podsumowanie ostatnich miesięcy</title><link href="http://feedproxy.google.com/~r/nmepl/~3/GtFtdJEUM6E/podsumowanie-ostatnich-miesiecy" rel="alternate" /><id>http://nme.pl/2010/07/podsumowanie-ostatnich-miesiecy</id><summary type="html">&lt;p&gt;Bardziej spostrzegawczy którzy tutaj zaglądają pewnie zauważyli, że od kilku miesięcy nie pojawił się na tym blogu żaden wpis - śpieszę więc z wyjaśnieniami.&lt;/p&gt;

&lt;p&gt;Na &lt;a href="http://nme.pl/"&gt;nme.pl&lt;/a&gt;, poza podstawowym blogiem, znajduje się jeszcze odrębna kategoria z własnym kanałem RSS - zawierająca &lt;a href="http://nme.pl/en"&gt;wpisy w języku angielskim&lt;/a&gt;. Trochę głupio to wyglądało, że widoczna była jedynie pusta kategoria - dlatego trafiło tam kilka wpisów. Z bloga zniknęły linki do &lt;a href="http://nme.pl/hyde"&gt;mojego minibloga&lt;/a&gt; i niedawno założonego &lt;a href="http://nme.pl/u"&gt;mikrobloga&lt;/a&gt;. Uznałem, że nie są tu potrzebne - jedynie zaciemniają wizerunek bloga, który miał być z założenia techniczny.&lt;/p&gt;

&lt;p&gt;Od mniej więcej miesiąca pracuje sobie nad nowym projektem w Django. Na chwilę obecną aktualny jego stan można zobaczyć na stronie &lt;a href="http://urevs.com/"&gt;urevs.com&lt;/a&gt;. Informacje na temat postępów prac opisuje na blogu pod adresem &lt;a href="http://blog.urevs.com/"&gt;blog.urevs.com&lt;/a&gt;. Projekt w obecnej postaci wydaje się być jeszcze nie zaczęty, ale zawiera już wiele funkcjonalności:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;możliwość zakładania kont które będą identyfikatorami OpenID (czyli OpenID Provider), podczas zakładania kont wykorzystana została &lt;a href="http://www.google.com/recaptcha"&gt;reCAPTCHA&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Aby zalogować się w serwisie nie trzeba mieć założonego lokalnie konta - można zalogować się poprzez m.in:
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://dev.twitter.com/pages/oauth_faq"&gt;Twitter OAuth&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://developers.facebook.com/docs/guides/web"&gt;Facebook Connect&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://code.google.com/intl/pl-PL/apis/accounts/docs/OpenID.html"&gt;Federated Login for Google Account Users&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://openid.yahoo.com/"&gt;Yahoo! ID&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://openid.net/get-an-openid/what-is-openid/"&gt;OpenID&lt;/a&gt; (gotowe skróty m.in do &lt;a href="http://www.wordpress.com"&gt;Wordpress.com&lt;/a&gt;, &lt;a href="http://blogger.com"&gt;Blogger&lt;/a&gt; itd)&lt;/li&gt;
&lt;/ul&gt;

&lt;/li&gt;
	&lt;li&gt;Serwis obsługuje https, lokalizację językową (obecnie dostępne są języki polski i angielski) i mój bootstrap do rozwijania aplikacji JavaScript i jego rozszerzenie - do generowania CSS'ów.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;W międzyczasie muszę się jeszcze zabrać do roboty i dokończyć odświeżoną wersję mojego portalu do zarządzania siecią, którą już kończę przenosić na Django. Zabrałbym się pewnie prędzej, gdyby nie kompletny brak motywacji... W końcu trwa lato... i nie chce się tyle czasu siedzieć nad mądrymi projektami :)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/GtFtdJEUM6E" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2010/07/podsumowanie-ostatnich-miesiecy</feedburner:origLink></entry><entry><title>Wygodny storage z użyciem memcache w Django</title><link href="http://feedproxy.google.com/~r/nmepl/~3/Q6ca76_mqFQ/wygodny-storage-z-uzyciem-memcache-w-django" rel="alternate" /><id>http://nme.pl/2010/05/wygodny-storage-z-uzyciem-memcache-w-django</id><summary type="html">&lt;img class="post-image" title="storage" src="/img/2010/05/storage.jpg" alt="" width="128" height="128" /&gt;

&lt;p&gt;Czasami zachodzi konieczność napisania na szybko aplikacji w Django która standardowo coś tam trzyma w bazie danych, coś przetwarza i wyświetla. Jeśli aplikacja ma być prosta, a w bazie mają być trzymane proste struktury danych, to czy napewno musimy tyle czasu poświęcać na dopracowanie modeli? Jasne, że nie.&lt;/p&gt;

&lt;p&gt;Poniższy kod oferuje nam możliwość trzymania dowolnych danych w postaci klucz-wartość w bazie danych. Dodatkowo - owe dane mogą mieć dowolną postać - może być to tekst, tablica asocjacyjna czy wartość typu Boolean.&lt;/p&gt;

&lt;p&gt;Ponadto - biblioteczka ta opiera się o opisaną w poprzednim wpisie &lt;a href="/2010/05/memcache-w-django-krok-ku-lepszej-skalowalnosci/"&gt;obsługę memcache'u w Django&lt;/a&gt; - co sprawia, że do póki nie zmienimy wartości danych, a ich obecność w cache'u nie zdąży wygasnąć - nie będziemy w ogóle obciążać naszej bazy danych. Osobiście wykorzystuję ten kod do trzymania ustawień aplikacji. Niektóre ustawienia są typu boolean, inne to stringi, jeszcze inne - tabele. Rozwiązanie sprawdza się świetnie. &lt;/p&gt;

&lt;h4&gt;Właściwy kod&lt;/h4&gt;

&lt;p&gt;Modele - &lt;code&gt;models.py&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2009 nme.pl
# Dual licensed under MIT and GPL.

from django.db import models

class Vars (models.Model):

    key = models.CharField(max_length=50)
    value = models.TextField()
&lt;/pre&gt;

&lt;p&gt;Proste prawda? Nie zapomnijcie wydać komendy &lt;code&gt;django-admin syncdb&lt;/code&gt; która utworzy odpowiednią tabelę w bazie. Teraz czas na właściwą bibliotekę - &lt;code&gt;vars.py&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2009 nme.pl
# Dual licensed under MIT and GPL.

""" Simple variables (key-value) handling with memcache """

import pickle,base64

import memcache,models

from settings import conf

class __Vars:

    def get (self,key,default=None):

        """ get Vars variable value """

        if memcache.enabled:
            value = memcache.get('va-%s' % key)
            if value != None:
                return pickle.loads(base64.b64decode(str(value)))
        settings = models.Vars.objects.filter(key=key)
        if settings:
            value = settings[0].value
            if value:
                return pickle.loads(base64.b64decode(str(value)))
            else:
                return default
        else:
            return default

    def __getitem__ (self,msg):

        return self.get(key)

    def set (self,key,value):

        """ set Vars variable value """

        value = base64.b64encode(pickle.dumps(value))
        if memcache.enabled:
            memcache.set('va-%s' % key,value)
        settings = models.Vars.objects.filter(key=key)
        if settings:
            setting = settings[0]
            setting.value = value
            setting.save()
        else:
            models.Vars(key=key,value=value).save()

    def has_key (self,key):

        """ return True or False if Vars variable exists """

        settings = models.Vars.objects.filter(key=key)
        if settings:
            return True
        else:
            return False

    def delete (self,key):

        """ deletes given key from Vars and memcache """

        if memcache.enabled:
            memcache.delete('va-%s' % key)
        settings = models.Vars.objects.filter(key=key)
        for i&lt;code&gt; &lt;/code&gt;in settings:
            i.delete()

variables = __Vars()
&lt;/pre&gt;

&lt;h4&gt;Przykładowe użycie&lt;/h4&gt;

&lt;p&gt;Zastosowanie biblioteki z poziomu &lt;code&gt;django-admin shell&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
In [1]: from vars import variables

In [2]: if not variables.has_key('test'):
   ...:     variables.set('test','tekst')
   ...:
   ...:     

In [3]: print variables.get('test')
tekst

In [4]: variables.set('test',{'asd':1,'data':['struct','ure']})

In [5]: variables.get('test')['data'][1]
Out[5]: 'ure'

In [6]: variables.delete('test')

In [7]: variables.get('test')

In [8]: variables.has_key('test')
Out[8]: False
&lt;/pre&gt;

&lt;h4&gt;Jak to działa?&lt;/h4&gt;

&lt;p&gt;Składowanie dowolnego typu danych w rekordzie bazy zrealizowane jest w oparciu o dwie standardowe biblioteki pythonowe - &lt;code&gt;pickle&lt;/code&gt; i &lt;code&gt;base64&lt;/code&gt;. Pierwsza z nich oferuje zakodowanie dowolnej struktury danych do stringa, druga natomiast - zastosowanie notacji base64 - przez co zabezpieczamy się przed ewentualnymi problemami z obsługą znaków z którymi nasz bazodanowy backend mógłby mieć ewentualnie problemy. Innymi słowy - rozwiązanie przedstawione powyżej gwarantuje nam pełną przenośność danych.&lt;/p&gt;

&lt;p&gt;Zachęcam gorąco do korzystania :)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/Q6ca76_mqFQ" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2010/05/wygodny-storage-z-uzyciem-memcache-w-django</feedburner:origLink></entry><entry><title>Memcache w Django: krok ku lepszej skalowalności</title><link href="http://feedproxy.google.com/~r/nmepl/~3/PeKNCWAo55g/memcache-w-django-krok-ku-lepszej-skalowalnosci" rel="alternate" /><id>http://nme.pl/2010/05/memcache-w-django-krok-ku-lepszej-skalowalnosci</id><summary type="html">&lt;p&gt;Podczas tworzenia aplikacji webowych, warto w miarę wcześnie pomyśleć o skali z jaką nasze rozwiązanie będzie miało się w przyszłości zmierzyć. Niezależnie od tego czy owa aplikacja ma pracować w jednym przedsiębiorstwie, czy próbuje zainstnieć szerzej, w sieci - w każdym przypadku może się okazać, że odniesie sukces. To z kolei sprawi, że ilość jej użytkowników urośnie... Firma może się rozwinąć, przejąć konkurencję, aplikacja webowa może się okazać takim strzałem w dziesiątkę jak nie tak dawno temu Nasza-Klasa - nigdy nie wiadomo :) W momencie gdy miałaby go odnieść, nie będzie już zbyt wiele czasu na przebudowę kodu, a napewno nie będzie go na jego całkowitą reorganizację.&lt;/p&gt;

&lt;p&gt;Jeśli rozwiązanie jest skryptem uruchamianym od święta - może to być zwykły skrypt &lt;code&gt;CGI&lt;/code&gt;. Jeśli jednak miałby być uruchamiany częściej - wartałoby już pomyśleć o &lt;code&gt;mod_php&lt;/code&gt; czy &lt;code&gt;mod_python&lt;/code&gt;... Albo jeszcze lepiej - &lt;code&gt;fastcgi&lt;/code&gt;, a w przypadku pythona - &lt;code&gt;wsgi&lt;/code&gt;. Kiedy użycie aplikacji rośnie nadal - frontend mnożymy na kolejne węzły stawiając przed nimi balancera robiącego za reverse proxy. A w backendzie klastrujemy... ale co na styku macierz, klaster? Ilość zapytań do bazy rośnie, io waity zaczynają rosnąć i robi się nieciekawie... Da się to rozwiązać?&lt;/p&gt;

&lt;h4&gt;Jak to robi Google&lt;/h4&gt;

&lt;p&gt;Google od jakiegoś czasu pokazuje nam jak powinny być tworzone intensywnie wykorzystywane aplikacje webowe i na jak zorganizowanym backendzie powinny pracować, aby skalowały się najefektywniej. Myślę, że warto z tej wiedzy skorzystać zanim io waity zaczną spędzać nam sen z powiek.&lt;/p&gt;

&lt;p&gt;Miałem okazję napisać sobie kilka małych aplikacji które pracują w chmurze na platformie Google - tzw. &lt;a href="http://code.google.com/intl/pl/appengine/"&gt;Google App Engine&lt;/a&gt; (w skrócie GAE). Warto było poświęcić trochę czasu aby to rozwiązanie poznać. Łatwiej było mi dzięki temu można zrozumieć między innymi dlaczego poszczególne serwery Google nie są potężnymi serwerami rackowymi z bardzo silnymi procesorami, ale raczej "lżejszymi" serwerkami, ale za to wypełnionymi po brzegi koścmi pamięci.&lt;/p&gt;

&lt;img class="center" title="google-server-node" src="/img/2010/05/google-server-node.jpg" alt="" width="620" height="342" /&gt;

&lt;p&gt;Dlaczego takie lżejsze maszyny? Poza oszczędnością energii i pieniędzy są one wystarczające do obsługi pythonowych frameworków, w przeciwieństwie do tych PHP'owych.&lt;/p&gt;

&lt;p&gt;Google skupia się na Javie i Pythonie, gdzie prawie pewne jest to, że ich rozproszony Datastore - system bazodanowy, został stworzony w oparciu o język Python. Język ten znany jest m.in z wydajności, szczególnie, jeśli osoba która go używa stosuje się do najbardziej podstawowych zasad jak nie allokowanie ogromnej ilości pamięci itp. Dlaczego więc w serwerach Google tyle pamięci? Odpowiedzią jest memcache.&lt;/p&gt;

&lt;p&gt;Google chwali się tym, że stworzyli sobie własną implementację cache, inspirowaną oprogramowaniem &lt;a href="http://memcached.org/"&gt;memcached&lt;/a&gt; i zachęca, aby developerzy aplikacji App Engine'owych również korzystali z memcache'a.&lt;/p&gt;

&lt;h4&gt;Na czym polega memcache&lt;/h4&gt;

&lt;p&gt;Uproszczony graf przedstawiający działanie memcache'u:&lt;/p&gt;

&lt;img class="center" src="/img/2010/05/memcached-flow.png" alt="" title="memcached-flow" width="260" height="395" /&gt;

&lt;p&gt;Koncepcja działania jest prosta - zamiast odwoływać się bezpośrednio do bazy danych, odwołujemy się do memcache'a - jeśli trafiliśmy na dane (&lt;code&gt;hit&lt;/code&gt;), wykorzystujemy je, jeśli nie (&lt;code&gt;miss&lt;/code&gt;), dopiero wtedy odwołujemy się do bazy, jednocześnie zapisując pobrane z bazy dane w naszym cache'u. Dzięki temu prostemu zabiegowi, nasza strona, która podczas każdego odwołania do niej potrzebuje jakichś danych z bazy, jest w stanie funkcjonować praktycznie w ogóle jej o nic nie odpytując - wszystko co potrzebne będzie trzymać w pamięci podręcznej.&lt;/p&gt;

&lt;h4&gt;Zastosowanie i dokumentacja&lt;/h4&gt;

&lt;p&gt;Aby wykorzystać memcache w Google App Engine, polecam zapoznanie się z &lt;a href="http://code.google.com/intl/pl/appengine/docs/python/memcache/usingmemcache.html"&gt;dokumentacją&lt;/a&gt; na stronach Google.&lt;/p&gt;

&lt;p&gt;A co jeśli chcielibyśmy wykorzystać memcache w Django? Naturalnie - nic nie stoi na przeszkodzie - Django posiada coś takiego jak cache framework, który na dodatek jest &lt;a href="http://docs.djangoproject.com/en/dev/topics/cache/"&gt;bardzo dobrze udokumentowany&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Django samo z siebie jest przystosowane do wykorzystania cache'u przy obsłudze widoków czy template'ów, ale również oferuje dostęp niskopoziomowy - niemalże analogiczny do tego z Google App Engine... Niemalże, bo jakoś wersja Google bardziej przypadła mi do gustu. Dlatego przygotowałem sobie prosty interfejs, który wydaje mi się być odrobinę bardziej logiczny. Kod oczywiście załączam. Mam nadzieję, że komuś się przyda.&lt;/p&gt;

&lt;h4&gt;Konfiguracja systemu, projektu Django oraz moja niskopoziomowa obsługa&lt;/h4&gt;

&lt;p&gt;Zakładając, że pracujemy na systemie GNU Debian/Ubuntu oraz Django jest już w systemie jakąś drogą zainstalowane (osobiście w tym akurat przypadku polecam instalację z oryginalnych źródeł nad paczką Django z dystrybucji), doinstalowujemy obługę memcached, włączamy ją i restartujemy demona memcached:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
sudo -i
aptitude install memcached python-memcache
sed -i 's/no/yes/' /etc/default/memcached
service memcached restart
exit
&lt;/pre&gt;

&lt;p&gt;teraz w naszym projekcie Django włączamy obsługę cache:&lt;/p&gt;

&lt;p&gt;w pliku &lt;code&gt;settings.py&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
CACHE_BACKEND = 'memcached://127.0.0.1:11211/'
&lt;/pre&gt;

&lt;p&gt;jeśli chcemy wykorzystać moją małą biblioteczkę poniżej, do &lt;code&gt;settings.py&lt;/code&gt; musimy dodać też konfigurację memcache:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
class conf:
    class memcache:
        disabled = False
        timeout = 600
&lt;/pre&gt;

&lt;p&gt;Moja niskopoziomowa obsługa &lt;code&gt;memcache.py&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
#!/usr/bin/python
# -*- coding: utf-8 -*-

""" cache low-level backend based on memcached """

from django.core.cache import cache

from settings import conf

def get(key, default=None, timeout=conf.memcache.timeout):

    """ returns value for given key from cache, and refreshes it
    in memcache with automatic conversion from unicode
    to str - fix to:
    __import__() argument 1 must be string without null bytes, not str """

    value = cache.get(key, default)

    if value is not default:
        cache.set(key, value, timeout)

    if type(value) is unicode:
        value = str(value)

    return value

def set(key, value, timeout=conf.memcache.timeout):

    """ sets a value for given key in cache """

    cache.set(key, value, timeout)

def delete(key):

    """ remove given key from cache """

    cache.delete(key)

# in the name of syntatic sugar ;)

disabled = bool(conf.memcache.disabled)
enabled = not disabled
&lt;/pre&gt;

&lt;p&gt;A przykład zastosowania pojawi się jutro albo pojutrze - w nowym wpisie.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/PeKNCWAo55g" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2010/05/memcache-w-django-krok-ku-lepszej-skalowalnosci</feedburner:origLink></entry><entry><title>Dodatkowy wolumin Ext3 jako plik na Fat32</title><link href="http://feedproxy.google.com/~r/nmepl/~3/OJpucsmPh9g/dodatkowy-wolumin-ext3-jako-plik-na-fat32" rel="alternate" /><id>http://nme.pl/2010/05/dodatkowy-wolumin-ext3-jako-plik-na-fat32</id><summary type="html">&lt;p&gt;Wielu użytkowników Linuxa ma zinstalowane dwa systemy operacyjne na notebookach i komputerach stacjonarnych. Nie jestem tutaj wyjątkiem. Jak już mam naklejkę licencyjną to przecież jej nie zdrapię ;) Mojemu Linuxowemu LVM'owi dałem 30 GB, Windowsowi również, a resztę stanowi wolumin FAT32. Kiedyś reszty nie było, ale cóż - musiałem kupić nowego twardziela z powodu podejścia producentów do &lt;a href="/2009/07/przedluz-czas-zycia-dysku-twardego/"&gt;"ekonomicznego" trybu pracy dysków twardych&lt;/a&gt; ;)&lt;/p&gt;

&lt;p&gt;Co jednak można zrobić w sytuacji, gdy nagle potrzebujemy trochę więcej przestrzeni dyskowej z obsługą Linuxowych uprawnień? Odpowiedź jest prosta - możemy wykorzystać trochę wolnej przestrzeni FAT32, aby stworzyć sobie na nim wolumin ext3 w postaci zwykłego pliku.&lt;/p&gt;

&lt;h4&gt;Tworzenie woluminu ext3 w pliku&lt;/h4&gt;

&lt;p&gt;Aby utworzyć 15 GB wolumin ext3, przechodzimy w linii komend na dysk FAT32 i wydajemy polecenie:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
cd /media/[nasz podmontowany wolumin FAT32]/

dd if=/dev/zero of=volume bs=1G count=15
&lt;/pre&gt;

&lt;p&gt;Chwilkę to potrwa, ale ostatecznie powstaje wolumin:&lt;/p&gt;

&lt;pre&gt;
15+0 przeczytanych recordów
15+0 zapisanych recordów
skopiowane 16106127360 bajtów (16 GB), 957,413 s, 16,8 MB/s
&lt;/pre&gt;
&lt;p&gt;
Sprawdzamy nasz plik:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;du -sh volume&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;
15G	volume
&lt;/pre&gt;

&lt;p&gt;Wszystko się zgadza. Tak przygotowany plik należy teraz sformatować:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mke2fs -j volume&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Zostaniemy zapytani, czy napewno chcemy formatować urządzenie które nie jest blokowe - potwierdzamy nasze intencje.&lt;/p&gt;

&lt;pre&gt;
mke2fs 1.41.11 (14-Mar-2010)
volume nie jest specjalnym urządzeniem blokowym.
Kontynuować mimo to? (t,n) t
warning: Unable to get device geometry for volume
Etykieta systemu plików=
Typ OS: Linux
Rozmiar bloku=4096 (log=2)
Rozmiar fragmentu=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
983040 i-węzłów, 3932160 bloków
196608 bloków (5.00%) zarezerwowanych dla superużytkownika
Pierwszy blok danych=0
Maksymalna liczba bloków systemu plików=4026531840
120 grup bloków
32768 bloków w grupie, 32768 fragmentów w grupie
8192 i-węzłów w grupie
Kopie zapasowe superbloku zapisane w blokach:
	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208

Zapis tablicy i-węzłów: zakończono
Tworzenie kroniki (32768 bloków): wykonano
Zapis superbloków i podsumowania systemu plików: wykonano

Ten system plików będzie automatycznie sprawdzany co każde 39 montowań
lub co 180 dni, zależnie co nastąpi pierwsze. Można to zmienić poprzez
tune2fs -c lub -i.
&lt;/pre&gt;

&lt;h4&gt;Montowanie woluminu plikowego&lt;/h4&gt;

&lt;p&gt;Teraz możemy już podmontować sobie tak stworzony wolumin:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo mkdir /mnt/tmp&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo mount -o loop volume /mnt/tmp&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;df -h&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;
System plików            rozm. użyte dost. %uż. zamont. na
/dev/mapper/sys-root   22G   11G  9,8G  52% /
[...]
/dev/loop0             15G  166M   14G   2% /mnt/tmp
&lt;/pre&gt;

&lt;p&gt;I to wszystko - wolumin jest już gotowy do użycia :)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/OJpucsmPh9g" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2010/05/dodatkowy-wolumin-ext3-jako-plik-na-fat32</feedburner:origLink></entry><entry><title>Wydajna i bezpieczna zdalna synchronizacja katalogów w Ubuntu</title><link href="http://feedproxy.google.com/~r/nmepl/~3/TKvP1FfNCpY/wydajna-i-bezpieczna-zdalna-synchronizacja-katalogow-w-ubuntu" rel="alternate" /><id>http://nme.pl/2010/04/wydajna-i-bezpieczna-zdalna-synchronizacja-katalogow-w-ubuntu</id><summary type="html">&lt;img class="post-image" src="/img/2010/04/sync-folders.png" alt="" title="sync-folders" width="78" height="62" /&gt;

&lt;p&gt;Będąc między innymi developerem, który pracuję na różnych maszynach, potrzebuje mieć swój kod dostępny na każdej stacji przy której zasiadam.&lt;/p&gt;

&lt;p&gt;Przez jakiś czas sprawdzał się rozproszony system kontroli wersji. Wystarczyło robić push i pull poprzez ssh. Z czasem, kiedy np. miałem rozgrzebany kod, nie chciałem robić commita, tworzyć odgałęzienia - zacząłem pakować kod i przesyłać w tej postaci. Przez jakiś czas to znosiłem. Nie było to jednak zbyt przyjemne. Kilka drobnych zmian, a okazywało się, że muszę przesyłać kilka MB danych. Nie narzekałbym, gdybym nie miał w domu łącza niesymetrycznego :)&lt;/p&gt;

&lt;p&gt;Z czasem, kiedy ilość projektów nad którymi pracowałem wzrosła, poczułem pewien dyskomfort (prawie jak pani Żanet Kaleta ;)). Tym większy, że zdarzało mi się pracować nad aplikacją i biblioteką jednocześnie w ramach jednego projektu, gdzie oba kody miały swoje indywidualne drzewa kontroli wersji. Nawet jeśli jedno było w podgałęzi drugiego - Mercurial, bo z tego systemu kontroli wersji korzystam - zdawał sobie sprawe, że dany katalog należy już do innego drzewa kontroli wersji.&lt;/p&gt;

&lt;p&gt;Co począć w takiej sytuacji? Rozwiązanie przypadkowo podsunął kolega, jednocześnie przypominając mi jak to rozwiązanie efektywnie spisywało się w dystrybucji Gentoo, z której miałem okazję jakiś czas temu przez dłuższy nawet czas korzystać. Chodzi oczywiście o rsync'a.&lt;/p&gt;

&lt;p&gt;Niżej przedstawioną metodę praktykuję już od jakiegoś czasu. Synchronizuję się do/z jednej centralnej maszyny. Synchronizuję katalog zawierający 300 MB kodu, źródeł grafik, duże drzewa hg. Nie zdarzyło mi się jeszcze, mimo wykonywania dość drastycznych zmian w podstrukturze, żeby trwało to dłużej niż wcześniej trwało przesłanie spakowanej paczki o rozmiarze 1 czy 2 MB. &lt;/p&gt;

&lt;p&gt;Załóżmy, że w katalogu domowym &lt;code&gt;/home/user/dev&lt;/code&gt; mam swoje repozytorium. Na maszynie centralnej, dane trzymane będą w katalogu &lt;code&gt;/srv/archive/dev&lt;/code&gt;.&lt;/p&gt;

Aby wysłać dane z notebooka, na serwer, wydajemy polecenie:

&lt;pre class="prettyprint"&gt;rsync -azv --delete -e ssh /home/user/dev MASZYNA_CENTRALNA:/srv/archive&lt;/pre&gt;

&lt;p&gt;Aby pobrać dane z serwera na notebooka wydajemy:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;rsync -azv --delete -e ssh MASZYNA_CENTRALNA:/srv/archive/dev /home/user&lt;/pre&gt;

&lt;p&gt;Jeśli nie jesteśmy pewni, czy efekty komendy będą zadowalające, warto dodać parametr &lt;code&gt;--dry-run&lt;/code&gt;, który sprawi, że zostanie nam wyświetlona jedynie lista zmian, a nic tak naprawdę nie zostanie zmienione.&lt;/p&gt;

&lt;p&gt;Myślę, że warto poświęcić kilka minut aby wewnątrz swojej biblioteczki stworzyć katalog sync, a w nim dwa skrypty &lt;code&gt;send&lt;/code&gt; i &lt;code&gt;recv&lt;/code&gt; które będą wykonywać te czynności, a gwarantuje, że w zamian zaoszczędzicie znacznie więcej czasu w przyszłości.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/TKvP1FfNCpY" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2010/04/wydajna-i-bezpieczna-zdalna-synchronizacja-katalogow-w-ubuntu</feedburner:origLink></entry><entry><title>Prosty plugin jQuery: Dynamiczny favicon</title><link href="http://feedproxy.google.com/~r/nmepl/~3/EpOxE6JLTX4/prosty-plugin-jquery-dynamiczny-favicon" rel="alternate" /><id>http://nme.pl/2010/04/prosty-plugin-jquery-dynamiczny-favicon</id><summary type="html">&lt;img class="post-image" title="favicons" src="/img/2010/04/favicons1.png" alt="" width="235" height="114" /&gt;

&lt;p&gt;Ten prosty wpis ma za zadanie przybliżyć Wam dwa tematy jednocześnie - jak stworzyć prosty plugin do jQuery oraz jak z poziomu JavaScriptu podmienić obrazek favicon dla strony. Zamierzam przedstawić plugin który właśnie taką czynność wykonuje :)&lt;/p&gt;

&lt;p&gt;&lt;a href="http://jquery.com"&gt;jQuery&lt;/a&gt; chyba nie trzeba przedstawiać. Jest to w mojej opinii najłatwiejsza w użyciu biblioteka czyniąca język JavaScript prostym i wygodnym w użyciu. Co więcej - można ją bardzo łatwo rozszerzać o dodatkową funkcjonalność za pomocą pluginów. Uważam, że warto wiedzieć jak taki plugin można sobie szybko przygotować.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;jquery.favicon_replace.js&lt;/code&gt; wygląda następująco:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
(function($) {
    $.fn.favicon_replace = function(url) {
        $('head link').each(function() {
            if ($(this).attr('rel') == 'shortcut icon') {
                $(this).remove();
            }
        });
        $('&amp;lt;link rel="shortcut icon" href="'+url+'" /&amp;gt;')
            .appendTo('head');
        return this;
    };
})(jQuery);
&lt;/pre&gt;

&lt;p&gt;Jak powyższy kod działa: tworzymy closure której jako parametr podajemy strukturę jQuery. Wewnątrz closury definiujemy funkcję, która sprawdza atrybut rel każdego taga typu link wewnątrz head porównując go do &lt;code&gt;shortcut icon&lt;/code&gt;. Znaleziony w ten sposób element jest kasowany. Następnie tworzony jest nowy link typu &lt;code&gt;shortcut icon&lt;/code&gt;, z nowym url'em. Urla podajemy funkcji jako parametr. Closura w postaci anonimowej funkcji jest wykonywana, a w efekcie jQuery zyskuje nową funkcję. &lt;code&gt;return this;&lt;/code&gt; na końcu funkcji umożliwia wywoływanie kolejnych funkcji jQuery.&lt;/p&gt;

&lt;p&gt;Zastosowanie tego plugina jest proste - oto przykład:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
$(document).favicon_replace('/images/new-favicon.ico');
&lt;/pre&gt;

&lt;p&gt;Warto napomnieć, że favicon wcale nie musi być ikoną. Możecie równie dobrze zaserwować przeglądarce animowanego gifa, nawet z rozszerzeniem ico, który zostanie automatycznie przeskalowany przez przeglądarkę i animowany na pasku adresu :)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/EpOxE6JLTX4" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2010/04/prosty-plugin-jquery-dynamiczny-favicon</feedburner:origLink></entry><entry><title>Generowanie losowych haseł w Ubuntu</title><link href="http://feedproxy.google.com/~r/nmepl/~3/yV7XnTpXBbE/generowanie-losowych-hase-w-ubuntu" rel="alternate" /><id>http://nme.pl/2010/02/generowanie-losowych-hase-w-ubuntu</id><summary type="html">&lt;img class="post-image" title="postitnote" src="/img/2010/02/postitnote.jpg" alt="" width="150" height="145" /&gt;

&lt;p&gt;Hasła, każdy ma ich przynajmniej kilka w pamięci, ale życie uczy, że nie warto stosować takich samych do autoryzacji bankowych, kont na naszej-klasie, gadu czy na roota ;)&lt;/p&gt;

&lt;p&gt;Chciałbym Wam przedstawić bardzo proste narzędzie z którego korzystam z powodzeniem od kilku lat - nazywa się &lt;a href="http://www.adel.nursat.kz/apg/"&gt;apg&lt;/a&gt; (Automated Password Generator) i służy do wygodnego generowania haseł.&lt;/p&gt;

&lt;p&gt;Narzędzie oferuje dwa rodzaje haseł - mniej zaawansowane, ale znacznie łatwiejsze do zapamiętania dla osób znających język angielski oraz bardziej zaawansowane (zawierające poza literami dodatkowe krzaczki). Za pomocą dodatkowych parametrów możemy wpłynąć na zawartość dużych, małych liter lub liczb.&lt;/p&gt;

&lt;p&gt;Instalacja jest standardowa:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;aptitude install apg&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;Help&lt;/h4&gt;

&lt;p&gt;Wygląda tak:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
apg -h

apg   Automated Password Generator
Copyright (c) Adel I. Mirzazhanov

apg   [-a algorithm] [-r file]
[-M mode] [-E char_string] [-n num_of_pass] [-m min_pass_len]
[-x max_pass_len] [-c cl_seed] [-d] [-s] [-h] [-y] [-q]

-M mode         new style password modes
-E char_string  exclude characters from password generation process
-r file         apply dictionary check against file
-b filter_file  apply bloom filter check against filter_file
(filter_file should be created with apgbfm(1) utility)
-p substr_len   paranoid modifier for bloom filter check
-a algorithm    choose algorithm
1 - random password generation according to
password modes
0 - pronounceable password generation
-n num_of_pass  generate num_of_pass passwords
-m min_pass_len minimum password length
-x max_pass_len maximum password length
-s              ask user for a random seed for password
generation
-c cl_seed      use cl_seed as a random seed for password
-d              do NOT use any delimiters between generated passwords
-l              spell generated password
-t              print pronunciation for generated pronounceable password
-y              print crypted passwords
-q              quiet mode (do not print warnings)
-h              print this help screen
-v              print version information
&lt;/pre&gt;

&lt;h4&gt;A teraz praktyka&lt;/h4&gt;

&lt;p&gt;Wystarczy znajomość kilku parametrów:&lt;/p&gt;

&lt;p&gt;Generowanie 5-ciu haseł: &lt;code&gt;-n&lt;/code&gt;&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
apg -n 5

ookyopIack
berpAxEr
DusEphac
yomlipvog~
weehacir
&lt;/pre&gt;

&lt;p&gt;Generowanie haseł o minimalnej długości: &lt;code&gt;-m&lt;/code&gt;&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
apg -n 5 -m 10

BlysBicWeo
fefimvesBa
CuAtecHeoc
crejvibred
CynfiShnoi
&lt;/pre&gt;

&lt;p&gt;Generowanie haseł z wymową (aby łatwiej było je zapamiętać): &lt;code&gt;-t&lt;/code&gt;&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
apg -n 5 -m 10 -t

WaigJocWig (Waig-Joc-Wig)
Geagsyinau (Geags-yin-au)
Cunefkalt9 (Cun-ef-kalt-NINE)
Pemyidyish (Pem-yid-yish)
agsirasuk7 (ags-ir-as-uk-SEVEN)
&lt;/pre&gt;

&lt;p&gt;Generowanie bardziej zaawansowanych haseł: &lt;code&gt;-a 1&lt;/code&gt;&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
apg -a 1 -n 5 -m 10

N;%5RWNM|B
$48+HGvlac
{@M!yPMa-y
jyI&amp;lt;{\3;{i
t)nThAUw?~
&lt;/pre&gt;

&lt;p&gt;Skrypt ten jest bardzo przydatny, kiedy musimy wygenerować komuś hasło ponieważ nie jest w stanie sobie czegoś wymyślić (i pewnie wymyślił by ostatecznie nazwę swojego psa lub imię małżonki) lub stawiamy następny z kolei serwer mysql, a nie chcemy zostawiać takiej dziury jak nie tak dawno ktoś z ekipy Wykopu, kiedy to &lt;a href="http://wiadomosci.gazeta.pl/Wiadomosci/1,80708,7005835,Z_Wykop_pl_skradziono_hasla_uzytkownikow.html"&gt;wykradziono im hasła&lt;/a&gt; użytkowników.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/yV7XnTpXBbE" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2010/02/generowanie-losowych-hase-w-ubuntu</feedburner:origLink></entry><entry><title>Wirtualni userzy ftp w Ubuntu</title><link href="http://feedproxy.google.com/~r/nmepl/~3/ox3w5ch-ghE/wirtualni-userzy-ftp-w-ubuntu" rel="alternate" /><id>http://nme.pl/2010/01/wirtualni-userzy-ftp-w-ubuntu</id><summary type="html">&lt;img class="post-image" title="ftp" src="/img/2010/01/ftp.jpg" alt="" width="150" height="112" /&gt;

&lt;p&gt;Poniżej znajduje się instrukcja opisująca jak skonfigurować krok po kroku bardzo prosty i bezpieczny serwer ftp obsługujący wirtualne konta - użytkowników, których fizycznie nie ma zdefinowanych w systemie. Jako serwer ftp wykorzystany zostanie&lt;a href="http://vsftpd.beasts.org/"&gt; vsftpd&lt;/a&gt; (very secure ftp daemon).&lt;/p&gt;

&lt;p&gt;Założenia: potrzebujemy prostego serwera ftp do którego możemy zdefiniować kilku użytkowników, gdzie &lt;strong&gt;każdy ma dostęp do tego samego katalogu&lt;/strong&gt; (opis jak należy to skonfigurować, aby każdy użytkownik miał swój własny katalog znajduje się we wpisie źródłowym, którego adres zamieściłem na końcu wpisu).&lt;/p&gt;

&lt;p&gt;Najpierw instalujemy serwer ftp oraz narzędzie do obsługi bazy użytkowników:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;aptitude install vsftpd db4.2-util&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Tworzymy katalog ftp:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
mkdir /home/ftp
chown ftp:ftp /home/ftp
&lt;/pre&gt;

&lt;p&gt;(aplikacja domyślnie podczas instalacji zakłada katalog /srv/ftp)&lt;/p&gt;

&lt;p&gt;Podmieniamy plik &lt;code&gt;/etc/vsftpd.conf&lt;/code&gt; na następujący:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
# /etc/vsftpd.conf
listen=YES
listen_ipv6=NO
#listen_port=2121

anonymous_enable=NO
local_enable=YES
guest_enable=YES

virtual_use_local_privs=YES
pam_service_name=vsftpd-virtual

guest_username=ftp

local_root=/home/ftp

local_umask=022
write_enable=YES
hide_ids=YES
dirmessage_enable=YES

use_localtime=YES
xferlog_enable=YES
log_ftp_protocol=YES
setproctitle_enable=YES

connect_from_port_20=YES

chroot_local_user=YES
chroot_list_enable=NO
secure_chroot_dir=/var/run/vsftpd/empty
&lt;/pre&gt;

&lt;p&gt;W razie potrzeb - zmieniamy ustawienia - np. jeśli chcemy zmienić port na którym aplikacja ma nasłuchiwać - usuwamy znak komentarza z linii listen_port i zmieniamy numer portu.&lt;/p&gt;

&lt;p&gt;Przygotowujemy plik &lt;code&gt;/etc/pam.d/vsftpd-virtual&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
auth required pam_userdb.so db=/etc/vsftpd-virtual
account required pam_userdb.so db=/etc/vsftpd-virtual
&lt;/pre&gt;

&lt;p&gt;Przygotowujemy plik z użytkownikami i hasłami &lt;code&gt;/etc/vsftpd-konta&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
uzytkownik1
haslo1
uzytkownik2
haslo2
&lt;/pre&gt;

&lt;p&gt;umieszczamy hasła w bazie:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;db4.2_load -T -t hash -f /etc/vsftpd-konta /etc/vsftpd-virtual.db&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;a następnie restartujemy usługę:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;service vsftpd restart&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Możemy już zalogować się do serwera, przykładowo:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
lftp -p 2121 -u uzytkownik1,haslo1 localhost
lftp test1@localhost:~&amp;gt; ls
lftp test1@localhost:/&amp;gt; 
&lt;/pre&gt;

&lt;p&gt;Źródło: &lt;a href="http://linuxforfun.net/2008/04/05/vsftpd-virtual-users/"&gt;http://linuxforfun.net/2008/04/05/vsftpd-virtual-users/&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/ox3w5ch-ghE" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2010/01/wirtualni-userzy-ftp-w-ubuntu</feedburner:origLink></entry><entry><title>Jabber od Google w Pidginie</title><link href="http://feedproxy.google.com/~r/nmepl/~3/5mHbYr4-xmE/jabber-od-google-w-pidginie" rel="alternate" /><id>http://nme.pl/2010/01/jabber-od-google-w-pidginie</id><summary type="html">&lt;img class="post-image" title="pidgin_protos" src="/img/2010/01/pidgin_protos.png" alt="" width="153" height="195" /&gt;

&lt;p&gt;Coraz więcej osób wyraża w różnych serwisach niezadowolenie z najnowszych usprawnień oferowanych przez GG Network S.A. w swoim sztandardowym produkcie - komunikatorze Gadu-Gadu. Niemniej jednak, większość z nas chcąc czy nie chcąc korzysta z Gadu. Powodem, dla którego nie odchodzimy od niego są dwa główne czynniki - jego popularność oraz wciąż niewielka popularność Jabbera.&lt;/p&gt;

&lt;h4&gt;Czym jest Jabber?&lt;/h4&gt;

&lt;p&gt;Jabber, pracujący w oparciu o protokół będący otwartym standardem &lt;a href="http://pl.wikipedia.org/wiki/Extensible_Messaging_and_Presence_Protocol"&gt;XMPP&lt;/a&gt; działa na zasadzie sieci rozproszonej. Każdy kto dysponuje domeną Internetową może postawić sobie swój własny serwer Jabbera i rozmawiać z innymi użytkownikami Jabbera na całym świecie.&lt;/p&gt;

&lt;p&gt;Identyfikator w Jabberze, tzw. JID, ma postać konto@domena - czyli analogicznie do adresów email. Użytkownik łączy się do swojego serwera Jabber. Nie ma serwera globalnego. Nie zdarzy się zatem sytuacja, jaka ma miejsce w sieci Gadu Gadu, kiedy padają ich serwery i w całej Polsce nikt nie może rozmawiać na Gadu.&lt;/p&gt;

&lt;p&gt;Serwerów Jabberowych oferujących darmowe konta jest dużo w Internecie. Wielu operatorów hostingowych którzy nie chcą zostawać w tyle, oferuje dla hostowanych u nich naszych domen, jednoczesną obsługę już nie tylko poczty, ale również Jabbera - przykładem jest &lt;a href="http://www.ovh.pl"&gt;ovh.pl&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Trzeba jeszcze nadmienić, że Jabber, pomimo braku intensywnego wzrostu użytkowników - nie jest w odwrocie. Protokół XMPP jest powszechnie uważany za bardzo dobry i niedoceniany. Ogólny trend Instant Message'ingu jest taki, że powstające komunikatory nie wymyślają już nowych, zamkniętych protokołów, tylko opierają się o XMPP. Oznacza to, że każdy nowo powstały komunikator będzie w stanie "rozmawiać" z naszym. Jeśli nie będzie - ma niewielkie szanse, żeby wogóle zostać zauważony.&lt;/p&gt;

&lt;h4&gt;Każdy z nas ma już konto Jabber w Google&lt;/h4&gt;

&lt;p&gt;Od jakiegoś czasu Google udostępnia nam coraz to więcej nowych usług, które w świetny sposób integrują się ze sobą. Ktoś kto zakłada sobie konto pocztowe w Googlach, automatycznie dostaje do dyspozycji konto w Google Talk, który jest w pełni zgodny z protokołem XMPP. Komunikatora tego można używać z poziomu  Gmaila (Chat). Nie jest to jednak zbyt praktyczne. Nic nie stoi jednak na przeszkodzie, aby podłączyć się do tego konta z komunikatora w postaci programu zainstalowanego na naszym komputerze.&lt;/p&gt;

&lt;h4&gt;Konfiguracja Google Talk w Pidginie&lt;/h4&gt;

&lt;p&gt;Pidgin może jednocześnie obsługiwać wiele protokołów, a nawet wiele instancji takich samych protokołów. Możemy dzięki temu w jednym pracującym Pidginie mieć jednoczesny dostęp przykładowo do naszego konta Gadu-Gadu, konta na jakimś serwisie Jabberowym oraz Google Talk. Jak to zrobić?&lt;/p&gt;

&lt;p&gt;W oknie Pidgina wybieramy z menu pozycję Konta / Zarządzaj:&lt;/p&gt;

&lt;p&gt;&lt;img class="center" title="pidgin_1" src="/img/2010/01/pidgin_1-300x122.png" alt="" width="300" height="122" /&gt;&lt;/p&gt;

&lt;p&gt;Naciskamy Dodaj:&lt;/p&gt;

&lt;p&gt;&lt;img class="center" title="pidgin_2" src="/img/2010/01/pidgin_2-300x197.png" alt="" width="300" height="197" /&gt;&lt;/p&gt;

&lt;p&gt;I przeprowadzamy właściwą konfigurację:&lt;/p&gt;

&lt;p class="center"&gt;&lt;img class="aligncenter" title="pidgin_3" src="/img/2010/01/pidgin_3-300x289.png" alt="" width="300" height="289" /&gt;&lt;/p&gt;

&lt;p&gt;[nazwa konta] - to sprzed małpki z adresu email :)&lt;/p&gt;

&lt;p&gt;[zasób] - warto podać tu inną wartość na każdym komputerze na którym pracujemy - dzięki temu jeśli np. zapomnimy zamknąć komunikator w pracy,  w domu "nie będzie nas rozłączać" i będziemy mogli prowadzić normalne rozmowy.&lt;/p&gt;

&lt;p&gt;Jeśli używacie zdjęcia profilu w &lt;strong&gt;Google Profile&lt;/strong&gt; - &lt;strong&gt;ważna uwaga&lt;/strong&gt;: łącząc się z komunikatora - ikona użytkownika zastąpi tą w Google Profile. Dlatego warto na każdym komunikatorze pamiętać aby to zdjęcie ustawić - inaczej nasze zdjęcie w profilu Google będzie nam znikać.&lt;/p&gt;

&lt;h4&gt;Google Talk dla konta Google Apps&lt;/h4&gt;

&lt;p&gt;Jeśli pracujecie na koncie Gmailowym które jest skonfigurowane na Twojej własnej domenie (opis usługi popełniłem &lt;a href="/2009/07/google-apps-twoje-wlasne-google/"&gt;w tym wpisie&lt;/a&gt;), dobra wiadomość - również możemy skonfigurować sobie Google Talka, ustawienia są następujące:&lt;/p&gt;

&lt;p&gt;[nazwa konta] - jak wyżej, czyli to co mamy przed małpką w adresie email&lt;/p&gt;

&lt;p&gt;[domena] - nasza domena&lt;/p&gt;

&lt;p&gt;Następnie w zakładce Zaawansowane (Advanced), w polu serwer wpisujemy &lt;code&gt;talk.google.com&lt;/code&gt; - i to wszystko :)&lt;/p&gt;

&lt;p&gt;Bardzo przyjemnym dodatkiem jest możliwość informowania nas przez Pidgina, że mamy nowe maile w Gmailu. Uważam, że to bardzo wygodne. Nowe maile Pidgin pokazuje w następujący sposób:&lt;/p&gt;

&lt;p&gt;&lt;img class="center" title="pidgin_4" src="/img/2010/01/pidgin_4-182x300.png" alt="" width="182" height="300" /&gt;&lt;/p&gt;

&lt;h4&gt;Integracja aplikacji w obrębie Google&lt;/h4&gt;

&lt;p&gt;Wspomniałem wcześniej, że Google bardzo fajnie integruje swoje usługi - świetnym przykładem jest pokazywanie statusu Google Talk w jednej z najlepszych aplikacji które oferuje nam Google jak zwykle nieodpłatnie - w &lt;a href="http://www.google.com/reader/"&gt;Google Reader&lt;/a&gt;ze (które przybliżyłem we wpisie &lt;a href="/2009/07/internet-na-biezaco/"&gt;Internet na bieżąco&lt;/a&gt;). Wygląda to tak:&lt;/p&gt;

&lt;p&gt;&lt;img class="center" title="reader_talk_status" src="/img/2010/01/reader_talk_status-300x131.png" alt="" width="300" height="131" /&gt;&lt;/p&gt;

&lt;p&gt;Życzę wszystkim miłego uniezależniania się od Gadu-Gadu! :)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/5mHbYr4-xmE" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2010/01/jabber-od-google-w-pidginie</feedburner:origLink></entry><entry><title>Pozytywne strony Microsoftu</title><link href="http://feedproxy.google.com/~r/nmepl/~3/_ZyENq5DCsU/pozytywne-strony-microsoftu" rel="alternate" /><id>http://nme.pl/2010/01/pozytywne-strony-microsoftu</id><summary type="html">&lt;img class="post-image" title="Microsoft" src="/img/2010/01/microsoft.jpg" alt="" width="270" height="195" /&gt;&lt;/a&gt;

&lt;p&gt;Usłyszałem, że mój blog jest stronniczy. Wszędzie tylko Linux to Linux tamto, Ubuntu jest fajne, a co Microsoft lub Windows to dziadostwo.&lt;/p&gt;

&lt;p&gt;Faktycznie można odnieść wrażenie, że jestem jakimś przeciwnikiem Microsoftu. Au contraire! :) Może nie specjalnie jestem fanem tej firmy - po prostu niezbyt często jest ich za co pochwalić. Sposób w jaki próbują zdobywać rynek, w jaki podchodzą do klienta, licencjonowanie produktów i wiele innych aspektów ich działalności sprawia, że włos mi się jeży na głowie. Chwalę zamiast tego za zwyczaj inną firmę - Google, ale dlatego, że ich metodologia zdobywania rynku bardzo mi się podoba i trzymam za nich jak najbardziej kciuki.&lt;/p&gt;

&lt;p&gt;Żeby jednak blog nie był taki całkiem stronniczy, napiszę teraz klika pozytywnych słów o Microsofcie :)&lt;/p&gt;

&lt;p&gt;Swojego czasu w jednej z aplikacji Microftu - &lt;a href="http://store.microsoft.com/Help/ISO-Tool"&gt;USB/DVD download tool&lt;/a&gt; - znaleziono kod, który został wcześniej opublikowany na licencji GPL. Informacje te &lt;a href="http://www.heise-online.pl/newsticker/news/item/Potwierdzone-naruszenie-warunkow-licencji-GPL-przez-Microsoft-860245.html"&gt;zostały potwierdzone&lt;/a&gt; przez Microsoft. Mieli w tej sytuacji trzy możliwości - przepisać fragment kodu, wycofać aplikację z rynku lub udostępnić ją na licencji Open Source. Pierwszą reakcją firmy była decyzja o wycofaniu programu z rynku, jednak ktoś ostatecznie &lt;a href="http://www.heise-online.pl/newsticker/news/item/Narzedzie-Microsoftu-na-licencji-GPL-882620.html"&gt;podjął decyzję&lt;/a&gt;, aby... wypuścić program na licencji GPL.&lt;/p&gt;

&lt;p&gt;Uważam, że taka decyzja ze strony Microsoftu jest świetna. W końcu - nic nie stoi na przeszkodzie, żeby nadal brali pieniądze za ich system, pakiet Office oraz specjalistyczne oprogramowanie, a mniejsze narzędzia - udostępniali na takiej licencji. Uważam, że gdyby poszli dalej tą drogą - takich mniejszych narzędzi mogłoby pojawiać się znacznie więcej, pojawiałyby się znacznie częściej (bo w końcu mogli by wykorzystać wszędobylski kod GPL), a społeczność oddanych programistów na pewno pomagałaby im łatać dziury w kodzie, których w ich aplikacjach jest bardzo dużo.&lt;/p&gt;

&lt;p&gt;Mając darmowe wsparcie ze strony developerów, przychylność związaną z przyklaskiwaniem tej bardzo dobrej metodzie publikacji programów zyskali by dużo więcej, niż tylko korzyści materialne, które to moim zdaniem byłyby całkiem wymierne.&lt;/p&gt;

&lt;p&gt;Drugim tematem, za który chciałbym ich pochwalić jest produkt &lt;a href="http://www.bing.com"&gt;Bing&lt;/a&gt; - czyli wyszukiwarka Internetowa. Jest szybka i znacznie bardziej dopracowana niż ich poprzednia wyszukiwarka - MSN Search. Wyszukiwanie nie jest tak inteligentne jak to które oferuje konkurencja, ale produkt jest już całkiem używalny. Usługę tą Microsoft integruje już z produktami innych firm - np. z Twitterem. W mojej opinii jest to krok milowy.&lt;/p&gt;

&lt;p&gt;Smutne jest jednak to, że wypuszczenie ów wyszukiwarki było podyktowane jedynie względami walki z konkurencją - Google. CEO Microsoftu, Steve Ballmer, w swoich wypowiedziach pokazał już nie raz, jak wielką pogardą obdarza firmę Google i ich podejście do zarabiania i oferowania usług oraz jak bardzo nie znosi pojęcia licencji GPL. Obawiam się więc, że opisane przeze mnie dwa pozytywne aspekty działania tej firmy nie mają szansy na zakorzenienie się w polityce Microsoftu jak długo obecny CEO będzie pełnił swoją funkcję.&lt;/p&gt;

&lt;div class="center"&gt;&lt;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="344" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="src" value="http://www.youtube.com/v/nKTnQYScpyk&amp;amp;hl=pl_PL&amp;amp;fs=1&amp;amp;rel=0" /&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;embed type="application/x-shockwave-flash" width="425" height="344" src="http://www.youtube.com/v/nKTnQYScpyk&amp;amp;hl=pl_PL&amp;amp;fs=1&amp;amp;rel=0" allowscriptaccess="always" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;

&lt;p style="margin-top:2em; font-size: 9px; text-align: center; line-height: 80%;"&gt;Wszystkie znaki towarowe i nazwy firm wymienione w tym wpisie zostały użyte tylko w celach informacyjnych i należą do ich właścicieli&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/_ZyENq5DCsU" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2010/01/pozytywne-strony-microsoftu</feedburner:origLink></entry><entry><title>DIY: Akcent świąteczny w miejscu pracy</title><link href="http://feedproxy.google.com/~r/nmepl/~3/YVAZ0pVzfUQ/diy-akcent-swiateczny-w-miejscu-pracy" rel="alternate" /><id>http://nme.pl/2009/12/diy-akcent-swiateczny-w-miejscu-pracy</id><summary type="html">&lt;p class="center"&gt;Zrób to sam: Choinka u Informatyków :)&lt;/p&gt;

&lt;div style="margin:1em auto; text-align:center;font-size:11px"&gt;
&lt;a href="/img/2009/12/daily_picdump_316_125.jpg"&gt;&lt;img title="daily_picdump_316_125" src="/img/2009/12/daily_picdump_316_125-300x225.jpg" alt="" width="300" height="225" /&gt;&lt;/a&gt;
&lt;p&gt;Kliknij, aby powiększyć&lt;/p&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/YVAZ0pVzfUQ" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/12/diy-akcent-swiateczny-w-miejscu-pracy</feedburner:origLink></entry><entry><title>ACL dla plików i katalogów w Ubuntu</title><link href="http://feedproxy.google.com/~r/nmepl/~3/NiPuaTJfZ9A/acl-dla-plikow-i-katalogow-w-ubuntu" rel="alternate" /><id>http://nme.pl/2009/12/acl-dla-plikow-i-katalogow-w-ubuntu</id><summary type="html">&lt;img class="post-image" src="/img/2009/12/acl.png" alt="" title="acl" width="72" height="83" /&gt;

&lt;p&gt;Unixowy system uprawnień dla plików i katalogów został naprawdę dobrze przemyślany i świetnie się sprawdza. Każdy jednak prędzej czy później może trafić na sytuację, w której możliwość stosowania rozszerzonych uprawnień dałaby znacznie większą swobodę i wygodę.&lt;/p&gt;

&lt;h4&gt;Kogo temat może zainteresować?&lt;/h4&gt;

&lt;p&gt;Wydaje mi się, że użytkownicy zwykłych desktopów nie będą ACL'i potrzebować. Jeśli jednak jakiś developer umieszcza przykładowo serwer z repozytorium u siebie albo jest administratorem jakiegoś serwera - myślę, że warto się zapoznać z poniższą tematyką.&lt;/p&gt;

&lt;h4&gt;Krok po kroku&lt;/h4&gt;

&lt;p&gt;Access Control Lists (ang. ACL), czyli listy kontroli dostępu są w jądrze Ubuntu wkompilowana domyślnie już od jakiegoś czasu. Niewiele stoi zatem nam na przeszkodzie, aby aktywnie zacząć z nich korzystać. &lt;strong&gt;ACL należy traktować jako rozszerzenie Unixowego systemu uprawnień plików i katalogów&lt;/strong&gt;, dlatego zestaw komend takich jak &lt;code&gt;chown&lt;/code&gt; czy &lt;code&gt;chmod&lt;/code&gt; nadal obowiązuje.&lt;/p&gt;

&lt;p&gt;Czego zatem potrzebujemy? Musimy uświadomić nasz system, że będziemy wykorzystywać ACL'e dla konkretnych systemów plików. No i przede wszystkim - musimy mieć narzędzia do zarządzania ACL'ami oraz wiedzieć, jak się ich używa :)&lt;/p&gt;

&lt;p&gt;Zatem po kolei.&lt;/p&gt;

&lt;p&gt;Sprawdźmy, czy mamy narzędzia do obsługi ACL'i. Narzędzia nazywają się &lt;code&gt;setfacl&lt;/code&gt;, &lt;code&gt;getfacl&lt;/code&gt; oraz &lt;code&gt;chacl&lt;/code&gt;.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
desktop repos # getfacl
Program getfacl nie jest obecnie zainstalowany.  Można go zainstalować wpisując:
apt-get install acl
getfacl: command not found
desktop repos #
&lt;/pre&gt;

&lt;p&gt;Więc go sobie instalujemy:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo aptitude install acl&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Spróbujmy ustawić jakąś rozszerzoną listę dostępu. Przejdźmy do katalogu domowego, załóżmy katalog test oraz nadajmy uprawnienia rwx użytkownikowi nobody.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
cd
mkdir test
setfacl -R -m u:nobody:rwX test
setfacl: test: Operation not supported
&lt;/pre&gt;

&lt;p&gt;Komunikat &lt;code&gt;Operation not supported&lt;/code&gt; oznacza nic innego jak brak obsługi ACL w systemie plików. Jeśli nasz katalog domowy znajduje się na odrębnym systemie plików home, możemy aktywować obsługę ACL komendą:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo mount -o remount,acl /home&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Teraz ustawianie rozszerzonych uprawnień powinno już działać. Ponowne wydanie komendy setfacl nie powinno już zwrócić błędu. &lt;/p&gt;

&lt;p&gt;Przy okazji, możemy zobaczyć jak wyglądają uprawnienia naszego katalogu:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
nme@desktop ~ $ setfacl -R -m u:nobody:rwX test
nme@desktop ~ $ ls -lad test/
drwxrwxr-x+ 2 nme nme 4096 2009-12-30 14:29 test/
nme@desktop ~ $ getfacl test
# file: test
# owner: nme
# group: nme
user::rwx
user:nobody:rwx
group::r-x
mask::rwx
other::r-x
&lt;/pre&gt;

&lt;p&gt;Warto zwrócić uwagę na uprawnienia zwracane komendą &lt;code&gt;ls -l&lt;/code&gt;: &lt;code&gt;drwxrwxr-x&lt;strong&gt;+&lt;/strong&gt;&lt;/code&gt; - na końcu listy uprawnień znajduje się znak &lt;code&gt;+&lt;/code&gt; oznaczający rozszerzone informacje. Takie uprawnienia możliwe są do odczytu za pośrednictwem &lt;code&gt;getfacl&lt;/code&gt; co też uczyniłem powyżej. Wynik komendy jest dość czytelny.&lt;/p&gt;

&lt;p&gt;Wracając do wydanej komendy:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;setfacl -R -m u:nobody:rwX test&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Co po naszemu brzmi - rekursywnie zmodyfikuj uprawnienia dla użytkownika nobody dla katalogu test ustawiając uprawnienia rwx dla katalogów i rw dla plików.&lt;/p&gt;

&lt;p&gt;Dziecinne proste. Rozbudujmy komendę:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;setfacl -Rm u:nobody:rwX,d:u:nobody:rwX test&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;(pierwsza część jest tak naprawde zbędna, ponieważ uprawnienia dla użytkownika już ustawiliśmy, ale chciałem przedstawić sposób w jaki możemy łączyć uprawnienia w obrębie jednej komendy)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;d:u:...&lt;/code&gt; można zapisać również jako &lt;code&gt;default:u:...&lt;/code&gt; co oznacza, że dla nowo zakładanych plików/katalogów, takie atrybuty mają być domyślnie dodawane.&lt;/p&gt;

&lt;h4&gt;Ważna sprawa, na koniec&lt;/h4&gt;

&lt;p&gt;Aby używać list dostępu, aktywowaliśmy opcję acl poprzez przemontowanie systemu pliku. Niestety, po restarcie, system plików nie będzie już obsługiwał list dostępu.&lt;/p&gt;

&lt;p&gt;Co zatem zrobić?&lt;/p&gt;

&lt;p&gt;Jeśli chcemy, aby nasz system plików pamiętał o tym, że ma obsługiwać rozszerzone listy dostępu, w pliku /etc/fstab należy to zaznaczyć, &lt;code&gt;acl&lt;/code&gt; jako opcję dla naszego systemu plików:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
/dev/mapper/desktop-home /home           ext3    defaults,acl        0       2
&lt;/pre&gt;

&lt;p&gt;Więcej informacji, wraz z przykładami znaleźć możecie na stronach manuala komend do obsługi acl które przedstawiłem w tym tekscie.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/NiPuaTJfZ9A" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/12/acl-dla-plikow-i-katalogow-w-ubuntu</feedburner:origLink></entry><entry><title>Infrastruktura PKI na podstawie SSH</title><link href="http://feedproxy.google.com/~r/nmepl/~3/V0wzMirTQ8I/infrastruktura-pki-na-podstawie-ssh" rel="alternate" /><id>http://nme.pl/2009/12/infrastruktura-pki-na-podstawie-ssh</id><summary type="html">&lt;img class="post-image" title="openssh_logo" src="/img/2009/12/openssh_logo.png" alt="openssh_logo" width="150" height="148" /&gt;

&lt;p&gt;Infrastruktura kluczy publicznych (ang. Public Key Infrastructure, w skrócie PKI) jest podstawą współczesnej kryptografii. Miałem już styczność z wieloma osobami z branży IT, które kompletnie nie czuły o co właściwie w tym chodzi.Myślę, że poniższy tekst napewno się komuś przyda oraz, że warto mu poświęcić 5 minut. &lt;strong&gt;Spróbuję się maksymalnie streścić&lt;/strong&gt; ;)&lt;/p&gt;

&lt;h4&gt;Klucze symetryczne i niesymetryczne&lt;/h4&gt;

&lt;p&gt;Większość szyfrowanych kanałów transmisji wykorzystuje jednocześnie klucze niesymetryczne jak i symetryczne.&lt;/p&gt;

&lt;p&gt;Zaletą &lt;strong&gt;kluczy symetrycznych&lt;/strong&gt; (takich jak AES, Blowfish czy DES) jest szybkość szyfrowania/deszyfrowania przy stosunkowo niskim obciążeniu procesora.&lt;/p&gt;

&lt;p&gt;Wadą kluczy symetrycznych jest etap nawiązania transmisji. Jeśli oba komputery nie posiadają tego samego klucza do szyfrowania/deszyfrowania wiadomości - klucz taki musiałby być wysłany z jednego z nich do drugiego drogą nieszyfrowaną. Taką wymianę klucza można byłoby łatwo podsłuchać. Następnie, korzystając z tak zdobytego klucza - można podsłuchać resztę transmisji (taki atak nosi nazwę Man In The Middle).&lt;/p&gt;

&lt;p&gt;Dlatego właśnie pojawiły się &lt;strong&gt;klucze niesymetryczne&lt;/strong&gt; (np. stosowany standardowo w protokole ssh - algorytm RSA). Klucz niesymetryczny składa się z dwóch części - publicznej i prywatnej. Posiadacz części publicznej klucza jest w stanie zaszyfrować wiadomość. Posiadacz klucza prywatnego - może taką wiadomość odszyfrować. Proste. Dodatkowo - na podstawie klucza publicznego jesteśmy w stanie zweryfikować odcisk klucza (fingerprint) - jeśli się zgadza, wiemy, że rozmawiamy z właściwym serwerem.&lt;/p&gt;

&lt;h4&gt;Klucze w praktyce&lt;/h4&gt;

&lt;p&gt;Serwery Linuxowe na których pracuje usługa ssh mają również wygenerowane swoje klucze. Autentykacja może być różnoraka, jednak do najpopularniejszych należą -  para użytkownik-hasło oraz łączenie się z wykorzystaniem kluczy.&lt;/p&gt;

&lt;p&gt;Wykorzystanie haseł jest proszeniem się o kłopoty. Warto przesiąść się na klucze. Jak to zrobić?&lt;/p&gt;

&lt;p&gt;Wygenerujmy sobie klucz. W obecnych czasach warto zaznaczyć, że chcemy mieć klucz 4096-bitowy, będzie się generował dłużej, ale będzie bezpieczniejszy. Warto też ustawić hasło dla klucza.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
nme@notebook ~ $ ssh-keygen -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/home/nme/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/nme/.ssh/id_rsa.
Your public key has been saved in /home/nme/.ssh/id_rsa.pub.
The key fingerprint is:
12:30:87:ca:06:81:d8:5a:32:41:81:4c:3a:74:33:a9 nme@notebook
The key's randomart image is:
+--[ RSA 4096]----+
|XO.++..          |
|X.+.++           |
|oB..  .          |
|.E+    .         |
| .    . S        |
|       .         |
|                 |
|                 |
|                 |
+-----------------+
nme@notebook ~ $
&lt;/pre&gt;

&lt;p&gt;W katalogu .ssh pojawiły się dwa pliki id_rsa - będący naszym kluczem prywatnym oraz id_rsa.pub - czyli klucz publiczny.&lt;/p&gt;

&lt;p&gt;Klucza publicznego nie trzeba specjalnie strzec. Ważne, aby nasz klucz prywatny nie dostał się w cudze ręce.&lt;/p&gt;

&lt;p&gt;Po co ten obrazek w ASCII? Abyśmy nie musieli weryfikować znak po znaku naszych kluczy. Jeśli chcemy odczytać fingerprint klucza, wydajemy komendę:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ssh-keygen -l&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Jeśli chcemy zobaczyć odcisk wraz z obrazkiem ASCII - wydajemy:&lt;/p&gt;

&lt;code&gt;ssh-keygen -lv&lt;/code&gt;

&lt;p&gt;Okej. Powiedzmy, że mamy klucze i serwer na który chcielibyśmy się łączyć za ich pomocą. Musimy umieścić zawartość naszego klucza publicznego w pliku .ssh/authorized_keys na serwerze docelowym. Możemy to zrobić komendą:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
nme@notebook ~ $ ssh-copy-id serwer:
The authenticity of host 'serwer (x.x.x.x)' can't be established.
RSA key fingerprint is fe:2b:6b:71:6f:81:ef:07:74:89:72:e7:ef:ab:f8:62.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'serwer,x.x.x.x' (RSA) to the list of known hosts.
Password:
nme@notebook ~ $
&lt;/pre&gt;

&lt;p&gt;teraz możemy już normalnie się zalogować:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
nme@notebook ~ $ ssh serwer
nme@serwer ~ $
&lt;/pre&gt;

&lt;p&gt;W pliku &lt;code&gt;.ssh/authorized_keys&lt;/code&gt; możemy trzymać dowolną ilość kluczy.&lt;/p&gt;

&lt;p&gt;Dobrą praktyką jest generowanie kluczy prywatnych na każdej stacji roboczej z której łączymy się na inne maszyny. W wypadku gdy np. ktoś ukradnie nam jedną z tych maszyn - wystarczy usunąć dane klucze z plików authorized_keys serwerów, do których mamy dostęp.&lt;/p&gt;

&lt;p&gt;Skoro już opanowaliśmy klucze - warto wyłączyć autoryzację do naszych serwerów za pośrednictwem par użytkownik-hasło. Robimy to edytując plik /etc/ssh/sshd_config - weryfikujemy ustawienia:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no

# Change to no to disable tunnelled clear text passwords
PasswordAuthentication no
&lt;/pre&gt;

&lt;p&gt;Restart sshd we współczesnych Ubuntu czy RedHatach wykonujemy komendą:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo service ssh restart&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Kiedy wyłączymy już logowanie na pary użytkownik-hasło i pozostawimy jedynie logowanie na klucze:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
nme@notebook ~ $ ssh serwer
Permission denied (publickey).
nme@notebook ~ $
&lt;/pre&gt;

&lt;h4&gt;Gdzie poza SSH stosowane są jeszcze klucze?&lt;/h4&gt;

&lt;p&gt;Infrastruktura kluczy publicznych (PKI) stosowana jest również przykładowo w HTTPS czy w sieciach bezprzewodowych - WPA2 (AES). Klucze niesymetryczne stosowane są do nawiązania transmisji między klientem i serwerem - celem wymiany klucza symetrycznego, a następnie transmisja jest już oparta o klucz symetryczny.&lt;/p&gt;

&lt;p&gt;Znajomość ogólnych zasad działania PKI jest bardzo praktyczna również w przypadku, jeśli przymierzamy się do wykorzystania &lt;a href="http://www.gnupg.org/"&gt;OpenPGP&lt;/a&gt; czy certyfikatów SSL, które możemy traktować jak wyższe stopnie zaawansowania ;)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/V0wzMirTQ8I" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/12/infrastruktura-pki-na-podstawie-ssh</feedburner:origLink></entry><entry><title>Python - Demonologia</title><link href="http://feedproxy.google.com/~r/nmepl/~3/OIXUM4-8qXk/python-demonologia" rel="alternate" /><id>http://nme.pl/2009/11/python-demonologia</id><summary type="html">&lt;a href="http://laurd.deviantart.com/art/The-Snake-Demon-23425999" title="artwork by ~laurD on DeviantART"&gt;&lt;img class="post-image" title="The_Snake_Demon_by_LaurD_scl" src="/img/2009/11/The_Snake_Demon_by_LaurD_scl.jpg" alt="" width="246" height="184" /&gt;&lt;/a&gt;

&lt;p&gt;Python jest świetnym językiem do całej palety zastosowań. Służy on pomocą zarówno administratorom systemów, osobom które potrzebują napisać prosty parser, a nawet twórcom aplikacji webowych - dzięki takim frameworkom jak Django. W poniższym tekscie chciałbym pokazać jak łatwo jest stworzyć usługę systemową (ang. daemon) w języku Python, która będzie wykonywała dla nas określoną czynność - jako przykład przedstawię fakedns - bardzo prostego daemona DNS, który na dowolne zapytanie o adres IP będzie zwracał zawsze ten sam.&lt;/p&gt;

&lt;h4&gt;Dlaczego Python? Co z innymi językami?&lt;/h4&gt;

&lt;p&gt;Nie lepiej mieć aplikację którą można skompilować? Absolwenci kierunków informatycznych jeszcze kilka lat temu dowiadywali się na studiach, że najbardziej zaawansowanym językiem do wszelakich zastosowań jest Java. Mieli praktyczne doświadczenie z tworzenia aplikacji w Javie... i zaczęli pisać. Kod który chciałbym tu przedstawić pisałem dwa lata temu. Zanim się za niego zabrałem, zacząłem od szukania już gotowego rozwiązania za pomocą Google. Znalazłem, nawet kilka. Jedno w Javie. O zgrozo. Ja wiem, że się da. Wiem, że Java jest naprawdę zaawansowanym językiem. Gotowa aplikacja wymaga jednak dużego nadkładu. Trzeba przygotować środowisko, przygotować konkretną ilość pamięci... i czekać kiedy aplikacja się wyłoży. Takie mam przynajmniej doświadczenia z aplikacjami w Javie, które pisali programiści zaraz po studiach, pracując w profesjonalnej firmie software'owej.&lt;/p&gt;

&lt;p&gt;A inne języki? Natualnie. Jest C. Świetny język, ale czy mamy wystarczająco dużo czasu aby w nim pisać nawet małe aplikacje? .NET ? Wolne żarty. Nie dość, że pod Linuxem jest bardzo grubymi nićmi przyszywany, to i nie mamy pewności, czy Microsoft nie powie pewnego dnia hola, jedynie na ich, komercyjnej platformie. Naddatek potrzebnej mocy obliczeniowej, pamięci, wymaganej przestrzeni dyskowej... i ta świadomość, że nie jest to dopracowane i pewnie nigdy nie będzie - niczym Samba próbująca naśladować również kalekie i dziurawe, Microsoftowe domeny.&lt;/p&gt;

&lt;p&gt;A co ze skryptowymi? Mnie na myśl przychodzą trzy alternatywy - Lua, Ruby i skrypt w bashu.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://pl.wikipedia.org/wiki/Lua"&gt;Lua&lt;/a&gt; - niesamowicie przejrzysty język. Piekielnie szybki, realizowany przez wręcz mikroskopijną bibliotekę. Na jego niekorzyść trzeba jednak zaliczyć wręcz niemal konieczność liczenia się z faktem, że jeśli rozwiązanie które potrzebujemy stworzyć, będzie wymagało biblioteki - będziemy zmuszeni długo jej szukać lub przygotować samemu jej obsługę za pomocą języka C.&lt;/p&gt;

&lt;p&gt;Ruby - chyba najbliższy Pythonowi. Dlaczego nie. Bibliotek jest coraz więcej, jest wydajny. Miałem okazję jakiś czas temu nawet coś napisać w tym języku (a dokładnie - przepisać mały framework z Pythona), ale... jakoś w Pythonie pisze mi się lepiej. Co ważne - Ruby jest głęboko zakorzeniony w Perlu. Programistom mówi się jak powinni pisać kod, jednak zawsze mogą robić w to w stylu Perlowym - pisać szybko i wydajnie, jednak przeczytanie i przeanalizowanie go po jakimś czasie staje się piekłem. Kod w Pythonie jest de facto zawsze taki sam, nie zależnie kto by go pisał - czytanie go jest proste i przyjemne.&lt;/p&gt;

&lt;p&gt;No i jeszcze uzupełnię o język skryptowy - Bash. Można w nim naprawdę dużo zrobić. Warto jednak zastanowić się na ile aplikacja będzie zaawansowana i czy zależy nam na wydajności. Podam przykład. Stworzyłem kiedyś skrypt w bashu generujący w oparciu o kilka plików wejściowych reguły dla firewalla, reguły shapera oraz treść dhcpd.conf. Skrypt wewnątrz wywoływał po kilka tysięcy razy awk/sed'a itp. Na maszynie jednoprocesorowej (Pentium 4 1.4 GHz), która pełniła funkcję routera dla sieci 100 Mbit/s, przy mniejszym obciążeniu - skrypt wykonywał się kilka minut. Przy większym - godzinę. Za każdym razem uruchamiając awk, spawnował odrębnego basha. Cóż. Przepisałem rozwiązanie na język Lua. Skrypt niezależnie od obciążenia maszyny wykonywał się w 0.02 sekundy. Jeśli byłby to Python czy Ruby - efekt byłby zapewne zbliżony do Lua.&lt;/p&gt;

&lt;h4&gt;Tworzenie usługi systemowej dla Linux/Unix&lt;/h4&gt;

&lt;p&gt;OK, zaczynamy. Usługa systemowa powinna przede wszystkim:&lt;br /&gt;
- wiedzieć jak pisać do sysloga&lt;br /&gt;
- zrzucić uprawnienia root'a&lt;br /&gt;
- odkleić się od stdin i stdout i przejść w tło&lt;/p&gt;

&lt;p&gt;Jeśli taka usługa dodatkowo potrzebuje obsługiwać jakiś systemowy port TCP/UDP (o numerze niższym niż 1024) - zanim zrzuci ona prawa roota, powinna otworzyć sobie określonego socketa.&lt;/p&gt;

&lt;p&gt;Nie będę tłumaczył poszczególnych fragmentu kodu ponieważ uważam, że jest on wystarczająco przejżysty.&lt;/p&gt;

&lt;h4&gt;fakedns.py&lt;/h4&gt;

&lt;pre class="prettyprint"&gt;
#!/usr/bin/python -u
# -*- coding: utf-8 -*-
" Fake DNS server: Always answer with the same, defined as conf.destip reply, listen at conf.listen "

class conf:
    listen='ADRES_IP_NA_KTÓRYM_APLIKACJA_MA_NASŁUCHIWAĆ'
    destip='ADRES_IP_NA_KTÓRY_APLIKACJA_BĘDZIE_KIEROWAĆ'

import os,sys,pwd,grp
import logging,logging.handlers
import socket

log=logging.getLogger('fakedns')
logging.basicConfig()
logging.root.setLevel(level=logging.INFO)
#logging.root.setLevel(level=logging.DEBUG)
hdlr=logging.handlers.SysLogHandler('/dev/log')
log.addHandler(hdlr)

def drop_privileges(uid_name='nobody',gid_name='nogroup'):
    starting_uid=os.getuid()
    starting_gid=os.getgid()
    starting_uid_name=pwd.getpwuid(starting_uid)[0]
    log.info('fakedns: drop_privileges: started as %s/%s'%(pwd.getpwuid(starting_uid)[0],grp.getgrgid(starting_gid)[0]))
    if os.getuid()!=0:
        log.info("fakedns: drop_privileges: already running as '%s'"%starting_uid_name)
        return
    if starting_uid==0:
        # Get the uid/gid from the name
        running_uid = pwd.getpwnam(uid_name)[2]
        running_gid = grp.getgrnam(gid_name)[2]
        # Try setting the new uid/gid
        try:
            os.setgid(running_gid)
        except OSError,e:
            log.error('Could not set effective group id: %s'%e)
        try:
            os.setuid(running_uid)
        except OSError,e:
            log.error('Could not set effective user id: %s'%e)
        # Ensure a very convervative umask
        new_umask=077
        old_umask=os.umask(new_umask)
        log.info('fakedns: drop_privileges: Old umask: %s, new umask: %s'%(oct(old_umask),oct(new_umask)))
    final_uid=os.getuid()
    final_gid=os.getgid()
    log.info('fakedns: drop_privileges: running as %s/%s'%(pwd.getpwuid(final_uid)[0],grp.getgrgid(final_gid)[0]))

def become_daemon(home='.',stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
    log.info('fakedns: deamonize')
    # perform first fork
    try:
        if os.fork()&amp;gt;0:
            sys.exit(0)
    except OSError,e:
        log.info("fakedns: 1st fork failed: %s"%e.strerror)
        sys.exit(1)
    os.setsid()
    os.chdir(home)
    os.umask(0)
    # second fork
    try:
        if os.fork()&amp;gt;0:
            sys.exit(0)
    except OSError,e:
        log.info("fakedns: 2nd fork failed: %s"%e.strerror)
        sys.exit(1)
    i=open(stdin,'r')
    o=open(stdout,'a+')
    e=open(stderr,'a+',0)
    os.dup2(i.fileno(),sys.stdin.fileno())
    os.dup2(o.fileno(),sys.stdout.fileno())
    os.dup2(e.fileno(),sys.stderr.fileno())

class DNSQuery:
    def __init__(self, data):
        self.data=data
        self.dominio=''

        tipo = (ord(data[2]) &amp;gt;&amp;gt; 3) &amp;amp; 15     # Opcode bits
        if tipo == 0: # Standard query
            ini=12
            lon=ord(data[ini])
            while lon != 0:
                self.dominio+=data[ini+1:ini+lon+1]+'.'
                ini+=lon+1
                lon=ord(data[ini])

    def respuesta(self, ip):
        packet=''
        if self.dominio:
            packet+=self.data[:2] + "\x81\x80"
            # Questions and Answers Counts
            packet+=self.data[4:6] + self.data[4:6] + '\x00\x00\x00\x00'
            # Original Domain Name Question
            packet+=self.data[12:]
            # Pointer to domain name
            packet+='\xc0\x0c'
            # Response type, ttl and resource data length -&amp;gt; 4 bytes
            packet+='\x00\x01\x00\x01\x00\x00\x00\x3c\x00\x04'
            # 4bytes of IP
            packet+=str.join('',map(lambda x: chr(int(x)), ip.split('.')))
        return packet

if __name__ == '__main__':
    udps = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        udps.bind((conf.listen,53))
    except socket.error, (val,e):
        log.info("fakedns: %s"%e)
        sys.exit(1)
    log.info('fakedns: dom.query. 60 IN A %s' % conf.destip)
    drop_privileges()
    become_daemon()
    try:
        while 1:
            data, addr = udps.recvfrom(1024)
            #log.info(addr)
            p=DNSQuery(data)
            udps.sendto(p.respuesta(conf.destip), addr)
            #log.info('%s -&amp;gt; %s' % (p.dominio, conf.destip))
            log.info('fakedns: %s -&amp;gt; %s'%(p.dominio,addr[0]))
    except KeyboardInterrupt:
        log.info('fakedns: done.' % (p.dominio, conf.destip))
        udps.close()
    except:
        log.info('fakedns: crashed serving %s (%s)'%(addr, data))
&lt;/pre&gt;
&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/OIXUM4-8qXk" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/11/python-demonologia</feedburner:origLink></entry><entry><title>Klikanie we Flasha w Ubuntu 9.10</title><link href="http://feedproxy.google.com/~r/nmepl/~3/8d2AOTgQKpM/klikanie-we-flasha-w-ubuntu-910" rel="alternate" /><id>http://nme.pl/2009/11/klikanie-we-flasha-w-ubuntu-910</id><summary type="html">&lt;p&gt;Nowe Ubuntu umożliwia nam skorzystanie z najnowszej wersji Flasha. Będziemy mieli okazje zapoznać się z takimi nowymi ficzerami jak migotanie obrazu uniemożliwiające oglądanie YouTube na pełnym ekranie czy niemożność kliknięcia w jakiś element wewnątrz Flasha (np. podczas ustawiania zakresu dat w Google Analytics). Adobe'a, firmę za Flasha odpowiedzialną oraz za to jak pracuje on pod Linuxem, pozostawiam Waszej ocenie - mnie skończył się na dzisiaj jad ;)&lt;/p&gt;

&lt;p&gt;Rozwiązanie drugiego z wyżej wymienionych problemów jest bardzo proste i znalazłem je &lt;a href="http://helpforlinux.blogspot.com/2009/11/i-cannot-click-on-flash-in-ubuntu.html"&gt;tutaj&lt;/a&gt;. Ten wpis jest jedynie tłumaczeniem.&lt;/p&gt;

&lt;p&gt;Gotowy?&lt;/p&gt;

&lt;p&gt;
* Naciśnij Alt+F2 i Enter&lt;br /&gt;
* &lt;code&gt;gksudo gedit /usr/lib/nspluginwrapper/i386/linux/npviewer&lt;/code&gt;&lt;br /&gt;
* Dodaj następującą linię przed ostatnią linią tekstu&lt;br /&gt;
* &lt;code&gt;export GDK_NATIVE_WINDOWS=1&lt;/code&gt;&lt;br /&gt;
* Zapisz.&lt;br /&gt;
* Zrestartuj aplikacje używające Flasha
&lt;/p&gt;

&lt;p&gt;Zawartość pliku ostatecznie powinna wyglądać tak:&lt;/p&gt;

&lt;img title="flash_wrapper_edit" src="/img/2009/11/flash_wrapper_edit1.png" alt="flash_wrapper_edit" width="342" height="87" /&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/8d2AOTgQKpM" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/11/klikanie-we-flasha-w-ubuntu-910</feedburner:origLink></entry><entry><title>Windows Vista? Zmniejszyć partycję i postawić Ubuntu</title><link href="http://feedproxy.google.com/~r/nmepl/~3/38Cry_0G1-4/windows-vista-zmniejszyc-partycje-i-postawic-ubuntu" rel="alternate" /><id>http://nme.pl/2009/11/windows-vista-zmniejszyc-partycje-i-postawic-ubuntu</id><summary type="html">&lt;img class="post-image" title="vista_cloud" src="/img/2009/11/vista_cloud.png" alt="vista_cloud" width="366" height="277" /&gt;

&lt;p&gt;Ten tekst pisałem miesiąc temu, ale nie miałem od tamtego czasu sposobności aby go opublikować. Plan był prosty. Na świeżo wypakowanym notebooku Della była zainstalowana Vista Home Premium - na jednej partycji, zajmującej cały dysk. Zaplanowałem zmniejszenie partycji do minimum, a następnie pozostawienie jej na później (w dalszym zamyśle - na nigdy), na reszcie dysku instalując Linux Ubuntu. Po kilku pierwszych czynnościach, próbach wykonania czegokolwiek, lekko sfrustrowany, zacząłem pisać tekst, który bardzo szybko przybrał na sile i urósł do rozmiarów tego wpisu :)&lt;/p&gt;

&lt;p&gt;Myślę, że produkt Microsoft Windows 7 zrecenzuję pod kątem wykonania podobnych czynności niebawem, ponieważ Microsoft dał mi prawo do darmowego upgrejdu Visty :)&lt;/p&gt;

&lt;h4&gt;Microsoft Windows Vista Home Premium&lt;/h4&gt;

&lt;p&gt;Świeży, preinstalowany system przez Della, zajmuje 30 GB. Windows XP z grami, pakietami Office i wieloma innymi aplikacjami zbieranymi przez lata, z tego co pamiętam, na partycji 25 GB miał jeszcze trochę miejsca. Ubuntu do swobodnej pracy, pomieści się na 10 GB i będzie miał jeszcze zapas. Ba, można go &lt;a href="/2009/08/instalacja-linux-ubuntu-9-04-na-pendrive-usb/"&gt;uruchomić nawet z 1 GB pendrive'a z persistent storage&lt;/a&gt; (tzw. trwały dysk - zapisywane dane pozostają obecne nawet po restarcie).&lt;/p&gt;

&lt;h4&gt;Pierwsze kliknięcia&lt;/h4&gt;

&lt;p&gt;Wybierając Komputer / Zarządzaj (zatwierdzając monit UAC), a tam Menadżer dysków - mamy możliwość zmniejszenia rozmiaru partycji. Tutaj zaskoczenie, minimalnym rozmiarem partycji systemowej (przy zajętości dysku 30 GB) okazuje się 150 GB. Cóż. Wybrałem ów minimalny rozmiar, zatwierdziłem zmiany, komputer przez chwilę się wytężał, aby ostatecznie pojawił się komunikat Odmowa dostępu. Ponowna próba dała ten sam rezultat.&lt;/p&gt;

&lt;h4&gt;Dalsze kliknięcia&lt;/h4&gt;

&lt;p&gt;Postanowiłem walczyć dalej. Znalazłem darmowe oprogramowanie do zmiany rozmiaru partycji - &lt;a href="http://www.partition-tool.com/personal.htm"&gt;EASEUS Partition Master Home Edition&lt;/a&gt; - łudząco przypominający program Partition Magic czy GParted. Niestety. Tutaj również poległem. Jak się okazało, ów oprogramowanie w wersji darmowej jest dostępne jedynie na wersję 32-bitową systemu. Za 64-bitową należy już zapłacić. To że 64-bitowy system nie jest w stanie poradzić sobie z aplikacją 32-bitową uważam również za porażkę architektów tego bądź co bądź - komercyjnego systemu.&lt;/p&gt;

&lt;p&gt;Zdalne wsparcie administracyjne w oparciu o &lt;a href="http://www.realvnc.com/products/free/4.1/index.html"&gt;RealVNC&lt;/a&gt; również nie jest możliwe o ile UAC jest włączony - kiedy tylko pojawia się monit UAC o autoryzację wykonania danej operacji, RealVNC jest rozłączane. Po ponownym połączeniu nie ma możliwości pracy na tym oknie poprzez RealVNC. Jest to oczywiście niesamowity sukces separacji, jak dla systemu, który był tworzony na bazie środowiska graficznego.&lt;/p&gt;

&lt;p&gt;Ostatecznie zdecydowałem się na wykorzystaniu Ubuntu Live CD i GParted'a. Jaki będzie efekt dowiem się za 7 minut. Aktualizacja: Po ponownym restarcie Visty, pojawiło się Narzędzie do naprawy systemu podczas uruchamiania pokazujące komunkat "Trwa próba naprawienia..." - próba trwała godzinę - przez ten czas nie było nam dane dowiedzieć się czy proces ten coś robi, czy się zawiesił. Zadnych szczegółów. Nic. A jednak! Vista odniosła sukces i wstała! Przypominają mi się tutaj narzekania użytkowników Gnome'a pod Linuxem, że jest mało opcji itp. Z tego co pamiętam, a Gnome używam na codzień - jeśli w jakiejś aplikacji trwa dłużej wykonywana czynność - zawsze istnieje możliwość zobaczenia szczegółów. Panowie z Visty powinni spróbować zgapić to tak samo jak ten widget zegarka ;)&lt;/p&gt;

&lt;p&gt;Coś mnie tchnęło i spróbowałem zainstalować jeszcze &lt;a href="http://www.virtualbox.org"&gt;VirtualBox&lt;/a&gt;'a. Oczywiście pojawiło się kilka monitów UAC, tak jakby jeden nie wystarczał... Ostatecznie sam instalator zdecydował, że dalej nie zabrnie, mimo kolejnych autoryzacji i zażyczył sobie za pośrednictwem kolejnego monitu, uruchomienie instalatora na prawach administratora. W takim momencie wystarczy nacisnąć Naprawa instalacji i zrobione. Postęp jest. Kiedyś było dalej, dalej, dalej. Teraz trzeba coś przeczytać i klikać w większej ilości miejsc.&lt;/p&gt;

&lt;h4&gt;Wrażenia okiem użytkownika Ubuntu&lt;/h4&gt;

&lt;p&gt;Opiszę jeszcze swoje wrażenia, jako człowieka pracującego na codzień na Linux Ubuntu. Szczerze współczuje użytkownikom Visty. Kilka na pozór łatwych czynności naprawdę mnie zmęczyły (fakt, były też zaawansowane, czyli takie które... właśnie ni stąd ni z owąd, pojawił się kolejny ekran autoryzacji UAC. Java się chce aktualizować... kontynuuj... czyli takie które mogą zainstalować wirusa w sterownikach urządzenia). Swoją drogą, takie wtrącenia są wkurzające, prawda? ;) Pod Linuxem Ubuntu wykorzystuje się sudo. Ma ono bardzo prostą właściwość włączoną domyślnie - jeśli trzeba wykonać jakąś czynność na uprawnieniach administratora - monit pojawia się raz. Jeśli w określonej ilości czasu miałaby nastąpić ponownie sytuacja z potrzebą uruchomienia danej czynności na administratorze, jest ona uruchamiana. Dopiero jeśli ten czas się skończy, użytkownik musi się ponownie autoryzować. Na dodatek nie jakimś głupim kliknięciem, tylko podając hasło do swojego konta.&lt;/p&gt;

&lt;div style="margin: 2em; text-align: center"&gt;&lt;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="344" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="src" value="http://www.youtube.com/v/80sWifG40B0&amp;amp;hl=pl_PL&amp;amp;fs=1&amp;amp;" /&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;embed type="application/x-shockwave-flash" width="425" height="344" src="http://www.youtube.com/v/80sWifG40B0&amp;amp;hl=pl_PL&amp;amp;fs=1&amp;amp;" allowscriptaccess="always" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;

&lt;p&gt;W tzw międzyczasie dowiedziałem się jeszcze, że Vista nie ma profili sprzętowych, czyli próba uruchomienia systemu za pomocą środowiska zwirtualizowanego na tym samym, fizycznym dysku twardym jest poważnym proszeniem się o kłopoty.&lt;/p&gt;

&lt;p&gt;Jako, że moje dotychczasowe doświadczenia z Vistą opierały się o wsparcie telefoniczne dla jej użytkowników, głównie w kwestiach uruchomienia sieci (a w zasadzie ewentualnego aktywowania ustawień DHCP), miałem okazję doświadczyć już problemów ze stosem IPv6 w tym systemie. Wygląda na to, że we wczesnych, nie aktualizowanych Vistach, jeśli użytkownik ma aktywowane IPv6 na interfejsie, nie uzyska adresu IPv4 od serwera DHCP. Takich przypadków miałem już kilka, co dość mizernie świadczy o tym systemie operacyjnym. Stos IP jest jest podwaliną na której można budować bezpieczny system. Jeśli ów stos kuleje, bezpieczeństwo systemu nie jest już tak istotne.&lt;/p&gt;

&lt;h4&gt;Podsumowanie&lt;/h4&gt;

&lt;p&gt;Nie wiem jak Wy oceniacie ten system, ale dla mnie, kierunek rozwoju platformy Microsoftu jest lotem koszącym. Nie wiem czego można się spodziewać po Windows 7, ale z tego co widziałem, wiem, że czeka mnie więcej telefonów od zagubionych dusz, które nie potrafią doklikać się do ustawień połączeń sieciowych. Złożoność systemu powinna rosnąć, ale nie w ten sposób. Przejście powinno być płynne. Bez rewolucji. Skoro architekci Windowsów tyle natchnienia czerpią z graficznych środowisk Linuxowych, to powinni zainteresować się tym, czy złożoność interfejsu oraz ilość "pokręteł" jest dla użytkowników problemem czy błogosławieństwem. Historii na ten temat nie trudno znaleźć. Przykładowa - sam Linus Torvalds, który stworzył pierwszego kernela Linuxowego, nie raz miał okazję się już przesiadać między Gnome, KDE i spowrotem :)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/38Cry_0G1-4" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/11/windows-vista-zmniejszyc-partycje-i-postawic-ubuntu</feedburner:origLink></entry><entry><title>Wyłączenie użytkownikowi MOTD na Ubuntu</title><link href="http://feedproxy.google.com/~r/nmepl/~3/uvfhQCgMdx8/wyaczenie-uzytkownikowi-motd-na-ubuntu" rel="alternate" /><id>http://nme.pl/2009/11/wyaczenie-uzytkownikowi-motd-na-ubuntu</id><summary type="html">&lt;p&gt;Tematyka niniejszego wpisu jest, można powiedzieć wręcz banalna, ale myślę, że to trick warty poznania lub przypomnienia. Nie dotyczy tylko i wyłącznie dystrybucji Ubuntu, ale w zasadzie wszystkich Linuxów.&lt;/p&gt;

&lt;p&gt;Jeśli logujesz się po ssh na inny komputer, wyświetlana jest zawartość Message Of The Day (/etc/motd). Jeśli nie chcesz tego widzieć, w swoim katalogu domowym wystarczy utworzyć plik o nazwie &lt;code&gt;.hushlogin&lt;/code&gt;, wersja copy &amp; paste:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
cd
touch .hushlogin
&lt;/pre&gt;

&lt;p&gt;(polecenie &lt;code&gt;cd&lt;/code&gt; bez parametrów to kolejny trick - sprawia, że zostajemy przeniesieni do naszego katalogu domowego)&lt;/p&gt;

&lt;h4&gt;Efekt&lt;/h4&gt;

&lt;p&gt;Zilustrowałem poniżej:&lt;/p&gt;


&lt;pre class="prettyprint"&gt;
nme@desktop ~ $ ssh laptop
Linux laptop 2.6.31-14-generic-pae #48-Ubuntu SMP Fri Oct 16 15:22:42 UTC 2009 i686

To access official Ubuntu documentation, please visit:
http://help.ubuntu.com/

  System information as of Fri Nov  6 20:56:41 CET 2009

  System load: 0.16              Memory usage: 18%   Processes:       155
  Usage of /:  7.1% of 35.51GB   Swap usage:   0%    Users logged in: 1

  Graph this data and manage this system at https://landscape.canonical.com/

Last login: Fri Nov  6 20:55:19 2009 from desktop.local
nme@laptop ~ $ touch .hushlogin
nme@laptop ~ $ logout
Connection to laptop closed.
nme@desktop ~ $ ssh laptop
nme@laptop ~ $ 
&lt;/pre&gt;

&lt;p&gt;Proste, aczkolwiek przydatne :)&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/uvfhQCgMdx8" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/11/wyaczenie-uzytkownikowi-motd-na-ubuntu</feedburner:origLink></entry><entry><title>Dwa komputery z Linuxem - jedna klawiatura i mysz</title><link href="http://feedproxy.google.com/~r/nmepl/~3/PZj-EyggV-0/dwa-komputery-z-linuxem-jedna-klawiatura-i-mysz" rel="alternate" /><id>http://nme.pl/2009/11/dwa-komputery-z-linuxem-jedna-klawiatura-i-mysz</id><summary type="html">&lt;p&gt;Czy kiedykolwiek zdarzyło Ci się pracować na dwóch komputerach - np. notebooku i komputerze stacjonarnym, albo dwóch stacjonarnych jednocześnie? Frustrujące uczucie, kiedy mylą się myszki, prawda? Jeśli oba komputery pracują pod Linuxem - jest na to sposób! :)&lt;/p&gt;

&lt;p&gt;&lt;img class="center" title="x2x" src="/img/2010/11/x2x-381x200.png" alt="x2x" width="381" height="200" /&gt;&lt;/p&gt;

&lt;p&gt;Ostatnio coraz częsciej pracuje na większej ilości komputerów jednocześnie. Zwykle jest to komputer stacjonarny i notebook, ale bywają też bardziej rozbudowane konfiguracje. W takich sytuacjach aż chce się mieć możliwość aby wyjechać myszką "za" ekran i "wjechać" na drugi, najechać na aplikację i coś wpisać za pomocą klawiatury, tej, z której korzystałem do pracy na pierwszej stacji roboczej. Da się to zrobić -  rozwiązaniem tego problemu jest mała aplikacja o nazwie x2x.&lt;/p&gt;

&lt;p&gt;Aplikacja x2x świetnie współpracuje z ssh. Mamy dzięki temu szyfrowane połączenie między oboma stacjami roboczymi i nie musimy się obawiać, że ktoś podsłucha co wpisujemy.&lt;/p&gt;

&lt;p&gt;Aby korzystać z x2x, musimy go najpierw zainstalować. Robimy to na komputerze do którego chcemy się podłączyć, czyli - jeśli standardowo pracujemy na komputerze stacjonarnym, a chcemy mieć możliwość "wyjechania myszką" na notebooka, x2x musimy zainstalować na notebooku.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo aptitude install x2x&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Kiedy mamy już zainstalowaną aplikację, możemy ją wykorzystać.&lt;/p&gt;

&lt;h4&gt;x2x w Ubuntu 9.04 i wcześniejszych&lt;/h4&gt;

&lt;p&gt;Jeśli notebook stoi po lewej stronie, jak na obrazku załączonym powyżej, musimy podać parametr &lt;code&gt;-west&lt;/code&gt;. Mamy do dyspozycji również &lt;code&gt;-north&lt;/code&gt;, &lt;code&gt;-south&lt;/code&gt; i &lt;code&gt;-east&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ssh -X notebook "x2x -west -to :0.0"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;W tym momencie możemy już pracować na obu komputerach, korzystając z klawiatury i myszy z pierwszego z nich.&lt;/p&gt;

&lt;h4&gt;x2x w Ubuntu 9.10 Karmic Koala&lt;/h4&gt;

&lt;p&gt;Nowe X'y, nowy gdm - sprawy się nieco skomplikowały. Problem zaczął doskwierać również innym i został &lt;a href="https://bugs.launchpad.net/ubuntu/+source/x2x/+bug/471726"&gt;rozwiązany przez Roberta Jennigsa i Davida Boersma'ę&lt;/a&gt;. Aby cieszyć się z x2x w Karmic, możemy skorzystać z poniższego skryptu.&lt;/p&gt;

&lt;p&gt;Musimy ustawić w nim następujące parametry:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;USER - nazwa użytkownika na którego logujemy się na zdalnej maszynie&lt;/li&gt;
&lt;li&gt;HOST - adres IP komputera lub jego nazwa w DNS lub /etc/hosts&lt;/li&gt;
&lt;li&gt;HOSTNAME - nazwa zdalnego komputera (taka sama jak zawartość /etc/hostname)&lt;/li&gt;
&lt;li&gt;SIDE - z której strony naszego podstawowego ekranu myszka może wyjechać&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="prettyprint"&gt;
#!/bin/bash
#
# x2x Karmic problem solution based upon:
# https://bugs.launchpad.net/ubuntu/+source/x2x/+bug/471726
# Many thanks to Robert Jennings and David Boersma!

# Setup:

USER=user               # remote host username
HOST=ip                 # remote host IP or name
HOSTNAME=nazwa_hosta    # remote /etc/hostname
SIDE=west               # north / south / west / east
COMPRESSION="-C"        # comment out for LAN

# No need to change anything below:

MERGE="xauth merge /var/run/gdm/auth-for-$USER*/database"
LIST="xauth list"
REMOVE="xauth remove $HOSTNAME/unix:0"
X2X="x2x -$SIDE -to :0.0"

#ssh -X $COMPRESSION $USER@$HOST "$MERGE; $LIST; $X2X; $REMOVE"
#ssh -X $COMPRESSION $USER@$HOST "$LIST"
ssh -X $COMPRESSION $USER@$HOST "$MERGE; $X2X; $REMOVE"
&lt;/pre&gt;

&lt;p&gt;Ja już się uzależniłem, Wam również polecam! :)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/PZj-EyggV-0" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/11/dwa-komputery-z-linuxem-jedna-klawiatura-i-mysz</feedburner:origLink></entry><entry><title>Cisza na blogu</title><link href="http://feedproxy.google.com/~r/nmepl/~3/tQ94Ci1swcE/cisza-na-blogu" rel="alternate" /><id>http://nme.pl/2009/11/cisza-na-blogu</id><summary type="html">&lt;p&gt;Kolega ostatnio zapytał, dlaczego na blogu zapanowała taka grobowa cisza.
Fakt, przez prawie półtorej miesiąca nic tu nie zamieściłem. Czynników które ten fakt spowodowały było kilka, m.in nowy rok akademicki który dla mnie wiąże się z nieco bardziej wytężoną pracą (korzystając z okazji pozdrawiam moich studentów i studentki :)) czy wrednym przeziębieniem które męczyło mnie ponad dwa tygodnie.&lt;/p&gt;

&lt;p&gt;Głównym czynnikiem który spowodował zastój na blogu była jednak zmiana pracy. Poznaje teraz nowe środowisko, zarówno pod względem społecznym jak i systemowym :) Nie mam w zasadzie powodów do narzekań - jest dobrze, choć niestety blog trochę ucierpiał, bo zmalała zarówno liczba subskrybentów jak również ilość dziennych odwiedzin.&lt;/p&gt;

&lt;p&gt;Mam jednak nadzieję, jako, że wspomniane wcześniej środowisko systemowe jest nieco odmienne, że będę miał niebawem więcej ciekawych zagadnień o których będę mógł napisać. Na tą chwilę więcej czytam niż piszę, ale sytuacja niebawem się odmieni. Dlatego dziewięciu wiernych słuchaczy nie powinno być zawiedzionych :) Jedno jest pewne - nie zamierzam tego bloga zarzucić.&lt;/p&gt;

&lt;p&gt;Przespałem, jeśli o wpisy chodzi, kilka ważnych wydarzeń - takich m.in jak wyjście nowego Ubuntu 9.10 Karmic czy betę VirtualBox 3.1.0, ale myślę, że wszystko jest do odrobienia :)&lt;/p&gt;

&lt;p&gt;Tych którzy wcześniej ten blog subskrybowali, a teraz przestali, jeśli będą mieli okazję ten tekst przeczytać - zachęcam do zastosowania prostej zasady - nigdy nie kasujcie subskrypcji ze swoich czytników feedów. Jeśli na jakimś blogu jest zastój, lub wpisy pojawiają się rzadziej - warto skatalogować je jako "Martwe" czy "Rzadkie", bo kto wie, może niechcący umkną Wam rzeczy o których chcielibyście wiedzieć, a dzięki takiemu zabiegowi od razu będziecie widzieli nową aktywność.&lt;/p&gt;

&lt;p&gt;Na koniec tego krótkiego wpisu mała dygresja - Media zapowiadają, że za dwa tygodnie nastąpi szczyt zachorowań na grypę. Pocieszające jest to, że na nową, AH1N1 choruje w kraju w przybliżeniu 600 osób. Dla kraju liczącego sobie 38 mln obywateli, ta liczba brzmi jak szansa na wygranie w Lotto... czego w przeciwieństwie do grypy, Wam życzę! :)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/tQ94Ci1swcE" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/11/cisza-na-blogu</feedburner:origLink></entry><entry><title>Wprowadzenie do systemu kontroli wersji Mercurial</title><link href="http://feedproxy.google.com/~r/nmepl/~3/PltXNMlzNKA/wprowadzenie-do-systemu-kontroli-wersji-mercurial" rel="alternate" /><id>http://nme.pl/2009/10/wprowadzenie-do-systemu-kontroli-wersji-mercurial</id><summary type="html">&lt;img class="post-image" title="mercurial" src="/img/2009/10/mercurial_1.jpg" alt="mercurial" width="200" height="240" /&gt;

&lt;p&gt;Poniższy tekst jest jedynie wprowadzeniem do pracy z Mercurialem. Osoby które chcą pogłębić swoją wiedzę w zakresie tego tematu - zachęcam do przeczytania darmowej książki dostępnej w Internecie - &lt;a href="http://hgbook.red-bean.com/read/"&gt;Mercurial: The Definitive Guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Aby pracować na Mercurialu musimy go najpierw zainstalować. Dla systemu Windows Mercurial jest jedną wygodną do zainstalowania paczką. Informację jak zalecam to zrobić pod Ubuntu, zamieściłem tu: &lt;a href="/2009/10/instalacja-mercurial-z-gui-tortoisehg-pod-ubuntu-904"&gt;Instalacja Mercurial z GUI TortoiseHG pod Ubuntu 9.04&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;Konfiguracja wstępna&lt;/h4&gt;

&lt;p&gt;Zanim rozpoczniemy pracę z Mercurialem, należy w swoim katalogu domowym utworzyć plik .hgrc w którym konfigurujemy swojego użytkownika. Plik ten powinien zawierać następującą treść:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
[ui]
username = Imie Nazwisko &amp;lt; konto@domena.pl &amp;gt;
&lt;/pre&gt;

&lt;p&gt;Pod Linuxem lub Unixem warto również ustawić zmienną środowiskową EDITOR wskazującą na nasz ulubiony edytor. W moim wypadku, w pliku .bashrc w katalogu domowym musiałem dodać na końcu linijkę:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;export EDITOR="vim"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;W tym momencie możemy już przystąpić do pracy.&lt;/p&gt;

&lt;h4&gt;Tworzenie repozytorium&lt;/h4&gt;

&lt;p&gt;Załóżmy, że jesteśmy w katalogu testy.&lt;/p&gt;

&lt;p&gt;Utwórzmy w nim plik notatki.txt zawierający jedną linijkę tekstu:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;To są moje notatki&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Utwórzmy też katalog dokumenty, a w nim umieśćmy plik do-zrobienia.txt zawierający następującą treść:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
[ ] Zrobić przelewy za październik
[ ] Podać do Energetyki stan licznika
&lt;/pre&gt;

&lt;p&gt;Struktura plików i katalogów wygląda zatem następująco:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;user@host testy $ ls
dokumenty  notatki.txt
user@host testy $ ls dokumenty/
do-zrobienia.txt
&lt;/pre&gt;

Możemy w tym momencie utworzyć sobie repozytorium Mercuriala. Przechodzimy zatem do katalogu testy i wydajemy komendę:

&lt;p&gt;&lt;code&gt;user@host testy $ hg init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;W katalogu powinien pojawić się podkatalog .hg&lt;/p&gt;

&lt;p&gt;Co teraz możemy zrobić? Dostępne komendy pojawią się po wydaniu komendy hg bez parametrów:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
user@host testy $ hg
Mercurial Distributed SCM

basic commands:

 add        add the specified files on the next commit
 annotate   show changeset information by line for each file
 clone      make a copy of an existing repository
 commit     commit the specified files or all outstanding changes
 diff       diff repository (or selected files)
 export     dump the header and diffs for one or more changesets
 forget     forget the specified files on the next commit
 init       create a new repository in the given directory
 log        show revision history of entire repository or files
 merge      merge working directory with another revision
 parents    show the parents of the working directory or revision
 pull       pull changes from the specified source
 push       push changes to the specified destination
 remove     remove the specified files on the next commit
 serve      export the repository via HTTP
 status     show changed files in the working directory
 update     update working directory
 view       start interactive history viewer

use "hg help" for the full list of commands or "hg -v" for details
&lt;/pre&gt;

&lt;p&gt;Jeśli chcemy uzyskać większą ilość komend, należy uruchomić polecenie
hg help.&lt;/p&gt;

&lt;p&gt;Zobaczmy status naszego katalogu. Możemy napisać hg status, jednak można też zastosować skróconą wersję komendy:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
user@host testy $ hg st
? dokumenty/do-zrobienia.txt
? notatki.txt
&lt;/pre&gt;

&lt;p&gt;Widzimy, że system Mercurial widzi dwa pliki. Przed ich nazwami figuruje znak pytajnika, co oznacza, że Mercurial nie do końca wie, co to za pliki.&lt;/p&gt;

&lt;h4&gt;Dodawanie plików do repozytorium&lt;/h4&gt;

&lt;p&gt;Do dodawania plików do repozytorium służy komenda hg add [nazwa pliku], przy czym nazwa pliku jest parametrem opcjonalnym. Jeśli jej nie podamy - Mercurial doda wszystkie nieznane pliki w naszym katalogu i podkatalogach do repozytorium.
Dodajmy nasze pliki do repozytorium.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
user@host testy $ hg add
adding dokumenty/do-zrobienia.txt
adding notatki.txt
&lt;/pre&gt;

&lt;p&gt;podglądając status widzimy:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
user@host testy $ hg st
A dokumenty/do-zrobienia.txt
A notatki.txt
&lt;/pre&gt;

&lt;h4&gt;Zatwierdzanie i weryfikowanie zmian&lt;/h4&gt;

&lt;p&gt;możemy w tym momencie zatwierdzić zmiany:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;user@host testy $ hg commit&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;W tym momencie uruchomi się nam edytor w którym uzupełniamy pierwszą linię. Pozostałe zostały zasugerowane przez Mercuriala:&lt;/p&gt;

&lt;p&gt;utworzone repozytorium&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
HG: Enter commit message.  Lines beginning with 'HG:' are removed.
HG: Leave message empty to abort commit.
HG: --
HG: user: Imie Nazwisko &amp;lt;konto@domena.pl&amp;gt;
HG: branch 'default'
HG: added dokumenty/do-zrobienia.txt
HG: added notatki.txt
&lt;/pre&gt;

&lt;p&gt;Jeśli chcemy którąś z tych linii pozostawić, powinniśmy usunąć HG: sprzed wpisu.&lt;/p&gt;

&lt;p&gt;Po zapisaniu pliku, jeśli Mercurial znajdzie choć jedną linię opisu (czyli w naszym wypadku tekst "utworzone repozytorium"), zapisze to jako nową wersję (revision).&lt;/p&gt;

&lt;p&gt;Możemy podejżeć zmiany:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
user@host testy $ hg st
user@host testy $
&lt;/pre&gt;

&lt;p&gt;Jak widać, nie ma żadnych. Zobaczmy zatem historię:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;user@host testy $ hg log
changeset:   0:996ae301b615
tag:         tip
user:        Imie Nazwisko &amp;lt;konto@domena.pl&amp;gt;
date:        Tue Oct 13 08:40:12 2009 +0200
summary:     utworzone repozytorium

user@host testy $
&lt;/pre&gt;

&lt;p&gt;Dokonajmy jakiejś zmiany w pliku dokumenty/do-zrobienia.txt, powiedzmy, że teraz wygląda tak:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
[x] Zrobić przelewy za październik
[ ] Podać do Energetyki stan licznika
&lt;/pre&gt;

&lt;p&gt;Sprawdzając status widzimy:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
user@host testy $ hg st
M dokumenty/do-zrobienia.txt
user@host testy $
&lt;/pre&gt;

&lt;p&gt;Możemy też podejżeć co zostało zmienione:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
user@host testy $ hg diff
diff -r 996ae301b615 dokumenty/do-zrobienia.txt
--- a/dokumenty/do-zrobienia.txt	Tue Oct 13 08:40:12 2009 +0200
+++ b/dokumenty/do-zrobienia.txt	Tue Oct 13 08:46:21 2009 +0200
@@ -1,2 +1,2 @@
-[ ] Zrobić przelewy za październik
+[x] Zrobić przelewy za październik
 [ ] Podać do Energetyki stan licznika
user@host testy $
&lt;/pre&gt;

&lt;p&gt;Zatwierdzę teraz zmiany, sprawdzę status i historię:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
user@host testy $ hg commit
user@host testy $ 

user@host testy $ hg st
user@host testy $ 

user@host testy $ hg log
changeset:   1:155c93da6b65
tag:         tip
user:        Imie Nazwisko &amp;lt;konto@domena.pl&amp;gt;
date:        Tue Oct 13 08:48:01 2009 +0200
summary:     aktualizacja

changeset:   0:996ae301b615
user:        Imie Nazwisko &amp;lt;konto@domena.pl&amp;gt;
date:        Tue Oct 13 08:40:12 2009 +0200
summary:     utworzone repozytorium

user@host testy $
&lt;/pre&gt;

&lt;h4&gt;Usuwanie plików z repozytorium&lt;/h4&gt;

&lt;p&gt;Teraz usunę plik notatki.txt:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
user@host testy $ hg remove notatki.txt
user@host testy $ ls
dokumenty
user@host testy $
&lt;/pre&gt;

&lt;p&gt;Zatwierdzę zmiany i zobaczę historię. Ograniczę sobie przy okazji historię do dwóch najaktualniejszych zmian:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
user@host testy $ hg commit
user@host testy $ hg log -l 2
changeset:   2:ec95d15664fb
tag:         tip
user:        Imie Nazwisko &amp;lt;konto@domena.pl&amp;gt;
date:        Tue Oct 13 08:51:36 2009 +0200
summary:     usunięte notatki

changeset:   1:155c93da6b65
user:        Imie Nazwisko &amp;lt;konto@domena.pl&amp;gt;
date:        Tue Oct 13 08:48:01 2009 +0200
summary:     aktualizacja

user@host testy $
&lt;/pre&gt;

&lt;p&gt;Zdecydowałem jednak, że przywrócę plik notatki. Cofnę zatem ostatniego commita komendą rollback, zobaczę jaki jest status i przywrócę plik notatki.txt:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
user@host testy $ hg rollback
rolling back last transaction
user@host testy $ hg log
changeset:   1:155c93da6b65
tag:         tip
user:        Imie Nazwisko &amp;lt;konto@domena.pl&amp;gt;
date:        Tue Oct 13 08:48:01 2009 +0200
summary:     aktualizacja

changeset:   0:996ae301b615
user:        Imie Nazwisko &amp;lt;konto@domena.pl&amp;gt;
date:        Tue Oct 13 08:40:12 2009 +0200
summary:     utworzone repozytorium

user@host testy $ hg st
R notatki.txt
user@host testy $ ls
dokumenty
user@host testy $ hg revert notatki.txt
user@host testy $ ls
dokumenty  notatki.txt
user@host testy $
&lt;/pre&gt;

&lt;p&gt;Myślę, że jako wprowadzenie, taki opis wystarczy :)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/PltXNMlzNKA" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/10/wprowadzenie-do-systemu-kontroli-wersji-mercurial</feedburner:origLink></entry><entry><title>Drażniący dzwięk podczas pracy na baterii w Ubuntu</title><link href="http://feedproxy.google.com/~r/nmepl/~3/UEejXZvUpXw/drazniacy-dzwiek-podczas-pracy-na-baterii-w-ubuntu" rel="alternate" /><id>http://nme.pl/2009/10/drazniacy-dzwiek-podczas-pracy-na-baterii-w-ubuntu</id><summary type="html">&lt;img class="post-image" src="/img/2009/10/intel-core2-duo.jpg" alt="intel-core2-duo" title="intel-core2-duo" width="128" height="96" /&gt;

&lt;p&gt;Linux Ubuntu jest na tą chwilę chyba najlepszą Linuxową dystrybucją na desktopa. Jest ona jednak nadal świeża i zdarza się, że czasami ma pewne problemy z nowszym sprzętem.&lt;/p&gt;

&lt;p&gt;Jednym z takich problemów z którym się zetknąłem jest drażniący pisk czyli &lt;strong&gt;dźwięk o wysokiej częstotliwości&lt;/strong&gt; (ang. &lt;strong&gt;high-pitch noise&lt;/strong&gt;) podczas pracy notebooka na zasilaniu bateryjnym. Przyczyną tego dzwięku jest wyższy tryb ACPI odpowiedzialny z zarządzaniem zasilaniem i temperaturą. Więcej szczegółów technicznych można znaleźć na stronach Intela opisujących &lt;a href="http://www.intel.com/technology/itj/2006/volume10issue02/art03_Power_and_Thermal_Management/p03_power_management.htm"&gt;C-State Architecture&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Mój notebook ma procesor Intel Centrino (Core2) Duo T5600 i niestety ten problem go dotyczy.&lt;/p&gt;

&lt;h4&gt;Stare rozwiązanie stosowane w Ubuntu 8.04&lt;/h4&gt;

&lt;p&gt;W jądrze systemu ustawiona jest możliwość zmiany tego parametru podczas pracy systemu (parametr &lt;code&gt;CONFIG_ACPI_PROCESSOR=y&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Aby dźwięk ustał należy uruchomić komendę:&lt;/p&gt;

&lt;code&gt;echo 2 &amp;gt;/sys/module/processor/parameters/max_cstate&lt;/code&gt;

Można pokusić się o dodanie takiego skryptu do /etc/acpi.d który ten problem rozwiąże, ale lepiej zastosować następne rozwiązanie.

&lt;p&gt;Szczegółowe informacje można znaleźć &lt;a href="http://www.thinkwiki.org/wiki/Problem_with_high_pitch_noises#Solutions_for_CPU-triggered_noise"&gt;tutaj&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;Nowe rozwiązanie dla Ubuntu 8.04, 8.10 i 9.04 oraz prawdopodobnie pozostałych&lt;/h4&gt;

&lt;p&gt;W konfiguracji grub'a, do parametrów kernela należy dodać &lt;code&gt;processor.max_cstate=2&lt;/code&gt;, przykładowy wpis:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
title           Ubuntu 9.04, kernel 2.6.28-15-generic
root            (hd0,1)
kernel          /vmlinuz-2.6.28-15-generic root=/dev/mapper/sys-root ro quiet splash processor.max_cstate=2
initrd          /initrd.img-2.6.28-15-generic
quiet
&lt;/pre&gt;

&lt;p&gt;Rozwiązanie to ma tą wadę - trzeba o nim pamiętać i uzupełniać w konfiguracji gruba nowe kernele o ten parametr. Jeśli to rozwiązanie jest dla Ciebie przydatne to zachęcam do oznaczenia go sobie w Google Readerze jako ulubione, bo kto wie, być może będzie potrzeba aby do niego wrócić :)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/UEejXZvUpXw" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/10/drazniacy-dzwiek-podczas-pracy-na-baterii-w-ubuntu</feedburner:origLink></entry><entry><title>Mercurial w Eclipse IDE</title><link href="http://feedproxy.google.com/~r/nmepl/~3/hpFSzgeE1RE/mercurial-w-eclipse-ide" rel="alternate" /><id>http://nme.pl/2009/10/mercurial-w-eclipse-ide</id><summary type="html">&lt;img class="post-image" title="eclipse_logo" src="/img/2009/10/eclipse_logo.jpg" alt="eclipse_logo" width="128" height="128" /&gt;

&lt;p&gt;Środowisko programistyczne &lt;a href="http://www.eclipse.org/"&gt;Eclipse&lt;/a&gt; jest jednym z najlepszych spośród tych dostępnych za darmo. Osobiście preferuję vim'a, ale większość programistów przywykło do większych luksusów :)&lt;/p&gt;

&lt;p&gt;Eclipse jest dostępny zarówno pod Windows jak i pod Linuxem. Jego instalacja w systemie Microsoftu jest dość prostą czynnością.&lt;/p&gt;

&lt;p&gt;W Linux Ubuntu, Eclipse jest niby też dostępny w standardowej dystrybucji, ale mnie osobiście nigdy nie udało się go z sukcesem uruchomić ze standardowej paczki. Tym z Was, którzy chcą z niego skorzystać pod Ubuntu zachęcam do pobrania Eclipse z ich strony, następnie rozpakowanie go do docelowego katalogu, a na koniec ręczne stworzenie skrótu.&lt;/p&gt;

&lt;p&gt;Eclipse zostało stworzone w Javie i w zamyśle jest IDE służącym do tworzenia aplikacji właśnie w tym języku. Dzięki zaawansowanemu  systemowi rozszerzeń możliwe jest jednak jego wykorzystanie do tworzenia aplikacji w innych językach. Właśnie ten mechanizm umożliwi nam również uzupełnienie Eclipse'a o system kontroli wersji.&lt;/p&gt;

&lt;p&gt;Aby mieć możliwość z korzystania z Mercuriala, konieczna będzie jego instalacja w systemie. Dla systemu Microsoft Windows można go pobrać &lt;a href="http://mercurial.berkwood.com/"&gt;z tej strony&lt;/a&gt;. Dodatkowo warto zainstalować &lt;a href="http://bitbucket.org/tortoisehg/stable/wiki/download"&gt;TortoiseHG&lt;/a&gt;. Kroki opisujące instalację pod Linux Ubuntu wraz z TortoiseHG opisałem &lt;a href="/2009/10/instalacja-mercurial-z-gui-tortoisehg-pod-ubuntu-904"&gt;tutaj&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;Wtyczka Mercurial-Eclipse&lt;/h4&gt;

&lt;p&gt;Aby za pomocą środowiska Eclipse posługiwać się systemem kontroli wersji Mercurial, konieczne będzie dodanie jego repozytorium do dostępnych źródeł w Eclipse. W tym celu wybieramy &lt;strong&gt;Help / Install new software... / Add...&lt;/strong&gt; i podajemy:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;name:&lt;/code&gt; &lt;code&gt;Mercurial Eclipse&lt;/code&gt;&lt;br /&gt;
&lt;code&gt;location:&lt;/code&gt; &lt;a href="http://www.vectrace.com/eclipse-update/"&gt;http://www.vectrace.com/eclipse-update/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Osobiście testowałem plugina w wersji &lt;strong&gt;1.4.1286&lt;/strong&gt; - zainstalował się i działał prawidłowo.&lt;/p&gt;

&lt;p&gt;Po zainstalowaniu, plugin poprosi o restart środowiska Eclipse. Kiedy już Eclipse zacznie ponownie działać, powinniśmy mieć dostęp do nowej funkcjonalności.&lt;/p&gt;

&lt;p&gt;Dość ważną kwestią jest na początku zaglądnięcie do ustawień Mercuriala - &lt;strong&gt;Window / Preferences&lt;/strong&gt;, wybieramy &lt;strong&gt;Team / Mercurial&lt;/strong&gt;. Należy tutaj podać Mercurial Username w postaci &lt;em&gt;Imię nazwisko &amp;lt;adres@email&amp;gt;&lt;/em&gt;. Zaleciłbym również zaznaczenie opcji &lt;strong&gt;Automatically associate Mercurial with new projects containing hg repository&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Jeśli chodzi o zakładanie repozytorium dla istniejącego już projektu - w Eksploratorze workspace wybieramy projekt, naciskamy prawy klawisz myszy, następnie &lt;strong&gt;Team / Share project&lt;/strong&gt; - tam wybieramy Mercurial i na następnej stronie wizarda &lt;strong&gt;Use project root&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Jeśli repozytorium już było założone - trzeba zaglądnąć do projektu podobnie jak przy tworzeniu nowego repozytorium, wybrać &lt;strong&gt;Share project&lt;/strong&gt;, a na końcu &lt;strong&gt;Use existing .hg repository&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;W tym momencie możemy już korzystać z bardziej urozmaiconej zawartości popup menu Team :)&lt;/p&gt;

&lt;p&gt;&lt;img style="margin:0.5em 0" title="eclipse-mercurial" src="/img/2009/10/eclipse-mercurial.jpg" alt="eclipse-mercurial" width="640" height="714" /&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/hpFSzgeE1RE" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/10/mercurial-w-eclipse-ide</feedburner:origLink></entry><entry><title>Instalacja Mercurial z GUI TortoiseHG pod Ubuntu 9.04</title><link href="http://feedproxy.google.com/~r/nmepl/~3/qr05t45muUk/instalacja-mercurial-z-gui-tortoisehg-pod-ubuntu-904" rel="alternate" /><id>http://nme.pl/2009/10/instalacja-mercurial-z-gui-tortoisehg-pod-ubuntu-904</id><summary type="html">&lt;img class="post-image" title="mercurial-3" src="/img/2009/10/mercurial-3.png" alt="mercurial-3" width="252" height="205" /&gt;

&lt;p&gt;&lt;a href="http://www.selenic.com/mercurial/"&gt;Mercurial&lt;/a&gt; jest jednym z najpopularniejszych ostatnio systemów kontroli wersji. Został on napisany w języku Python i coraz więcej projektów jest do niego migrowanych. Google Code umożliwia wybór jednego z dwóch systemów kontroli wersji - jednym z nich jest SVN, drugim właśnie Mercurial.&lt;/p&gt;

&lt;h4&gt;Różnice między scentralizowanym a&amp;nbsp;rozproszonym systemem kontroli wersji&lt;/h4&gt;

&lt;p&gt;Zasada działania Mercuriala jest zbliżona do &lt;a href="http://git-scm.com/"&gt;Git&lt;/a&gt;'a - oba są tzw. rozproszonymi systemami kontroli wersji. SVN z drugiej strony jest systemem zcentralizowanym. Praca na systemie rozproszonym jest o tyle wygodna, że każda lokalna kopia repozytorium może być traktowana jako pełnoprawna i całkowicie niezależna. Rozwijając kod który jest obsługiwany w takim systemie kontroli wersji, commitowanie, czyli zatwierdzanie mniejszych porcji zmian jest znacznie wygodniejsze i nie wymaga zaprzątania głowy głównego repozytorium... którego tak naprawdę wcale nie musi być.&lt;/p&gt;

&lt;h4&gt;Jak to robi Linus Torvalds?&lt;/h4&gt;

&lt;p&gt;Większe projekty, takie jak jądro Linuxa coraz częściej przechodzą na rozproszone systemy kontroli wersji. Linus Torvalds bardzo zachęca wszystkich do migrowania do Gita z SVN'a. Git został napisany właśnie z myślą o developerach jądra systemu Linux. Głównymi zaletami według niego są dwie kwestie - pierwsza: znacznie &lt;strong&gt;wygodniejsze merge'owanie&lt;/strong&gt; (łączenie zmian wprowadzonych przez różnych developerów) oraz druga - rozproszone repozytoria pozwalają na &lt;strong&gt;hierarchiczne scalanie kodu&lt;/strong&gt; (z punktu widzenia pracy grupowej). Dzięki tej drugiej, Linus może powierzyć np. opiekę nad modułami jądra dotyczącymi sieci komuś, kto zna się na tym konkretnym temacie lepiej, potrafi weryfikować zmiany i poprawki. Zebrane do repozytorium przez opiekuna drzewa sieci poprawki, Linus może włączyć do jego repozytorium, które traktowane jest jako główne mając pewność, że wszystkie zmiany zostały odpowiednio zweryfikowane.&lt;/p&gt;

&lt;h4&gt;Kontrola wersji z linii komend&lt;/h4&gt;

&lt;p&gt;Mercuriala można zainstalować ze standardowego pakietu w Ubuntu. Na pakiet składa się jedna aplikacja - hg. Za jej pomocą można wykonać wszystkie operacje na repozytorium z poziomu linii komend.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
$ hg
Mercurial Distributed SCM

basic commands:

 add        add the specified files on the next commit
 annotate   show changeset information by line for each file
 clone      make a copy of an existing repository
 commit     commit the specified files or all outstanding changes
 diff       diff repository (or selected files)
 export     dump the header and diffs for one or more changesets
 forget     forget the specified files on the next commit
 init       create a new repository in the given directory
 log        show revision history of entire repository or files
 merge      merge working directory with another revision
 parents    show the parents of the working directory or revision
 pull       pull changes from the specified source
 push       push changes to the specified destination
 remove     remove the specified files on the next commit
 serve      export the repository via HTTP
 status     show changed files in the working directory
 update     update working directory
 view       start interactive history viewer

use "hg help" for the full list of commands or "hg -v" for details
&lt;/pre&gt;

&lt;h4&gt;Kontrola wersji z poziomu interfejsu graficznego&lt;/h4&gt;

&lt;p&gt;Istnieje jednak możliwość pracy graficznej. Windowsowi użytkownicy jako graficzny interfejs zwykle wykorzystują TortoiseHG, który wywodzi się z TortoiseSVN. Pod Linuxem możemy również wykorzystać TortoiseHG. &lt;/p&gt;

&lt;h4&gt;Instalacja Mercuriala i TortoiseHG pod Ubuntu 9.04&lt;/h4&gt;

&lt;p&gt;Uruchomienie komend zamieszczonych poniżej sprawi, że nasz Mercurial zostanie "podniesiony" do najnowszej stabilnej wersji, pojawi się nam TortoiseHG również w wersji stabilnej, a następnie TortoiseHG zostanie włączone do domyślnego menadżera plików w Gnome - Nautilusa. Zainstalowana zostanie również aplikacja Meld, która czyni merge'owanie całkiem przyjemną czynnością w interfejsie graficznym :)&lt;/p&gt;

&lt;pre class="prettyprint"&gt;# Najpierw przechodzimy na roota, tego którego w Ubuntu nie ma ;) 

sudo -i

# Dodajemy drzewo stable repozytorium Mercuriala z Ubuntu Launchpad PPA

cat &amp;gt;/etc/apt/sources.list.d/mercurial.list &amp;lt;&amp;lt; EOF
deb http://ppa.launchpad.net/mercurial-ppa/stable-snapshots/ubuntu jaunty main
deb-src http://ppa.launchpad.net/mercurial-ppa/stable-snapshots/ubuntu jaunty main
EOF
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-key 323293EE

# Dodajemy drzewo stable repozytorium TortoiseHG z Ubuntu Launchpad PPA
cat &amp;gt;/etc/apt/sources.list.d/tortoisehg.list &amp;lt;&amp;lt; EOF
deb http://ppa.launchpad.net/tortoisehg-ppa/stable-snapshots/ubuntu jaunty main
deb-src http://ppa.launchpad.net/tortoisehg-ppa/stable-snapshots/ubuntu jaunty main
EOF
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-key D5056DDE

# odświeżamy listę repozytoriów i pobieramy pakiety oraz dodajemy obsługę bindingsów Pythona w Nautilusie

aptitude update
aptitude install -y python-nautilus mercurial tortoisehg tortoisehg-nautilus meld

# doinstalowujemy pakiet iniparse
wget http://iniparse.googlecode.com/files/python-iniparse_0.3.1-1_all.deb
dpkg -i python-iniparse_0.3.1-1_all.deb
rm python-iniparse_0.3.1-1_all.deb
&lt;/pre&gt;

&lt;p&gt;Po wykonaniu tych komend najlepiej się przelogować ponownie, aby Nautilus zdał sobię sprawę z wprowadzonych zmian. Można też (już na swoim użytkowniku) uruchomić komendę:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;nautilus -q&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Która spowoduje przeładowanie Nautilusa (może nam zniknąć do następnego zalogowania zawartość pulpitu). Jeśli wszystko pójdzie pomyślnie, w efekcie możemy zarządzać repozytorium w następujący sposób:&lt;/p&gt;

&lt;p&gt;&lt;img class="center" title="mercurial-1" src="/img/2009/10/mercurial-1.jpg" alt="mercurial-1" width="646" height="624" /&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/qr05t45muUk" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/10/instalacja-mercurial-z-gui-tortoisehg-pod-ubuntu-904</feedburner:origLink></entry><entry><title>Powiadomienia SMS mBank mobile - drugie podejście</title><link href="http://feedproxy.google.com/~r/nmepl/~3/9CfGNKNI_Tc/powiadomienia-sms-mbank-mobile-drugie-podejscie" rel="alternate" /><id>http://nme.pl/2009/09/powiadomienia-sms-mbank-mobile-drugie-podejscie</id><summary type="html">&lt;p&gt;Dwa miesiące temu przedstawiłem dwa sposoby w jaki można sobie uruchomić powiadomienia SMS od aplikacji lub o przychodzących mailach. Oba miały pewne wady więc zdecydowałem się powrócić do tematu raz jeszcze.&lt;/p&gt;

&lt;p&gt;&lt;a href="/2009/08/mbank-mobile-email-jako-sms/"&gt;Pierwszym&lt;/a&gt; rozwiązaniem, było wykorzystanie &lt;strong&gt;+48xxxxxxxxx@text.plusgsm.pl&lt;/strong&gt;
Rozwiązanie dobre, bo dostajemy natychmiast powiadomienie na komórkę. Dodatkowo większość skrzynek pocztowych ma możliwość ustawienia automatycznej kopii na drugi adres - więc w dosłownie chwilę możemy sobie ustawić automatyczne powiadomienie o mailach.&lt;/p&gt;

&lt;p&gt;Rozwiązanie to ma jednak swoją wadę - dostajemy pełną treść, która nie zmieści się w jednym SMS'ie jeśli w mailu jest jakakolwiek treść poza samym tematem.&lt;/p&gt;

&lt;p&gt;&lt;a href="/2009/08/bramka-sms-od-google/"&gt;Drugim&lt;/a&gt; zasugerowanym przeze mnie rozwiązaniem było wykorzystanie możliwości &lt;strong&gt;wysyłania powiadomień SMS z Google Calendar&lt;/strong&gt;. To rozwiązanie również jest dobre. Możemy wykorzystać &lt;a href="/2009/07/google-apps-twoje-wlasne-google/"&gt;konto w Google Apps&lt;/a&gt;, dzięki czemu adres powiadomień jest bardziej uniwersalny, ale ma też swoje wady - chodzi mianowicie o dzienny limit powiadomień SMS z kalendarza Google. Jak się przekonałem, taki limit jest. Dokładnej liczby nie znam, ale w przybliżeniu to około 25 SMS'ów.&lt;/p&gt;

&lt;h4&gt;Rozwiązanie optymalne?&lt;/h4&gt;

&lt;p&gt;Postanowiłem zatem poszukać czegoś po środku. Wykorzystałem obsługę skrzynki Google do pobierania wiadomości, a następnie jedynie nadawcę i temat przekazuje do usługi text.plusgsm.pl. Wydaje mi się, że rozwiązanie jest optymalne. Oto kod:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
#!/usr/bin/env python
# -- encoding: utf8 --

__author__ = 'mw AT nme.pl'
__version__ = '1.4'
__date__ = 'pią, 25 wrz 2009, 13:22:28 CEST'

class setup:
    verbose = False
    class google:
        login = 'KONTO@GOOGLE'
        password = 'HASŁO'
    class notify:
        recipient="+48xxxxxxxxx@text.plusgsm.pl"

import poplib
import email
import email.Header
#import sms
import smtplib
import re

class Fwd:

    def __init__(self,address,subject):

        mesg = "From: %s\nTo: %s\nSubject: %s\n\n" % (address, setup.notify.recipient, subject)
        server = smtplib.SMTP('smsb.plusgsm.pl')
        if setup.verbose:
            server.set_debuglevel(1)
        server.sendmail (address, setup.notify.recipient, mesg)
        server.quit()

class Mailbox:

    def __init__(self):

        self.server = poplib.POP3_SSL('pop.gmail.com', 995)
        self.server.user(setup.google.login)
        self.server.pass_(setup.google.password)
        self.server.set_debuglevel(0)

        # fetch
        count = self.server.stat()[0]
        if setup.verbose:
                print count
        if count:
            for i in range(1,count+1):
                (header, msg, octets) = self.server.retr (i)
                mail = email.message_from_string('\n'.join(msg))
                address = email.Header.decode_header(mail['From'])[1]
                if address[1]:
                    address = address[0].decode(address[1],'ignore')
                else:
                    address = address[0]
                address = re.sub('&gt;\s*$','',re.sub('^\s*&lt; ','',address))
                subject = email.Header.decode_header(mail['Subject'])[0]
                if subject[1]:
                    subject = subject[0].decode(subject[1],'ignore')
                else:
                    subject = subject[0]
                #print subject
                #sms.parse(subject.split())
                Fwd(address,subject)
                #self.server.dele (i)

        # commit
        self.server.quit()

mbox = Mailbox()
&lt;/pre&gt;

Aby te powiadomienia działały, na koncie shellowym umieszczamy skrypt, nadajemy mu prawa do uruchomienia, przechodzimy do edycji crona:

&lt;p&gt;&lt;code&gt;chmod +x pop2smsV2.py&lt;br /&gt;
crontab -e&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;dodajemy zadanie do crona, aby był uruchamiany co minutę:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;* * * * * /home/NAZWA/bin/pop2smsV2.py &amp;gt;/dev/null 2&amp;gt;&amp;amp;1&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;Podsumowanie&lt;/h4&gt;

&lt;p&gt;Teraz to rozwiązanie najbardziej przypomina mi to które miałem w Erze. Trzeba niestety użyć do tego shella z cronem. OVH odpada z dwóch powodów - brak crona oraz brak dostępu do sieci z poziomu shella. Może i by się dało uruchomić to jako CGI z ich webowym cronem, ale niestety mija się to trochę z celem, ponieważ cron OVH może być uruchamiany najczęściej co godzinę.&lt;/p&gt;

&lt;p&gt;Przewagą tego rozwiązania nad powiadomieniem z Ery jest brak limitu skrzynki 12 MB. Limitem jest ponad 7 GB co nie stanowi już problemu. Jeśli nie chcemy zostawiać na skrzynce śladu - możemy usunąć komentarz z linii self.server.dele (i) - co spowoduje kasowanie przesłanych jako SMS wiadomości.&lt;/p&gt;

&lt;p&gt;Zaletą obsługi powiadomień za pomocą crona jest to, że możemy ustalić sztywne godziny w których skrypt ma działać - możemy ustawić, że powiadomienia mogą przychodzić pomiędzy 8:00, a 16:00 oraz 18:00 - 22:00 (trzeba się wtedy liczyć z faktem, że o ósmej rano otrzymamy wszystkie SMS'y z nocy). Jeśli chcemy mieć powiadomienia aktywne w godzinach 8:30 - 22:30, robimy to następującymi regułami:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
30-59   8 * * * /home/nme/sms-notify/pop2smsV2.py &gt;/dev/null 2&gt;&amp;1
*    9-21 * * * /home/nme/sms-notify/pop2smsV2.py &gt;/dev/null 2&gt;&amp;1
0-30   22 * * * /home/nme/sms-notify/pop2smsV2.py &gt;/dev/null 2&gt;&amp;1
&lt;/pre&gt;

&lt;p&gt;Dodatkowo - dzięki temu rozwiązaniu mamy adres do powiadomień, znacznie łatwiejszy do zapamiętania - bo w postaci np. powiadomienia@nasza-domena.pl :)&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/9CfGNKNI_Tc" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/09/powiadomienia-sms-mbank-mobile-drugie-podejscie</feedburner:origLink></entry><entry><title>Moje szkice</title><link href="http://feedproxy.google.com/~r/nmepl/~3/ci1nfAvLpDY/moje-szkice" rel="alternate" /><id>http://nme.pl/2009/09/moje-szkice</id><summary type="html">&lt;p&gt;Przypomniałem sobie, że kiedyś rysowałem ;) Szkice wykonałem w 2004. Mam nadzieję, że wybaczycie kiepską jakość - fotek oczywiście, bo rysunki są cacy :P&lt;/p&gt;

&lt;p&gt;&lt;a href="/img/2009/09/sketch-1.jpg"&gt;&lt;img class="center" title="sketch-1" src="/img/2009/09/sketch-1-350x449.jpg" alt="sketch-1" width="350" height="449" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="/img/2009/09/sketch-2.jpg"&gt;&lt;img class="center" title="sketch-2" src="/img/2009/09/sketch-2-350x202.jpg" alt="sketch-2" width="350" height="202" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/ci1nfAvLpDY" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/09/moje-szkice</feedburner:origLink></entry><entry><title>Dynamiczny CSS z poziomu JavaScript</title><link href="http://feedproxy.google.com/~r/nmepl/~3/Pq4XfeCIHqU/dynamiczny-css-z-poziomu-javascript" rel="alternate" /><id>http://nme.pl/2009/09/dynamiczny-css-z-poziomu-javascript</id><summary type="html">&lt;p&gt;Jak zapewne większość developerów używających JavaScriptu, mam swoją własną biblioteczkę skryptów oraz dodatkowych narzędzi która stanowi dla mnie formę bootstrapu do tworzenia nowej aplikacji. Z każdym projektem biblioteczka rośnie i staje się bardziej dojżała. Przymierzam się od jakiegoś czasu do opublikowania całego bootstrapu, bo uważam, że jest warty uwagi, ale jakoś nie miałem do tej pory zbytnio na to czasu.&lt;/p&gt;

&lt;p&gt;W tym tekscie poniżej przedstawie jeden ze skryptów który należy do mojej biblioteczki. Załączam go standardowo do każdej swojej aplikacji, szczególnie teraz, kiedy zacząłem przygotowywać swoje własne rozszerzenia &lt;a href="http://jqueryui.com/"&gt;JQuery UI&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;Swobodniejsze podejście&lt;/h4&gt;

&lt;p&gt;Bardzo lubie dbać o to, aby struktura aplikacji była zwięzła, łatwa do ogarnięcia oraz estetyczna. W dobie Javascriptu mamy coraz to większe możliwości aby samemu sobie ustrukturyzować aplikacje.&lt;/p&gt;

&lt;p&gt;Wielu doświadczonych developerów zakłada, sztywny podział - czyli, że wygląd powinien być w plikach CSS, funkcjonalność w JavaScript, a dane na serwerze. Oczywiście z trzecim się zgadzam, ale z podziałem na wygląd i funkcjonalność - już nie koniecznie.&lt;/p&gt;

&lt;p&gt;Przykładowo - w naszym pliku CSS wykorzystujemy -moz-border-radius i -webkit-border-radius, dzięki czemu mamy zaokrąglone rogi wszędzie, poza Internet Explorerem. Musimy dodać zaokrąglone rogi w Explorerze. Co począć? Nabrudzić sobie w CSSie? A później za pomocą JQuery sprawdzić wersję przeglądarki i ustawić te klasy? Można i tak. Możemy jednak sprawdzić czy mamy do czynienia z IE i jeśli tak - dopiero wtedy dodać nowe klasy CSS.&lt;/p&gt;

&lt;p&gt;Dynamiczne ładowanie lub generowanie CSS nie jest czymś bez czego nie możnaby się obyć, ale dzięki warstwom abstrakcji możemy sobie nie śmiecić w plikach z layoutem.&lt;/p&gt;

&lt;p&gt;Poniższy kod działa bez problemu w każdej zaawansowanej przeglądarce WWW oraz w Internet Explorerze :)&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
/*
 * CSS Gen
 * Copyright (c) 2009 nme.pl
 * Dual licensed under MIT and GPL.
 *
 * from scratch, based on article &lt;a href="http://www.hunlock.com/blogs/Totally_Pwn_CSS_with_Javascript"&gt;http://www.hunlock.com/blogs/Totally_Pwn_CSS_with_Javascript&lt;/a&gt;
 *
 * Example usage:
 *
 * var css = new CSS('dynamic'); // Create new stylesheet
 * css.replace('.asd',{'color':'green'}); // If there is no asd class definition yet, it will be created
 *
 */

var CSS = function(name,url) {
	if (name === undefined) {
		return false;
	}
	var styles = document.styleSheets;
	if (!styles) {
		return null;
	}
	this.find_style = function(name) {
		if (styles) {
			for (var i in styles) {
				if (styles[i].title === name) {
					return styles[i];
				}
			}
		}
		return null;
	};
	var create_style = function(name) {
		var node = document.createElement('style');
		node.type = 'text/css';
		node.rel = 'stylesheet';
		node.media = 'screen';
		node.title = name;
		document.getElementsByTagName(”head”)[0].appendChild(node);
		return node;
	};
	var load_style = function(name,url) {
		var node = document.createElement('link');
		node.type = 'text/css';
		node.rel = 'stylesheet';
		node.href = url;
		node.media = 'screen';
		node.title = name;
		document.getElementsByTagName(”head”)[0].appendChild(node);
		return node;
	};
	var style = this.find_style(name);
	if (style === null) {
		if (url === undefined) {
			style = create_style(name);
		} else {
			style = load_style(name,url);
		}
	}
	var sheet = null;
	if (style !== null) {
		if (style.styleSheet !== undefined) {
			sheet = style.styleSheet;
		} else {
			sheet = style.sheet;
		}
	}
	this.index = function(search) {
		search = search.toLowerCase();
		var i=0;
		var rule=null;
		if (sheet === undefined) {
			return null;
		}
		do {
			if (sheet.cssRules) {
				rule = sheet.cssRules[i];
			} else if (sheet.rules) {
				rule = sheet.rules[i];
			}
			if (rule) {
				if (rule.selectorText.toLowerCase() == search) {
					return i;
				}
				i++;
			}
		} while (rule);
		return null;
	};
	this.rule = function(search) {
		search = search.toLowerCase();
		var i=0;
		var rule=null;
		if (sheet === undefined) {
			return null;
		}
		do {
			if (sheet.cssRules) {
				rule = sheet.cssRules[i];
			} else if (sheet.rules) {
				rule = sheet.rules[i];
			}
			if (rule) {
				if (rule.selectorText.toLowerCase() == search) {
					return rule;
				}
				i++;
			}
		} while (rule);
		return null;
	};
	this.add = function(search, body) {
		if (sheet === undefined) {
			return null;
		}
		if (typeof body === 'object') {
			var rules='';
			for (var i in body) {
				if (body.hasOwnProperty(i)) {
					rules = rules+i+':'+body[i]+';\n';
				}
			}
			body = rules;
		}
		if (!this.rule(search)) {
			if (sheet.cssRules) {
				sheet.insertRule(search+' {'+body+'}', 0);
			} else if (sheet.rules) {
				sheet.addRule(search, body);
			}
		}
		return this.rule(search);
	};
	this.remove = function(search) {
		var i = this.index(search);
		if (i !== null) {
			if (sheet.cssRules) {
				sheet.deleteRule(i);
			} else if (sheet.rules) {
				sheet.removeRule(i);
			}
		}
	};
	this.replace = function(search, body) {
		this.remove(search);
		return this.add(search,body);
	};
};
&lt;/pre&gt;

&lt;p&gt;Jak tego używać? Na początku przygotowujemy nowy, dynamiczny stylesheet:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;var css = new CSS('dynamic');&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Jeśli klasa asd nie została jeszcze zdefiniowana, robimy to teraz oraz ustawiamy jej następujące atrybuty:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;css.replace('.asd',{'color':'green'});&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Pseudoklasa CSS umożliwia również dynamiczne ładowanie CSS'ów czy usuwanie poszczególnych reguł styli. W razie wątpliwości - zachęcam do zaglądania do kodu oraz do kontaktu ze mną :)&lt;/p&gt;

&lt;p&gt;Przykładową aplikacją, która dość intensywnie korzysta z tego fagmentu kodu jest &lt;a href="http://mlchat.appspot.com"&gt;http://mlchat.appspot.com&lt;/a&gt; - czat, który uruchomiłem na &lt;a href="http://code.google.com/appengine/"&gt;Google App Engine&lt;/a&gt;, który jednak zarzuciłem, bo nie znalazłem już sił po stworzeniu go na jego odpluskwianie i promocję ;) Wygląd aplikacji miał być z zamierzenia łudząco podobny do &lt;a href="http://code.google.com/webtoolkit/"&gt;Google Web Toolkit&lt;/a&gt;'u i co za tym idzie takich aplikacji jak &lt;a href="http://www.google.com/reader/"&gt;Google Reader&lt;/a&gt;, ale tak naprawdę było to &lt;a href="http://jquery.com/"&gt;JQuery&lt;/a&gt; i trochę pracy :) Zachęcam do poklikania - ludzi tam raczej nie ma, jak sugerowałyby liczby, to tylko duchy - stare sesje się nie kasują jak powinny ;)&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/Pq4XfeCIHqU" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/09/dynamiczny-css-z-poziomu-javascript</feedburner:origLink></entry><entry><title>Niech ktoś to zrobi pod Windowsem :P</title><link href="http://feedproxy.google.com/~r/nmepl/~3/B5b0EW9AZuE/niech-ktos-to-zrobi-pod-windowsem" rel="alternate" /><id>http://nme.pl/2009/09/niech-ktos-to-zrobi-pod-windowsem</id><summary type="html">&lt;p&gt;Wyobraźmy sobie, że surfujemy pod Windowsem, natrafiamy na coś takiego...&lt;/p&gt;

&lt;p&gt;&lt;img class="center" title="diox-before" src="/img/2009/09/diox-before.jpg" alt="diox-before" width="410" height="307" /&gt;&lt;/p&gt;

&lt;p&gt;...a pod Linuxem wystarczy jeden skrót klawiszowy i mamy taki efekt:&lt;/p&gt;

&lt;p&gt;&lt;img class="center" title="diox-after" src="/img/2009/09/diox-after.jpg" alt="diox-after" width="410" height="307" /&gt;&lt;/p&gt;

&lt;p&gt;:) Aby móc to robić potrzebny jest uruchomiony Compiz. Tą funkcjonalność (Dostępność / Negatyw) i inne najwygodniej skonfigurować, lub włączyć za pomocą System / Preferencje / Menadżer ustawień CompizConfig. Jeśli takowego nie posiadamy - możemy go sobie zainstalować następującą komendą:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo aptitude install compizconfig-settings-manager&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Skróty negatyw danego okna lub negatyw ekranu są wbrew pozorom dość przydatne, zwłaszcza wieczorem, podczas czytania ebooków.&lt;/p&gt;

&lt;p&gt;Aniołek pochodzi ze strony &lt;a href="http://diox.mylog.pl"&gt;http://diox.mylog.pl&lt;/a&gt; ;)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/B5b0EW9AZuE" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/09/niech-ktos-to-zrobi-pod-windowsem</feedburner:origLink></entry><entry><title>Instalacja Chromium w Ubuntu Jaunty</title><link href="http://feedproxy.google.com/~r/nmepl/~3/BFAoDed5C_Q/instalacja-chromium-w-ubuntu-jaunty" rel="alternate" /><id>http://nme.pl/2009/09/instalacja-chromium-w-ubuntu-jaunty</id><summary type="html">&lt;img class="post-image" title="chromium-corner" src="/img/2009/09/chromium-corner.png" alt="chromium-corner" width="257" height="138" /&gt;

&lt;p&gt;Przeglądarka WWW giganta z Mountain View o nazwie Google Chrome jest dostępna póki co jedynie dla Windows. Była ona tworzona w pośpiechu i tajemnicy. Kiedy została wydana, Google jednocześnie otworzyło otwartoźródłowy projekt o nazwie &lt;a href="http://code.google.com/chromium/"&gt;Chromium&lt;/a&gt;. Składają się na niego między innymi własny fork silnika do renderingu stron - &lt;a href="http://webkit.org/"&gt;WebKit&lt;/a&gt; czy stworzony przez Google - bardzo wydajny silnik Javascriptu o nazwie &lt;a href="http://code.google.com/p/v8/"&gt;V8&lt;/a&gt;. Dzięki otwarciu kodu, umożliwiony został szybszy rozwój oraz poprawę tego, co było zrobione na szybko oraz tego, czego najbardziej brakuje. Do projektu Chromium dołączyło wielu developerów spoza Google, którzy bardzo aktywnie zaczęli podrzucać łaty, mające na celu umożliwienie uruchamianie Chrome pod Linuxem. Prace się jeszcze nie skończyły, ale już teraz możemy uruchomić wersję developerską - Chromium, na własnym Linuksie. W tym tekscie pokażę, jak tego dokonać pod Ubuntu 9.04.&lt;/p&gt;

&lt;p&gt;Dlaczego chcę o tym pisać, kiedy lada dzień ma wyjść Ubuntu 9.10? Z przyczyn archiwalnych, ponieważ w Ubuntu 9.10 będzie się to robiło już inaczej, znacznie prościej. Nie oznacza to, że jeśli zainstalujemy teraz Chromium, będziemy musieli wykonywać nowe kroki po aktualizacji do 9.10 - Chromium będzie działał jak dawniej.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
# Najpierw przechodzimy na roota, tego którego w Ubuntu nie ma ;)

sudo -i

# Dodajemy repozytorium Chromium z Ubuntu Launchpad PPA

cat &amp;gt;/etc/apt/sources.list.d/chromium.list &amp;lt;&amp;lt; EOF
deb http://ppa.launchpad.net/chromium-daily/ppa/ubuntu jaunty main
deb-src http://ppa.launchpad.net/chromium-daily/ppa/ubuntu jaunty main
EOF

# Dodajemy klucz do pakietów z repozytorium Chromium

gpg --keyserver hkp://wwwkeys.eu.pgp.net --recv-keys 5A9BF3BB4E5E17B5
gpg --export --armor 5A9BF3BB4E5E17B5 | sudo apt-key add -

# Aktualizujemy repozytoria i instalujemy Chromium wraz z wersją Polską :)

aptitude update
aptitude install -y chromium browser chromium-browser-l10n
&lt;/pre&gt;

&lt;p&gt;Po pierwszym uruchomieniu, Chromium pyta o ustawienie go jako domyślnej przeglądarki oraz import z Firefoxa - ustawienia jako domyślnej przeglądarki póki co nie polecam, a import u mnie to jeszcze nie działa.&lt;/p&gt;

&lt;p&gt;Żeby było bardziej pod kolor, warto nacisnąć Ustawienia, Opcje, zakładka Prywatne rzeczy, Motywy: Ustaw motyw na GTK+.&lt;/p&gt;

&lt;p&gt;Obsługa Flasha i innych wtyczek jest narazie eksperymentalna, ale mnie przynajmniej nic się nie jeszcze zawiesiło - YouTube można oglądać. Aby działał Flash, skrót do Chromium należy uruchamiać z parametrem &lt;code&gt;--enable-plugins&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;chromium-browser --enable-plugins&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Przeglądarka działa lekko i przyjemnie - w moim odczuciu - o wiele lżej niż Firefox, którego ostatnio coraz bardziej nie mogę znieść - nie ważne czy to pobranego bezpośrednio ze stron Mozilli, czy tego z repozytoriów Ubuntu. Chromium jest też w moim odczuciu stabilniejszy niż Midori, którego do tej pory używałem do testowania moich aplikacji webowych pod kątem WebKit'a pod Linuxem. Spróbujcie, warto.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/BFAoDed5C_Q" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/09/instalacja-chromium-w-ubuntu-jaunty</feedburner:origLink></entry><entry><title>Podgląd strony do pliku jpg?</title><link href="http://feedproxy.google.com/~r/nmepl/~3/opqsZ8oU2BQ/podglad-strony-do-pliku-jpg" rel="alternate" /><id>http://nme.pl/2009/08/podglad-strony-do-pliku-jpg</id><summary type="html">&lt;p&gt;Poruszenie w Internecie tematyką wprowadzania cenzury, o której &lt;a href="/2009/08/koniec-anonimowosci-w-internecie"&gt;ostatnio pisałem&lt;/a&gt;, podsunęło mi pewien pomysł, który mam nadzieję niebawem Wam przedstawię. W między czasie uznałem, że w projekcie przyda mi się funkcjonalność zautomatyzowanego robienia podglądów (thumbnail) stron WWW do obrazków. Miałem przy tym całkiem dużo frajdy i mam nadzieję, że efekty mojej pracy komuś się to przydadzą.&lt;/p&gt;

&lt;p&gt;Serwisów które przygotowują podgląd stron jest w sieci niewiele, a takich, które za darmo udostępniają wygodne API, nie mają śmiesznie małych limitów przygotowań podglądów nie znalazłem. Napisałem sobie takie narzędzie sam. Jeśli ktoś chce wykorzystać ten kod - proszę bardzo - proszę tylko o informację gdzie jest on dostępny oraz liczę na darmowy dostęp ;)&lt;/p&gt;

&lt;h4&gt;Twoja własna mini-przeglądarka&lt;/h4&gt;

&lt;p&gt;Jak szybko zrobić sobie przeglądarkę z obsługą Flasha, JavaScriptu i tych wszystkich urozmaiceń? Wystarczyło mi kilkanaście minut :) Zdecydowałem się na użycie GTK (domyślnego zestawu kontrolek dla m.in. Gnome) oraz Webkit'a - silnika do renderowania wykorzystywanego w takich przeglądarkach jak Safari (Mac OS), Google Chrome (Windows) czy Midori (Linux):&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
#!/usr/bin/env python

url = 'http://www.nme.pl'
size = [800, 600]

import gtk,webkit
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_default_size(size[0], size[1])
window.connect('destroy', gtk.main_quit)
preview = webkit.WebView()
preview.open(url)
scrolled = gtk.ScrolledWindow()
scrolled.add(preview)
window.add(scrolled)
window.show_all()
gtk.main()
&lt;/pre&gt;

&lt;h4&gt;Właściwy podgląd strony&lt;/h4&gt;

&lt;p&gt;Kod trzeba było trochę rozbudować. Konfiguracja jest w klasie &lt;code&gt;conf&lt;/code&gt;. Uruchamiając kod w pierwszym parametrze należy podać adres strony (nie zapominając o nazwie protokołu, np. &lt;strong&gt;http://&lt;/strong&gt;www.nme.pl).&lt;/p&gt;

&lt;p&gt;w katalogu w którym znajduje się skrypt trzeba założyć podkatalog &lt;code&gt;thumb&lt;/code&gt;, w którym zapisywane będą obrazki jpg.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;shot.py&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
#!/usr/bin/env python
__author__ = 'mw AT nme.pl'
__version__ = '1.0'
__date__ = 'wto, 25 sie 2009, 09:15:48 CEST'

import pygtk
pygtk.require('2.0')
import gtk,gtk.gdk,gobject
import webkit
import hashlib
import os,sys

class conf:
    show_scrollbars = True
    show_progress = True
    script_timeout_secs = 15
    size = [1024, 768]

class Snapshot:

    def load_progress_changed(self, view, progress):
        print '%d%%' % progress

    def load_finished(self, view, frame):
        print 'loading finished'
        w = gtk.gdk.get_default_root_window()
        wp = self.window.get_position()
        ws = self.window.get_size()
        sz = w.get_size()
        pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,ws[0],ws[1])
        pb = pb.get_from_drawable(w,w.get_colormap(),wp[0],wp[1],0,0,ws[0],ws[1])
        if (pb != None):
            pb.save('thumbs/'+self.file+'.jpg','jpeg',{'quality':'95'})
        gtk.main_quit()

    def __init__(self, url=None):

        self.url = url
        self.file = hashlib.sha512(url).hexdigest()
        self.overtime = False
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_default_size(conf.size[0], conf.size[1])
        self.window.set_decorated(False)
        self.window.connect('destroy', gtk.main_quit)
        self.preview = webkit.WebView()
        self.preview.open(self.url)
        if conf.show_progress:
            self.preview.connect('load-progress-changed',self.load_progress_changed)
        self.preview.connect('load-finished',self.load_finished)
        self.scrolled = gtk.ScrolledWindow()
        if conf.show_scrollbars:
            self.scrolled.props.hscrollbar_policy = gtk.POLICY_AUTOMATIC
            self.scrolled.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC
        else:
            self.scrolled.props.hscrollbar_policy = gtk.POLICY_NEVER
            self.scrolled.props.vscrollbar_policy = gtk.POLICY_NEVER
        self.scrolled.add(self.preview)
        self.window.add(self.scrolled)
        self.window.show_all()
        gobject.timeout_add(conf.script_timeout_secs*1000, self.timeout)
        gtk.main()

    def timeout(self):
        gtk.main_quit()
        sys.exit(1)

if len(sys.argv)==2:
    Snapshot(url=sys.argv[1])
else:
    print &amp;gt;&amp;gt; sys.stderr, "Usage: %s url\n" % sys.argv[0]
    sys.exit(1)
&lt;/pre&gt;

&lt;h4&gt;Wrapper do generowania właściwego poglądu&lt;/h4&gt;

&lt;p&gt;Skrypt działa, ale wymaga działania X'ów, coś nam jeszcze wyświetla i zapisuje obrazek w skali 1:1. Da się to zrobić w tle. Potrzebujemy do tego dwóch narzędzi - &lt;code&gt;convert&lt;/code&gt; z pakietu &lt;strong&gt;imagemagick&lt;/strong&gt; oraz pakietu &lt;strong&gt;xvfb&lt;/strong&gt; - &lt;em&gt;Virtual Framebuffer 'fake' X server&lt;/em&gt;. Mając już te narzędzia - całą robotę zrobi za nas skrypt o nazwie &lt;code&gt;snap&lt;/code&gt;:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
#!/bin/bash

state=0
plik=`python -c "import hashlib; print hashlib.sha512('$1').hexdigest()+'.jpg'"`
[ -e "thumbs/$plik" ] || {
	xvfb-run -a --server-args='-screen 0 1024x768x16' python shot.py $1
}
state=$?
[ "$state" -eq "0" ] &amp;amp;&amp;amp; {
	[ -e "thumbs/$plik" ] &amp;amp;&amp;amp; {
		convert -scale 310x -quality 75 thumbs/$plik thumbs/$plik
	} || {
		exit 1
	}
} || {
	exit 1
}
&lt;/pre&gt;

&lt;p&gt;skryptowi nadajemy prawa do jego uruchamiania:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;chmod +x snap&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;i uruchamiamy:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;./snap http://www.nme.pl&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;w katalogu thumb odnajdujemy gotowego jpg'a (jego nazwa jest hashem sha512 URL'a). Wygląda to tak:&lt;/p&gt;

&lt;p&gt;&lt;img class="center" title="www.nme.pl-thumb" src="/img/2009/08/www.nme.pl-thumb.jpg" alt="www.nme.pl-thumb" width="310" height="233" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Powiązane, teksty w języku angielskim:&lt;/em&gt;&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;em&gt;Podobne &lt;a href="http://www.insecure.ws/2008/09/16/xserver-less-webpage-screenshot"&gt;rozwiązanie&lt;/a&gt; w oparciu o Qt, warto obejrzeć.&lt;/em&gt;&lt;/li&gt;
	&lt;li&gt;&lt;em&gt;Przykładowy &lt;a href="http://lapin-blanc.net/09/11/2008/django-website-thumbnail-generator/"&gt;opis&lt;/a&gt; jak można uruchomić serwis do generowania podglądów w oparciu o&amp;nbsp;&lt;strong&gt;Django&lt;/strong&gt; z nawiązaniem do gotowych już rozwiązań.&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/opqsZ8oU2BQ" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/08/podglad-strony-do-pliku-jpg</feedburner:origLink></entry><entry><title>Koniec anonimowości w Internecie?</title><link href="http://feedproxy.google.com/~r/nmepl/~3/tAOxnJg5040/koniec-anonimowosci-w-internecie" rel="alternate" /><id>http://nme.pl/2009/08/koniec-anonimowosci-w-internecie</id><summary type="html">&lt;a href="http://vbeta.pl/2009/06/19/the-pirate-bay-tworzy-anonymous-iran/"&gt;&lt;img class="post-image" style="margin-left: 1em; margin-top: 0.4em;" title="anonymous1-496x496" src="/img/2009/08/anonymous1-496x496-150x150.jpg" alt="anonymous1-496x496" width="150" height="150" /&gt;&lt;/a&gt;

&lt;p&gt;Przez wszelkie możliwe media tydzień temu przetoczyła się dyskusja na temat anonimowości w Internecie oraz jaka to ona jest zła. Wszystko zaczęło się od... kobiety ;) a dokładnie - kapitana żeńskiej reprezentacji polski w siatkówce - &lt;a href="http://pl.wikipedia.org/wiki/Dorota_%C5%9Awieniewicz"&gt;Doroty Świeniewicz&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Pani kapitan oświadczyła, że kończy karierę ponieważ nie może znieść wyzwisk pod jej imieniem na portalach Internetowych - wolne żarty! Kariera zawodowa pani kapitan jest jednoznacznie związana z popularnością i rozpoznawalnością. Powinna liczyć się z tym, że nie każdy będzie jej ślepo oddany. Wina Internautów? Bzdura. Z własnego doświadczenia wiem, że nawet administrator sieci dla tysiąca użytkowników też musi radzić sobie z tym, że mimo własnej woli słyszy negatywne opinie na temat swojej pracy, ale co ma zrobić - musi z tym żyć.&lt;/p&gt;

&lt;p&gt;Każdy z nas jest istotą w jakimś stopniu egocentryczną - oraz, jakby na to nie patrzeć - społeczną. Zwracamy uwagę na to jak jesteśmy postrzegani przez innych. Są &lt;a href="http://www.wykop.pl/ramka/220439/seksturystyka-polek-punkt-widzenia-zdradzonego-meza" target="_blank"&gt;udokumentowane przykłady&lt;/a&gt;, że wystarczy odpowiednio połechtać człowieka, aby odwrócić mu świat do góry nogami. Jeśli faktycznie dla pani kapitan nie było racjonalnego powodu dla którego zrezygnowała z dalszej kariery - pewnie miała po prostu gorsze dni (może trwało to dłużej) i nie radziła sobie z własną psychiką. Cóż. Na pewno nie byli temu winni Internauci.&lt;/p&gt;

&lt;h4&gt;Jeden redaktor postanowił skorzystać z okazji i się wypromować&lt;/h4&gt;

&lt;p&gt;Redaktor Jacek Żakowski w radiu TOK FM przygotował na temat cenzurowania portali Internetowych audycje. Zaprosił gościa do studia, drugiego trzymał na telefonie, wydrukował sobie znaleziony wcześniej jakiś prostacki cytat który przeszedł moderacje i próbował z tego zrobić aferę. Panowie zaproszeni do audycji byli zresztą nastawieni na odpieranie tego rodzaju ataków o czym świadczyło ich przygotowanie. Szkoda, bo mogli rozmawiać o tym, w jaki sposób można coś z tym robić.&lt;/p&gt;

&lt;p&gt;Pan redaktor Żakowski z drugiej strony, przygotowany nie był w ogóle. Powinien zastanowić się, zapytać jakiegoś specjalistę wcześniej - jakie są trendy na tego rodzaju portalach, jakie serwisy powstają wokół - ktoś powinien powiedzieć mu np. o Wykopie i o tym jak tam użytkownicy sami mogą oceniać komentarze, które swoją drogą są na wiele wyższym poziomie niż takich Onetach, Money.pl czy im podobnych.&lt;/p&gt;

&lt;p&gt;Reakcja po audycji była bolesna. Media się poruszyły - od blogów, na których informacja zwykle pojawia się najpierw, po portale - wszędzie były te bzdury. Większości się to &lt;a href="http://www.webpuls.pl/2009/08/internet-bez-hamstwa-co-to-kwa-jest.html"&gt;nie spodobało&lt;/a&gt;, ale nikt tej marnej dyskusji nie wyśmiał. Ktoś nawet stworzył serwis z opisem zasad według których powinien żyć komentujący Internauta - &lt;a href="http://internetbezchamstwa.pl/" target="_blank"&gt;Internet bez ch@mstw&lt;/a&gt;a - ludzie, na Boga - szanujmy się. Czy przeszkadzają Wam komentarze na Onecie? Ktoś z Was je czyta? Ja nie. Często jednak czytam te na &lt;a href="http://www.wykop.pl/"&gt;Wykopie&lt;/a&gt;. Są dłuższe ;) ale zwykle z klasą. Jeśli jednak nie są z klasą to wiem, że zostałem ostrzeżony i nie ma co ich rozwijać, bo trafia się na weteranów komentowania z Onetu - przykładowo tych:&lt;/p&gt;

&lt;img class="alignnone size-full wp-image-415" title="komentator-z-onetu-na-wykopie" src="/img/2009/08/komentator-z-onetu-na-wykopie.png" alt="komentator-z-onetu-na-wykopie" width="620" height="230" /&gt;

&lt;p&gt;Co się później działo - telewizja i wypytywanie o zdanie ludzi z ekipy rządzącej. Telewizja jak to telewizja - za punkt honoru miała to, żeby pokazać, że jest w stanie coś zdziałać... i zdziałała. Pech chciał, że na tą chwilę w ekipie dominują ludzie nie potrafiący podjąć najprostszej... nawet błędnej decyzji. Ktoś tam odważniejszy z góry, z MSWiA &lt;a href="http://www.rp.pl/artykul/67344,351244_Czy_to_koniec_anonimowosci_w_Internecie_.html" target="_blank"&gt;wpadł na pomysł&lt;/a&gt; aby zmusić portale do dokładniejszej cenzury. Rewelacja. Już miałem nadzieję, że powiedzą, że zapłacą im za to - jeśli tak by było to sam bym otworzył portal ;) Niestety - jak można byłoby się spodziewać - pomysł &lt;a href="http://www.wykop.pl/ramka/226160/upadl-pomysl-sledzenia-internautow" target="_blank"&gt;upadł&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;Względy technologiczne&lt;/h4&gt;

&lt;p&gt;Czytając wpisy na blogach traktujące o pomysłach walczenia z anonimowością, brakowało mi wpisu, w którym ktoś zrobiłby zestawienie - gdzie jesteśmy, dokąd zmierzamy, jakie mamy teraz możliwości technologiczne, aby uchronić swoje oczy przed komentarzami na niskim poziomie. Spróbuję zatem coś takiego popełnić.&lt;/p&gt;

&lt;p&gt;Wspominano o moderacji, panowie z portali podczas rozmowy w audycji TOK FM mówili, że takowa istnieje. Paweł Opydo, pracujący w Interii, na swoim blogu &lt;a href="http://www.playr.pl/2009/08/redaktor-zakowski-chcialby-moderowac-internet-ponad-prawem-wtf/"&gt;wspomniał&lt;/a&gt; nawet, podczas dyskusji, że wszystkie większe portale prowadzą &lt;strong&gt;pre moderację&lt;/strong&gt;. Jak jednak ona działa mieliśmy się okazję przekonać w audycji. Nie trzeba mieć bujnej wyobraźni, żeby zdać sobie sprawę z kosztów realnej pracy takich systemów - trzeba mieć aplikację dla wielu użytkowników, logowania/wylogowania operatorów cenzurujących, możliwość bardzo szybkiej premoderacji w czasie rzeczywistym. Taki system dużo kosztuje, biorąc pod uwagę przede wszystkim pensje dla cenzorów. Jak dla mnie - odpada.&lt;/p&gt;

&lt;p&gt;Wspomniałem już o systemie&lt;strong&gt; oceny komentarzy&lt;/strong&gt; - pracuje to z powodzeniem w takich serwisach jak LinuxNews (strzelam, dawno tam nie byłem, ponieważ mają tam moderację artykułów, nie moderując RSS'ów - o jedno 404 za daleko i przestałem ich subskrybować), lub Wykop. System o dziwo - sprawdza się świetnie i nic nie kosztuje. Żaden większy portal chyba tego nie ma, a szkoda. Gdyby któryś portal zdecydował się na wprowadzenie takiego systemu - niech przy okazji pomyślą nad poprawą sposobów wyświetlania komentarzy, bo to co do tej pory widziałem jest baardzo słabe.&lt;/p&gt;

&lt;p&gt;Co dalej - prosta sprawa - osoba która odwiedza portal, trafia na dużą ilość reklam, żartuje! - chodziło oczywiście o treści ;) Komentarze pod tekstem nie są dość przyjemne. Wpływ innych czytelników w treść jest minimalna. To aspekt psychologiczny - użytkownik może czuć się wyobcowany. Może się poczuć tak jakby sam był w galerii handlowej. Wszystko wokół jest dla niego - on jest panem. Więc robi co mu przyjdzie do głowy i nawet nie zastanawia się jak zostanie to odebrane przez innych. Ani aktywność "ochrony" nie rzuca się w oczy, ani inni użytkownicy. Słowem - brakuje możliwości &lt;strong&gt;raportowania nadużyć&lt;/strong&gt; innych. "Surfowanie" w przeglądarce umożliwia zarządzającym danym serwisem Internetowym całkiem precyzyjne śledzenie czynności danego użytkownika - to nie jest technologia rakietowa - sesje zaimplementować potrafi przeciętny programista, a większość nowoczesnych frameworków oferuje to w standardzie. Jeśli więc na dany portal trafi rozjuszony niedowartościowany człowiek i pozostawi podczas jednej sesji kilka komentarzy - można oprogramować dany serwis tak, że jeśli któryś z nich zostanie zaraportowany - wszystkie z danej sesji zostaną ukryte.&lt;/p&gt;

&lt;p&gt;Odchodząc od konkretnych serwisów - co mogą robić &lt;strong&gt;operatorzy.&lt;/strong&gt; Niby wiele, ale tak naprawdę to nic poza logowaniem. Często jednak takie logi są niewiele warte. Do momentu, kiedy Internet nie zrezygnuje z IPv4, operatorzy nie zaczną poważnie traktować bezpieczeństwa sieci WIFI w ich urządzeniach które dają swoim klientom - żadnemu Internaucie nie będzie można udowodnić, że to tak naprawdę on robił dane rzeczy na konkretnych serwisach.&lt;strong&gt; IPv6&lt;/strong&gt; - jest już coraz bliżej, ale niestety strasznie daleko. Póki co mamy domowe routery, podsieci lokalne i maskarady - nic z tego nie sprzyja "zakończeniu anonimowości w Internecie" ;)&lt;/p&gt;

&lt;p&gt;No i na koniec -&lt;strong&gt; aplikacje filtrujące treści&lt;/strong&gt; na komputerach osobistych. Witamy w Chinach? Nie, w Polsce to nie przejdzie, ponieważ oprogramowanie musiałoby działać na każdym systemie operacyjnym, byłoby zbyt drogie jego utrzymanie, a wątpliwe jest bardzo, żeby ktoś mógł zmusić obywateli do wprowadzenie do domu konia trojańskiego rodem ze świata Orwella. Jest u nas demokracja na szczęście i ja wybieram pracę na systemie Linux Ubuntu. Nikt mnie nie zmusi do systemu Microsoft Windows. Jeśli by próbował - są w naszej wspaniałej Unii różnego rodzaju trybunały ;)&lt;/p&gt;

&lt;div class="footnotes-red"&gt;Jeśli powyższa treść jest nazbyt kontrowersyjna, jeśli kogoś uraziłem - proszę o opinie i komentarze - obiecuję, że cenzury nie będzie :)
&lt;div style="margin-top:0.5em; font-size:80%"&gt;PS. Jeśli ktoś nie będzie potrafił napisać komentarza na poziomie - proszę skorzystać z asysty rodziców. Dziękuję ;)&lt;/div&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/tAOxnJg5040" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/08/koniec-anonimowosci-w-internecie</feedburner:origLink></entry><entry><title>Instalacja Linux Ubuntu 9.04 na pendrive USB</title><link href="http://feedproxy.google.com/~r/nmepl/~3/iUmmHFdziQE/instalacja-linux-ubuntu-9-04-na-pendrive-usb" rel="alternate" /><id>http://nme.pl/2009/08/instalacja-linux-ubuntu-9-04-na-pendrive-usb</id><summary type="html">&lt;img class="post-image" title="supertalent-pico-c-pendrive" src="/img/2009/08/supertalent-pico-c-pendrive-150x150.jpg" alt="supertalent-pico-c-pendrive" width="150" height="150" /&gt;

&lt;p&gt;Temat ten był już poruszany na blogach i serwisach traktujących o Linux Ubuntu nie raz, nie jest to żadna nowość, ale ten wpis będzie mi potrzebny, aby się do niego odwołać niebawem.&lt;/p&gt;

&lt;p&gt;Mamy już technologię ;) umożliwiającą nam pracę na systemie operacyjnym zainstalowanym na własnym nośniku USB. Można go zabrać wszędzie i wystarczy w miarę współczesny komputer z możliwością ładowania systemu po USB. I &lt;strong&gt;co najważniejsze&lt;/strong&gt; - &lt;strong&gt;to co zrobimy w systemie&lt;/strong&gt;, wystartowanym z takiego nośnika USB - w przeciwieństwie do wersji Live startowanych z płyt CD / DVD - &lt;strong&gt;pozostanie obecne nawet po restarcie&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ta właściwość nazywa się &lt;strong&gt;persistent storage&lt;/strong&gt; - czyli &lt;strong&gt;trwały dysk&lt;/strong&gt;. Jeśli zainstalujemy sobie program, umieścimy skrót, zapiszemy dokument - po restarcie, nie ważne czy na tym samym komputerze czy innym - ów zmiana dalej będzie widoczna. To właśnie dzięki temu - warto mieć taki nośnik.&lt;/p&gt;

&lt;p&gt;Co więcej - na nośniku możemy mieć też zapisane inne dane, o ile tylko mamy na nim jeszcze jakieś wolne miejsce :)&lt;/p&gt;

&lt;h4&gt;Wymagania&lt;/h4&gt;

&lt;p&gt;Do instalacji systemu Linux Ubuntu na pendrive, wystarczy nam nawet 2 GB nośnik USB sformatowany w systemie FAT (rekomendowane FAT32, jeśli chcemy zapisać na nim plik trwałego dysku większy niż 4 GB).&lt;/p&gt;

&lt;p&gt;Będzie nam potrzebny również komputer z systemem Microsoft Windows - albo zainstalowanym klasycznie, albo jako maszyna wirtualna (która musi obsługiwać USB).&lt;/p&gt;

&lt;h4&gt;Przygotowanie i instalacja&lt;/h4&gt;

&lt;p&gt;Jeśli powyższe wymagania udało się nam spełnić - zabieramy się do roboty - &lt;strong&gt;na dysku twardym&lt;/strong&gt; (to ważne, bo jeśli wrzucimy to od razu na pendrive'a, to skrypt instalacyjny sobie nie poradzi) swojego komputera tworzymy sobie katalog, do którego ściągamy następujące pliki:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.pendrivelinux.com/downloads/u904/U904p.exe"&gt;U904p.exe&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://releases.ubuntu.com/9.04/ubuntu-9.04-desktop-i386.iso"&gt;Ubuntu 9.04 ISO&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Jeśli chcemy mieć większy trwały dysk niż domyślny - 1 GB - pobieramy jeden z tych: &lt;a href="http://www.pendrivelinux.com/downloads/casper-rw/2GB-casper-rw.zip"&gt;2 GB&lt;/a&gt;, &lt;a href="http://www.pendrivelinux.com/downloads/casper-rw/3GB-casper-rw.zip"&gt;3 GB&lt;/a&gt;, &lt;a href="http://www.pendrivelinux.com/downloads/casper-rw/4GB-casper-rw.zip"&gt;4 GB&lt;/a&gt; lub tworzymy swój własny.&lt;/p&gt;

&lt;p&gt;Kiedy już mamy wszystko - uruchamiamy &lt;code&gt;U904p.exe&lt;/code&gt;. Jest to archiwum samorozpakowujące się. Po jego rozpakowaniu, wrzucamy plik iso Ubuntu oraz ewentualnie - pobrany i rozpakowany trwały dysk.&lt;/p&gt;

&lt;p&gt;Teraz wystarczy tylko sprawdzić literkę dysku, pod którą znajduje się nasz pendrive, bo zostaniemy o to za chwilkę zapytani i uruchomić &lt;code&gt;U904p.bat&lt;/code&gt; z katalogu &lt;code&gt;U904p&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To w zasadzie wszystko - po restarcie z włożonym dyskiem USB do komputera, kiedy na ekranie zaczną pojawiać się pierwsze komunikaty, wciskamy kilkukrotnie klawisz F12 - powinno pojawić się menu z pytaniem z którego napędu chcesz wystartować system. Wybieramy nasz dysk USB.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Źródło: &lt;a href="http://www.pendrivelinux.com/usb-ubuntu-904-persistent-install-windows/"&gt;http://www.pendrivelinux.com/usb-ubuntu-904-persistent-install-windows/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;div class="footnotes"&gt;&lt;em&gt;Pendrive na obrazku powyżej to &lt;a href="http://www.supertalent.com/products/stt_usb_detail.php"&gt;Super Talent Pico C&lt;/a&gt;. Dostępne są metalowe, niklowane oraz złocone o pojemnościach 2GB - 32GB. Przy pierwszym użyciu już widać, że wkładanie go do portu USB sprawia, że pojawiają się na nim rysy i dość topornie się go wkłada/wyciąga. Kończę go recenzować bo mi to nie wychodzi ;) Generalnie - nie żałuję zakupu.&lt;/em&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/iUmmHFdziQE" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/08/instalacja-linux-ubuntu-9-04-na-pendrive-usb</feedburner:origLink></entry><entry><title>Moja recenzja e-papierosa</title><link href="http://feedproxy.google.com/~r/nmepl/~3/JxS2MUT3PKs/moja-recenzja-e-papierosa" rel="alternate" /><id>http://nme.pl/2009/08/moja-recenzja-e-papierosa</id><summary type="html">&lt;img class="post-image" title="e-papieros" src="/img/2009/08/e-papieros1.jpg" alt="e-papieros" width="148" height="118" /&gt;

&lt;p&gt;Ostatnimi dniami we wpisie pół żartem pół serio - &lt;a href="/2009/08/unboxing-tajemniczego-przedmiotu"&gt;Unboxing tajemniczego przedmiotu&lt;/a&gt;, przedstawiłem sesję zdjęciową z rozpakowania e-papierosa, którego sobie kupiłem. Nadszedł teraz czas, żeby go dokładniej zrecenzować.&lt;/p&gt;

&lt;p&gt;Zacznijmy od początku - więc... rzuciłem palenie :) Nie, serio... rzuciłem. Byłem na bioprądach czy czymś takim, zapłaciłem 80 zł i odechciało mi się palić. Przez ponad miesiąc nie zapaliłem. Po tygodniu poprawiło się samopoczucie, po trzech tygodniach wrócił lepszy smak i węch.&lt;/p&gt;

&lt;p&gt;Niestety, czasami np. po tym jak mocno dałem sobie w kość na rowerze, padając z nóg pojawiała się z nikąd myśl "ile dałbym za jednego macha" ;) Jak wieczorem trafił się film akcji, w którym przepoceni, zakrwawieni bohaterowie sięgają po papierosa i zaciągają się z taką przyjemnością... Ech ;) Sniło mi się później palenie całą noc. Niestety - palę od 10 lat i po prostu potrzebuję czasami poczuć coś na oskrzelach.&lt;/p&gt;

&lt;p&gt;Po jednej z nocy, gdzie śniło mi się palenie - jakoś przypomniałem sobie jak ktoś kiedyś wspomniał o e-papierosach. Dwa dni spędziłem przeglądając YouTube'a, Allegro, kilku serwisów i fora o e-paleniu. Dowiedziałem się wystarczająco dużo, żeby się skusić.&lt;/p&gt;

&lt;p&gt;Zasada działania e-papierosa jest w miarę prosta - pociągając powietrze przez ustnik aktwuje się bateria, czego znakiem jest zapalenia się diody na jej końcu. Bateria uruchamia atomizer, który, jeśli jego końcówka ma styczność z e-liquidem, substancją bazującą na glikolu propylenowego, rozpyla ją, tworząc parę, wyglądem przypominającą dym. Nic się nie spala. Zamiast 4000 substancji trujących, podobno nie przyjmuje się żadnej. O aspektach szkodliwości glikolów można poczytać &lt;a href="http://www.digicig.pl/dc/zdrowie"&gt;tutaj&lt;/a&gt;. Nikotyna - która może być obecna w e-liquidzie - jest przyjmowana w postaci pary wodnej i trafia do mózgu po 7 sekundach od zaciągnięcia. Można sobie to wytłumaczyć w ten sposób, że jest przez organizm przyjmowana niczym reklamowana "lecznicza nikotyna" z plastrów Nicotine czy innych.&lt;/p&gt;

&lt;p&gt;Wybrałem sobie markę, model, poszukałem dystrybutorów - okazało się, że jest w Katowicach człowiek, który to sprzedaje. Pojechałem i kupiłem.&lt;/p&gt;

&lt;h4&gt;Pierwsze wrażenia&lt;/h4&gt;

&lt;p&gt;Kupiłem e-papierosa firmy Joye, &lt;a href="http://www.sklep.e-cigar.pl/index.php?p29,joye-306-white-mini-98-mm-2-atomizery-w-zestawie"&gt;model 306&lt;/a&gt;.&lt;/p&gt;

Za pudełko zawierające:
&lt;ol&gt;
&lt;li&gt;dwie baterie&lt;/li&gt;
&lt;li&gt;dwa atomizery&lt;/li&gt;
&lt;li&gt;ładowarkę sieciową&lt;/li&gt;
&lt;li&gt;5 wkładów&lt;/li&gt;
&lt;li&gt;instrukcję obsługi&lt;/li&gt;
&lt;li&gt;gwarancję (3 miesiące)&lt;/li&gt;
&lt;/ol&gt;

&lt;img class="center" title="unboxing-joye-306-4" src="/img/2009/08/unboxing-joye-306-4.jpg" alt="unboxing-joye-306-4" width="620" height="465" /&gt;

&lt;p&gt;Czyli w zasadzie dwa kompletne e-papierosy, z jedną ładowarką, zapłaciłem 200 zł. Dostałem od sprzedawcy dodatkowo wydrukowaną na papierze A4 instrukcję oraz wygięty spinacz. Odbierając spinacz usłyszałem, że jest to podstawowe narzędzie do obsługi papierosów :)&lt;/p&gt;

&lt;img class="center" title="unboxing-joye-306-7" src="/img/2009/08/unboxing-joye-306-7.jpg" alt="unboxing-joye-306-7" width="620" height="465" /&gt;

&lt;p&gt;Po zdjęciu wkładu z e-papierosa, atomizer jest wkręcony do baterii. Wkład zawiera mały pojemniczek wypełniony wato-podobną, nasiąkniętą e-liquidem kuleczką :) Po włożeniu pojemniczka do wkładu, nakładamy to na atomizer i już możemy palić.&lt;/p&gt;

&lt;div style="text-align:center;margin:2em"&gt;&lt;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="344" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="src" value="http://www.youtube.com/v/AzdJu5lKAM8&amp;amp;hl=pl&amp;amp;fs=1&amp;amp;" /&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;embed type="application/x-shockwave-flash" width="425" height="344" src="http://www.youtube.com/v/AzdJu5lKAM8&amp;amp;hl=pl&amp;amp;fs=1&amp;amp;" allowscriptaccess="always" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;
Wystarczy pociągnąć. Nic nie trzeba włączać. Kończymy palić - odkładamy go na bok. Żadnego popiołu, nie da się niczym oparzyć.

&lt;p&gt;Podczas ciągnięcia, zapala się dioda imitująca żar, pojawia się dym, czuć smak. Smak jest inny niż zwykłych papierosów. Marlboro MED (o średniej zawartości nikotyny) smakuje trochę cytrynowo. Jeśli ktoś palił kiedyś fajkę - e-papieros to coś pomiędzy papierosem, a fajką - można się zaciągnąć do płuc, a z drugiej strony, jeśli pociągniemy jeden raz za drugim, tylko do ust, nie do płuc - czuć naprawdę dobry smak... Dobry, ale słabszy niż z analogów (tak e-palacze określają zwykłe papierosy ;)). Dym - cóż - kiedy zaciągamy się do płuc jest wyraźnie mniejszy. Chyba, że dopiero co nasączyliśmy wkład e-liquidem, ale o tym później. Bateria po naładowaniu wystarcza na 200 pociągnięć. Ładuje się około 1 godziny.&lt;/p&gt;

&lt;p&gt;Aby odkręcić baterię od atomizera - wystarczy przycisnąć wkład i odkręcić. Nie zdarzyło mi się, żebym się z tym szarpał. Odkręcona bateria od atomizera z wkładem to sugerowana metoda przenoszenia e-papierosa.&lt;/p&gt;

&lt;h4&gt;Dodatkowe zakupy&lt;/h4&gt;

&lt;img class="center" title="joye-306-3" src="/img/2009/08/joye-306-3.jpg" alt="joye-306-3" width="620" height="465" /&gt;

&lt;p&gt;Za pierwszym razem nie udało się kupić wszystkiego. Nabyłem jeszcze e-liquid Marlboro LOW, bodajże 30 ml - 40 zł oraz ładowarkę USB za 25 zł. Można jeszcze kupić ładowarkę samochodową, ale ładowarka sieciowa ma wejście na 12V więc prawdopodobnie wystarczy jedynie przejściowka, aby używać jej w samochodzie.&lt;/p&gt;

&lt;p&gt;Jeśli o e-liquidy chodzi - mamy różne smaki oraz różną zawartość nikotyny: ZERO - brak, LOW - minimalna, MED - średnia, HIGH - wysoka. Póki co dotarły do mnie odrobine sprzeczne informacje odnośnie zawartości nikotyny i smaku. Na Allegro można kupić dowolny smak, wraz z Tabacco oraz Marlboro jako ZERO czyli bez nikotyny. Mój sprzedawca twierdzi, że te dwa smaki zaczynają się od LOW, a ZERO są np. cytryna czy truskawka. Muszę się w tym temacie dodatkowo rozeznać.&lt;/p&gt;

&lt;p&gt;Nie kupiłem jeszcze żadnego etui. Myślę jednak nad czymś bardziej nietypowym, bo do standardowego etui nie zmieści się pojemniczek z e-liquidem. Moje papierosy trzymam jeszcze w oryginalnym opakowaniu. Aby nie męczyć się z ich wyciąganiem (do tego spinacz był równie przydatny co do procesu napełniania wkładu), moja przyjaciółka podsunęła mi pomysł, aby zastosować wstążkę (wstążki się bierze od kobiet, nie pytajcie mnie skąd one je biorą, ja jestem techniczny):&lt;/p&gt;

&lt;img class="center" title="joye-306-1" src="/img/2009/08/joye-306-1.jpg" alt="joye-306-1" width="620" height="465" /&gt;

&lt;h4&gt;Wrażenia i różnice&lt;/h4&gt;

&lt;p&gt;Rewelacja :) Można sobie pociągnąć w samochodzie, biurze. "Dym" nie ma zapachu. W samochodzie sprawdza się naprawdę super. Można palić w czasie jazdy, kiedy trzeba wykonać manewr - rzucam go na fotel, między nogi. Ktoś mi powiedział, że wyrabiam sobie zły nawyk, ale cóż :) Wyrabiam też inne - przykładowo - e-papieros jest trochę cięższy od zwykłego papierosa dzięki baterii, dlatego inaczej go trzymam - za okolice diody. Teraz stwierdzam, że jeśli papieros byłby dłuższy - nie byłoby źle... A większość e-papierosów jest dłuższa. W samochodzie przykładowo - nie musiałbym do popielniczki wkładać chusteczki, żeby mieć pewność, że nie będzie mi wpadał do środka.&lt;/p&gt;

&lt;img class="center" title="joye-306-2" src="/img/2009/08/joye-306-2.jpg" alt="joye-306-2" width="620" height="465" /&gt;

&lt;h4&gt;Po tygodniu e-palenia&lt;/h4&gt;

&lt;p&gt;Nie wróciłem do zwykłych papierosów i nie zamierzam. Nie odczuwam potrzeby palenia więcej, ale coraz bardziej mam ochotę zakupić kilka dodatkowych e-liquidów i z nimi poeksperymentować. Odwiedzę kilka stoisk, m.in w M1 i Silesii, może pojadę do Bytomia bo znalazłem jednego handlarza tanich e-liquidów na Allegro. Zobaczymy. Myślę, że jeszcze coś o e-paleniu napiszę.&lt;/p&gt;

&lt;p&gt;Z tego co czytałem w Internecie - bardzo dużo osób doradza e-papierosa DSE 901 - kosztuje około 130 zł - jest trochę dłuższy - przez inną budowę atomizera, ale ponoć dzięki temu świetnie się dymi. Zastanawiam się czy nie uzupełnić swojego zestawu o coś takiego... Póki co - skoncentruję się jednak na e-liquidach :)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/JxS2MUT3PKs" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/08/moja-recenzja-e-papierosa</feedburner:origLink></entry><entry><title>Unboxing tajemniczego przedmiotu</title><link href="http://feedproxy.google.com/~r/nmepl/~3/CePvv8NVuNw/unboxing-tajemniczego-przedmiotu" rel="alternate" /><id>http://nme.pl/2009/08/unboxing-tajemniczego-przedmiotu</id><summary type="html">&lt;p&gt;Gorączka ostatnio nastała na &lt;a href="http://antyweb.pl/unboxing-tajemniczego-przedmiotu/"&gt;dokumentowanie czynności rozpakowywania&lt;/a&gt; różnego rodzaju sprzętów ;) Jako, że kupiłem całkiem ciekawy gadżet - nie obędzie się bez kilku zdjęć :)&lt;/p&gt;

&lt;p&gt;&lt;img title="unboxing-joye-306-1" src="/img/2009/08/unboxing-joye-306-1-300x225.jpg" alt="unboxing-joye-306-1" width="300" height="225" /&gt;
&lt;img style="margin-left:1em" title="unboxing-joye-306-2" src="/img/2009/08/unboxing-joye-306-2-300x225.jpg" alt="unboxing-joye-306-2" width="300" height="225" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img title="unboxing-joye-306-3" src="/img/2009/08/unboxing-joye-306-3-300x225.jpg" alt="unboxing-joye-306-3" width="300" height="225" /&gt;
&lt;img style="margin-left:1em" title="unboxing-joye-306-4" src="/img/2009/08/unboxing-joye-306-4-300x225.jpg" alt="unboxing-joye-306-4" width="300" height="225" /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img title="unboxing-joye-306-5" src="/img/2009/08/unboxing-joye-306-5-300x225.jpg" alt="unboxing-joye-306-5" width="300" height="225" /&gt;
&lt;img style="margin-left:1em" title="unboxing-joye-306-6" src="/img/2009/08/unboxing-joye-306-6-300x225.jpg" alt="unboxing-joye-306-6" width="300" height="225" /&gt;&lt;/p&gt;

&lt;div style="clear:both"&gt;&lt;/div&gt;

&lt;p&gt;Więcej szczegółów oraz moja wstępna recenzja pojawi się w następnym wpisie.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/CePvv8NVuNw" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/08/unboxing-tajemniczego-przedmiotu</feedburner:origLink></entry><entry><title>Ubuntu 9.10 coraz bliżej...</title><link href="http://feedproxy.google.com/~r/nmepl/~3/9uqPbE8tOJI/ubuntu-910-coraz-blizej" rel="alternate" /><id>http://nme.pl/2009/08/ubuntu-910-coraz-blizej</id><summary type="html">&lt;p&gt;Właśnie skończyłem lekturę wpisu &lt;a href="http://www.ubucentrum.net/2009/08/dla-czego-ubuntu-tak-nie-wyglada.html"&gt;Dlaczego Ubuntu tak NIE wygląda?&lt;/a&gt; na jednym z blogów Adriana Nowaka, z czołówki moich ulubionych bloggerów. Tym razem wyjątkowo muszę przyznać, że się z nim nie zgadzam :)&lt;/p&gt;

&lt;p&gt;Nie zgadzam się do tego stopnia, że nie chciałem zostawiać pod jego artykułem komentarza, bo byłby negatywnie nacechowany, nazbyt rozwlekły i trochę nie na temat, a jako, że trochę ostatnio zapuściłem główny blog, przyda się coś nowego.&lt;/p&gt;

&lt;h4&gt;Wygląd systemu operacyjnego&lt;/h4&gt;

&lt;p&gt;Czy to takie ważne? Obecność jakiegoś ładnego zegarka albo widoczków w małej ramce (screen po lewej) jest taka istotna? Żeby pochwalić się, Compiz chyba wystarczy (screen po prawej).&lt;/p&gt;

&lt;div&gt;&lt;img style="margin-left:10px" title="kde_plasma" src="/img/2009/08/kde_plasma-300x225.jpg" alt="kde_plasma" width="300" height="225" /&gt;&lt;img style="margin-left:1em" src="/img/2009/08/xgl-compiz-300x225.jpg" alt="xgl-compiz" width="300" height="225" /&gt;&lt;/div&gt;

&lt;p&gt;Pamiętam czasy, kiedy pracowałem na Debianie z KDE 3.5. Nie było to znowu tak dawno temu. Byłem bardzo zadowolony. Pulpit wyglądał schludnie, mogłem pracować wydajnie nie będąc rozpraszany żadnymi animowanymi zegarkami i innymi widgetami na pulpicie.&lt;/p&gt;

&lt;p&gt;Wtedy pojawiło się nowe KDE... Opcji było kilka - m.in. iść wraz z nurtem - a nurt był niezwykle rwący, bo programiści postawili całe środowisko KDE do góry nogami. Można było też ustawić na sztywno piny tak, aby KDE się nam nie aktualizowało... Też mi to jakoś nie specjalnie pasowało...&lt;/p&gt;

&lt;p&gt;Jako, że o Ubuntu mówiło się coraz głośniej - zdecydowałem się na wykorzystanie duetu Ubuntu z domyślnym środowiskiem Gnome. Temat graficzny od Ubuntu odpowiada mi wystarczająco, żebym nie potrzebował przy nim cokolwiek robić.&lt;/p&gt;

&lt;p&gt;&lt;img class="center" title="ubuntu_9_04_default" src="/img/2009/08/ubuntu_9_04_default.jpg" alt="ubuntu_9_04_default" width="620" height="465" /&gt;&lt;/p&gt;

&lt;p&gt;Z tuningu wyglądu który stosuje przy konfiguracji swojego konta:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;skróty klawiszowe pulpitu, programów i gnome-terminala&lt;/li&gt;
	&lt;li&gt;wrzucenie ikon kilku aplikacji na górną belkę&lt;/li&gt;
	&lt;li&gt;dodanie monitora systemu dla wszystkich zasobów na górną belkę&lt;/li&gt;
	&lt;li&gt;ustawienia Compiza&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Szczytową funkcjonalnością której używam jest zoomowanie obrazu za pomocą Compiza (Win+Scroll Up/Dn myszką lub Win+[1,2,3]) oraz malowanie ogniem (Win+Shift+lewy klawisz myszy ;) ).&lt;/p&gt;

&lt;p&gt;Uważam, że nie potrzebujemy do szczęścia widgetów ani menu w stylu Mac'a.&lt;/p&gt;

&lt;h4&gt;Na co panowie z Ubuntu powinni położyć nacisk?&lt;/h4&gt;

&lt;p&gt;Na swoje korzenie. Mój kolega, który stara się szerokim łukiem obchodzić wszystkie dystrybucje inne niż Slackware ;) bardzo słusznie wytknął Ubuntu jego największą wadę - Ubuntu jest forkiem &lt;strong&gt;_GNU_&lt;/strong&gt; Debiana. Działając w oparciu o GNU, Debian zawsze był wolny od oprogramowania zamkniętego. Wszystkie pakiety, których licencja nie stanowi o ich otwartości trafiają do zagrody non-free i nie są domyślnie instalowane w systemie. Póki co - z tą polityką się zgadzam.&lt;/p&gt;

&lt;p&gt;Kiedy oprogramowanie tak kluczowe jak Java czy OpenSSL ma zamkniętą licencję, a GNU Debian unika takiego oprogramowania to co się dzieje? Developerzy mają dwa wyjścia - albo uznają, że użytkownicy i tak zainstalują to oprogramowanie, albo poszukają otwartych alternatyw. Takie alternatywy są... naturalnie... problem w tym, że nie są tak stabilne, jak się tego od nich oczekuje...&lt;/p&gt;

&lt;h4&gt;A tym czasem maintainerzy paczek Debiana...&lt;/h4&gt;

&lt;p&gt;Debian może poszczycić się ogromną ilością paczek. Praktycznie każde oprogramowanie na licencji GPL można znaleźć w gotowej do instalacji paczce .deb. Aby przygotować taką paczkę, osoba, która się nią zajmuje, tzw. maintainer musi ustalić jak ma być kompilowana i z jakimi bibliotekami linkowana. Jeśli zlinkuje z oprogramowaniem non-free, zacznie się na grupie dyskusyjnej dyskusja. Zaczną się naciski, zacznie się wymienianie oprogramowania zgodnego z GNU... Więc maintainer przygotuje paczkę zgodną z GNU.&lt;/p&gt;

&lt;p&gt;Większość paczek da się przygotować tak, aby były w pełni funkcjonalne... Niestety, pomimo otwarcia Javy, wiele paczek jest nadal linkowanych z gcj - co sprawia, że np. programistyczne IDE dla Javy, Eclipse, nie da się uruchomić z domyślnej paczki... Trzeba sobie Eclipse'a pobrać ze strony projektu.&lt;/p&gt;

&lt;p&gt;Podobnie jeśli chodzi o SSL - zamiast standardowego OpenSSL'a, w paczkach Debiana które wymagają tej funkcjonalności - wykorzystuje się GnuTLS. Jeśli ktoś chciałby w Ubuntu uruchomić OpenLDAP'a bazując o domyślną paczkę (na bazie tej z Debiana), powinien zdawać sobie sprawę, jak wiele złego mówi się o &lt;a href="http://www.openldap.org/lists/openldap-devel/200802/msg00072.html"&gt;potencjalnych dziurach w GnuTLS&lt;/a&gt;. Z moich własnych doświadczeń - obsługa SSL wymaga wyłączenia sprawdzania poprawności certyfikatów... Dlatego - w Debian/Ubuntu OpenLDAP'a należy sobie przekompilować ręcznie, linkując z OpenSSL'em, jeśli myśli się poważnie o bezpieczeństwie.&lt;/p&gt;

&lt;p&gt;Takich kwiatków jest więcej. Miałem okazję nawet jakiś czas temu rozmawiać na kanale IRCowym z developerami Ubuntu, ale dostałem tą odpowiedź której się spodziewałem - brak odpowiedniej ilości rąk do pracy. Gdyby nacisk był kładziony nie na wygląd, a na poprawę takich właśnie problemów - byłoby znacznie lepiej, a i może rąk by starczyło. Bo przecież zarówno Gnome jak i Compiz są rozwijane przez społeczeństwo, a nie maintainerów Ubuntu.&lt;/p&gt;

&lt;h4&gt;Podsumowując&lt;/h4&gt;

&lt;p&gt;Czy ekipa Ubuntu zdąży dopiąć wszystko na ostatni guzik w 9.10? Nie zdąży i jestem tego pewien. Niektóre rzeczy nie będą ze sobą tak grać, jak będziemy tego oczekiwać. Już kilka razy zdarzało mi się żałować bo za wcześnie przeszedłem na "stabilną" nową wersję... ;) Cóż - przez pierwsze pół roku nowe Ubuntu będzie czymś w stylu bleeding edge + unstable z Debiana i na to się radzę wszystkim przygotować :)) Dlatego moja rada - nie śpieszmy się z aktualizacją oraz czytajmy &lt;em&gt;known issues&lt;/em&gt; w opisie nowego release'u.&lt;/p&gt;

&lt;p&gt;Miejmy nadzieję, że po wydaniu Ubuntu 9.10, Mark Shuttleworth pozwoli swoim ludziom &lt;a href="/img/2009/08/thinking-man.jpg"&gt;oderwać ręce od myślenia nad nowym wyglądem&lt;/a&gt;, tak aby mieli możliwość szybkiego naprawienia niedoróbek ;)&lt;/p&gt;

&lt;p&gt;Nawiązując jeszcze do KDE... Najnowsze coraz bardziej zaczyna mi się podobać. Jest mniej krzykliwe i wydaje się mieć wszystko na miejscu:&lt;/p&gt;

&lt;p&gt;&lt;img class="center" title="kde-4.2RC1-4" src="/img/2009/08/kde-4.2RC1-4.jpg" alt="kde-4.2RC1-4" width="620" height="388" /&gt;&lt;/p&gt;

&lt;p&gt;Screen, jak wszystkie inne w tym wpisie - zapożyczone skądś z odchłani Internetu... mam nadzieję, że żaden nie przedstawia Windowsa ;)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/9uqPbE8tOJI" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/08/ubuntu-910-coraz-blizej</feedburner:origLink></entry><entry><title>CV designera</title><link href="http://feedproxy.google.com/~r/nmepl/~3/U3qNEviUWV4/cv-designera" rel="alternate" /><id>http://nme.pl/2009/08/cv-designera</id><summary type="html">&lt;p&gt;Robi wrażenie :)&lt;/p&gt;

&lt;div style="overflow:hidden;margin-left:20px;width:599px;height:462px;border:1px solid #e6e6e6"&gt;&lt;a href="/img/2009/08/geek_resume.jpg"&gt;&lt;img class="aligncenter size-full wp-image-250" title="geek_resume" src="/img/2009/08/geek_resume.jpg" alt="geek_resume" width="600" height="463" style="margin-left:-1px; margin-top:-1px"/&gt;&lt;/a&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/U3qNEviUWV4" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/08/cv-designera</feedburner:origLink></entry><entry><title>Poczucie humoru inżynierów z Cisco</title><link href="http://feedproxy.google.com/~r/nmepl/~3/OOKa2YJMlMw/poczucie-humoru-inzynierow-z-cisco" rel="alternate" /><id>http://nme.pl/2009/08/poczucie-humoru-inzynierow-z-cisco</id><summary type="html">&lt;p&gt;Jako, że popsuł się nam jeden Cisco Catalyst 2960G, a samo Cisco nie specjalnie garnęło się do natychmiastowej pomocy - otworzyliśmy go sobie, żeby zobaczyć co jest przyczyną problemów. Przy okazji zwróciłem uwagę na nazwy ich chipsetów, bardzo sympatyczny wybór :)&lt;/p&gt;

&lt;div&gt;&lt;img title="Cisco Catalyst - Sasquatch" src="/img/2009/08/cisco_catalyst_sasquatch.png" alt="Cisco Catalyst - Sasquatch" width="313" height="207" /&gt;&lt;img style="margin-left:1em" title="Cisco Catalyst - Yeti" src="/img/2009/08/cisco_catalyst_yeti.png" alt="Cisco Catalyst - Yeti" width="313" height="207" /&gt;&lt;/div&gt;
&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/OOKa2YJMlMw" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/08/poczucie-humoru-inzynierow-z-cisco</feedburner:origLink></entry><entry><title>Powiadomienie SMS na OVH</title><link href="http://feedproxy.google.com/~r/nmepl/~3/ZQQ0Fn0FO1I/powiadomienie-sms-na-ovh" rel="alternate" /><id>http://nme.pl/2009/08/powiadomienie-sms-na-ovh</id><summary type="html">&lt;p&gt;Ten wpis jest zwieńczeniem trzech poprzednich i opisuje w jaki sposób umieścić skrypty na koncie shellowym. Jako, że już wspomniałem, że na chwilę obecną korzystam z usług &lt;a href="http://www.ovh.pl" target="_blank"&gt;OVH&lt;/a&gt;, uważam, że warto opisać, jak takie powiadomienia u nich uruchomić.&lt;/p&gt;

&lt;p&gt;Potrzebne są dane do konta w Gmailu z aktywowanym kalendarzem. Jeśli chodzi o pliki - wystarczy &lt;a href="http://code.google.com/p/gdata-python-client/"&gt;biblioteka kliencka Google&lt;/a&gt; oraz &lt;a href="/pub/files/sms-notify.tar.bz2"&gt;przygotowana przeze mnie paczka&lt;/a&gt;. Oba pliki umieszczamy na koncie w katalogu domowym, logujemy się za pomocą ssh, po czym wydajemy następujące komendy:&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
tar jxvf sms-notify.tar.bz2
mkdir -p lib/api
cd lib/api
tar zxvf ~/gdata-2.0.1.tar.gz
cd ..
ln -s api/gdata-2.0.1/src/atom
ln -s api/gdata-2.0.1/src/gdata
cd ~
&lt;/pre&gt;

&lt;p&gt;następnie edytujemy plik z ustawieniami ustawiając konto i hasło dla aplikacji:&lt;/p&gt;

&lt;code&gt;nano lib/conf.py&lt;/code&gt;

&lt;p&gt;Kiedy już to zrobimy - możemy sprawdzić czy działa pojedyncze powiadomienie:&lt;/p&gt;

&lt;code&gt;./lib/sms.py @ovh testowe powiadomienie&lt;/code&gt;

&lt;p&gt;SMS powinien przyjść na komórkę po czasie 1 minuty. Jeśli wszystko pójdzie dobrze, możemy wysłać na to konto pocztowe maila, a następnie wymusić pojedyncze sprawdzenie:&lt;/p&gt;

&lt;code&gt;./lib/pop2sms.py&lt;/code&gt;

&lt;p&gt;Następnie możemy sprawdzić te same operacje z poziomu skryptów CGI; w celu wysłania SMSa - odwiedzamy:&lt;/p&gt;

&lt;code&gt;http://www.twoja-domena.pl/cgi-bin/sms.py?q=@gdzieś treść powiadomienia&lt;/code&gt;

&lt;p&gt;a kiedy wyślemy sobie na konto maila, możemy sprawdzić czy doszedł, a następnie przekierować do komórki odwiedzając:&lt;/p&gt;

&lt;code&gt;http://www.twoja-domena.pl/cgi-bin/pop.py&lt;/code&gt;

&lt;p&gt;Jeśli wszystko działa, pozostaje nam tylko &lt;a href="https://www.ovh.pl/managerv3/"&gt;zalogowanie do interfejsu zarządzającego OVH&lt;/a&gt; i ustawienie crona... Niestety jednak, na ich serwerach sytuacja jest dość nietypowa, ponieważ najczęstszym wywołaniem nie jest wywołanie co minutę, ale co godzinę. Obniża to niestety odrobinę responsywność naszego automatu. W niektórych sytuacjach może to być akurat plus, ale jakby na to nie patrzeć - niestety - wymuszony ograniczeniami... Jeśli ktoś potrzebuje częstszych powiadomień - musi niestety umieścić skrypty w miarę możliwości na innych serwerach (lub ustawić / poprosić kogoś, kto ma konto gdzieś indziej, aby uruchomił u siebie skrypt wykonujący HTTP GET do naszego skryptu &lt;code&gt;pop.py&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Decydując się na wykorzystanie OVH, warto pomyśleć o zmianie nazw plików w katalogu &lt;code&gt;cgi-bin&lt;/code&gt; na bardziej losowe, np. &lt;code&gt;sms.py&lt;/code&gt; -&amp;gt; &lt;code&gt;sms-d9pVExhQg.py&lt;/code&gt; - dzięki temu zabiegowi możemy uniknąć ślepych prób uruchamiania skryptów z katalogu&lt;code&gt; cgi-bin&lt;/code&gt;. Dla własnego użytku można dodatkowo ustawić sobie odpowiedni wpis w &lt;code&gt;.htaccess&lt;/code&gt; za pomocą &lt;a href="http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html"&gt;mod_rewrite&lt;/a&gt;, który będzie łatwiejszy do zapamiętania i wygodniejszy w użyciu.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/ZQQ0Fn0FO1I" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/08/powiadomienie-sms-na-ovh</feedburner:origLink></entry><entry><title>Oskryptowanie Gmaila</title><link href="http://feedproxy.google.com/~r/nmepl/~3/wOZErSl-QTo/oskryptowanie-gmaila" rel="alternate" /><id>http://nme.pl/2009/08/oskryptowanie-gmaila</id><summary type="html">&lt;p&gt;Google nie udostępniło do Gmaila tak wygodnego API jak dla Google Calendar, którego &lt;a href="/2009/08/mbank-mobile-email-jako-sms"&gt;przykład zastosowania&lt;/a&gt; umieściłem w poprzednim wpisie. Zastanawiając się jednak chwilę - mamy przecież dostęp do protokołu POP, więc jakieś API się znajdzie ;)&lt;/p&gt;

&lt;p&gt;Kontynuując myśl z poprzedniego tekstu - jeśli mam już gotowy skrypt który potrafi wysłać powiadomienie SMS o konkretnej treści, można zrobić skrypt, który jako SMS wyśle np. temat z maila. Et voila:&lt;/p&gt;

&lt;p&gt;Wymagania: Python 2.4+, skrypt z &lt;code&gt;sms.py&lt;/code&gt; z poprzedniego wpisu.&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
#!/usr/bin/env python

__author__ = 'mw AT nme.pl'
__version__ = '1.2'
__date__ = 'pią lip 31 13:17:45 CEST 2009'

class setup:
    class google:
        login = 'KONTO@GOOGLE'
        password = 'HASŁO'

import poplib
import email
import email.Header
import sms

class Mailbox:

    def __init__(self):

        self.server = poplib.POP3_SSL('pop.gmail.com', 995)
        self.server.user(setup.google.login)
        self.server.pass_(setup.google.password)
        self.server.set_debuglevel(0)

        # fetch
        count = self.server.stat()[0]
        print count
        if count:
            for i in range(1,count+1):
                (header, msg, octets) = self.server.retr (i)
                mail = email.message_from_string('\n'.join(msg))
                subject = email.Header.decode_header(mail['Subject'])[0]
                if subject[1]:
                    subject = subject[0].decode(subject[1],'ignore')
                else:
                    subject = subject[0]
                #print subject
                sms.parse(subject.split())
                self.server.dele (i)

        # commit
        self.server.quit()

mbox = Mailbox()
&lt;/pre&gt;
&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/wOZErSl-QTo" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/08/oskryptowanie-gmaila</feedburner:origLink></entry><entry><title>Bramka SMS od Google</title><link href="http://feedproxy.google.com/~r/nmepl/~3/XoQlgj62gto/bramka-sms-od-google" rel="alternate" /><id>http://nme.pl/2009/08/bramka-sms-od-google</id><summary type="html">&lt;p&gt;Oficjalnie Google takiej usługi przynajmniej w Polsce nie udostępnia. Można to jednak osiągnąć w sposób pośredni, który chciałbym dzisiaj przedstawić. Jest bardzo prawdopodobne, że już niebawem, stosowanie takich rozwiązań będzie zbędne, bo ceny usług transmisji danych tanieją, a telefony swoją funkcjonalnością przypominają coraz bardziej PDA.&lt;/p&gt;

&lt;p&gt;Spośród aplikacji Google, powiadomienia SMS na tą chwilę możemy otrzymywać jedynie &lt;a href="http://www.google.com/calendar"&gt;Google Calendar&lt;/a&gt;. Dzięki bardzo dobrej polityce tej firmy, do większości ich aplikacji dostępne jest API, które sprawia, że ich integracja ze swoimi rozwiązaniami jest znacznie prostsza. Calendar API jest &lt;a href="http://code.google.com/intl/pl/apis/calendar/docs/1.0/developers_guide_python.html"&gt;świetnie udokumentowane&lt;/a&gt;, wystarczyła chwila i narzędzie do wysyłania SMS'ów było gotowe.&lt;/p&gt;

&lt;p&gt;Do pełni szczęścia potrzebne jest konto w Google, a na nim Gmail i kalendarz. Posiadając własną domenę oraz &lt;a href="/2009/07/google-apps-twoje-wlasne-google"&gt;uruchomione Google Apps&lt;/a&gt;, można założyć sobie dedykowane konto np. &lt;code&gt;powiadomienia@domena.pl&lt;/code&gt; co jest znacznie elastyczniejszym rozwiązaniem.&lt;/p&gt;

&lt;p&gt;Wymagania: Python 2.4+, &lt;a href="http://code.google.com/p/gdata-python-client/"&gt;Python Client Library&lt;/a&gt;&lt;/p&gt;

&lt;pre class="prettyprint"&gt;
#!/usr/bin/python

__author__ = 'mw AT nme.pl'
__version__ = '1.1'
__date__ = 'pią lip 31 10:42:26 CEST 2009'

class setup:
    class google:
        login = 'KONTO@GOOGLE'
        password = 'HASŁO'
    retries = 3

from elementtree import ElementTree
import gdata.calendar.service
import gdata.service
import atom.service
import gdata.calendar
import atom
import getopt
import sys
import string
import time

class CalendarNotify:

    def __init__(self):

        self.cal_client = gdata.calendar.service.CalendarService()
        self.cal_client.email = setup.google.login
        self.cal_client.password = setup.google.password
        self.cal_client.source = 'api'
        self.cal_client.ProgrammaticLogin()

    def reminder(self,event,minutes):

        for a_when in event.when:
            if len(a_when.reminder) &amp;gt; 0:
                a_when.reminder[0].minutes = minutes
            else:
                a_when.reminder.append(gdata.calendar.Reminder(minutes=minutes))
        self.cal_client.UpdateEvent(event.GetEditLink().href, event)

    def event(self,title,where=None):

        try:
            # add event
            event = gdata.calendar.CalendarEventEntry()
            event.title = atom.Title(text=title)
            #event.content = atom.Content(text=content)
            if where:
                event.where.append(gdata.calendar.Where(value_string=where))
            start_time = time.strftime('%Y-%m-%dT%H:%M:%S.000Z', time.gmtime(time.time() + 180))
            end_time = time.strftime('%Y-%m-%dT%H:%M:%S.000Z', time.gmtime(time.time() + 180 + 60))
            event.when.append(gdata.calendar.When(start_time=start_time, end_time=end_time))
            new_event = self.cal_client.InsertEvent(event, '/calendar/feeds/default/private/full')
            # add reminder
            self.reminder(new_event,1)
        except:
            return False
        return True

def parse(args):

    where = None
    if len(args):
        if args[0][0] == '@':
            where = args.pop(0)

    count = 0
    while count &amp;lt; setup.retries:
        if cal.event(' '.join(args),where):
            break
        count += 1

try:
    cal = CalendarNotify()
except:
    print &amp;gt;&amp;gt;sys.stderr, 'Unable to login to Google Calendar!'
    exit(1)

if __name__ == '__main__':

    args = sys.argv
    name = args.pop(0)

    if not len(args):
        print &amp;gt;&amp;gt;sys.stderr, 'Usage: %s [@where] message\n' % name
        exit(1)

    parse(args)
&lt;/pre&gt;

&lt;p&gt;Uruchamiając skrypt można podać opcjonalny parametr @lokalizacja, a następnie podajemy treść powiadomienia - przykładowa komenda:&lt;/p&gt;

&lt;code&gt;./sms.py @firma awaria bazy danych&lt;/code&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/XoQlgj62gto" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/08/bramka-sms-od-google</feedburner:origLink></entry><entry><title>Mbank Mobile: E-mail jako SMS</title><link href="http://feedproxy.google.com/~r/nmepl/~3/HZchMjfshew/mbank-mobile-email-jako-sms" rel="alternate" /><id>http://nme.pl/2009/08/mbank-mobile-email-jako-sms</id><summary type="html">Zdecydowałem się na skorzystanie z oferty wirtualnego operatora komórkowego &lt;a href="http://mbankmobile.pl/"&gt;Mbank Mobile&lt;/a&gt;, którego &lt;a href="http://www.wykop.pl/ramka/215966/absurdalnie-do-play-rowniez"&gt;najnowsza oferta&lt;/a&gt; okazała się być prawie dokładnie taką, jakiej potrzebowałem.

Brakowało mi w ich ofercie informacji - czy (lub w jaki sposób) można wysłać sobie samemu na komórkę, smsy z Internetu. Każdy kto ma styczność z administracją serwerami lub aplikacjami, może potrzebować tego rodzaju powiadomień o problemach lub zdarzeniach.

Jak się okazało po włożeniu karty do telefonu - Mbank Mobile jest wirtualnym operatorem Plusa, zatem wysyłanie maili na &lt;code&gt;48xxxxxxxxx@text.plusgsm.pl&lt;/code&gt; działa normalnie.

Zanim jednak włożyłem kartę do telefonu... przygotowałem sobie rozwiązanie które:
&lt;ol&gt;
	&lt;li&gt;wykorzystuje &lt;a href="/2009/08/bramka-sms-od-google"&gt;powiadomienia SMS w aplikacji Google Calendar&lt;/a&gt; z poziomu skryptu&lt;/li&gt;
	&lt;li&gt;uruchomiłem &lt;a href="/2009/08/oskryptowanie-gmaila"&gt;własny mail2sms&lt;/a&gt; uzupełniając rozwiązanie o funkcjonalność obsługi dedykowanego konta w usłudze Google Apps&lt;/li&gt;
	&lt;li&gt;ostatecznie &lt;a href="http://www.nme.pl/2009/08/powiadomienie-sms-na-ovh/"&gt;uruchomiłem na swoim koncie w OVH&lt;/a&gt; całą usługę&lt;/li&gt;
&lt;/ol&gt;
Dla własnych potrzeb zdecydowałem się ostatecznie na rozwiązanie oparte o Google - mam nadzieję, że komuś również się przyda :)&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/HZchMjfshew" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/08/mbank-mobile-email-jako-sms</feedburner:origLink></entry><entry><title>Google Apps: Twoje własne Google</title><link href="http://feedproxy.google.com/~r/nmepl/~3/gCBRrE9oAVo/google-apps-twoje-wlasne-google" rel="alternate" /><id>http://nme.pl/2009/07/google-apps-twoje-wlasne-google</id><summary type="html">&lt;img class="post-image" title="Google Apps Circle" src="/img/2009/07/google-apps-circle.png" alt="Google Apps Circle" /&gt;

&lt;p&gt;Bez zbędnego wstępu - chciałbym Was namówić do wykorzystania kolejnej - darmowej i uzależniającej usługi od Google ;) Artykuł ten zakłada, że użytkownik posiada własną domenę - jeśli nie posiada - warto zapoznać się z poprzednim artykułem który dotyczy &lt;a href="/2009/07/twoja-wasna-domena"&gt;rejestracji domeny&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;W sierpniu 2006, Google udostępniło światu nową usługę - &lt;a href="http://www.google.com/a/" target="_blank"&gt;Google Apps&lt;/a&gt;. Jej zadaniem jest umożliwienie wykorzystania aplikacji Google takich jak poczta, współdzielonych kalendarzy czy dokumentów w obrębie własnej domeny oraz przygotowanie jednolitej struktury stron startowych. Usługa ta powoli aczkolwiek systematycznie&lt;a href="http://www.google.com/trends?q=google+apps"&gt; zyskuje zainteresowanie&lt;/a&gt; na rynku, a w lipcu 2009 straciła przypisek Beta - co oznacza, że można ją uznać za w pełni przetestowaną. Stało się to w tym samym momencie, w którym status testowy został zdjęty z takich aplikacji jak Gmail czy kalendarz, co tylko pokazuje, jak bardzo usługa Apps jest z nimi głęboko zintegrowana. Zmiany i aktualizacje są dość częste, dostępny jest &lt;a href="http://feeds.feedburner.com/GoogleAppsUpdates" target="_blank"&gt;kanał RSS&lt;/a&gt; (po angielsku).&lt;/p&gt;

&lt;p&gt;Google Apps (nie mylić z &lt;a href="http://code.google.com/appengine/" target="_blank"&gt;Google App Engine&lt;/a&gt;) dostępne jest w dwóch wersjach - profesjonalnej - przygotowanej dla przedsiębiorstw, oraz standardowej - dla mniejszych społeczności.&lt;span&gt; &lt;/span&gt; Wersja profesjonalna jest pozbawiona ograniczeń ilości kont. Wersja standardowa ma takie ograniczenie, ale jest darmowa. Ja mam w mojej instancji ustawiony limit 100 kont użytkowników, ale zaraz obok limitu jest odnośnik do formularza w którym można poprosić o zwiększenie limitu podając ilość kont które będą nam potrzebne wraz z uzasadnieniem prośby. Zdaje się, że obecnie zakładane konta mają domyślnie ograniczenie do 50 kont co i tak jest w pełni wystarczające dla naszych potrzeb.&lt;/p&gt;

&lt;p&gt;Co zyskamy &lt;a href="http://www.google.com/a/cpanel/domain/new?hl=pl" target="_blank"&gt;rejestrując się w usłudze Google Apps w wersji standard&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;możliwość zakładania dla siebie i dla swoich bliskich lub znajomych kont w postaci &lt;code&gt;nazwa_konta@twoja_domena&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;możliwość przygotowania serwisu WWW dla swojej domeny w operaciu o &lt;a href="http://sites.google.com/" target="_blank"&gt;Google Sites&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;możliwość stworzenia strony startowej w stylu &lt;a href="http://www.google.pl/ig" target="_blank"&gt;iGoogle&lt;/a&gt;, z widgetami oraz wyszukiwarką Googli, rzecz jasna&lt;/li&gt;
	&lt;li&gt;możliwość przygotowania współdzielonych kalendarzy i dokumentów w obrębie swojej domeny&lt;/li&gt;
	&lt;li&gt;aplikacja Gmail dla każdego konta&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Oznacza to nic innego jak możliwość dalszego wykorzystywania usług Google, z tą różnicą, że w obrębie własnej domeny Internetowej oraz pełną customizację - możemy zmienić logo Google na swoje, dodać dodatkową treść i ujednolicić interfejs dla wszystkich.&lt;/p&gt;

&lt;p&gt;Wymienione przeze mnie wyżej powody mogą wydawać się mało istotne. Według mnie jednak skorzystać z tej możliwości i to z kilku powodów...&lt;/p&gt;

&lt;p&gt;Przede wszystkim - będziemy polegać na najprężniej rozwijającej się na świecie firmie, której polityka (hasło "Nie czyń zła", zadbaj jak możesz o swoich pracowników, daj klientom coś użytycznego i zarabiaj na usługach pochodnych) jest obecnie wzorem dla innych firm. O Google można opowiadać wiele, ale trudno znaleźć coś złego. Są niesamowicie oszczędni i wiedzą na czym należy w pierwszej kolejności to robić - zaprojektowane przez nich energooszczędne, dobrze chłodzone farmy serwerów w kontenerach wywodzące się z komputerów PC były chyba absolutną nowością na taką skalę. Słyszał ktoś kiedyś, aby Microsoft martwił się o pobór mocy ich serwerowni? Po co, w końcu klienci kupią te Windowsy czy pakiety Office i będą mieli na rachunki. Google jest też bardzo niezawodne, ma serwerownie na całym świecie, wykorzystuje rozpiętą po świecie superszybką sieć Akamai aby zapewniać użytkownikom końcowym jak największy komfort pracy. Daje nam też bardzo wiele produktów, za które wszystkie inne firmy zarządałyby opłat. To może zabrzmieć zabawnie, ale to Google na tą chwilę, dzięki swojej konkurencyjności kreuje ceny wielu produktów na rynku. No i... są tak dobzi, że mają u mnie darmową reklamę w postaci tego tekstu :)&lt;/p&gt;

&lt;p&gt;Druga sprawa - usługa &lt;a href="http://www.google.com/a/" target="_blank"&gt;Google Apps&lt;/a&gt; daje nam możliwość stworzenia dla siebie coś na kształt koszyka usług, dokładnie tak, jak specjaliści finansowi proponują robić z poszczególnymi rachunkami bankowymi w obrębie danego banku. Świadomy użytkownik Google Apps może odpowiednio przygotować dla siebie konta które będą służyły do różnych celów - takich przykładowo jak poszczególnie definiowanie grup mailowe, gdzie każda grupa posiada odrębne konto (a następnie ustawienie przekierowywania poczty na swoje właściwe konto).&lt;/p&gt;

&lt;p&gt;No i trzeci powód - w tym roku, na Google IO, firma &lt;a href="http://www.youtube.com/watch?v=v_UyVmITiYQ" target="_blank"&gt;zaprezentowała&lt;/a&gt; protokół wraz z implementacją, nad którym obecnie pracują, który ma być w stanie zostawić obecne sposoby komunikacji takie jak email - daleko w tyle. &lt;a href="http://wave.google.com/" target="_blank"&gt;Google Wave&lt;/a&gt;, bo o nim mowa, jeśli się nie mylę, na samym starcie będzie zintegrowany z Google Apps. Dzięki temu firmy, które będą chciały go wykorzystać, będą mogły to zrobić w najprostszy sposób wykorzystując właśnie tą usługę. Zanim powstaną interfejsy do API od firm, użytkownicy Google Apps będą się już mogli cieszyć Google Wave.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/gCBRrE9oAVo" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/07/google-apps-twoje-wlasne-google</feedburner:origLink></entry><entry><title>Twoja własna domena</title><link href="http://feedproxy.google.com/~r/nmepl/~3/MF3eEcvnDNE/twoja-wasna-domena" rel="alternate" /><id>http://nme.pl/2009/07/twoja-wasna-domena</id><summary type="html">&lt;p&gt;Postanowiłem przygotować kilka artykułów traktujących o &lt;em&gt;"zaistnieniu w sieci"&lt;/em&gt;. Określenie to zmieniło ostatnio trochę swoje znaczenie z powodu wysypu serwisów społecznościowych takich jak &lt;a href="http://nasza-klasa.pl/" target="_self"&gt;Nasza-klasa&lt;/a&gt; czy &lt;a href="http://www.facebook.com/"&gt;Facebook&lt;/a&gt;, ale mnie chodzi o stworzenie strony Internetowej na której mamy pełną swobodę edycji treści i układu. O serwisach społecznościowych zamierzam zresztą również trochę napisać, ale w późniejszym czasie ;)&lt;/p&gt;

&lt;p&gt;Teksty te nie będą jednak poradnikiem który należy w pełni przerobić, a jedynie luźnymi sugestiami i podpowiedziami mającymi za zadanie ułatwić czytelnikowi pierwsze kroki. Zdecydowałem się na wymienienie konkretnych rozwiązań z którymi się zetknąłem, ich ocenę oraz wybór najlepszego pod względem cenowym i jakościowym. Postanowiłem też na przedstawienie gdzie to tylko możliwe dwóch według mnie najlepszych wariantów - jeden - najlepszy spośród darmowych, drugi - najbardziej konkurencyjny, ale płatny.&lt;/p&gt;

&lt;p&gt;Własna domena - &lt;code&gt;.pl&lt;/code&gt;, &lt;code&gt;.com&lt;/code&gt; czy inne - pytanie czy jest Ci potrzebna. Zwykle, a już napewno na samym początku - można się bez niej obejść. Wiele darmowych rozwiązań hostujących oferuje nam możliwość umieszczenia swojej treści jako poddomena. Z darmowych rozwiązań, pozbawionych reklam (możemy dodać własne, jeśli chcemy na witrynie w ten sposób zarabiać), ograniczając do samego Google:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.blogger.com/" target="_blank"&gt;Blogger&lt;/a&gt; - nasza strona miałaby adres &lt;code&gt;&lt;em&gt;nazwa_blogu&lt;/em&gt;.blogspot.com&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://appengine.google.com/" target="_blank"&gt;Google App Engine&lt;/a&gt; - &lt;code&gt;&lt;em&gt;nazwa_aplikacji&lt;/em&gt;.appspot.com&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Google oferuje nam również darmową usługę &lt;a href="http://sites.google.com/" target="_blank"&gt;Google Sites&lt;/a&gt;, w której tworzone strony mają adres w postaci &lt;code&gt;http://sites.google.com/site/&lt;em&gt;twoja_nazwa&lt;/em&gt;/&lt;/code&gt; .
Każda z wymienionych powyżej usług Google daje nam również możliwość wykorzystania własnej domeny.&lt;/p&gt;

&lt;p&gt;Jeśli zatem zdecydowaliśmy się na własną domenę - niestety trzeba liczyć się z kosztami. Nie są one duże, ale warto dokładnie zastanowić się gdzie tą domenę kupić, aby koszty nie okazały być znacznie większe.&lt;/p&gt;

&lt;p&gt;No to zaczynamy:&lt;/p&gt;

&lt;p&gt;Serwis &lt;a href="http://www.domeny.pl/" target="_blank"&gt;domeny.pl&lt;/a&gt; - sprawdźmy co piszą o nich inni - wyszukiwanie "domeny.pl" w serwisie&lt;a href="http://www.wykop.pl/" target="_blank"&gt; Wykop&lt;/a&gt;: przerażające &lt;a href="http://www.wykop.pl/search?phrase=domeny.pl&amp;amp;adv=0&amp;amp;advShow=0&amp;amp;zakres=1&amp;amp;typ[tekst]=on&amp;amp;typ[video]=on&amp;amp;typ[obrazek]=on&amp;amp;data[od]=&amp;amp;data[do]="&gt;wyniki&lt;/a&gt; (lokalna &lt;a href="/img/2009/07/domeny.pl-wykop-search.png" target="_blank"&gt;kopia&lt;/a&gt;). O serwisie swojego czasu zrobiło się bardzo głośno kiedy domeny w promocji z serwerami za bodajże 30 zł okazywały się już po 3 miesiącach znacznie droższe, a firma domeny.pl jeśli ktoś nie uiścił opłaty - kierowała sprawę do sądu. Napisałem wcześniej, że moje wypowiedzi będą dotyczyły serwisów z którymi miałem styczność - nigdy nie byłem ich klientem, ale uważam, że o tym serwisie słyszałem już tyle złego, że warto o tym, wspomnieć dla przestrogi. Wydaje mi się, że wystarczy. Zakop ;)&lt;/p&gt;

&lt;p&gt;Serwis &lt;a href="http://www.nazwa.pl" target="_blank"&gt;nazwa.pl&lt;/a&gt; - firma NetArt - byłem ich klientem przez kilka lat. Wykupiłem za ich pośrednictwem kilka domen, a następnie je przedłużałem. Do takich celów serwis nadaje się wyśmienicie - dostajemy przypomnienia, że domena wygasa, fakturę, po uiszczeniu opłaty dostajemy informację, że opłata wpłynęła i domena została przedłużona - pełen profesjonalizm... NetArt był początkowo całkiem konkurencyjny cenowo na rynku, z powodu absurdalnie wysokich cen w &lt;a href="http://www.nask.pl"&gt;NASK&lt;/a&gt;. Z czasem jednak, kiedy dostawca ten poczuł się wystarczająco pewnie - przestał być konkurencyjny. Jako klient posiadający u nich swoje domeny, z panelu administracyjnego miałem do wyboru następujące możliwości:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;zaparkowanie domeny (czyli domena nie skonfigurowana)&lt;/li&gt;
	&lt;li&gt;ustawienie własnych serwerów DNS (usługa hostingowa u operatora zewnętrznego)&lt;/li&gt;
	&lt;li&gt;wykorzystanie usługi hostingowej NetArt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wykorzystywałem drugą - co to oznacza? Chodzi mianowicie o to, że musiałem wykupić usługę hostingową w innej firmie. Tą firmą był &lt;a href="http://www.risp.pl" target="_blank"&gt;RISP&lt;/a&gt; - usługa hostingowa z shellem oraz interfejs zarządzania domeną - bardzo atrakcyjnie cenowo.  Dlaczego na to się zdecydowałem? Ponieważ oferta hostingowa &lt;a href="http://www.nazwa.pl"&gt;NetArt&lt;/a&gt; jest dość ograniczona oraz jest stosunkowo droga.&lt;/p&gt;

&lt;p&gt;Okej, co mają inni czego nie ma &lt;a href="http://www.nazwa.pl"&gt;NetArt&lt;/a&gt;? Możliwość zarządzania swoją domeną. Według mnie jest to absurdalne, że tego nie oferują swoim klientom. Uważam, że w obecnych czasach jest to nie do pomyślenia, o czym miałem okazję już ich nawet informować. Firma wysyła swoim klientom maile opisując usprawnienia jakie się u nich pojawiają, wysłałem do nich &lt;a href="/img/2009/07/nazwa.pl-mail.png"&gt;maila&lt;/a&gt;, na który jednak nie dostałem odpowiedzi. Kilka miesięcy później dostałem kolejny opis usprawnień w ich ofercie, stwierdziłem, że zostałem kompletnie zignorowany i od nich odszedłem. Transfer domeny z &lt;a href="http://www.nazwa.pl"&gt;NetArt&lt;/a&gt; jest również realizowany przez nich profesjonalne. Wszystko udało mi się załatwić błyskawicznie, razem z weryfikacją listowną. Żadnych zastrzeżeń.&lt;/p&gt;

&lt;p&gt;Wracając jeszcze do szczegółów ich oferty - sprzedaży domen bez interfejsu do ich zarządzania - to bardzo ciekawy biznes - to tak, jakby ktoś otworzył lodziarnię i nie miał kubeczków. Chociaż... w Warszawie ponoć panuje ostatnio moda na &lt;a href="/img/2009/07/starbucks_iphone_lans.png"&gt;chodzenie wszędzie z kubkiem ze Starbucks'a&lt;/a&gt;, więc tam taki biznes mógłby odnieść sukces ;)&lt;/p&gt;

&lt;p&gt;Czasy się zmieniają, a oferty firm stają się bardziej kompleksowe. Wykorzystując ten fakt, przeniosłem się do &lt;a href="http://www.ovh.pl" target="_blank"&gt;OVH&lt;/a&gt; i póki co jestem zadowolony. Ich oferta jest bardzo zróżnicowana - zależnie od potrzeb klienta. Możemy obsługiwać tylko i wyłącznie domeny, możemy wykupić małą usługę hostingową na środowisku wirtualnym, a ostatecznie, jeśli okaże się, że potrzebujemy jeszcze więcej - w ich ofercie są serwery dedykowane. Oferta jest bardzo kompleksowa - wykupując 90plan, dostałem rozbudowany interfejs do zarządzania bazami danych, możliwość zarządzania pocztą (z której nie korzystam, bo preferuję darmową ofertę Google w tym temacie), obsługę Jabbera dla mojej domeny no i oczywiście shell. Są również bardzo konkurencyjni cenowo.&lt;/p&gt;

&lt;p&gt;W wypadku tak zaawansowanych serwisów jak &lt;a href="http://www.ovh.pl" target="_blank"&gt;OVH&lt;/a&gt;, trzeba wziąść pod uwagę ważną kwestię - osoba, która nie jest zbyt techniczna, może mieć problemy z konfiguracją usług jeśli ustawienia domyślne okażą się niewystarczające.  Interfejs konfiguracji domeny jest łatwy dla osoby, która potrafi administrować serwery DNS, ale raczej nie dla zwykłego użytkownika. Warto więc, jeśli nie jesteśmy w pełni techniczni, znaleźć sobie kogoś, kto nam w tym pomoże. Tutaj można wymienić jeszcze jedną zaletę &lt;a href="http://www.ovh.pl" target="_blank"&gt;OVH&lt;/a&gt; - w interfejsie zarządzającym możemy zdefiniować odrębne konta do interfejsu administracyjnego dla właściciela DNS, administratora serwera, administratora poczty i w obrębie każdego z nich możliwość zdefiniowania kontaktu technicznego. Można w ten sposób uniknąć sytuacji z którymi już miałem okazję się spotkać - kiedy to administrator na swoim koncie u operatora miał zarejestrowaną domenę firmy, w której pracował.&lt;/p&gt;

&lt;p&gt;Osobiście polecam &lt;a href="http://www.ovh.pl"&gt;OVH&lt;/a&gt;, ale po cichu czekam z nadzieją, aż Google udostępni tego rodzaju usługi za darmo, wraz z obsługą domen narodowych oraz wszystkich typów wpisów. Gdyby się to stało, prawdopodobnie wystarczyłoby jedynie opłacać za pośrednictwem Google własną domenę nie ponosząc już żadnych innych kosztów. Póki co, Google oferuje taką usługę, podczas rejestracji konta w &lt;a href="https://www.google.com/a/" target="_blank"&gt;Google Apps&lt;/a&gt;, ale rejestrację wykonuje firma partnerska Google, a użytkownik jest ograniczony jedynie do podstawowych domen (&lt;code&gt;.com&lt;/code&gt;, &lt;code&gt;.net&lt;/code&gt; itp). Kiedy jednak Google zdecydowałoby się na taki krok - oznaczałoby raczej rychły schyłek mniejszych providerów oraz prawdopodobnie szybkie podbicie rynku rejestratorów domen. Jest to niestety mało prawdopodobne z powodu &lt;a href="http://googlesystem.blogspot.com/2006/01/how-to-make-money-without-doing-evil.html" target="_blank"&gt;ich polityki&lt;/a&gt;. Jeśli jednak coś w tym temacie się zmieni - napewno o tym napiszę.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/MF3eEcvnDNE" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/07/twoja-wasna-domena</feedburner:origLink></entry><entry><title>Przedłuż czas życia dysku twardego</title><link href="http://feedproxy.google.com/~r/nmepl/~3/YHdu6UOTrHo/przedluz-czas-zycia-dysku-twardego" rel="alternate" /><id>http://nme.pl/2009/07/przedluz-czas-zycia-dysku-twardego</id><summary type="html">&lt;img class="post-image" title="sata_disk" src="/img/2009/07/sata_disk.png" alt="sata_disk" width="160" height="131" /&gt;

&lt;p&gt;Dyski SSD (Solid State Drive) są w momencie pisania tego tekstu wciąż drogie, a ich pojemności są nieporównywalnie mniejsze od dysków starego typu. Warto zatem zadbać jeszcze przez kilka lat o swoje stare dyski, aby mogły nam służyć przynajmniej do momentu, kiedy te dwa parametry zaczną się między nimi zacierać :)&lt;/p&gt;

&lt;p&gt;Jeśli używamy w laptopie dysku twardego starego typu (mechaniczne, z talerzami) powinniśmy zdawać sobie sprawę z faktu, że na jego czas życia wpływa wiele parametrów. Jedym z nich jest ilość cyklów parkowania/odparkowania (ang. load/unload cycles), który dla większości dysków przewidziany jest przez producenta na około &lt;em&gt;600 000&lt;/em&gt;. Liczba ta jest wysoka, ale można ją niechcący bardzo szybko przekroczyć. Okazuje się, że może się tak zdarzyć, że nasz świeżo zainstalowany system, wraz ze sterownikami i oprogramowaniem do oszczędzania energii sprawi, że dysk będzie parkowany co minutę.&lt;/p&gt;

&lt;p&gt;Wszystkiemu winne oszczędzanie energii w wydaniu producentów dysków twardych. Kto wie, może jest to wybieg celowy. System operacyjny, bez znaczenia czy jest to Windows, Linux czy coś innego, ustawia sprzętowi tryb pracy APM (Advanced Power Managment). Jeśli dysk twardy obsługuje APM, przechodzi w odpowiedni tryb pracy. Czym tryb będzie bardziej energooszczędny - tym dysk będzie starał się parkować głowice po krótszym czasie bezczynności.&lt;/p&gt;

&lt;p&gt;Parametr trybu APM może przyjąć wartość w zakresie 0-255. Domyślna wartość dla pracy bez zasilania to 128, a dla pracy z zasilaniem - 254 (chociaż bezpieczniej jest wyłączyć APM ustawiając ten parametr na 255). Problem w tym, że systemy operacyjne bądź z powodu ustawień domyślnych (np. Ubuntu Linux), bądź z powodu sterowników dołączonych do notebooka (np. sterowniki Fujitsu Lifebook S dla Windows XP) ustawiają te parametry niewłaściwie.&lt;/p&gt;

&lt;h4&gt;Rozwiązanie problemu dla Windows&lt;/h4&gt;

&lt;p&gt;Trzeba wykorzystanie aplikację &lt;a href="http://sites.google.com/site/quiethdd/"&gt;QuietHDD&lt;/a&gt;. Program należy wypakować do lokalizacji docelowej, a następnie utworzyć do niej skrót. Po uruchomieniu programu, w jego lokalizacji tworzy się plik ini z utawieniami. Możemy wtedy ustawić tryb APM na 255, a następnie zamykamy program. Przygotowany wcześniej skrót można zaopatrzyć w dopisek &lt;code&gt;/notray&lt;/code&gt;, a następnie trzeba go przenieść do Autostartu.&lt;/p&gt;

&lt;p&gt;&lt;img class="center" title="quiet hdd" src="/img/2009/07/quiethdd.jpg" alt="quiet hdd" width="486" height="334" /&gt;&lt;/p&gt;

&lt;h4&gt;Rozwiązanie dla Linux Ubuntu&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://bugs.launchpad.net/ubuntu/+source/acpi-support/+bug/59695/comments/14" target="_blank"&gt;Źródło&lt;/a&gt;, tłumaczenie:&lt;/p&gt;

&lt;ol&gt;
	&lt;li&gt;stwórz plik o nazwie &lt;code&gt;99-hdd-spin-fix.sh&lt;/code&gt;. Ważne jest, aby zaczynał się od &lt;code&gt;99&lt;/code&gt;.&lt;/li&gt;
	&lt;li&gt;uzupełnij plik o następujące 2 linie:&lt;br /&gt;
&lt;code&gt;#!/bin/sh&lt;br /&gt;
hdparm -B 255 /dev/sda&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;skopiuj plik do 3 lokalizacji:&lt;br /&gt;
&lt;code&gt;/etc/acpi/suspend.d/&lt;br /&gt;
/etc/acpi/resume.d/&lt;br /&gt;
/etc/acpi/start.d/&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Panowie z Ubuntu obiecują, że naprawią problem w nowej wersji systemu, ale od tamtego czasu numerki wersji już kilka razy się zmieniły. Powyższe rozwiązanie do najładniejszych nie należy, ale się sprawdza.&lt;/p&gt;

&lt;p&gt;Dodatkowo, sprawdzenie stanu APM wykonujemy komendą: &lt;br /&gt;
&lt;code&gt;sudo hdparm -I /dev/sda | grep level&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Sprawdzenie obecnej ilości cyklów możemy sprawdzić wydając: &lt;br /&gt;
&lt;code&gt;sudo smartctl -a /dev/sda | grep Load&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Jako, że era tego rodzaju dysków dobiega powoli końca, warto zobaczyć jak wyglądał jeden z &lt;a href="http://commons.wikimedia.org/wiki/File:IBM_old_hdd.jpg" target="_blank"&gt;pierwszych modeli&lt;/a&gt; :)&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/YHdu6UOTrHo" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/07/przedluz-czas-zycia-dysku-twardego</feedburner:origLink></entry><entry><title>Internet na bieżąco - czyli RSS</title><link href="http://feedproxy.google.com/~r/nmepl/~3/1c_k5e6SLtc/internet-na-biezaco" rel="alternate" /><id>http://nme.pl/2009/07/internet-na-biezaco</id><summary type="html">&lt;p&gt;Dostępność Internetu w ciągu ostatnich 10 lat umożliwiła umieszczenie w nim ogromnej ilości informacji w postaci treści na stronach WWW. Odszukanie tego, co nas interesuje to obecnie kwestia sekund lub w gorszym wypadku minut. Docieramy do tego zwykle używając wyszukiwarek Internetowych (&lt;a title="Google" href="http://www.google.com"&gt;Google&lt;/a&gt;, &lt;a title="Yahoo" href="http://www.yahoo.com/"&gt;Yahoo&lt;/a&gt;, czy &lt;a title="Bing" href="http://www.bing.com"&gt;Bing&lt;/a&gt;). Są jednak takie sytuacje, w których bardziej od wyszukania informacji na dany temat, jesteśmy zainteresowani śledzeniem zmian w ich obrębie. Do takich celów stworzono kanały RSS / Atom, których wygodę użycia chciałbym omówić jako pierwszy tekst na tym nowo-powstałym blogu :)&lt;/p&gt;

&lt;p&gt;Dla kogo ten wpis może okazać się przydatny? Wydaje mi się, że dla każdego, kto ma dostęp do Internetu i lubi czytać informacje na tematy które go interesują. Wiele osób nie zdaje sobie sprawy, że RSS jest taki prosty w obsłudze i kończy na takich stronach jak &lt;a title="Onet" href="http://www.onet.pl" target="_blank"&gt;Onet&lt;/a&gt;,  czytając bzdurne teksty których celem jest przyciągnięcie uwagi każdego, a jednocześnie nie niosące za sobą żadnej treści (żeby przypadkiem kogoś nie urazić, rzecz jasna).&lt;/p&gt;

&lt;h4&gt;Trochę historii&lt;/h4&gt;

&lt;p&gt;Najpierw trochę historii - na samym początku WWW, treść (ang. content) na stronach była raczej niezmienna, nie było jej wiele i służyły one tylko określonym jednostkom. Kiedy zaczęło jej przybywać, twórcy stron skupili się na odpowiednim sposobie ich kategoryzowania. Zaczęły się wtedy pojawiać się nowe linki, podstrony.  Serwery WWW serwowały wtedy jedynie przygotowane statyczne dokumenty HTML. Kiedy różnego rodzaju treści zaczęło przyrastać, administratorzy zaprzęgli do pracy bazy danych i języki programowania, które umożliwiły generowanie treści stron dynamicznie. Otwartość kodu, sprawiła, że rozwój w tym zakresie był bardzo szybki, co umożliwiło przeciętnemu domorosłemu programiście stworzenie całkiem wymyślnej aplikacji po stronie serwera. Niedaleko potem w przeglądarkach Internetowych pojawiła się implementacja objektu XMLHttpRequest dzięki któremu strony stały się jeszcze bardziej responsywne, a Macromedia (później Adobe) umożliwiła strumieniowanie muzyki i video w osadzonym na stronie obiekcie Flash.&lt;/p&gt;

&lt;p&gt;Wtedy mniej więcej wyłonił się Web 2.0 - strony Internetowe, które umożliwiały użytkownikom interakcję, zmieniając się, siłą rzeczy w aplikacje Internetowe. Zwykły użytkownik był teraz w stanie zamieszczać treść w intuicyjny sposób. Znajomość języka HTML przestała być już konieczna. Pojawiły się blogi i reklamy kontekstowe. Nowy ekosystem zaczął żyć pełnią życia. Wszystko czego brakowało do szczęścia to ujednolicenie języka opisu "życia" takiego konkretnego bloga lub serwisu Internetowego. Kiedy tylko pojawiał się nowy wpis - informacje o nim są umieszczane w jego kanale RSS / Atom. &lt;a title="Atom" href="http://pl.wikipedia.org/wiki/Atom_(standard)" target="_blank"&gt;Atom&lt;/a&gt; jest nieco świeższy niż &lt;a title="RSS" href="http://pl.wikipedia.org/wiki/RSS" target="_blank"&gt;RSS&lt;/a&gt; i umożliwia zawarcie w danym kanale więcej informacji i w przeciwieństwie do RSS będzie nadal rozwijany.&lt;/p&gt;

&lt;h4&gt;Kanały RSS i Atom&lt;/h4&gt;

&lt;p&gt;Co się z nimi robi? Subskrybuje - można wykorzystać do tego odrębny program lub inną aplikację Internetową. Ja preferuję Google Readera. Aby móc z niego skorzystać, wymagane jest założenie konta w Google. Mamy tutaj dwie możliwości - jeśli nie mamy konta pocztowego - możemy&lt;a href="https://www.google.com/accounts/NewAccount?service=mail" target="_blank"&gt; założyć konto Google wraz z kontem Gmail&lt;/a&gt; lub &lt;a href="https://www.google.com/accounts/NewAccount" target="_blank"&gt;założyć konto Google powiązane z kontem pocztowym w innym serwisie&lt;/a&gt;. Będąc zalogowanym w Google, możemy przejść do &lt;a title="Google Reader" href="http://www.google.com/reader" target="_blank"&gt;Google Readera&lt;/a&gt; i zacząć subskrybować serwisy, które udostępniają nam kanały RSS / Atom:&lt;/p&gt;

&lt;p&gt;&lt;img class="center" title="rss_in_url" src="/img/2009/07/rss_in_url.png" alt="rss_in_url" width="430" height="100" /&gt;&lt;/p&gt;

&lt;h4&gt;Google Reader - komfort i wygoda&lt;/h4&gt;

&lt;p&gt;Od kiedy zacząłem korzystać z tej aplikacji, śledzenie informacji stało się prostsze, wygodniejsze oraz dostępne z każdego miejsca. Obecnie przy subskrypcjach które posiadam, nie potrzebuje już czytać czasopism informatycznych, a kiedy do takich zaglądam, okazuje się, że nowości o których piszą czytałem 2-3 miesiące wcześniej.&lt;/p&gt;

&lt;p&gt;&lt;a title="Google Reader" href="http://www.google.com/reader/" target="_blank"&gt;Google Reader&lt;/a&gt; wygląda mniej więcej tak (osobiście używam wersji angielskiej, domyślnie aktywna jest wersja polska):&lt;/p&gt;

&lt;p style="margin:1em 0 2em"&gt;&lt;img class="center" src="/img/2009/07/google_reader_screenshot.png" alt="google_reader_screenshot" width="556" height="243" /&gt;&lt;/p&gt;

&lt;h4&gt;Od czego warto zacząć&lt;/h4&gt;

&lt;p&gt;Na koniec tego tekstu, chciałbym polecić kilka serwisów na dobry początek. Zapewne macie swoje ulubione strony na których okaże się, że dostępny jest kanał RSS lub Atom - trzeba sobie tylko wyrobić odruch i odszukać tą magiczną ikonkę którą zakreśliłem powyżej. Tak czy inaczej, uważam, że warto dodać kanały z poniżej zaprezentowanych przeze mnie stron... w końcu zawsze można je później usunąć:&lt;/p&gt;

&lt;h5&gt;Relaks&lt;/h5&gt;

&lt;p style="text-align: left;"&gt;&lt;a title="Kopalnia wiedzy" href="http://kopalniawiedzy.pl/" target="_blank"&gt;http://kopalniawiedzy.pl&lt;/a&gt; - Rewelacyjne ciekawostki ze świata&lt;/p&gt;
&lt;p style="text-align: left;"&gt;&lt;a title="990px" href="http://www.990px.pl/" target="_blank"&gt;http://www.990px.pl&lt;/a&gt; - Fotoreportaże w świetnej jakości na różne tematy&lt;/p&gt;
&lt;p style="text-align: left;"&gt;&lt;a title="Joe Monster" href="http://www.joemonster.org/" target="_blank"&gt;http://www.joemonster.org&lt;/a&gt; - jeśli już nic nie potrafi rozśmieszyć - to ostatnia deska ratunku ;)&lt;/p&gt;

&lt;h5&gt;Ekonomia&lt;/h5&gt;

&lt;p style="text-align: left;"&gt;&lt;a title="Forsal" href="http://forsal.pl/" target="_blank"&gt;http://forsal.pl&lt;/a&gt; - Informacje z dziedziny gospodarki i ekonomii&lt;/p&gt;
&lt;p style="text-align: left;"&gt;&lt;a title="Trystero" href="http://www.trystero.pl/" target="_blank"&gt;http://www.trystero.pl&lt;/a&gt; - Niezwykle aktywny twórca bloga finansowego&lt;/p&gt;
&lt;p style="text-align: left;"&gt;&lt;a title="Dwa grosze" href="http://dwagrosze.blogspot.com/" target="_blank"&gt;http://dwagrosze.blogspot.com&lt;/a&gt; - Humorystyczne felietony o gospodarce, polityce i ekonomii&lt;/p&gt;

&lt;h5&gt;Branża IT&lt;/h5&gt;

&lt;p style="text-align: left;"&gt;&lt;a title="Heise Online" href="http://www.heise-online.pl/" target="_blank"&gt;http://www.heise-online.pl&lt;/a&gt; - Według mnie - najlepsze newsy z branży informatycznej&lt;/p&gt;
&lt;p style="text-align: left;"&gt;&lt;a title="Blog o Linux Ubuntu" href="http://www.ubucentrum.net/" target="_blank"&gt;http://www.ubucentrum.net&lt;/a&gt; - Używasz Linux Ubuntu? Jeśli tak - to obowiązkowa lektura&lt;/p&gt;
&lt;p style="text-align: left;"&gt;&lt;a title="VBeta" href="http://vbeta.pl/" target="_blank"&gt;http://vbeta.pl&lt;/a&gt; - Wydarzenia w tematyce serwisów społecznościowych i Internetu&lt;/p&gt;

&lt;p style="margin:1em 0 2em"&gt;Oczywiście, jeśli któryś z serwisów trafi do Waszego Readera, a nie przypadnie Wam do gustu - jak wspomniałem wcześniej - możecie go usunąć. Polecam jednak stworzyć sobie kategorię - np. Niefajne - i tam je wrzucić. Może przecież nadajść chwila, że będziecie się nudzić i może akurat przeglądnięcie tej kategorii dostarczy Wam rozrywki.&lt;/p&gt;

&lt;p class="footnotes"&gt;&lt;span class="warn"&gt;Edit:&lt;/span&gt; &lt;em&gt;Tekst został odrobinę odświeżony.&lt;br style="margin-bottom:1em" /&gt;Zdecydowałem niefortunnie, że będzie on pierwszym wpisem na tym blogu - nie znalazł on z tego powodu niestety zbyt wielu odbiorców, a szkoda.&lt;br style="margin-bottom:1em" /&gt;Zachęcam do zapoznania się z tym tekstem oraz wypróbowania &lt;a href="http://www.google.com/reader"&gt;Google Readera&lt;/a&gt; - dla mnie przynajmniej ta aplikacja jest krokiem milowym w surfowaniu ;)&lt;/em&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/1c_k5e6SLtc" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/07/internet-na-biezaco</feedburner:origLink></entry><entry><title>nme.pl: Zaczynamy</title><link href="http://feedproxy.google.com/~r/nmepl/~3/Acyu0IzmLDs/nmepl-zaczynamy" rel="alternate" /><id>http://nme.pl/2009/07/nmepl-zaczynamy</id><summary type="html">&lt;p&gt;Przyszedł czas zacząć coś pisać od siebie.&lt;/p&gt;

&lt;p&gt;Na wstępie kilka słów o mnie; skończyłem studia i pracuję od kilku lat w branży IT. Specyfika moich zainteresowań w tej tematyce jest dość szeroka - mam styczność zarówno z systemami Microsoftu, Unixami jak i Linuxem, sprzętem desktopowym, serwerowym i sieciowym, a na dodatek tworze różnego rodzaju aplikacje. Kiedy mogę, staram się faworyzować rozwiązania OpenSource'owe. W wolnych chwilach interesuję się ekonomią, psychologią i jak każdy polak - polityką.&lt;/p&gt;

&lt;p&gt;Jak każdy polak również - mam humory... Trudno ich nie mieć, skoro raz w tym kraju jest mroźnie, raz deszczowo i szaro, innym razem przechodzą przez ten kraj ulewy, trąby powietrzne, a kiedy już powinno być ok - jest tak gorąco, że aż trudno wytrzymać ;) Dlatego więc, jako że ów humory mam, nie mogę zagwarantować, że teksty które będę pisał będą bezstronne i obiektywne, choć będę się starał :)&lt;/p&gt;

&lt;p&gt;Mam nadzieję, że informacje tudzież przemyślenia które zamierzam tutaj zamieścić komuś przypadną do gustu. Osoby którym nie przypadną - zapraszam do dyskusji. Wszelka konstruktywna krytyka jest mile widziana.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/nmepl/~4/Acyu0IzmLDs" height="1" width="1"/&gt;</summary><feedburner:origLink>http://nme.pl/2009/07/nmepl-zaczynamy</feedburner:origLink></entry></feed>

