Archiwum dla kategorii Kurs

Dzisiaj przypadkowo natknąłem się na pewną niedogodność w kliencie poczty Thunderbird. Na jednym ze swoich kont używam kilku tożsamości. Dla konta głównego ustawiłem certyfikat S/MIME, a następnie próbowałem wysłać podpisanego cyfrowo e-maila korzystając z innej (nie głównej) tożsamości. Efekt - program Thunderbird nie potrafi odnaleźć właściwego certyfikatu.
W interfejsie ustawień poszczególnych tożsamości nie ma możliwości określenia certyfikatu, co jest ewidentną niedoróbką.
Trzeba zajrzeć pod przykrycie i dotrzeć do plików konfiguracyjnych - można to zrobić na dwa sposoby: “Opcje -> Zaawansowane -> Ogólne -> Edytor ustawień” lub wyszukując plik pref.js w katalogu profilu klienta pocztowego.

Procedura dodawania ceryfikatu S/MIME do tożsamości:
1. Szukamy w mail.server.server[ID] identyfikatora naszego serwera [ID]
2. Następnie w mail.account.account[ID].identities odszukujemy identyfikatory tożsamości [tID…]
3. Jeden z identyfikatorów tożsamości (przypuszczalnie pierwszy) mail.identity.id[tID] będzie miał przypisane dane certyfikatu S/MIME. Jeżeli dla innych tożsamości chcemy wykorzystać ten sam certyfikat, to dane te wystarczy skopiować, jeżeli inne, wówczas należy je właściwie określić.
4. Dla każdych innych tożsamości mail.identity.id[tID] należy utworzyć wpisy z odpowiednią zawartością:
mail.identity.idX.sign_mail
mail.identity.idX.signing_cert_name
mail.identity.idX.encryption_cert_name
mail.identity.idX.encryptionpolicy

Więcej informacji: http://forums.mozillazine.org/viewtopic.php?t=455694

JSON (JavaScript Object Notation) jest drugim, po XML, najpopularniejszym formatem przesyłania danych stosowanym w technologi AJAX. Niewątpliwą przewagą JSON’a nad XML’em jest jego natywne parsowanie po stronie klienta (funkcja JavaScriptu eval()). JSON pozwala również na proste serializowanie obiektów JavaScript.

Przykład składni JSON (przykład z Wikipedii na licencji GPL FDL):

{"menu": {
  "id": "file",
  "value": "File",
  "popup": {
    "menuitem": [
      {"value": "New", "onclick": "CreateNewDoc()"},
      {"value": "Open", "onclick": "OpenDoc()"},
      {"value": "Close", "onclick": "CloseDoc()"}
    ]
  }
}}
 

Analogiczny zapis w XML:

<menu id="file" value="File">
  <popup>
    <menuitem value="New" onclick="CreateNewDoc()" />
    <menuitem value="Open" onclick="OpenDoc()" />
    <menuitem value="Close" onclick="CloseDoc()" />
  </popup>
</menu>
 

Parsowanie JSON po stronie JavaScript sprowadza się do pojedynczej instrukcji:

var obiekt = eval(‘(’ + JSON + ‘)’);
 

Następnie do zmiennej obiekt można się odwoływać jak do zwykłego obiektu:

alert(obiekt.menu.id);  //zwróci "file"
alert(obiekt.menu.popup.menuitem[1].onclick); //zwróci "OpenDoc()"
 

Warto zaznaczyć, że JSON nie wymaga obecności znacznika głównego, tak więc zapis można jeszcze bardzie skrócić.

Pomimo iż według standardu JSON można przesyłać tylko dane (proste typy obsługiwane w JavaScript oraz obiekty JS), to jednak nie ma problemu z przesłaniem funkcji (w tym wypadku należy to rozumieć jako metodę obiektu):

{
  nazwa: "Funkcja",
  func: function(arg) { alert(arg); }
}
 

Przykład 1

Następnie funkcje wywołujemy:

var obiekt = eval(‘(’ + JSON + ‘)’);
obiekt.func(‘hello’);
 

Oczywiście możliwe jest traktowanie funkcji jako części obiektu (choć nie wchodzi to w skład standardu JSON!):

{
  nazwa: "Funkcja",
  func: function(arg) { alert(arg); },
  func2: function() { alert(this.nazwa); }
}
 

Wówczas:

obiekt.func2();
 

wyświetli napis “Funkcja”.

Przykład 2

Prezentacja wideo:

Zobacz prezentacje wideo

W przeciągu ostatniego roku można zauważyć zwiększenie zainteresowania formatem JSON. Do najbliższej specyfikacji języka Javascript zgłoszono dwie nowe metody klasy Object (klasy superbazowej) służące do serializacji i deserializacji obiektów. Wiele popularnych bibliotek i frameworków AJAX’owych korzysta z JSON jako podstawowego sposobu komunikacji.

PHP począwszy od wersji 5.2 posiada wsparcie do generowania i parsowania zapisu JSON (http://pl.php.net/json).

Przykład (zaczerpnięty z dokumentacji PHP):

< ?php
$arr = array (‘a’=>1,‘b’=>2,‘c’=>3,‘d’=>4,‘e’=>5);

echo json_encode($arr);
?>
 

wypisze:

{"a":1,"b":2,"c":3,"d":4,"e":5}
 

Natomiast:

< ?php
$json = ‘{"a":1,"b":2,"c":3,"d":4,"e":5}’;

var_dump(json_decode($json, true));
?>
 

zwróci tablicę:

array(5) {
    ["a"] => int(1)
    ["b"] => int(2)
    ["c"] => int(3)
    ["d"] => int(4)
    ["e"] => int(5)
}
 

Niezależnie od tych rozwiązań powstały zewnętrzne biblioteki, często o dużo większych możliwościach. Linki do tych rozwiązań można znaleźć na stronie: www.json.org.

Nie brakuje przy tym bibliotek dedykowanych językowi Java.

Dwie oficjalne można znaleźć na stronach: http://www.json.org/java/index.html oraz http://www.json.org/java/simple.txt (obydwie na otwartych i darmowych licencjach).

JSON.simple

W przypadku JSON.simple należy ściągnąć archiwum http://www.JSON.org/java/json_simple.zip
Wewnątrz znajduje się plik json_simple.jar, który należy dodać do projektu (umieszczając go w podkatalogu WEB-INF/lib/ projektu).

Od tej chwili możemy skorzystać z gotowych klas znajdujących się w pakiecie: org.json.simple.*. W szczególności wykorzystuje się dwie:

JSONArray
JSONObject
 

Zacznijmy od drugie. Można zrobić porównanie, że generuje ono jednopoziomową tablicę asocjacyjną:

import org.json.simple.JSONObject;

JSONObject obj=new JSONObject();
obj.put("name","foo");
obj.put("num",new Integer(100));
obj.put("balance",new Double(1000.21));
obj.put("is_vip",new Boolean(true));
obj.put("nickname",null);
System.out.print(obj);
 

Powyższy kod wygeneruje odpowiednio zakodowany i sformatowany ciąg JSON:

{"nickname":null,"num":100,"balance":1000.21,"is_vip":true,"name":"foo"}
 

JSONArray zachowuje się trochę inaczej. Tworzy, jak sama nazwa wskazuje, tablicę elementów (mogą być różnego typu!):

import org.json.simple.JSONArray;

JSONArray tab = new JSONArray();
tab.add("111");
tab.add(new Integer(222));
tab.add(new Double(333.33));
System.out.print(tab);
 

wypisze:

{["111",222,333.33]}
 

Obiekty te można wzajemnie łączyć, tworząc wielopoziomowe struktury:

JSONObject json = new JSONObject();
json.put("napis", "to jest napis");
json.put("liczba", new Integer(999));

JSONArray tab = new JSONArray();
tab.add("111");
tab.add(new Integer(222));
tab.add(new Double(333.33));

json.put("tablica", tab);
out.print(json);
 

Rezultat:

{"napis":"to jest napis","liczba":999,"tablica":["111",222,333.33]}
 

Przykład 3

Prezentacja wideo:

Zobacz prezentacje wideo

JSON in Java

JSON.simple jest prostą, aczkolwiek w kompletną biblioteką.

Jeżeli jednak potrzebujemy więcej, należy sięgnąć do innych. Pełniejszą odmianą JSON.simple jest „JSON in Java? (http://www.json.org/java/index.html). Instalacja oraz wykorzystanie jest bardzo zbliżone do JSON.simple. Biblioteka oprócz prostego tworzenia danych JSON, umożliwia też łatwiejsze jego odczytywanie, wspiera konwersje z/do XML oraz zawiera kilka mniej ważnych elementów, których pozbawiona jest uproszczona wersja.

JSON-lib

Obydwie wyżej opisane biblioteki są zgodne ze standardem JSON. Wprowadza to pewne ograniczenia, na przykład w kwestii przesyłania funkcji.
Dużo bardziej liberalna i rozbudowana jest biblioteka json-lib (json-lib.sourceforge.net) rozprowadzana na licencji Apache 2.0.

Instalacja nie jest w tym wypadku tak prosta, bowiem json-lib posiada listę zależność zawierającą:
xom (http://www.xom.nu/)
commons-lang (http://jakarta.apache.org/commons/lang/)
commons-beanutils (http://jakarta.apache.org/commons/beanutils/)
ezmorph (http://ezmorph.sourceforge.net/)

Należy zainstalować wymagane zależności, a na końcu pobrać plik jar odnoszący się do json-lib (json-lib-1.0b1-jdk13.jar lub json-lib-1.0b1-jdk15.jar). Wszystkie pliki jar umieszczamy w podkatalogu WEB-INF/lib na serwerze. Po odświeżeniu danych serwera zostanie udostępniona przestrzeń nazw net.sf.json.*

Podstawowe użycie jest analogiczne jak wyżej (przykłady pochodzą w części ze strony http://json-lib.sourceforge.net):

int[] array = new int[]{1,2,3};
JSONArray jsonArray = JSONArray.fromObject( array );
out.print(jsonArray);
 

wypisze:

[1,2,3]
 

Natomiast:

List list = new ArrayList();
list.add( "A" );
list.add( "B" );
JSONArray jsonArray = JSONArray.fromObject( list );
out.print( jsonArray );
 

wypisze:

["A","B"]
 

W kolejnym przykładzie widać utworzenie prostej funkcji:

Map map = new HashMap();
map.put( "name", "json" );
map.put( "bool", Boolean.TRUE );
map.put( "int", new Integer(1) );
map.put( "arr", new String[]{"a","b"} );
map.put( "func", "function(i){ return this.arr[i]; }" );
JSONObject json = JSONObject.fromObject( map );
out.print( json );
 

zwróci:

{"func":function(i){ return this.arr[i]; },"arr":["a","b"],"int":1,"name":"json","bool":true}
 

Wielką przewagą json-lib nad podobnymi bibliotekami jest możliwość serializacji klas języka Java do postaci JSON:

class MyBean{
    private String name = "json";
    private int pojoId = 1;
    private char[] options = new char[]{‘a’,‘f’};
    private String func1 = "function(i){ return this.options[i]; }";
    private JSONFunction func2 = new JSONFunction(new String[]{"i"},"return this.options[i];");

    // getters & setters
    …
}

JSONObject jsonObject = JSONObject.fromObject( new MyBean() );
System.out.println( jsonObject );
 

kod zwróci:

{"name":"json","pojoId":1,"options":["a","f"],
"func1":function(i){ return this.options[i];},
"func2":function(i){ return this.options[i];}}
 

W czasie konwersji obiekty klasy JSONFunction są zamieniane na funkcje języka JavaScript.
Możliwa jest także konwersja w drugą stronę.

Dodatkowo json-lib pozwala na konwersje formatu JSON na XML i odwrotnie.

Bardziej szczegółowy opis JSON można znaleźć w dokumencie: http://www.ietf.org/rfc/rfc4627.txt

Ajax Kurs cz. 1:
http://www.tpython.com/index.php/2007/08/23/kurs-ajax-cz1/

Około pół roku temu realizowałem referat akademicki o technologii Ajax. Dzisiaj przedstawiam pierwszą część tego opracowania.

Stworzenie bazowego projektu:

Zobacz prezentacje

XMLHttpRequest jest podstawowym obiektem języka JavaScript służącym do asynchronicznej komunikacji klienta z serwerem.

Pierwotnie obiekt pojawił się w przeglądarce Internet Explorer, a precyzyjniej w dołączanej do niej bibliotece MSXML. Z czasem został zaimportowany do innych przeglądarek, aż wreszcie został zatwierdzony przez organizację W3 w ramy standardowego elementu JavaScript (http://www.w3.org/TR/XMLHttpRequest/).

Tworzenie obiektu:

Internet Explorer 6.0 i wcześniejsze:

var http_request = new ActiveXObject("Msxml2.XMLHTTP");

pozostałe przeglądarki oraz IE 7.0:

var http_request = new XMLHttpRequest();

Dla zapewnienia działania w każdej przeglądarce można skorzystać z kodu:

var http_request = false;if (window.XMLHttpRequest) { // Mozilla, Safari, …
    http_request = new XMLHttpRequest();
    if (http_request.overrideMimeType) {
        http_request.overrideMimeType(’text/xml’);
    }
} else if (window.ActiveXObject) { // IE
    try {
        http_request = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e) {
        try {
            http_request = new ActiveXObject("Microsoft.XMLHTTP");
        } catch (e) {}
    }
}

Zapytanie do serwera (typu “get”):

http_request.onreadystatechange = function() { /* */ };
http_request.open(’GET’, url, true);

http_request.send(null);

W pierwszej linii ustawiamy funkcję, która będzie wykonana za każdym razem gdy obiekt http_request zmieni stan (tzw. callback). Stan przechowywany jest w zmiennej http_request.readyState

    Może on przyjmować następujące wartości:

  1. 0 = niezainicjalizowany
  2. 1 = połączenie otwarte (http_request.open)
  3. 2 = żądanie zostało wysłane (http_request.send)
  4. 3 = trwa odbieranie danych
  5. 4 = odbieranie zakończone

Stany te następuje po sobie w kolejności. W praktyce sprawdza się tylko kiedy wystąpił stan 4.

Tak więc funkcję można zaimplementować następująco:

http_request.onreadystatechange = function() {
 if( http_request.readyState == 4) {
  // rób coś ciekawego
 }

};

Pełną implementacją funkcji zajmę się w dalszej części.

Polecenie

http_request.open(’GET’, url, true);

otwiera połączenie z serwerem podanym jako adres “url”. Warto nadmienić, że musi być to połączenie wykorzystujące protokół HTTP, połączenia lokalne (file://) nie działają poprawnie.

Funkcja open może przyjmować pięć parametrów (dwa pierwsze są niezbędne)

open(in DOMString method, in DOMString url, in boolean async, in DOMString user, in DOMString password)
  • method - najczęściej “GET” lub “POST”
  • url - adres docelowy
  • async - true jeżeli połączenie ma być asynchroniczne (domyślnie)
  • user, password - dane autentyfikacyjne (domyślnie null)

Polecenie

http_request.send(null);

wysyła żądanie do serwera.

Jako parametr podaje się najczęściej null gdy żądanie jest typu “GET” lub ciąg parametrów (na przykład “action=remove&id=10&time=1000000″) dla „POST’.

W celu zapewnienia poprawności przesyłanych danych powinny być one sformatowanie przy pomocy funkcji “encodeURIComponent”:

var dane = encodeURIComponent(’action’) + ‘=’ + encodeURIComponent(’test=?&;test’);

Taka postać danych powinna zostać odzwierciedlona w zmianie nagłówka “Content-Type”:

http_request.setRequestHeader(’Content-Type’, ‘application/x-www-form-urlenpred’);

Jest to wymagane w przypadku gdy method jest “POST”.

Ostatecznie, przykład wykorzystania obiektu XMLHttpRequest może wyglądać następująco:

var dane = encodeURIComponent(’action’) + ‘=’ + encodeURIComponent(’test=?&;test’);
http_request.onreadystatechange = function() {
  if( http_request.readyState == 4) {
    alert(http_request.responseText);
  }
};

http_request.open(’POST’, ’serwer’, true);
http_request.setRequestHeader(’Content-Type’, ‘application/x-www-form-urlenpred’);
http_request.send(dane);

Jeżeli teraz na serwerze utworzymy plik tekstowy o nazwie “serwer”, to po wywołaniu żądania pojawi się okienko z zawartością pliku.

Co się jednak stanie gdy plik “serwer” nie istnieje?
Zostanie zwrócony błąd o numerze 404.
W przypadku powodzenia zwrócona zostanie wartość 200.

http_request.onreadystatechange = function() {
  if( http_request.readyState == 4) {
    if( http_request.status == 200 ) {
      alert(http_request.responseText);
  } else if ( http_request.status == 404 ) alert(’Plik nie istnieje’);
    else alert(’inny błąd’);
  }

};

Zobacz prezentacje

Obok właściwości http_request.responseText występuje druga http_request.responseXML, użyteczna wówczas, gdy do komunikacji używany jest język XML.
Przykładowo jeżeli plik “serwer” będzie miał zawartość:

<?xml version="1.0"?>
<root>
    hello world
</root>

Można zawartość <root/> odczytać:

http_request.onreadystatechange = function() {
  if( http_request.readyState == 4) {
    if( http_request.status == 200 ) {
      var xml = http_request.responseXML;
      alert(xml.firstChild.firstChild.data);
  } else alert(’błąd’);
  }
};

Aby zakończyć opis obiektu XMLHttpRequest należy wspomnieć o jeszcze jednej instrukcji:

http_request.abort();

Przerywa ona połączenie na danym obiekcie i przywraca jego wartości początkowe.

Zobacz prezentacje

Pozostałe metody i właściwości klasy nie są często używane. Ich opis znajduje się w (http://www.w3.org/TR/XMLHttpRequest/).

XMLHttpRequest domyślnie używa kodowania znaków UTF-8.

Na stronie http://eclipsetutorial.sourceforge.net/ znajduje się dobrze zrealizowany kurs języka Java i środowiska Eclipse dla początkujących. 16 lekcji, każda około 10-minutowa, w formie filmu z komentarzem (po angielsku) przedstawia między innymi: tworzenie klas, JUnit, kolekcje, refactoring.
Całość dostępna jest na otwartej licencji Educational Community License 1.0.