Delphi i PHP


Technika
Delphi i PHP
Komunikacja
Pomiędzy Delphi i PHP można stworzyć własne aplikacje do komunikacji
pomiędzy tymi językami. Służy do tego metoda POST.
Jak pamiętamy, dane przesyłane metodą POST
Dowiesz się... Powinieneś wiedzieć... mają postać:
" W jaki sposób odebrać dane ze skryptu. " Powinieneś znać podstawy języka i środowi-
" W jaki sposób wysłać dane do skryptu. ska Delphi. pole1=wartość&pole2=wartość2.
" Powinieneś znać podstawy języka PHP i HTML.
" Powinieneś znać podstawowe pojęcia związa- Dlatego musimy je przesłać w taki sposób.
ne z protokołem http. Nazwy pól:  text1 i  text2 są nazwami przy-
kładowymi, które następnie zastosujemy
w skrypcie odbierającym dane. Należy pamię-
niśmy im nadać, zostały zaprezentowane na tać, że będą one różne dla każdej strony, która
Rysunku 1. odbiera pakiety z danymi.
Poziom trudności Po umieszczeniu wszystkich elementów, Powyższa linijka tworzy ciąg powstały z po-
kliknijmy tylko raz na komponent IdHTTP łączenia tekstu w cudzysłowie, z tekstem wpi-
i przejdzmy do Object Inspector a, a następ- sanym w Edit2 i Edit3. Owy ciąg jest następ-
nie  odszukajmy listę Request. Po jej rozwinię- nie wysyłany do skryptu za pomocą funkcji
posób komunikacji, opiera się na meto- ciu ukaże się nam kilka atrybutów, interesować POST komponentu IdHTTP. Ostatnim kro-
dzie POST, która umożliwia wysyłanie nas będzie ten o nazwie ContentType. W to pole kiem będzie zapisanie i skompilowanie nasze-
Sdanych przy pomocy nagłówków HTTP. musimy wpisać ciąg: go projektu.
Dane przesyłane tą metodą mają postać: Gdy mamy już gotową aplikację, może-
application/x-www-form-urlencoded. my stworzyć najprostszy plik PHP, który po-
pole1=wartość&pole2=wartość2. służy nam do jej testowania. Propozycja ko-
Więcej o kodowaniu danych możemy przeczy- du znajduje się na Listingu 3. W skrypcie,
Tak więc: nazwa pola jest oddzielona od jego tać w ramce  Kodowanie danych . dla ułatwienia, zostały zastosowane zmien-
wartości znakiem  = ne o takich samych nazwach, jak w naszym
, natomiast poszczególne
porcje danych oddziela znak  & programie.
. Przykładowy Pisanie kodu
nagłówek z powyższymi informacjami wyglą- Projektowanie aplikacji mamy już za sobą, czas Po zapisaniu pliku PHP i umieszczeniu go
dałby więc tak, jak na Listingu 1. więc na napisanie kilku linijek kodu. Nasz pro- na serwerze, uruchamiamy naszą aplikację, po-
gram będzie miał za zadanie: dajemy odpowiednie parametry i naciskamy
Z Delphi do PHP przycisk POST. Pole tekstowe  Memo podpisa-
Zacznijmy projektować naszą aplikację, która " pobrać adres strony; ne jako  Kod wynikowy zostanie automatycz-
prześle dane do skryptu metodą POST . Uru- " pobrać dwie zmienne do wysłania; nie uzupełnione danymi zwróconymi przez
chamiamy Delphi i z menu File wybieramy " wysłać dane; skrypt. Przedstawia to Rysunek 2.
New Application. " odebrać kod wynikowy.
Po instalacji pakietu INDY w Delphi, przy-
Listing 1. Przykładowy nagłówek z danymi
będzie nam kilka nowych zakładek na pa- Jego lista zadań jest krótka. Dzięki zastoso-
wysłanymi metodą POST
lecie komponentów. Odszukajmy zakład- waniu komponentu IdHTTP, kod również bę-
kę Indy Clients i wybierzmy z niej kompo- dzie krótki. Kliknijmy dwa razy na Button ie POST /index.php HTTP/1.1
nent IdHTTP. To on umożliwi nam wysyła- i wpiszmy kod, który znajduje się na Listingu 2. Host: www.domena.com
nie danych. Przyjrzyjmy się linijce odpowiadającej za User-Agent: Mozilla/5.0
Umieścimy jeszcze następujące kompo- utworzenie strumienia StreamIn, a szczególnie Content-Length: 28
nenty: 3x Edit, 4x Label, 1x Button, oraz 1x fragmentowi: Content-Type: application/x-www-form-
Memo (wszystkie one znajdują się w zakład- urlencoded
ce Standard). Ich przykładowe rozmieszcze- (Format('text1=%s&text2=%s', [Edit2.Text,Ed pole1=wartość&pole2=wartość2
nie, a także właściwości Caption jakie powin- it3.Text])).
26 06/2007
Delphi i PHP
Przykładowe zastosowanie
Listing 2. Wysyłanie danych z aplikacji do skryptu metodą POST
Przykładowym zastosowaniem powyższej
procedure TForm1.Button1Click(Sender: TObject); metody komunikacji może być program, któ-
var ry będzie uploadował wybrane obrazy z na-
StreamIn,StreamOut: TStringStream; szego dysku twardego na darmowy hosting
begin zdjęć ImageShack (dostępny pod adresem
try www.imageshack.us). Zaczniemy od małego
{Tworzymy strumień StreamIn zawierający łańcuch danych, rekonesansu, tak więc otwieramy ową stro-
zostanie on potem wysłany do skryptu} nę. Aby uniknąć żmudnej analizy kodu w
StreamIn := TStringStream.Create(Format('text1=%s&text2=%s', [Edit2.Text,Edit3.Text] celu  wydobycia szczegółów, skorzystajmy
)); z wtyczki do Firefox a pod nazwą Web Develo-
{Tworzymy pusty strumień StreamOut. Będzie on odpowiedzialny per (link znajduje się w ramce  W Sieci ). Po-
za odbiór kodu wynikowego skryptu} siada ona funkcję, która modyfikuje wyświe-
StreamOut := TStringStream.Create(''); tlaną stronę pokazując, na przykład, szcze-
{Procedura POST komponentu IdHTTP i jej kolejne parametry: góły formularzy. Zostało to pokazane na Ry-
Adres URL, strumień z danymi, strumień odbierający} sunku 3.
IdHTTP1.Post(Edit1.Text,StreamIn,StreamOut); Co na nim widzimy? Po pierwsze  for-
{Wyświetlamy kod wynikowy ze strumienia w Memo} mularz odwołuje się do strony głównej Ima-
Memo1.Lines.Text:=StreamOut.DataString; geShack.us (fragment form action=  ), po
finally drugie- format kodowania danych to multipart/
{Zwalniamy strumienie} form-data (fragment enctype=  ), i wreszcie po
StreamIn.Free; trzecie- pole, z którego pobierana jest ścież-
StreamOut.Free; ka do wysyłanego pliku (input name="fileuplo-
end; ad ). Posiadając te informacje możemy rozpo-
end; cząć projektowanie aplikacji.
Listing 3. Odbieranie danych z aplikacji wysłanych metodą POST
Przykładowa aplikacja
$text1=$_POST['text1']; tu. Potrzebne nam będą komponenty: 1x
$text2=$_POST['text2']; Edit, 1x Memo, 1x button, a także komponent
echo "Zmienna \"text1\" to: $text1\n"; //wyświetlamy zmienną  text1 IdHTTP.
echo "Zmienna \"text2\" to: $text2\n"; //wyświetlamy zmienną  text2 Podobnie jak ostatnio  kliknijmy raz na
?> komponent IdHTTP i przejdzmy do Object
Inspector a , a następnie  odszukajmy li-
stę Request. Po jej rozwinięciu ukaże nam się
kilka atrybutów; interesować nas będzie ten
o nazwie ContentType. W to pole musimy wpi-
sać ciąg:
multipart/form-data.
Teraz, kliknijmy dwa razy na komponent But-
ton, i w edytorze kodu wpiszmy fragment
z Listingu 4. Jak widać została tam zawarta
zmienna MyData typu TIdMultiPartFormDa-
taStream. Jest to specyficzny typ strumienia
Rysunek 3. Wtyczka Web Developer wyświetlająca szczegóły formularza na stronie ImageShack.us
Rysunek 1. Przykładowe rozmieszczenie komponentów. Z lewej strony  komponenty ze standardowymi Rysunek 2. Gotowa aplikacja wysyłająca dane do
właściwościami Caption, natomiast z prawej  komponenty posiadające zmodyfikowaną tę właściwość skryptu
06/2007 www.phpsolmag.org 27
Technika
z danymi, którego implementacja konieczna oraz 2x Memo (wszystkie one znajdują się w OnClose naszej formy, wpiszemy ponownie
jest do wysłania danych, zakodowanych w for- zakładce Standard). Ostatnio użyliśmy kom- kod z Listingu 5. który tym razem jest opisa-
macie multipart/form-data. Aby z niego skorzy- ponentu, który był klientem protokołu HTTP. ny jako:
stać, konieczne jest dodanie do sekcji Uses mo- Pisząc tę aplikację, będziemy musieli stwo-
dułu IdMultipartFormData. Jest on dołączony rzyć serwer HTTP. Odszukajmy więc zakład- {Procedura OnClose}.
do pakietu INDY. Po kompilacji projektu na- kę Indy Servers i wybierzmy z niej komponent
leży w pole Edit wpisać ścieżkę obrazu, któ- IdHTTPServer. Ich przykładowe rozmieszcze- Główne zdarzenia zostały już napisane, czas
ry chcemy uploadować, a następnie nacisnąć nie, a także właściwości Caption jakie powin- teraz na kod, który umożliwi odbieranie da-
przycisk Button. niśmy im nadać, zostały zaprezentowane na nych. Klikamy na komponent IdHTTPServer1
Zachęcam do przejrzenia kodów zródło- Rysunku 5. i przechodzimy do Object Inspector. Odszu-
wych, które zostały dołączone do płyty. Do kujemy Event podpisany jako OnCommand-
aplikacji dodałem również parser, który po- Pisanie kodu Get i wpisujemy kod z Listingu 6.
biera z kodu wynikowego linki do naszego Przyszedł czas na oprogramowanie naszej apli- Aplikacja jest już gotowa, możemy ją zapi-
obrazu, ale to temat na inny artykuł. Przy- kacji. Zacznijmy od aktywacji serwera- klikamy sać i skompilować. Podobnie jak wcześniej,
kład działania aplikacji pokazany jest na Ry- na formie i odszukujemy właściwość OnCre- stworzymy jeszcze plik PHP, z tym, że te-
sunku 4. ate na zakładce Events w oknie Object Inspector raz to on będzie wysyłał dane do serwera.
i wpisujemy tam fragment kodu z Listingu 5. W tym celu posłużymy się najprostszym for-
Z PHP do Delphi... podpisanego jako: mularzem, którego propozycja kodu znajdu-
Teraz nadszedł czas na napisanie programu, je się na Listingu 7. Pamiętajmy, że nasz pro-
który będzie umożliwiał odbieranie zmien- {Procedura OnCreate}. gram działa na porcie 8008 (aby uniknąć ko-
nych wysyłanych przez skrypt. lizji z innymi aplikacjami), więc będziemy
Stworzymy nową aplikację i na formie Deaktywacja serwera odbywać się będzie pod- odwoływać się do niego w następujący spo-
umieścimy komponenty: 2x Label, 1x Edit czas zamykania programu, więc w zdarzenie sób http://AdresIP:NumerPortu, czyli http://
localhost:8008.
Teraz musimy jeszcze uruchomić nasz pro-
Listing 4. Wysyłanie danych z aplikacji do strony ImageShack
gram i wypełnić pola formularza, a następnie
procedure TForm1.Button1Click(Sender: TObject); go zatwierdzić. Wynik działania aplikacji, która
var odebrała parametry i zwróciła wynik do prze-
MyData: TIdMultiPartFormDataStream; glądarki znajduje się na Rysunku 6.
begin
{tworzymy specyficzny strumień z danymi} Przykładowe zastosowanie
MyData:=TIdMultiPartFormDataStream.Create; Powyższy sposób komunikacji może być wyko-
try rzystany- np. do zdalnej administracji kompu-
{kolejny krok to dodanie do strumienia, metodą AddFile, kolejno: terem poprzez stronę WWW.
nazwy pola (fileupload),ścieżki pliku, a także typu zawartości Wg definicji serwera aplikacji jest to  pro-
pakietu z danymi(file)} gram działający na zdalnej maszynie obsługu-
MyData.AddFile('fileupload',Edit1.Text,'file'); jący żądania kierowane do aplikacji, do której
{kod wynikowy zostanie wyświetlony w Memo1} dostęp zapewnia. Użytkownik łączy się za po-
Memo1.Lines.Text:=IdHTTP1.Post('http://imageshack.us/',MyData); średnictwem przeglądarki internetowej, kieru-
finally je żądanie do wybranej aplikacji, a całość ope-
{Zwalniamy strumień} racji odbywa się po stronie komputera nale-
MyData.Free; żącego do organizacji, która udostępnia daną
end; aplikację. (pl.wikipedia.org).Zastanówmy się naj-
end; pierw nad ogólną koncepcją naszej aplika-
cji  zarówno klienta jak i serwera. Klient 
Listing 5. Aktywacja i deaktywacja serwera IdHTTPServer1
w tym przypadku strona WWW  powinien
{Procedura OnCreate} zawierać pola:  Login oraz  Hasło , aby nasze-
procedure TForm1.FormCreate(Sender: TObject); go zdalnego systemu nie mogły przechwycić
begin
{Ustawiamy numer portu dla serwera}
IdHTTPServer1.DefaultPort := 8008; Kodowanie danych
Jeżeli chcemy wysłać dane do serwera za-
{aktywujemy serwer}
wierające elementy formularza, to muszą
IdHTTPServer1.Active:=True;
one wcześniej zostać zakodowane. Kodo-
end;
wanie application/x-www-form-urlencoded
{- - -}
jest kodowaniem domyślnym, które prze-
{procedura OnClose}
glądarka wysyła do skryptu; używamy go
do wysyłania małych ilości informacji. Nie
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
sprawdza się ono jednak podczas wysyła-
begin
nia dużych ilości danych binarnych lub roz-
{dezaktywujemy serwer}
ległego tekstu. Do tego celu należy użyć ko-
IdHTTPServer1.Active:=False;
dowania multipart/form-data.
end;
Niezależnie od tego, na jakie kodowa-
{- - -} nie się zdecydujemy, musimy pamiętać o je-
go implementacji w naszym programie.
28 06/2007
Delphi i PHP
niepowołane osoby, a także kilka opcji wybo-
Listing 6. Odbieranie danych przez aplikację
ru, które będą reprezentowały możliwe do wy-
konania funkcje przez zdalny system. Po wy- procedure TForm1.IdHTTPServer1CommandGet(AThread: TIdPeerThread;
braniu opcji  Wyślij , skrypt wyśle parametry ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
do aplikacji  serwera. var
Serwer natomiast, po odbiorze porcji da- StrResult: String;
nych, powinien mieć możliwość ich wali- begin
dacji, w tym danych użytkownika (jego na- {w Memo zostaną umieszczone żądania (request server)}
zwy oraz hasła), który chce skorzystać z jego Memo1.Lines.Add(ARequestInfo.Document);
usług, a także oczywiście mieć możliwość wy- {tworzymy kod wynikowy dla przeglądarki}
konania żądanego polecenia. Po jego wykona- StrResult := '

Testowa strona serwera.

'
niu serwer powinien zwrócić wynik, następ- +'Odebrane dane:'
nie wszystkie operacje powinny być zapisywa- {ARequestInfo.Host zawiera informacje o hoście użytkownika...}
ne w logach. + '

Host: ' + ARequestInfo.Host + '

'
{...natomiast ARequestInfo.UnparsedParams wyświetla parametry
przekazane do naszego serwera}
+ '

Parametry: ' + ARequestInfo.UnparsedParams + '

';
{wyświetlamy w przeglądarce stworzony łańcuch}
AResponseInfo.ContentText := StrResult;
{do Edit1 dodajemy parametry przekazane do serwera}
Edit1.Text:=ARequestInfo.UnparsedParams;
end;
Listing 7. Formularz wysyłający zmienne metodą POST do aplikacji







Rysunek 4. Gotowa aplikacja wysyłająca


obrazy na hosting ImageShack.us i parsująca kod

wynikowy








Listing 8. Przykładowa aplikacja klienta
Rysunek 5. Przykładowe rozmieszczenie

komponentów. Z góry: komponenty

ze standardowymi właściwościami Caption,
natomiast u dołu: komponenty posiadające
zmodyfikowaną tą właściwość














Rysunek 6. Gotowa aplikacja odbierająca dane
Wyłącz zdalny komputer
od skryptu


Wyślij wiadomość:








Rysunek 7. Zarządzanie komputerem z poziomu
przeglądarki
06/2007 www.phpsolmag.org 29
Technika
Listing 9. Odbieranie danych przez aplikację i wykonywanie żądanych poleceń
W Sieci
procedure TForm1.IdHTTPServer1CommandGet(AThread: TIdPeerThread;
" http://www.codegear.com/downloads/
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
free/delphi
var
" http://www.indyproject.org/
StrResult: String;
" https://addons.mozilla.org/pl/firefox/
login,pass,autoryzacja: boolean;
addon/60
begin " http://www.4programmers.net
{w Memo zostaną umieszczone żądania (request server)}
Memo1.Lines.Add(ARequestInfo.Document);
{do logów dodajemy parametry przekazane do serwera} więc do sekcji Uses musimy dodać moduł
Memo1.Lines.Add('Odebrane parametry:'); ShellAPI.
Memo1.Lines.Add(ARequestInfo.Params.Text); Sam kod nie jest trudny do zrozumienia, zo-
{walidacja danych:} stał on oczywiście opatrzony komentarzami,
{czy login (parametr 0) jest poprawny?} dlatego zachęcam do jego przejrzenia. Przyj-
if ARequestInfo.Params[0]='login=admin' rzyjmy się fragmentowi odpowiedzialnemu za
then login:=True else login:=False; walidację danych.
{czy hasło (parametr 1) jest poprawne?} Zmienna ARequestInfo.Params[index] zawie-
if ARequestInfo.Params[1]='pass=password' ra kolejne parametry, do których możemy od-
then pass:=True else pass:=False; woływać się po ich indeksie. Nasz skrypt, który
{identyfikacja} pisaliśmy wcześniej, wysyła kolejno porcje da-
if (login and pass) then autoryzacja:=True nych: login, będący parametrem zerowym, ha-
else autoryzacja:=False; sło, będące parametrem pierwszym, i tak da-
{wypisujemy kod wynikowy} lej. Ważna jest kolejność, jaką zachowujemy.
StrResult := 'Odebrane dane:' Wysyłając najpierw hasło, a dopiero potem lo-
+ '

Autoryzacja loginu: ' + BoolToStr(login,True) + '

' gin do serwera- automatycznie zmieniamy ich
+ '

Autoryzacja hasła: ' + BoolToStr(pass,True) + '

' indeksy, co powoduje, że dane nie przechodzą
+ '

Wykonanie polecenia: ' + BoolToStr(autoryzacja,True) + '

'; walidacji.
AResponseInfo.ContentText := StrResult; Możemy oczywiście skorzystać na przykład z
{zwracamy informację do przeglądarki} instrukcji for...to i sprawdzać po kolei wszystkie
AResponseInfo.WriteContent; odebrane skrypty, jednakże, przy tak małej ilo-
{sprawdzenie polecenia} ści danych nie jest to konieczne.
if ((ARequestInfo.Params[2]='opcje=message') and autoryzacja)
then Wynik działania
ShowMessage(StringReplace(ARequestInfo.Params[3],'wiadomość=','',[])) Proces tworzenia aplikacji, zarówno serwe-
else ra jak i klienta, mamy już za sobą. Teraz nad-
if ((ARequestInfo.Params[2]='opcje=shutdown') and autoryzacja) szedł czas na przyjrzenie się rezultatom ich
then działania.
{wywołanie cmd.exe z parametrem shutdown- zamykamy system} Tak więc: uruchamiamy nasze aplikacje- ser-
ShellExecute(Handle,'open','cmd.exe','/c shutdown /s','C:',SW_HIDE) wer i stronę z formularzem. Wypełniamy poda-
else ne pola (niekoniecznie poprawnie, aby zoba-
end; czyć, czy wszystko działa tak jak należy) i wysy-
łamy dane. Przykład działania aplikacji pokaza-
ny jest na Rysunku 7.
Projekt klienta Projekt serwera
Pierwszym krokiem będzie stworzenie stro- Projekt serwera w dużej mierze opierać bę- Podsumowanie
ny WWW, której funkcją będzie wysyłanie pa- dzie się na aplikacji zaprezentowanej na po- Mój niewielki artykuł opisuje tylko wierz-
kietów z danymi do naszej aplikacji. Opierać czątku obecnego rozdziału. Śmiało możemy chołek góry lodowej, jaką jest pakiet INDY.
się ona będzie na prostym formularzu, które- otworzyć tamten projekt i zacząć go mody- Dla jego potrzeb wykorzystałem zaledwie
go kod został zaprezentowany na Listingu 8. fikować. dwa komponenty z ponad ich stuelemento-
Podobnie jak poprzednio, będziemy korzystać Zacznijmy od usunięcia Label-u podpi- wej kolekcji. Pamiętaj, że  teoria śni, prakty-
z portu numer 8008. Jeżeli zamierzamy korzy- sanego jako  Odebrane parametry , a także ka uczy . W momencie, gdy sam stworzysz
stać z aplikacji, z innego komputera niż local- komponentu Edit1. Nie będą one nam już i przeanalizujesz aplikacje, zmodyfikujesz
host, niekiedy wymagane będzie odblokowanie potrzebne. ich kody i prześledzisz działanie, będziesz
tego portu na firewall u. Następnie, tak jak poprzednio, klikamy na mógł w pełni zrozumieć zagadnienia, które
Przyjrzyjmy się Listingowi 8. Jak widać, zo- komponent IdHTTPServer1 i przechodzimy do nimi kierują.
stały w nim zawarte planowane pola: Login oraz Object Inspector a. Odszukujemy Event pod-
Hasło, a także pola typu  Radio , które repre- pisany jako OnCommandGet i wpisujemy kod
zentują możliwe do wykonania zadania. Dla z Listingu 9. Pozostałe procedury projektu po- ARTUR CHUDZIK
przykładu umieściłem dwa: możliwość wyłą- zostawiamy bez zmian. Autor w wolnych chwilach zajmuje się progra-
czenia zdalnego komputera, a także opcję wy- Procedura OnCommandGet, którą przed mowaniem, a także administracją portalem We-
świetlenia na nim wiadomości. Skoro ten etap chwilą wpisaliśmy, zawiera przykładowe po- bHat.pl, którego jest założycielem. Obecnie uczy się
mamy już za sobą możemy przejść do projekto- lecenie zamykające system- w tym wypad- w drugiej klasie 1LO w Aańcucie.
wania serwera. ku posłużyliśmy się funkcją ShellExecute, tak Kontakt z autorem: admin@webhat.pl
30 06/2007


Wyszukiwarka

Podobne podstrony:
php 2
Biblioteka PHP Wysyłanie pliku na serwer
k php
Delphi Leksykon kieszonkowy?lplk
php 2
php 3
PHP i Oracle Tworzenie aplikacji webowych od przetwarzania danych po Ajaksa
instructions for php scripts
PHP i MySQL Dla kazdego
kurs php
www mediweb pl sex wyswietl vad php id=703
PHP JS readme

więcej podobnych podstron