piątek, 27 lipca 2007
Google Analytics po naszemu
czwartek, 26 lipca 2007
Google Gears - brakujący pierwiastek
O co chodzi?
Co znowu wymyślili chłopaki z Googla? Niby nic rewolucyjnego, wystarczyło wzbogacić przeglądarki o 3 elementy.
- Serwer Lokalny: służy on do składowania obrazków, css'ów i wszystkiego czego tylko chcesz podczas przebywania w trybie offline.
- Baza danych: prosta baza SQLite, wysyłania do której można wykonywać prosto z JavaScriptu na stronie.
- WorkerPool: dodatkowe rozszerzenie JavaScriptu umożliwiające tworzenie wątków dla długo trwających zapytań. Po co? Żeby przeglądarka nie "zamarzła".
Bezpiecznie panowie (i panie)
Bezpieczeństwo przede wszystkim. Taka przyświeca nam wszystkim zasada. I słusznie! Tutaj też to działa. A przynajmniej w obrębie jednego programisty. Konkrety? Służę, baza stworzona z jednej domeny (przykładowo domena1.pl) może być obsługiwana tylko przez tą jedną domenę. Czyli zła konkurencja z domeny domena2.pl nic nam nie namiesza.
Troszkę kodu
Weźmy na warsztat prościutki system dodawania artykułów. Chcemy tylko mieć dostęp do dodanych artykułów zarówno w wersji online jak i offline. Po stronie serwera jedna baza artykułów, prosty formularz dodawania i strona podziękowania za wpis. Nie będę tego pisał, każdy robił to już tysiące razy. Nie? Szukać w necie ;)
Co jeszcze po stronie serwera? Potrzebujemy plik articles.php generujący nam prostego xml'a. Przykładowy output mógłby wyglądać tak:
Teraz plik z dodawaniem artykułów do Google Gears... Dla uproszczenia użyję zapytań Ajaxa używając Prototype. Plik gears_init.js natomiast jest dodawany do zestawu developerskiego Google. Oba zaincludowane w headzie.<articles>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
<article id="1" title="Hate test strings">Test article here bla bla</article>
<article id="2" title="Lorem ipsum forever"></article>
</articles>
<html>
<head>
<script type="text/javascript" src="gears_init.js"></script>
<script type="text/javascript" src="prototype.js"></script>
</head>
<body onload="initializedb()">
<table width="100%">
<tr><td width="20%" valign="top">
<table width="100%" id="elArticles">
</table>
</td><td width="80%" valign="top">
<div id="elContent"></div>
</td></tr></table>
<a href="javascript:void sync();">Synchronizuj</a>
<script>
var db;
function sync()
{
new Ajax.Request( 'articles.php', { method: 'get',
onSuccess: function( transport ) {
var articleTags = transport.responseXML.getElementsByTagName( 'article' );
for( var a = 0; a < articleTags.length; a++ ) {
addArticle( parseInt( articleTags[a].getAttribute('id') ),
articleTags[a].getAttribute('title'),
articleTags[a].firstChild.nodeValue );
}
showArticles();
} } );
}
function initializedb() {
if (!window.google || !google.gears)
return;
try {
db = google.gears.factory.create('beta.database', '1.0');
} catch (ex) {
alert('Could not create database: ' + ex.message);
}
if (db) {
db.open('gearsintro');
db.execute('create table if not exists articles' +
' ( article_id int, title varchar(255), content text )');
}
showArticles();
}
function showArticle( id )
{
var rs = db.execute( 'select content from articles where article_id = ?', [ id ] );
var found = 0;
while (rs.isValidRow()) { $('elContent').innerHTML = rs.field(0); rs.next(); }
rs.close();
}
function showArticles()
{
while( $('elArticles').rows.length > 0 )
$('elArticles').deleteRow( -1 );
var rs = db.execute( 'select * from articles' );
while (rs.isValidRow())
{
var elTR = $('elArticles').insertRow( -1 );
var elTD = elTR.insertCell( -1 );
elTD.onmouseover = function() { this.style.background = '#eee'; };
elTD.onmouseout = function() { this.style.background = 'none'; };
elTD.id = rs.field( 0 );
elTD.onmouseup = function() { showArticle( this.id ); };
elTD.appendChild( document.createTextNode( rs.field(1) ) );
rs.next();
}
rs.close();
}
function addArticle( id, title, content )
{
var rs = db.execute( 'select * from articles where article_id = ?', [ id ] );
var found = 0;
while (rs.isValidRow()) { found++; rs.next(); }
rs.close();
if ( found == 0 )
db.execute('insert into articles values (?, ?, ?)', [id, title, content]);
}
</script>
</body>
</html>
Google Gears uruchamiamy z użyciem funkcji initializedb, co otwiera połączenie z bazą i tworzy tablicę artykułów. Ostatnią rzeczą w initialize db jest metoda showArticles, która szuka artykułów w bazie Gears i wyświetla je w tablicy. Funkcja sync, którą uruchamia się po kliknięciu linka synchronizuj pobiera Ajaxem plik articles.php z xml'em i wywołuje metodę addArticle dla każdego artykułu. Ta z kolei dodaje artykuł do bazy o ile artykuł z takim ID nie istnieje w bazie. Potem po raz kolejny wywoływana jest metoda showArticles.
Tradycyjne podsumowanie
Warto? Hah! Odwieczne pytanie. Oczywiście zależy od aplikacji. Warunkowe użycie (świat to nie Firefox + IE), dodatkowe pisanie, stany offline i online ... to problemy, które dochodzą i tak już zapracowanemu programiście. W każdym razie po raz kolejny Google dało nam znakomite narzędzie, jak je użyjemy ...
wtorek, 17 lipca 2007
Umarł król, niech żyje król
Jak wygląda kalendarz? Do końca roku zapewniony jest support dla PHP4, natomiast do 08.08.2008 (ładna data ;) będą wypuszczane łatki krytyczne. Potem? Hulaj hakerska duszo! Pół roku na przesiadkę na PHP5 moim zdaniem to aż za dużo. Lista niekompatybilnych zmian dostępna jest tutaj. Krótka? Oczywiście, wszyscy to powtarzają już od 3 lat ;)
Pisałem o wyborze PHP jako platformy. Problem sie skończył ... teraz jedyną opcją jest PHP5. Do czasu kiedy światło dzienne ujrzy PHP6 i jazda zacznie się od nowa ...
środa, 4 lipca 2007
HTML Purifier - i życie stało się ... bezpieczniejsze
Jest to biblioteka oferująca filtr, zamieniający wprowadzony ciąg znaków na validujący się kod HTML. Nie tylko usuwa złośliwy kod wprowadzony przez użytkownika (znany jako XSS), ale też zamyka tagi i zapewnia pełną zgodność z W3C.
Osobiście polecam używanie tego rodzaju bibliotek. Uważam tą za dobrze napisaną i wartą uwagi. Jak działa można sprawdzić samemu tutaj.



