2006.05_Lazarus i pudełko z hasłami_[Programowanie].pdf

(809 KB) Pobierz
439113757 UNPDF
dla programistów
Lazarus i pudełko
z hasłami
Marek Sawerwain
jania oprogramowania (ang. rapid
application development , w skrócie
RAD ) są bardzo popularne wśród
osób, które tworzą oprogramowanie z inter-
fejsem GUI. Podstawową zaletą tego typu
narzędzi jest skrócenie czasu pracy nad
interfejsem. Znanym przykładem tego typu
środowiska jest Delphi .
Przez długi czas Delphi było dostęp-
ne tylko dla systemu Windows. W końcu
irma Borland postanowiła wydać wersję
dla Linuksa, ale trzeba przyznać, że Kylix
nie zachwycił programistów związanych
z Linuksem, nawet gdy Borland wydał
wersję C++ Buildera dla Linuksa, dostęp-
ną w ramach pakietu Kylix 3. Podstawo-
wą wadą było oparcie całego środowiska
o emulator Wine , co spowodowało, iż śro-
dowisko wymagało bardzo mocnej maszy-
ny. Dziś może nie jest to już tak ważne, ale
przecież Linux jako system, wraz z serwe-
rem X Window i środowiskami KDE czy
GNOME , jest wystarczająco dojrzałym
produktem i nie ma potrzeby emulowa-
nia środowiska WIN32, aby istniały dobre
i dostępne dla każdego środowiska RAD.
Drugą wadą jest licencja oraz cena pakietu
Borlanda. Co prawda, dostępna jest wersja
darmowa, ale względem wersji komercyj-
nej jest ona pozbawiona wielu cennych
kontrolek.
Środowisko programistów skupionych
wokół idei Open Source udowodniło, iż
potrai wytworzyć oprogramowanie bardzo
dobrej jakości, czego znakomitym przykła-
dem jest jądro Linuksa, kompilator GCC
i wiele innych projektów, takich jak GIMP ,
KDE , GNOME czy nawet OpenOfice.org
i Blender , choć dwa ostatnie przykłady wy-
wodzą się z aplikacji komercyjnych. Do
wymienionych pakietów można także
dołączyć jeszcze jeden pakiet, który może
przyczynić się do jeszcze większej popu-
larności Linuksa, a jest nim Lazarus , czyli
w pewnym sensie darmowe Delphi. Sam
pakiet, co prawda, ciągle posiada status
Bety, ale zaraz postaram się udowodnić,
iż jest to projekt, który warto wypróbować
już teraz.
DVD
Po uruchomieniu Linux+ Live
DVD możesz zapoznać się
z Lazarusem i gotową aplikacją
do przechowywania haseł.
Instalacja pakietu
Lazarus
Instalację pakietu najlepiej wykonać za po-
mocą przygotowanych pakietów w forma-
cie rpm , ale przygotowano również pakiety
w formacie deb . W pierwszej kolejności in-
stalujemy pakiet fpc , a później fpc-doc
oraz fpc-src . Ostatni w kolejności jest sam
pakiet Lazarus . Warto pokusić się o insta-
lację snapshotów, gdyż dość często to te
wersje posiadają najnowsze komponenty,
ale, jak można łatwo zgadnąć, mogą być bar-
dzo niestabilne. W przypadku Linuksa La-
zarus wymaga do pracy obecności biblio-
teki GTK+ 1.2. Z tego powodu musimy zad-
bać o instalację tego pakietu. Warto też in-
stalować pakiety Lazarusa bez spełniania
zależności, co jest ważne, jeśli system pa-
kietów rpm w danej dystrybucji nie dostar-
cza wprost odpowiednich nazw zgodnych
z pakietem Lazarusa. W tym przypadku
instalację wykonujemy za pomocą pole-
cenia:
Na płycie CD/DVD
Na płycie CD/DVD znajduje
się środowisko deweloperskie
Lazarus oraz kod źródłowy
tworzonego programu.
rpm -i --nodeps lazarus-0.9.12
-0.i386.rpm
70 maj 2006
Ś rodowiska błyskawicznego rozwi-
439113757.048.png 439113757.056.png 439113757.057.png
 
439113757.001.png 439113757.002.png 439113757.003.png 439113757.004.png 439113757.005.png 439113757.006.png 439113757.007.png 439113757.008.png 439113757.009.png
 
Lazarus
dla programistów
Listing 1. Kopiowanie hasła do schowka
Pascal wiecznie żywy
Kolejne pokolenia programistów nadal
mogą programować w języku Pascal dzię-
ki Delphi oraz darmowemu pakietowi
FPC ( Free Pascal Compiler ). Ten drugi
stał się podstawą środowiska Lazarus.
Zawiera kompilator języka Pascal i trze-
ba przyznać, że jest on jednym z lep-
szych. Ponadto, jest dostępny dla wielu
różnych platform sprzętowo-programo-
wych.
Najważniejszą zaletą kompilatora
FPC jest implementacja języka zgodnego
z najpopularniejszą wersją Pascala, przy-
gotowaną przez irmę Borland. Dostępne
są moduły typowe dla Borlanda, takie jak
Crt , a nawet BGI , ale obecnych jest rów-
nież wiele rozszerzeń, takich jak np. API
OpenGL czy dostęp do GTK +. Jedną z wie-
lu cennych innowacji wprowadzonych do
języka jest możliwość bezpośredniego
stosowania instrukcji MMX.
Autorzy wprowadzili także przeciąża-
nie operatorów, a to oznacza, iż w Pas-
calu możemy pisać kod typu c:=a+b; ,
w którym poszczególne zmienne są np.
typu TVector2D . Sam operator dodawa-
nia został przeciążony w następujący spo-
sób:
procedure TMainForm . CopyPassToClipBTNClick ( Sender : Tobject );
var
s : string ;
c : Tclipboard ;
begin
if sel_row <> - 1 then
begin
s := CategoryGrid . Cells [ 1 , sel_row ];
c := clipbrd . Clipboard ;
c . AsText := s ;
end ;
end ;
Nasz projekt
Program „pudełko z hasłami” możemy bez
trudu napisać również za pomocą bibliote-
ki GTK+ czy Qt, ale zastosowanie Lazarusa
pozwoli nam na wstępne zapoznanie się ze
środowiskiem oraz sprawdzenie, czy będzie
nam ono przydatne.
Naszym zadaniem jest utworzyć aplika-
cję, w której będziemy przechowywać hasła,
wykorzystywane np. podczas korzystania
z różnorakich serwisów WWW. W apli-
kacji będziemy przechowywać spis haseł,
a program będzie generował losowe ha-
sła o zadanej długości. Aby nasza aplikacja
była łatwiejsza w użyciu podczas codzien-
nej pracy, do naszego programu doda-
my również funkcję kopiowania hasła do
schowka. W ten sposób użytkownik może
obsługiwać program bez konieczności samo-
dzielnego przepisywania hasła do np. prze-
glądarki WWW.
Oczywiście, nasza aplikacja będzie po-
siadać tylko niezbędną funkcjonalność. Do
programu można jeszcze dodać wiele wa-
żnych funkcji, takich jak np. szyfrowanie
pliku, w którym program przechowuje ha-
sła użytkownika.
Zanim przejdziemy do implementacji,
warto jeszcze zastanowić się na strukturą
naszej aplikacji. W Lazarusie, podobnie jak
w oryginale, podstawową kontrolką jest for-
mularz (reprezentowany przez typ TForm ),
czyli okno. W naszym programie mamy
trzy okna: główne okno aplikacji TMainWin
(to okno zobaczymy po uruchomieniu pro-
gramu), okno informacji o programie TAbout-
Win oraz okno, w którym tworzone jest ha-
sło, reprezentowane przez typ TGenerate
PasswordWin . Samodzielnie tworzone jest tyl-
ko główne okno, gdyż zarządzanie pozosta-
łymi będzie realizowane przez nas własny
kod. Przy czym, jak się za chwilę okaże,
będzie to zaledwie kilka linijek kodu.
Jak zawsze, warto przygotować dia-
gram blokowy najważniejszych zdarzeń,
które pojawiają się w programie. Przed-
stawia go Rysunek 1.
Początek i główne okno
Tworzenie naszego programu należy roz-
począć od utworzenia odpowiedniego
typu projektu. W tym celu udajemy się
do menu File i wybieramy opcję o nazwie
New... (jeśli w naszym systemie zmien-
na LC_ALL jest ustawiona na język polski,
to Lazarus będzie posługiwał się polski-
mi nazwami). Ukaże się okno, w którym
wybierzemy typ projektu. W naszym
przypadku interesuje nas kategoria Project ,
a w niej pozycja Application . Po jej wybra-
niu i naciśnięciu przycisku OK , Lazarus
utworzy projekt oraz jedno okno formu-
larza. Zgodnie z naszymi wcześniejszymi
założeniami, nazwę tego formularza (wła-
sność Name ) ustalamy na MainWin . Duża
litera „T” zostanie dołączona do nazwy
typu samoczynnie przez środowisko.
W tym momencie za pomocą opcji New
Form z menu File należy utworzyć dwa
nowe formularze i przystąpić do tworze-
nia interfejsu użytkownika. Siłą Lazarusa
jest to, iż cały ten proces jest obsługiwany
za pomocą myszy, więc możemy dowol-
nie rozstawiać poszczególne komponenty.
Co więcej, środowisko pomaga podczas
projektowania interfejsu pokazując linie
wyrównania, gdy chcemy, aby kilka przy-
cisków zostało wyrównanych do prawej
oraz lewej strony.
Ponieważ proces tworzenie interfej-
su jest łatwy – jest to w końcu główna
zaleta Lazarusa – przejdziemy od razu
do tworzenia kodu. Warto jeszcze zwrócić
uwagę, aby odpowiednio nazwać poszcze-
gólne kontrolki, dzięki czemu kod źródło-
wy będzie czytelny dla osób postronnych.
operator + (v1,v2 : TVector2D)
vout : Tvector2D;
begin
vout.a := v1.a + v2.a;
vout.b := v1.b + v2.b;
end;
W głównym oknie wykonujemy pod-
stawowe czynności w naszym progra-
mie. W następnym punkcie przedstawię
dokładnie, jak przedstawia się zarządza-
nie hasłami. Teraz zajmiemy się innymi
ważnymi elementami.
Pierwszy to obsługa przycisku OK ,
który, zgodnie z niepisaną zasadą, zawsze
zamyka okno. Aby przejść do kodu obsłu-
gi tego przycisku, wystarczy dwukrotnie
kliknąć na przycisk w formularzu i zosta-
niemy przeniesieni do okna edycji kodu.
Procedura obsługująca kod zdarzenia
OnClick dla przycisku OK przedstawia się
następująco:
procedure TMainForm.EndWorkBTNClick
(Sender: Tobject);
begin
Close;
end;
www.lpmagazine.org
71
439113757.010.png 439113757.011.png 439113757.012.png 439113757.013.png 439113757.014.png 439113757.015.png 439113757.016.png
dla programistów
sza wybranego przez użytkownika). War-
tość -1 oznacza, że żaden wiersz nie został
wybrany. Następnie inicjalizujemy gene-
rator liczb pseudolosowych dobrze znaną
procedurą randomize . Ponieważ w naszej
aplikacji znajduje się mały gadżet, tzn.
zegar, to trzeba zadbać, aby w etykiecie już
na samym początku znalazł się aktualny
czas. Do pola edycyjnego należy również
wpisać pusty ciąg znaków. Ostatnim ele-
mentem, o którym w dalszej części będzie
jeszcze mowa, jest załadowanie aktualne-
go spisu haseł.
Opisane czynności są realizowane za
pomocą następujących linii kodu:
CategoryGrid.RowCount:=1;
sel_row:=-1;
randomize; ClockLBL.Text:
=TimeToStr(Time);
NewBoxNameEDT.Text:=''; LoadData;
Obsługa tabeli kategorii
Innym istotnym elementem jest dodanie
nowej kategorii do tabeli CategoryGrid .
Jest to realizowane przez obsługę przyci-
sku o nazwie AddCategoryBTN . Przedstawia
się to następująco:
if NewBoxNameEDT.Text<>'' then
begin
CategoryGrid.RowCount:=
CategoryGrid.RowCount+1;
CategoryGrid.Cells[0,CategoryGrid.
RowCount-1]:=NewBoxNameEDT.Text;
end
else
Application.MessageBox
('Please, enter a category
name.','Error',0);
Rysunek 1. Schemat przepływu zdarzeń w programie PasswordBox
Sprawdzamy, czy użytkownik istotnie
wpisał nazwę kategorii. W tym celu wy-
starczy sprawdzić zawartość pola, a do-
kładniej wartość własności Text , czy nie
zawiera przypadkiem pustego ciągu zna-
ków. Jeśli zawartość Text jest różna od pus-
tego ciągu, powiększamy ilość wierszy
w tabeli kategorii, zwiększając RowCount .
Następnie do ostatniego wiersza kolum-
ny z indeksem zero wpisujemy nazwę
nowej kategorii. Poszczególne komórki
są dostępne przez własność Cells , która
jest niczym innym jak dwuwymiarową
tablicą. Z tego powodu obsługa tej tabli-
cy jest bardzo łatwa, np. usunięcie wska-
zanej kategorii za pomocą przycisku
DelCategoryBTN sprowadza się tylko do
jednej linii kodu:
Jest to tylko wywołanie metody Close ,
zamykającej okno, a ponieważ zamyka-
my główne okno, to również cała aplikacja
zakończy swoje działanie. Podczas zamy-
kania aplikacji zapisywana jest także lista
z hasłami, ale jak przedstawia się ten pro-
ces, opiszę później.
Z punktu widzenia przepływu infor-
macji, pierwsze czynności, które zostaną
wykonane podczas uruchamiania progra-
mu, znajdują się w obsłudze zdarzenia
OnFormCreate . Ustalamy w niej domyślną
ilość wierszy, a zmiennej sel_row nadaje-
my wartość -1 (zawiera ona numer wier-
72 maj 2006
439113757.017.png 439113757.018.png 439113757.019.png
 
439113757.020.png 439113757.021.png 439113757.022.png 439113757.023.png 439113757.024.png 439113757.025.png 439113757.026.png 439113757.027.png 439113757.028.png 439113757.029.png 439113757.030.png 439113757.031.png 439113757.032.png 439113757.033.png 439113757.034.png 439113757.035.png
 
Lazarus
dla programistów
ukazuje kompletną funkcję, która umiesz-
cza w schowku hasło z aktualnie wska-
zanej kategorii. Kod jest bardzo prosty.
Wystarczy odczytać referencję do obiek-
tu Clipboard i do własności AsText wpisać
tekst, który chcemy umieścić w schowku.
Jeśli chcemy odczytać zawartość schowka
i oczekujemy tekstu, to wystarczy odczy-
tać wartość własności AsText .
Rysunek 2. „Pudełko z hasłami” w Lazarusie
Zapis oraz odczyt
listy kategorii
Aplikacja, którą tutaj opisuję, jest małą
wprawką, ale aby była w pełni użytecz-
na, musimy zapisywać zawartość tabeli
o nazwie CategoryGrid . W niej znajdują się
nazwy kategorii, do których są przypisane
hasła. Zapis haseł następuje samoczynnie
podczas zamykania aplikacji. Po wywo-
łaniu metody Close występuje zdarzenie
OnClose , w którym wywołujemy prywatną
metodę o nazwie SaveData . Listing 2 pre-
zentuje jej kod źródłowy.
Wykorzystujemy klasę TFileStream do
obsługi plików. Utworzenie obiektu jest ty-
powe dla Lazarusa (czy raczej dla Delphi)
i przedstawia się następująco:
CategoryGrid.DeleteColRow
(false, sel_row);
sel_row , a nazwa kategorii przeniesiona do
pola edycyjnego. Obsługa przycisku o ety-
kiecie Update Category ponownie przenie-
sie tekst z pola do wybranego wcześniej
wiersza. W ten sposób mamy możliwość
zmiany nazwy kategorii.
Zmienna sel_row zawiera indeks wybra-
nego przez nas wiersza. Aby poznać nu-
mer wiersza wybranego przez użytkowni-
ka, należy skorzystać ze zdarzenia OnSelect-
Cell . Przedstawia się ono następująco:
f:=TFileStream.Create('data.txt',
fmCreate or fmOpenWrite);
Obsługa schowka
Ponieważ chcemy przesłać do schowka
tylko tekst, to wykorzystując API Lazaru-
sa zadanie to staje się trywialne. Wystar-
czy do aplikacji dołączyć moduł o nazwie
clipbrd , przy czym możemy go dołączyć
w dwóch miejscach, po słowie kluczowym
inferface bądź implementation . Listing 1
Flagi fmCreate oraz fmOpenWrite zapew-
niają nam, że jeśli plik nie istnieje, to zo-
stanie utworzony, a istniejący plik nad-
pisany. Sam proces zapisu danych w przy-
padku ciągu znaków warto wykonywać
tak, jak to pokazuje Listing 2. Gdy zapi-
sujemy kategorię, w pierwszej kolejno-
ści wyznaczamy długość ciągu znaków
procedure TMainForm.CategoryGridSel
ectCell(Sender: TObject; Col, Row:
Integer; var CanSelect: Boolean);
begin
sel_row:=Row;
NewBoxNameEDT.Text:=
CategoryGrid.Cells[0,sel_row];
end;
Współrzędne aktualnie wybranej komór-
ki znajdują się w argumentach Col oraz
Row . Zdarzenie to, jak można się domy-
śleć po nazwie i postaci argumentów, nie
służy do wybierania wierszy, ale dowolnej
komórki. Jeśli w inspektorze obiektów we
własności Options dla obiektu tabeli usta-
limy wartość pola goRowSelect na True , to
w ten sposób zawsze będzie wybierany cały
wiersz, a nie poszczególne komórki tabeli.
Ostatnim istotnym elementem jest moż-
liwość zmiany nazwy kategorii za pomocą
przycisku o nazwie UpdateCategoryBTN .
Polega to na tym, że jeśli użytkownik klik-
nie na pewien wiersz, to tak jak to przed
chwilą zostało opisane, zostanie odczyta-
ny jego indeks i umieszczony w zmiennej
Rysunek 3. Działający program PasswordBox podczas generowania hasła
www.lpmagazine.org
73
439113757.036.png 439113757.037.png 439113757.038.png 439113757.039.png 439113757.040.png 439113757.041.png 439113757.042.png 439113757.043.png 439113757.044.png 439113757.045.png 439113757.046.png
dla programistów
i zapisujemy otrzymaną wartość do stru-
mienia:
Listing 2. Zapis haseł do pliku
len:=length(c);
f.Write(len, sizeof(len));
procedure TmainForm . SaveData ;
var
i , len : integer ;
c , p : string ;
f : TileStream ;
begin
f := TFileStream . Create ( 'data.txt' , fmCreate or fmOpenWrite );
len := CategoryGrid . RowCount - 1 ;
Teraz możemy zapisać ciąg znaków. W przy-
padku Pascala taka operacja zawsze była
nieco kłopotliwa. W Lazarusie (analogi-
cznie jak w oryginale), aby rezultat był
poprawny, należy dokonać konwersji ty-
pu string na wskaźnik do typu PChar
(jest to typ odpowiadający ciągowi zna-
ków w języku C). Przedstawia się to nastę-
pująco:
f . Write ( len , sizeof ( len ));
for i := 1 to CategoryGrid . RowCount - 1 do
begin
c := CategoryGrid . Cells [ 0 , i ]; p := CategoryGrid . Cells [ 1 , i ];
f.Write(PChar(c)^, len);
Bliźniacza funkcja LoadData przedstawia się
podobnie, jak funkcja z Listingu 2. Podczas
tworzenia strumienia podajemy lagę fmO-
penRead , aby otworzyć plik tylko do odczy-
tu. Sam proces odczytywania wymaga uży-
cia jednej dodatkowej funkcji. Po odczytaniu
długości danego ciągu znaków:
len := length ( c );
f . Write ( len , sizeof ( len ));
f . Write ( PChar ( c ) ^, len );
len := length ( p );
f . Write ( len , sizeof ( len ));
f . Write ( PChar ( p ) ^, len );
end ;
f . Free ;
end ;
f.Read(len, sizeof(len));
ustalamy długość zmiennej za pomocą fun-
kcji o nazwie SetLength i odczytujemy ze
strumienia odpowiednią ilość znaków:
t:=TAboutWin.Create(self);
t.ShowModal;
t.Free;
przycisków został wybrany przez użyt-
kownika, aby zamknąć okno.
Naciśnięcie OK oznacza, że użytkow-
nik chce, aby wygenerowane hasło zostało
umieszczone w tabeli, a naciśnięcie przy-
cisku Cancel oznacza, że nie chcemy tego
zrobić.
W obsłudze dwóch wspomnianych przy-
cisków musimy określić dokładnie, jaka
wartość będzie zwracana przez metodę
ShowModal . Wystarczy wpisać odpowiednią
wartość do własności ModelResult, np.
w obsłudze przycisku Cancel umieszcza-
my wartość mrCancel (self.ModalResult:
=mrCancel; ), a przypadku przycisku OK mrOK
( self.ModalResult:=mrOK; ).
Wykrycie, czy użytkownik zamknął
okno generowania hasła wybierając przy-
cisk OK , sprowadza się tylko do sprawdze-
nia, czy wartość zwrócona przez ShowModal
jest równa mrOK :
SetLength(c, len);
f.Read(PChar(c)^, len);
W pierwszej linii tworzymy okno. Jego
pokazanie na ekranie w trybie modalnym
(co oznacza, iż musimy zamknąć okno dia-
logowe, aby uzyskać dostęp do okna, które
utworzyło oraz wywołało okno dialogowe),
realizujemy za pomocą funkcji ShowModal .
Ostatecznie, każdy obiekt musi zostać usu-
nięty i robimy to wywołując metodę Free .
Drugie okno wymaga od nas troski
o dwa istotne dla nas szczegóły. Pierwszy
polega na sprawdzeniu, czy użytkow-
nik naszego programu wybrał jakikolwiek
wiersz z tabeli kategorii, sprawdzając war-
tość zmiennej sel_row . Gdy zmienna jest
równa minus jeden, to wyświetlamy krótki
komunikat:
Wczytanie zawartości znaków jest wyko-
nywane w zdarzeniu FormCreate , więc tuż
przed wyświetleniem głównego okna na
ekranie.
Zarządzanie innymi oknami
Ponieważ założyliśmy, że tylko główne
okno będzie tworzone samodzielnie przez
system, to dodatkowe okna musimy utwo-
rzyć jawnie. Wbrew pozorom, jest to łatwy
proces, szczególnie w naszym przypadku,
ponieważ oba okna są oknami dialogowy-
mi. Gdy jedno z naszych dwóch okien jest
wyświetlone, to nie mamy dostępu do ele-
mentów z głównego okna.
Wyświetlenie okna informacyjnego jest
bardzo łatwe. Deiniujemy nową zmienną:
if sel_row=-1 then
begin
Application.MessageBox('Please,
select category.','Error',0);
end else // reszta programu
if a.ShowModal = mrOK then
CategoryGrid.Cells[1, sel_row]:
=a.PasswordEdit.Text;
t : TAboutWin;
Generowanie hasła
Ostatni element, który należy przedstawić,
to proces generowania losowego hasła. Sys-
tem sam je zbuduje (z liter małych bądź du-
Oznacza to też, iż musimy dołączyć unit
UaboutWin , zawierający deinicję typu Tabout-
Win . Ostatecznie, niezbędny kod składa się
z trzech linii:
W sekcji else tworzenie okna odbywa się
w identyczny sposób jak opisany wcześniej,
ale interesuje nas również, który z dwóch
74 maj 2006
439113757.047.png 439113757.049.png 439113757.050.png
 
439113757.051.png 439113757.052.png 439113757.053.png 439113757.054.png 439113757.055.png
 
Zgłoś jeśli naruszono regulamin