Sign in Join
Wiki copytemporary

Synapse/pl: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Synapse/pl

OldNewLine
1+Synapse ułatwia użycie portu szeregowego i dostarcza synchroniczną bibliotekę TCP/IP.
2+
3+## Przegląd
4+
5+Synapse oferuje obsługę portu [[Hardware Access|szeregowego]] oraz łączność TCP/IP. Różni się od innych bibliotek tym, że wymaga jedynie dodania do kodu kilku plików kodu źródłowego Synapse Pascal; nie ma potrzeby instalowania całych pakietów itp. Jedynym wyjątkiem jest to, że będziesz potrzebować zewnętrznej biblioteki kryptograficznej, jeśli chcesz używać szyfrowania, takiego jak SSL/TLS/SSH.
6+
7+Zobacz dokumentację na oficjalnej stronie (link poniżej), aby uzyskać więcej informacji.
8+
9+## Instalacja
10+
11+Instalacja może być tak prosta, jak po prostu skopiowanie wszystkich plików do katalogu aplikacji i dodanie odpowiednich modułów Synapse do klauzuli *uses*.
12+
13+Bardziej eleganckim i zalecanym sposobem jest kompilacja pakietu laz_synapse.lpk, dzięki czemu możesz używać tych samych modułów we wszystkich swoich projektach.
14+
15+Strona informacyjna pobierania/SVN Synapse: [Strona pobierania Synapse](http://www.ararat.cz/synapse/doku.php/download)
16+
17+## Wsparcie i zgłaszanie błędów
18+
19+Projekt Synapse posiada listę mailingową, na której udzielane jest wsparcie i można przesyłać łatki.
20+
21+Raporty o błędach można również przesyłać pocztą na listę dyskusyjną.
22+
23+Zobacz [strona pomocy Synapse](http://www.ararat.cz/synapse/doku.php/support)
24+
25+## Obsługa SSL/TLS
26+
27+Z Synapse możesz korzystać z obsługi OpenSSL, CryptLib, StreamSecII lub OpenStreamSecII SSL. Domyślnie nie jest używana obsługa SSL.
28+
29+Wsparcie jest aktywowane poprzez umieszczenie wybranej nazwy modułu w sekcji **uses** w swoim projekcie. Musisz także umieścić plik biblioteki binarnej w ścieżce projektu (Windows) lub zainstalować go w ścieżce wyszukiwania biblioteki (Linux, macOS, FreeBSD).
30+
31+Synapse ładuje pliki bibliotek SSL w środowisku wykonawczym jako biblioteki dynamiczne.
32+
33+- Szczegółowe informacje można znaleźć na stronie [Architektura wtyczek SSL/TLS](http://www.ararat.cz/synapse/doku.php/public:howto:sslplugin)
34+- Niektóre biblioteki kryptograficzne można uzyskać pod adresem: <http://synapse.ararat.cz/files/crypt/>
35+
36+### Brakująca biblioteka
37+
38+W systemie Linux musisz upewnić się, że wymagana biblioteka dynamiczna jest obecna/zainstalowana w twoim systemie. Jeśli biblioteki nie ma w systemie, to w przypadku cryptlib, podczas linkowania pojawia się komunikat o błędzie:
39+
40+`/usr/bin/ld: cannot find -lcl`
41+
42+Podobny komunikat zostanie wyświetlony podczas korzystania z innych bibliotek dynamicznych.
43+
44+## Przykład serwera WWW
45+
46+Zobacz ten [[Networking|przykład serwera internetowego (www)]].
47+
48+## Przykład zapytania serwera QOTD
49+
50+Zobacz ten [[QOTD|przykład zapytania serwera - Cytat dnia]].
51+
52+## Wysyłanie email
53+
54+Artykuł opisujący wysyłanie e-maili wraz z załącznikami za pomocą Synapse: <http://www.freepascal.org/~michael/articles/lazmail/lazmail-en.pdf>
55+
56+Przykład z [postu na forum](http://forum.lazarus.freepascal.org/index.php/topic,21157.msg123501.html#msg123501); współpracuje np. z Gmailem (czy to jest aktualne?):
57+
58+``` pascal
59+{Ten kod obsługuje szyfrowanie TLS/SSL; jeśli wysyłasz do portu 25, SMTP używa zwykłego tekstu.}
60+
61+uses
62+ ..., smtpsend,ssl_openssl; //prawdopodobnie można użyć również inne moduły SSL.
63+
64+// MailData to tekst wiadomości.
65+function SendMail(
66+ User, Password,
67+ MailFrom, MailTo,
68+ SMTPHost, SMTPPort: string;
69+ MailData: string): Boolean;
70+var
71+ SMTP: TSMTPSend;
72+ sl:TStringList;
73+begin
74+ Result:=False;
75+ SMTP:=TSMTPSend.Create;
76+ sl:=TStringList.Create;
77+ try
78+ sl.text:=Maildata;
79+ SMTP.UserName:=User;
80+ SMTP.Password:=Password;
81+ SMTP.TargetHost:=SMTPHost;
82+ SMTP.TargetPort:=SMTPPort;
83+ SMTP.AutoTLS:=true;
84+ if Trim(SMTPPort)<>'25' then
85+ SMTP.FullSSL:=true; // jeśli wysyłasz na port 25, nie używaj szyfrowania
86+ if SMTP.Login then
87+ begin
88+ result:=SMTP.MailFrom(MailFrom, Length(MailData)) and
89+ SMTP.MailTo(MailTo) and
90+ SMTP.MailData(sl);
91+ SMTP.Logout;
92+ end;
93+ finally
94+ SMTP.Free;
95+ sl.Free;
96+ end;
97+end;
98+```
99+
100+### Wysyłanie załączników
101+
102+Proszę zapoznać się z tą [dokumentacją Synapse](http://synapse.ararat.cz/doku.php/public:howto:tmimepart).
103+
104+## Pobieranie plików
105+
106+### Z serwera FTP
107+
108+Po podaniu adresu URL (i ścieżki) oraz nazwy pliku, zostanie on pobrany z serwera FTP. Jest to głównie opakowanie wokół kodu Synapse, które ma ułatwić pobieranie dowolnych plików. Jeśli dokładnie wiesz, co i gdzie chcesz pobrać, wystarczy wywołać Synapse:
109+
110+``` pascal
111+FtpGetFile
112+```
113+
114+zaprowadzi cię bardzo daleko.
115+
116+``` pascal
117+function DownloadFTP(URL, TargetFile: string): boolean;
118+const
119+ FTPPort=21;
120+ FTPScheme='ftp://'; //Nazwa schematu URI dla adresów URL FTP
121+var
122+ Host: string;
123+ Port: integer;
124+ Source: string;
125+ FoundPos: integer;
126+begin
127+ // Usuń informacje o schemacie:
128+ if LeftStr(URL, length(FTPScheme))=FTPScheme then URL:=Copy(URL, length(FTPScheme)+1, length(URL));
129+
130+ // Surowa analiza; można użyć kodu parsującego URI z pakietów FPC...
131+ FoundPos:=pos('/', URL);
132+ Host:=LeftStr(URL, FoundPos-1);
133+ Source:=Copy(URL, FoundPos+1, Length(URL));
134+
135+ //Sprawdź numery portów:
136+ FoundPos:=pos(':', Host);
137+ Port:=FTPPort;
138+ if FoundPos>0 then
139+ begin
140+ Host:=LeftStr(Host, FoundPos-1);
141+ Port:=StrToIntDef(Copy(Host, FoundPos+1, Length(Host)),21);
142+ end;
143+ Result:=FtpGetFile(Host, IntToStr(Port), Source, TargetFile, 'anonymous', 'fpc@example.com');
144+ if result=false then writeln('DownloadFTP: error downloading '+URL+'. Details: host: '+Host+'; port: '+Inttostr(Port)+'; remote path: '+Source+' to '+TargetFile);
145+end;
146+```
147+
148+Przykład pobrania listy plików dostępnych w podanej ścieżce
149+
150+``` pascal
151+//Użyj modułu ftpsend
152+
153+function FtpGetDir(const IP, Port, Path, User, Pass: string; DirList: TStringList): Boolean;
154+var
155+ i: Integer;
156+ s: string;
157+begin
158+ Result := False;
159+ with TFTPSend.Create do
160+ try
161+ Username := User;
162+ Password := Pass;
163+ TargetHost := IP;
164+ TargetPort := Port;
165+ if not Login then
166+ Exit;
167+ Result := List(Path, False);
168+ for i := 0 to FtpList.Count -1 do
169+ begin
170+ s := FTPList[i].FileName;
171+ DirList.Add(s);
172+ end;
173+ Logout;
174+ finally
175+ Free;
176+ end;
177+end;
178+```
179+
180+### Z serwera HTTP
181+
182+Po podaniu adresu URL (i ścieżki) oraz nazwy pliku, zostanie on pobrany z serwera HTTP. Zauważ, że ten kod sprawdza kod statusu HTTP (np. 200, 404), aby sprawdzić, czy dokument, który otrzymaliśmy z serwera, jest żądanym plikiem czy stroną błędu.
183+
184+#### Wersja prosta
185+
186+``` pascal
187+...
188+uses httpsend,
189+...
190+function DownloadHTTP(URL, TargetFile: string): Boolean;
191+var
192+ HTTPGetResult: Boolean;
193+ HTTPSender: THTTPSend;
194+begin
195+ Result := False;
196+ HTTPSender := THTTPSend.Create;
197+ try
198+ HTTPGetResult := HTTPSender.HTTPMethod('GET', URL);
199+ if (HTTPSender.ResultCode >= 100) and (HTTPSender.ResultCode<=299) then begin
200+ HTTPSender.Document.SaveToFile(TargetFile);
201+ Result := True;
202+ end;
203+ finally
204+ HTTPSender.Free;
205+ end;
206+end;
207+```
208+
209+#### Wersja zaawansowana
210+
211+``` pascal
212+...
213+uses httpsend
214+...
215+function DownloadHTTP(URL, TargetFile: string): Boolean;
216+// Pobieranie pliku; w razie potrzeby spróbuj ponownie.
217+// Można próbować użyć funkcji Synapse HttpGetBinary, ale to nie działa
218+// z kodami wyników (tzn. szczęśliwie pobiera dokument błędu 404)
219+const
220+ MaxRetries = 3;
221+var
222+ HTTPGetResult: Boolean;
223+ HTTPSender: THTTPSend;
224+ RetryAttempt: Integer;
225+begin
226+ Result := False;
227+ RetryAttempt := 1;
228+ HTTPSender := THTTPSend.Create;
229+ try
230+ try
231+ // Spróbuj pobrać plik
232+ HTTPGetResult := HTTPSender.HTTPMethod('GET', URL);
233+ while (HTTPGetResult = False) and (RetryAttempt < MaxRetries) do
234+ begin
235+ Sleep(500 * RetryAttempt);
236+ HTTPSender.Clear;
237+ HTTPGetResult := HTTPSender.HTTPMethod('GET', URL);
238+ RetryAttempt := RetryAttempt + 1;
239+ end;
240+ // Jeśli mamy odpowiedź z serwera, sprawdź, czy plik został do nas wysłany.
241+ case HTTPSender.Resultcode of
242+ 100..299:
243+ begin
244+ HTTPSender.Document.SaveToFile(TargetFile);
245+ Result := True;
246+ end; //informational, success
247+ 300..399: Result := False; // przekierowanie. Nie zaimplementowano, ale może się zdarzyć.
248+ 400..499: Result := False; // błąd klienta; 404 nie znaleziono itp.
249+ 500..599: Result := False; // wewnętrzny błąd serwera
250+ else Result := False; // kod nieznany
251+ end;
252+ except
253+ // Nie obchodzi nas przyczyna tego błędu; pobieranie nie powiodło się.
254+ Result := False;
255+ end;
256+ finally
257+ HTTPSender.Free;
258+ end;
259+end;
260+```
261+
262+#### Prosta wersja z paskiem postępu
263+
264+Poniższy przykład pokazuje, jak uzyskać informacje o postępie z pobierania HTTP, a także rozmiar pliku. Rozmiar pliku jest pobierany z informacji zawartej w nagłówku.
265+
266+> **Note:** Wcześniejsze wersje free pascala wymagały użycia trybu {\$mode Delphi} do poprawnego działania poniższych przykładów. Obecnie bez problemu można używać trybu {\$mode objfpc}{\$H+}. Testowane na wersji FPC:3.2.2, Lazarus:2.0.12
267+
268+``` pascal
269+unit uhttpdownloader;
270+
271+{$mode objfpc}{$H+}
272+
273+interface
274+
275+uses
276+ Classes, SysUtils, httpsend, blcksock, typinfo;
277+
278+type
279+ IProgress = interface
280+ procedure ProgressNotification(Text: String; CurrentProgress : integer; MaxProgress : integer);
281+ end;
282+
283+type
284+ { THttpDownloader }
285+
286+ THttpDownloader = class
287+ public
288+ function DownloadHTTP(URL, TargetFile: string; ProgressMonitor : IProgress): Boolean;
289+ private
290+ Bytes : Integer;
291+ MaxBytes : Integer;
292+ HTTPSender: THTTPSend;
293+ ProgressMonitor : IProgress;
294+ procedure Status(Sender: TObject; Reason: THookSocketReason; const Value: String);
295+ function GetSizeFromHeader(Header: String):integer;
296+ end;
297+
298+implementation
299+
300+function THttpDownloader.DownloadHTTP(URL, TargetFile: string; ProgressMonitor : IProgress): Boolean;
301+var
302+ HTTPGetResult: Boolean;
303+begin
304+ Result := False;
305+ Bytes:= 0;
306+ MaxBytes:= -1;
307+ Self.ProgressMonitor:= ProgressMonitor;
308+
309+ HTTPSender := THTTPSend.Create;
310+ try
311+ HTTPSender.Sock.OnStatus:= Status;
312+ HTTPGetResult := HTTPSender.HTTPMethod('GET', URL);
313+ if (HTTPSender.ResultCode >= 100) and (HTTPSender.ResultCode<=299) then begin
314+ HTTPSender.Document.SaveToFile(TargetFile);
315+ Result := True;
316+ end;
317+ finally
318+ HTTPSender.Free;
319+ end;
320+end;
321+
322+procedure THttpDownloader.Status(Sender: TObject; Reason: THookSocketReason; const Value: String);
323+var
324+ V, currentHeader: String;
325+ i: integer;
326+begin
327+ //spróbuj pobrać rozmiar pliku z nagłówków
328+ if (MaxBytes = -1) then
329+ begin
330+ for i:= 0 to HTTPSender.Headers.Count - 1 do
331+ begin
332+ currentHeader:= HTTPSender.Headers[i];
333+ MaxBytes:= GetSizeFromHeader(currentHeader);
334+ if MaxBytes <> -1 then break;
335+ end;
336+ end;
337+
338+ V := GetEnumName(TypeInfo(THookSocketReason), Integer(Reason)) + ' ' + Value;
339+
340+ if Reason = THookSocketReason.HR_ReadCount then
341+ begin
342+ Bytes:= Bytes + StrToInt(Value);
343+ ProgressMonitor.ProgressNotification(V, Bytes, MaxBytes);
344+ end;
345+end;
346+
347+function THttpDownloader.GetSizeFromHeader(Header: String): integer;
348+var
349+ item : TStringList;
350+begin
351+ Result:= -1;
352+
353+ if Pos('Content-Length:', Header) <> 0 then
354+ begin
355+ item:= TStringList.Create();
356+ item.Delimiter:= ':';
357+ item.StrictDelimiter:=true;
358+ item.DelimitedText:=Header;
359+ if item.Count = 2 then
360+ begin
361+ Result:= StrToInt(Trim(item[1]));
362+ end;
363+ end;
364+end;
365+
366+end.
367+```
368+
369+Co my tu robimy?
370+
371+Przede wszystkim zaglądamy do nagłówków, aby uzyskać rozmiar pliku. Musimy poczekać i sprawdzić, czy nagłówek tam jest. Pierwsze zdarzenia nie zawierają informacji o treści Content-Length.
372+
373+Po znalezieniu wyodrębniamy te informacje. Pojawia się tutaj kilka zdarzeń, na które możesz zareagować. Ale w tym przykładzie sprawdzamy tylko THookSocketReason.HR_ReadCount.
374+
375+„HR_ReadCount” dostarcza nam informacji ile bajtów zostało odczytanych od ostatniego zdarzenia.
376+
377+Postęp jest następnie zgłaszany do interfejsu użytkownika:
378+
379+``` pascal
380+procedure TMainForm.ProgressNotification(Text: String; CurrentProgress: integer; MaxProgress: integer);
381+begin
382+ if (MaxProgress <> -1) then
383+ begin
384+ ProgressBar.Max:= MaxProgress;
385+ end;
386+
387+ ProgressBar.Position:= CurrentProgress;
388+ memoStatus.Lines.Add(Text);
389+ Application.ProcessMessages;
390+end;
391+```
392+
393+Tak więc ostatecznym głównym modułem będzie:
394+
395+``` pascal
396+unit uMain;
397+
398+{$mode objfpc}{$H+}
399+
400+interface
401+
402+uses
403+ Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls, httpsend, blcksock, typinfo,
404+ uhttpdownloader;
405+
406+type
407+
408+ { TMainForm }
409+
410+ TMainForm = class(TForm, IProgress)
411+ btnStartDownload: TButton;
412+ edtUrl: TEdit;
413+ labelUrl: TLabel;
414+ memoStatus: TMemo;
415+ ProgressBar: TProgressBar;
416+ SaveDialog: TSaveDialog;
417+ procedure btnStartDownloadClick(Sender: TObject);
418+ private
419+ { private declarations }
420+ function GetFileNameFromURL(url: String):string;
421+ public
422+ { public declarations }
423+ procedure ProgressNotification(Text: String; CurrentProgress : integer; MaxProgress : integer);
424+ end;
425+
426+var
427+ MainForm: TMainForm;
428+
429+implementation
430+
431+{$R *.lfm}
432+
433+{ TMainForm }
434+
435+procedure TMainForm.btnStartDownloadClick(Sender: TObject);
436+var
437+ fileName: String;
438+ downloader: THttpDownloader;
439+ success: boolean;
440+begin
441+ fileName:= GetFileNameFromURL(edtUrl.Text);
442+ SaveDialog.FileName:=fileName;
443+ if (SaveDialog.Execute) then
444+ begin
445+ memoStatus.Lines.Clear;
446+ ProgressBar.Position:=0;
447+ downloader:= THttpDownloader.Create();
448+ success:= downloader.DownloadHTTP(edtUrl.Text, SaveDialog.FileName, Self);
449+
450+ ProgressBar.Position:=0;
451+ if Success then
452+ memoStatus.Lines.Add('Download successful')
453+ else
454+ memoStatus.Lines.Add('Error during download');
455+
456+ end;
457+end;
458+
459+function TMainForm.GetFileNameFromURL(url: String): string;
460+var i, l : integer;
461+ fileName, current : String;
462+begin
463+ fileName:= '';
464+ l:= Length(url);
465+ for i:= l downto 0 do begin
466+ current:= url[i];
467+ if current <> '/' then
468+ begin
469+ fileName:= current + fileName;
470+ end else begin
471+ Result:= fileName;
472+ break;
473+ end;
474+ end;
475+end;
476+
477+procedure TMainForm.ProgressNotification(Text: String; CurrentProgress: integer; MaxProgress: integer);
478+begin
479+ if (MaxProgress <> -1) then ProgressBar.Max:= MaxProgress;
480+ ProgressBar.Position:= CurrentProgress;
481+ memoStatus.Lines.Add(Text);
482+ Application.ProcessMessages;
483+end;
484+
485+end.
486+```
487+
488+Odnosnik: <https://andydunkel.net/2015/09/09/lazarus_synapse_progress/>
489+
490+#### Z serwera HTTP przez parsowanie adresów URL: Sourceforge
491+
492+Zobacz [[Download from SourceForge|Pobieranie z SourceForge]], aby zapoznać się z przykładem pobierania z sourceforge.net.
493+
494+### Z serwera HTTPS
495+
496+Jest to podobne do pobierania z serwera HTTP. Dodatkowo musisz [[Synapse|aktywować obsługę SSL/TLS]] i uzyskać plik(i) binarny wymaganej biblioteki. Następnie możesz użyć tej samej funkcji DownloadHTTP do pobrania pliku z adresu URL zaczynającego się od **<https://>**.
497+
498+## Przykładowy program klienta SSH/Telnet
499+
500+Poniżej znajdziesz moduł, który pozwala na korzystanie z funkcjonalności klienta telnet/SSH, która wykorzystuje moduł synapse tlntsend.pas. Przykładowy program pokazuje, jak tego używać. Inny, prostszy sposób ilustruje Leonardo Ramé na [1](http://leonardorame.blogspot.com/2010/01/synapse-based-ssh-client.html). Jego przykład nie może jednak używać telnetu i wysyła tylko jedno polecenie.
501+
502+### Wymagania
503+
504+Oprócz źródeł Synapse (z których potrzebujesz tylko kilku), jeśli chcesz korzystać z funkcjonalności SSH, będziesz potrzebować biblioteki szyfrowania, której używa Synapse. Chyba, że używasz tylko usługi Telnet, wówczas tego nie potrzebujesz.
505+
506+Istnieją 2 możliwości:
507+
508+- Biblioteka Cryptlib. Zaleta: stabilna. Najwyraźniej można używać kluczy prywatnych, ale są one stosowane w pewnym formacie, który nie jest powszechnie obsługiwany.
509+- Biblioteka LibSSH2. Obsługa w Pascalu jest nadal w fazie rozwoju, ale do uwierzytelnienia możesz użyć pliku z kluczem prywatnym (w formacie OpenSSH).
510+
511+#### Cryptlib
512+
513+- W systemie Windows pobierz binarną wersję biblioteki DLL cryptlib (CL32.DLL) i umieść ją w katalogu źródłowym. Jeśli kompilujesz do innego katalogu lub rozprowadzasz swój program, będziesz musiał również rozesłać bibliotekę DLL.
514+- W systemach Linux i OSX zainstaluj cryptlib za pomocą menedżera pakietów lub z innych źródeł. Podczas dystrybucji aplikacji oznacz cryptlib jako wymaganie w swoim pakiecie .deb/.rpm/inny.
515+
516+Będziesz także potrzebował dowiązań (cryptlib.pas), obecnych w źródłach dystrybucji cryptlib.
517+
518+Wersje pliku binarnego cryptlib i dowiązania muszą być zgodne.
519+
520+> **Note:** Wygląda na to, że cryptlib nie nadaje się do łączenia z maszynami linuksowymi, chociaż w systemie AIX działa. Zamiast tego użyj SSH2.
521+
522+#### LibSSH2
523+
524+- W systemie Windows pobierz binarną wersję biblioteki DLL libssh2 (LIBSSH2.DLL) i umieść ją w katalogu źródłowym. Jeśli kompilujesz do innego katalogu lub rozprowadzasz swój program, będziesz musiał również rozesłać tą bibliotekę DLL.
525+- W systemach Linux i macOS zainstaluj libssh2 za pomocą menedżera pakietów lub z innych środków. Ponadto dystrybuując swoją aplikację:
526+ - Linux: oznacz libssh2 jako wymaganie w swoim pakiecie .deb/.rpm/inny.
527+ - macOS: dołącz libssh2 do katalogu zasobów [[Application Bundle|Pakietu aplikacji]].
528+
529+Będziesz także potrzebował ssl_libssh2.pas (patrz poniżej) i dowiązań: (libssh2.pas, zobacz [ten post na forum](http://www.lazarus.freepascal.org/index.php/topic,15935.msg86465.html#msg86465)). Plik binarny libssh2 i dowiązania muszą być zgodne.
530+
531+### Wtyczka Synapse libssh2 SSL
532+
533+> **Note:** Wtyczka nie jest ukończona.
534+
535+``` pascal
536+{
537+ ssl_libssh2.pas wersja 0.2
538+
539+ Wtyczka obsługi SSH2 (zarys) dla biblioteki Synapse (http://www.ararat.cz/synapse) do LibSSH2 (http://libssh2.org)
540+ Wymaga: interfejsu libssh2 pascal - http://www.lazarus.freepascal.org/index.php/topic,15935.msg86465.html#msg86465 oraz
541+ libssh2.dll z OpenSSL.
542+
543+ (С) Alexey Suhinin http://x-alexey.narod.ru
544+}
545+
546+{$IFDEF FPC}
547+ {$MODE DELPHI}
548+{$ENDIF}
549+{$H+}
550+
551+unit ssl_libssh2;
552+
553+interface
554+
555+uses
556+ SysUtils,
557+ blcksock, synsock,
558+ libssh2;
559+
560+type
561+ {:@abstract(klasa implementująca wtyczkę CryptLib SSL/SSH.)
562+ Instancja tej klasy zostanie utworzona dla każdego @link(TTCPBlockSocket).
563+ Nie musisz tworzyć instancji tej klasy, wszystko robi sam Synapse!}
564+ TSSLLibSSH2 = class(TCustomSSL)
565+ protected
566+ FSession: PLIBSSH2_SESSION;
567+ FChannel: PLIBSSH2_CHANNEL;
568+ function SSHCheck(Value: integer): Boolean;
569+ function DeInit: Boolean;
570+ public
571+ {:Zobacz @inherited}
572+ constructor Create(const Value: TTCPBlockSocket); override;
573+ destructor Destroy; override;
574+ function Connect: boolean; override;
575+ function LibName: String; override;
576+ function Shutdown: boolean; override;
577+ {:Zobacz @inherited}
578+ function BiShutdown: boolean; override;
579+ {:Zobacz @inherited}
580+ function SendBuffer(Buffer: TMemory; Len: Integer): Integer; override;
581+ {:Zobacz @inherited}
582+ function RecvBuffer(Buffer: TMemory; Len: Integer): Integer; override;
583+ {:Zobacz @inherited}
584+ function WaitingData: Integer; override;
585+ {:Zobacz @inherited}
586+ function GetSSLVersion: string; override;
587+ published
588+ end;
589+
590+implementation
591+
592+{==============================================================================}
593+function TSSLLibSSH2.SSHCheck(Value: integer): Boolean;
594+var
595+ PLastError: PAnsiChar;
596+ ErrMsgLen: Integer;
597+begin
598+ Result := true;
599+ FLastError := 0;
600+ FLastErrorDesc := '';
601+ if Value<0 then
602+ begin
603+ FLastError := libssh2_session_last_error(FSession, PLastError, ErrMsglen, 0);
604+ FLastErrorDesc := PLastError;
605+ Result := false;
606+ end;
607+end;
608+
609+function TSSLLibSSH2.DeInit: Boolean;
610+begin
611+ if Assigned(FChannel) then
612+ begin
613+ libssh2_channel_free(FChannel);
614+ FChannel := nil;
615+ end;
616+ if Assigned(FSession) then
617+ begin
618+ libssh2_session_disconnect(FSession,'Goodbye');
619+ libssh2_session_free(FSession);
620+ FSession := nil;
621+ end;
622+ FSSLEnabled := False;
623+ Result := true;
624+end;
625+
626+constructor TSSLLibSSH2.Create(const Value: TTCPBlockSocket);
627+begin
628+ inherited Create(Value);
629+ FSession := nil;
630+ FChannel := nil;
631+end;
632+
633+destructor TSSLLibSSH2.Destroy;
634+begin
635+ DeInit;
636+ inherited Destroy;
637+end;
638+
639+function TSSLLibSSH2.Connect: boolean;
640+begin
641+ Result := False;
642+ if SSLEnabled then DeInit;
643+ if (FSocket.Socket <> INVALID_SOCKET) and (FSocket.SSL.SSLType = LT_SSHv2) then
644+ begin
645+ FSession := libssh2_session_init();
646+ if not Assigned(FSession) then
647+ begin
648+ FLastError := -999;
649+ FLastErrorDesc := 'Cannot initialize SSH session';
650+ exit;
651+ end;
652+ if not SSHCheck(libssh2_session_startup(FSession, FSocket.Socket)) then
653+ exit;
654+ if (FSocket.SSL.PrivateKeyFile<>'') then
655+ begin
656+ if (not SSHCheck(libssh2_userauth_publickey_fromfile(FSession, PChar(FSocket.SSL.Username), nil, PChar(FSocket.SSL.PrivateKeyFile), PChar(FSocket.SSL.KeyPassword)))) then
657+ exit;
658+ end
659+ else
660+ if (FSocket.SSL.Username<>'') and (FSocket.SSL.Password<>'') then
661+ begin
662+ if (not SSHCheck(libssh2_userauth_password(FSession, PChar(FSocket.SSL.Username), PChar(FSocket.SSL.Password)))) then
663+ exit;
664+ end;
665+ FChannel := libssh2_channel_open_session(FSession);
666+ if not assigned(FChannel) then
667+ begin
668+ SSHCheck(-1); // get error
669+ if FLastError = 0 then
670+ begin
671+ FLastError := -999; // unknown error
672+ FLastErrorDesc := 'Cannot open session';
673+ end;
674+ exit;
675+ end;
676+ if not SSHCheck(libssh2_channel_request_pty(FChannel, 'vanilla')) then
677+ exit;
678+ if not SSHCheck(libssh2_channel_shell(FChannel)) then
679+ exit;
680+ FSSLEnabled := True;
681+ Result := True;
682+ end;
683+end;
684+
685+function TSSLLibSSH2.LibName: String;
686+begin
687+ Result := 'ssl_libssh2';
688+end;
689+
690+function TSSLLibSSH2.Shutdown: boolean;
691+begin
692+ Result := DeInit;
693+end;
694+
695+function TSSLLibSSH2.BiShutdown: boolean;
696+begin
697+ Result := DeInit;
698+end;
699+
700+function TSSLLibSSH2.SendBuffer(Buffer: TMemory; Len: Integer): Integer;
701+begin
702+ Result:=libssh2_channel_write(FChannel, PChar(Buffer), Len);
703+ SSHCheck(Result);
704+end;
705+
706+function TSSLLibSSH2.RecvBuffer(Buffer: TMemory; Len: Integer): Integer;
707+begin
708+ result:=libssh2_channel_read(FChannel, PChar(Buffer), Len);
709+ SSHCheck(Result);
710+end;
711+
712+function TSSLLibSSH2.WaitingData: Integer;
713+begin
714+ if libssh2_poll_channel_read(FChannel, Result) <> 1 then Result := 0;
715+end;
716+
717+function TSSLLibSSH2.GetSSLVersion: string;
718+begin
719+ Result:=libssh2_version(0);
720+end;
721+
722+initialization
723+ if libssh2_init(0)=0 then
724+ SSLImplementation := TSSLLibSSH2;
725+
726+finalization
727+ libssh2_exit;
728+
729+end.
730+```
731+
732+### Klasa klienta terminala
733+
734+Poniższy moduł telnetsshclient.pas wykorzystuje moduł Synapse tlntsend.pas i opisuje logowanie, wysyłanie poleceń, odbieranie danych wyjściowych i wylogowywanie.
735+
736+Jeśli potrzebujesz tylko klienta telnet i możesz żyć bez obsługi SSH, zakomentuj {\$DEFINE HAS_SSH_SUPPORT} poniżej, aby kod nie wymagał biblioteki libssh2.
737+
738+To urządzenie zostało lekko przetestowane na serwerze Linux ssh/telnet. Dodatkowe testy mile widziane.
739+
740+``` pascal
741+unit telnetsshclient;
742+
743+{ Wrapper wokół bibliotek Synapse i biblioteki SSL (obecnie używane są libssh2+libssl)
744+Pobierz skompilowaną bibliotekę Windows dll, np. z
745+http://alxdm.dyndns-at-work.com:808/files/windll_libssh2.zip
746+Pobierz pliki interfejsu FreePascal:
747+http://www.lazarus.freepascal.org/index.php/topic,15935.msg86465.html#msg86465
748+
749+Ten moduł umożliwia użytkownikowi wysyłanie poleceń Telnet lub SSH i uzyskiwanie danych wyjściowych
750+Dzięki Leonardo Rame
751+http://leonardorame.blogspot.com/2010/01/synapse-based-ssh-client.html
752+i Ludo Brands.
753+
754+Napisany przez Reiniera Olislagersa 2011.
755+Zmodyfikowany dla libssh2 przez Alexeya Suhinina 2012.
756+
757+Licencja kodu:
758+* MIT
759+* LGPLv2 lub nowszy (z wyjątkiem statycznego linkowania FreePascal)
760+* GPLv2 lub nowszy
761+zgodnie z twoim wyborem.
762+Dozwolone jest bezpłatne korzystanie, ale proszę nie pozywać mnie ani nie obwiniać.
763+
764+Korzysta z innych bibliotek/komponentów, dla których mogą obowiązywać różne licencje, które również mogą wpływać na skompilowaną pracę.
765+}
766+
767+{$mode objfpc}{$H+}
768+{$DEFINE HAS_SSH_SUPPORT} //zakomentuj, jeśli wymagana jest tylko obsługa telnet
769+{$DEFINE LIBSSH2}
770+
771+interface
772+
773+uses
774+ Classes, SysUtils,
775+ tlntsend
776+ {$IFDEF HAS_SSH_SUPPORT}
777+ {ssl - a właściwie teraz ssh - biblioteki wymagane przez tlntsend}
778+ {$IFDEF LIBSSH2}
779+ ssl_libssh2
780+ {$ELSE}
781+ ssl_cryptlib
782+ {$ENDIF}
783+ {$ENDIF HAS_SSH_SUPPORT} ;
784+
785+type
786+ TProtocolType = (Telnet, SSH); //Różne sposoby łączenia
787+ TServerType = (Unix, Windows); //głównie dotyczy zakończenia linii tekstu
788+ { TelnetSSHClient }
789+
790+ { TTelnetSSHClient }
791+
792+ TTelnetSSHClient = class(TTelnetSend)
793+ protected
794+ FConnected: boolean;
795+ FOutputPosition: integer; //Śledzi pozycję w strumieniu wyjściowym
796+ FProtocolType: TProtocolType;
797+ FServerLineEnding: string; //zależy od FServerType
798+ FServerType: TServerType;
799+ FWelcomeMessage, FTelnetLoginPrompt, FTelnetPasswordPrompt: string;
800+ procedure SetPrivateKeyFile(Value: string);
801+ function GetPrivateKeyFile: string;
802+ { Na podstawie protokołu i typu serwera ustaw oczekiwane zakończenie linii po stronie serwera}
803+ procedure DetermineLineEnding;
804+ { Ustawia port, jeśli portu nie ustawiono jawnie. Używa protokołu typu: SSH lub telnet}
805+ procedure DeterminePort;
806+ function GetSessionLog: string;
807+ procedure ProtocolTypeChange(Value: TProtocolType);
808+ function ReceiveData: string; //Może być używany do odbierania wiadomości powitalnej itp.
809+ procedure SendData(Data: string);
810+ procedure ServerTypeChange(Value: TServerType);
811+ public
812+ {Wszystkie dane wyjściowe wygenerowane podczas całej sesji do tej pory}
813+ property AllOutput: string read GetSessionLog;
814+ {Ma wartość True, jeśli jest podłączony do serwera}
815+ property Connected: boolean read FConnected;
816+ {Nazwa lub adres IP hosta, z którym chcesz się połączyć}
817+ property HostName: string read FTargetHost write FTargetHost;
818+ {Port na hoście używany do połączenia. Jeśli zostanie pozostawiony jako 0, zostanie określony przez typ protokołu (22 dla SSH, 23 dla Telnet}
819+ property Port: String read FTargetPort write FTargetPort;
820+ {Lokalizacja pliku klucza prywatnego}
821+ property PrivateKeyFile: string read GetPrivateKeyFile write SetPrivateKeyFile;
822+ {Pytanie o login Telnet}
823+ property TelnetLoginPrompt: string read FTelnetLoginPrompt write FTelnetLoginPrompt;
824+ {Pytanie o hasło Telnet}
825+ property TelnetPasswordPrompt: string read FTelnetPasswordPrompt write FTelnetPasswordPrompt;
826+ {Nazwa użytkownika używana podczas łączenia}
827+ property UserName: string read FUserName write FUserName;
828+ {Hasło używane podczas łączenia. Używane jako hasło (passphrase), jeśli używany jest klucz prywatny}
829+ property Password: string read FPassword write FPassword;
830+ {Czy powinniśmy rozmawiać z serwerem przez Telnet czy SSH? Domyślnie jest to SSH}
831+ property ProtocolType: TProtocolType read FProtocolType write ProtocolTypeChange;
832+ {Serwer Windows czy Unix/Linux? Ma to wpływ na końcówki linii. Domyślnie jest to Unix. UWAGA: nieprzetestowane}
833+ property Servertype: TServerType read FServerType write ServerTypeChange;
834+ {Pierwsza wiadomość wyświetlana przy logowaniu}
835+ property WelcomeMessage: string read FWelcomeMessage;
836+ {Połącz/zaloguj się do serwera. Wymaga poprawnych wszystkich opcji uwierzytelniania, protokołu i nazwy hosta/portu.
837+ Zwraca opisowy wynik. Następnie możesz użyć właściwości Connected.}
838+ function Connect: string;
839+ {Jeśli połączony, wyloguj się z serwera}
840+ procedure Disconnect;
841+ {Wyślij polecenie do serwera i odbierz wynik}
842+ function CommandResult(Command: string): string; //Wyślij polecenie i uzyskaj wyniki
843+ constructor Create;
844+ destructor Destroy; override;
845+ end;
846+
847+implementation
848+
849+
850+{ TelnetSSHClient }
851+procedure TTelnetSSHClient.SetPrivateKeyFile(value: string);
852+begin
853+ Sock.SSL.PrivateKeyFile := value;
854+end;
855+
856+function TTelnetSSHClient.GetPrivateKeyFile: string;
857+begin
858+ Result := Sock.SSL.PrivateKeyFile;
859+end;
860+
861+procedure TTelnetSSHClient.DetermineLineEnding;
862+begin
863+ case FProtocolType of
864+ SSH:
865+ begin
866+ if FServerType = Unix then
867+ FServerLineEnding := #10 //Unix
868+ else
869+ FServerLineEnding := #13 + #10; //windows
870+ end;
871+ Telnet:
872+ begin
873+ if FServerType = Unix then
874+ FServerLineEnding := #10 //Unix
875+ else
876+ FServerLineEnding := #13 + #10; //windows
877+ end;
878+ else
879+ raise Exception.Create('Nieznany typ protokołu.');
880+ end;
881+end;
882+
883+procedure Ttelnetsshclient.DeterminePort;
884+begin
885+ if FTargetPort = '' then
886+ //Ustaw domyślny port dla protokołu
887+ begin
888+ case FProtocolType of
889+ Telnet: FTargetPort := '23';
890+ SSH: FTargetPort := '22';
891+ else
892+ raise Exception.Create('Nieznany typ protokołu.');
893+ end;
894+
895+ end;
896+end;
897+
898+procedure TTelnetSSHClient.ServerTypeChange(Value: Tservertype);
899+begin
900+ FServerType := Value;
901+ DetermineLineEnding;
902+end;
903+
904+function TTelnetSSHClient.Connect: string;
905+var
906+ Received: string;
907+begin
908+ result:='Nieznany błąd podczas łączenia';
909+ FOutputPosition := 1; //Pierwszy znak w strumieniu wyjściowym
910+ FWelcomeMessage := '';
911+ //Tylko dla pewności:
912+ DetermineLineEnding;
913+ DeterminePort;
914+ if FTargetPort='0' then
915+ begin
916+ result:='Port nie może być równy 0.';
917+ exit; //wyskoczyć z funkcji
918+ end;
919+ case FProtocolType of
920+ Telnet:
921+ begin
922+ try
923+ if Login then
924+ begin
925+ FConnected := True;
926+ result:='Połączono z serwerem telnet.';
927+ end
928+ else
929+ if Sock.LastError<>0 then raise Exception.Create(Sock.LastErrorDesc);
930+ except
931+ on E: Exception do
932+ begin
933+ FConnected:=false;
934+ result:='Błąd połączenia z serwerem telnet '+FTargetHost+':'+
935+ FTargetPort+' jako użytkownik ' + FUserName +
936+ '. Szczegóły techniczne: '+E.Message;
937+ end;
938+ end;
939+ end;
940+ SSH:
941+ begin
942+ {$IFNDEF HAS_SSH_SUPPORT}
943+ raise Exception.Create(
944+ 'Obsługa SSH nie została skompilowana do biblioteki telnetsshclient.');
945+ {$ENDIF HAS_SSH_SUPPORT}
946+ try
947+ if (PrivateKeyFile <> '') and (FPassword <> '') then
948+ Sock.SSL.KeyPassword:=FPassword;
949+ if SSHLogin then
950+ begin
951+ FConnected := True;
952+ result:='Connected to SSH server.';
953+ end
954+ else
955+ begin
956+ if Sock.LastError<>0 then raise Exception.Create(Sock.LastErrorDesc);
957+ if Sock.SSL.LastError<0 then raise Exception.Create(Sock.SSL.LastErrorDesc);
958+ end;
959+ except
960+ on E: Exception do
961+ begin
962+ FConnected:=false;
963+ result:='Błąd połączenia z serwerem SSH '+FTargetHost+':'+
964+ FTargetPort+' jako użytkownik ' + FUserName +
965+ '. Szczegóły techniczne: '+E.Message;
966+ end;
967+ end;
968+ end;
969+ else
970+ raise Exception.Create('Nieznany typ protokołu.');
971+ end;
972+ if FConnected = True then
973+ begin
974+ FWelcomeMessage := ReceiveData;
975+ if FProtocolType=Telnet then
976+ begin
977+ //Niestety, będziemy musieli sami wyodrębnić login
978+ //Mam nadzieję, że dotyczy to wszystkich typów serwerów.
979+ if (AnsiPos(AnsiLowerCase(FTelnetLoginPrompt),AnsiLowerCase(FWelcomeMessage))>0) then
980+ begin
981+ SendData(UserName);
982+ end;
983+ Received:=ReceiveData;
984+ if (AnsiPos(AnsiLowerCase(FTelnetPasswordPrompt),AnsiLowerCase(Received))>0) then
985+ begin
986+ SendData(Password);
987+ end;
988+ //Otrzymuj dodatkową wiadomość powitalną/wiadomość dnia
989+ FWelcomeMessage:=FWelcomeMessage+LineEnding+ReceiveData;
990+ end;
991+ end;
992+end;
993+
994+procedure TTelnetSSHClient.Disconnect;
995+begin
996+ Logout;
997+ FConnected := False;
998+end;
999+
1000+function TTelnetSSHClient.ReceiveData: string;
1001+begin
1002+ Result := '';
1003+ while Sock.CanRead(1000) or (Sock.WaitingData > 0) do
1004+ begin
1005+ Sock.RecvPacket(1000);
1006+ Result := Result + Copy(SessionLog, FOutputPosition,
1007+ Length(SessionLog));
1008+ FOutputPosition := Length(SessionLog) + 1;
1009+ end;
1010+end;
1011+
1012+procedure Ttelnetsshclient.SendData(Data: String);
1013+begin
1014+ Data := Data + FServerLineEnding; //Może to być linux, może być Windows
1015+ Send(Data);
1016+end;
1017+
1018+function TTelnetSSHClient.GetSessionLog: string;
1019+begin
1020+ // Do tej pory uzyskuje pełne dane wyjściowe
1021+ Result := SessionLog;
1022+end;
1023+
1024+procedure TTelnetSSHClient.ProtocolTypeChange(Value: Tprotocoltype);
1025+begin
1026+ FProtocolType := Value;
1027+ //W razie potrzeby automatycznie określ port i zakończenie linii
1028+ DeterminePort;
1029+ DetermineLineEnding;
1030+end;
1031+
1032+function TTelnetSSHClient.CommandResult(Command: string): string;
1033+begin
1034+ Result := '';
1035+ if FConnected then
1036+ begin
1037+ SendData(Command);
1038+ Result := ReceiveData; //dostaje za dużo
1039+ end
1040+ else
1041+ begin
1042+ //podnieś wyjątek
1043+ Result := '';
1044+ raise Exception.Create('Polecenie można uruchomić tylko po podłączeniu');
1045+ end;
1046+end;
1047+
1048+constructor TTelnetSSHClient.Create;
1049+begin
1050+ inherited;
1051+ FConnected := False;
1052+ FProtocolType := SSH; //Może to też być telnet
1053+ FServerType := Unix; //Prawdopodobnie bezpieczna wartość domyślna.
1054+ FTelnetLoginPrompt := 'login:';
1055+ FTelnetPasswordPrompt := 'password:';
1056+ DetermineLineEnding;
1057+ DeterminePort;
1058+end;
1059+
1060+destructor TTelnetSSHClient.Destroy;
1061+begin
1062+ if FConnected then
1063+ Disconnect;
1064+ inherited Destroy;
1065+end;
1066+
1067+end.
1068+```
1069+
1070+### Przykładowy kod klienta
1071+
1072+Aby użyć właśnie stworzonej przez nas klasy TTelnetSSHClient, możesz wypróbować przykładową aplikację, sshtest.lpr. Zauważ, że kod musi być skompilowany przez Lazarusa, ponieważ potrzebuje komponentów LCL do pracy z Synapse:
1073+
1074+``` pascal
1075+program sshtest;
1076+
1077+{Program testowy dla telnetsshclient
1078+
1079+Napisany przez Reiniera Olislagersa 2011.
1080+Zmodyfikowany dla libssh2 przez Alexeya Suhinina 2012.
1081+
1082+Licencja kodu:
1083+* MIT
1084+* LGPLv2 lub nowszy (z wyjątkiem statycznego linkowania FreePascal)
1085+* GPLv2 lub nowszy
1086+zgodnie z twoim wyborem.
1087+Dozwolone jest bezpłatne korzystanie, ale proszę nie pozywać mnie ani nie obwiniać.
1088+
1089+Korzysta z innych bibliotek/komponentów, dla których mogą obowiązywać różne licencje, które również mogą wpływać na skompilowaną pracę.
1090+
1091+Uruchamianie: sshtest <serverIPorhostname> [PrivateKeyFile]
1092+}
1093+{$mode objfpc}{$H+}
1094+{$APPTYPE CONSOLE}
1095+
1096+uses
1097+ telnetsshclient;
1098+var
1099+ comm: TTelnetSSHClient;
1100+ Command: string;
1101+begin
1102+ writeln('Start.');
1103+ comm:=TTelnetSSHClient.Create;
1104+ comm.HostName:= ParamStr(1); //Pierwszy argument w wierszu poleceń
1105+ if comm.HostName='' then
1106+ begin
1107+ writeln('Proszę podać nazwę hosta w wierszu poleceń.');
1108+ halt(1);
1109+ end;
1110+
1111+ comm.PrivateKeyFile := ParamStr(2);
1112+
1113+ comm.TargetPort:='0'; //automatyczne określanie na podstawie typu protokołu
1114+ comm.UserName:='root'; //zmień dla swojej sytuacji
1115+ comm.Password:='password'; //zmień dla swojej sytuacji
1116+ comm.ProtocolType:=SSH; //Telnet lub SSH
1117+ writeln(comm.Connect); //Pokaż wynik połączenia
1118+ if comm.Connected then
1119+ begin
1120+ writeln('Serwer: ' + comm.HostName + ':'+comm.TargetPort+', użytkownik: '+comm.UserName);
1121+ writeln('Wiadomość powitalna:');
1122+ writeln(comm.WelcomeMessage);
1123+ Command:='ls -al';
1124+ writeln('*** Wysyłanie ' + Command);
1125+ writeln('*** Początek wyniku****');
1126+ writeln(comm.CommandResult(Command));
1127+ writeln('*** Koniec wyniku****');
1128+ writeln('');
1129+ writeln('');
1130+ Command:='df -h';
1131+ writeln('*** Wysyłanie ' + Command);
1132+ writeln('*** Początek wyniku****');
1133+ writeln(comm.CommandResult(Command));
1134+ writeln('*** Koniec wyniku****');
1135+ writeln('');
1136+ writeln('');
1137+ writeln('Wszystkie wyjścia:');
1138+ writeln('*** Początek wyniku****');
1139+ writeln(comm.AllOutput);
1140+ writeln('*** Koniec wyniku****');
1141+ comm.Disconnect;
1142+ end
1143+ else
1144+ begin
1145+ writeln('Połączenie z ' +
1146+ comm.HostName + ':' +
1147+ comm.TargetPort + ' nie udało się.');
1148+ end;
1149+ comm.Free;
1150+end.
1151+```
1152+
1153+## Integracja z OAuth v1/Twitter/Plurk
1154+
1155+Biblioteka OAuth v1 napisana w FPC, która używa Synapse (i jest gotowa do obsługi innych bibliotek sieciowych, takich jak lNet) jest dostępna w [[fpctwit]]. FPCtwit zawiera również przykładowe programy klienckie FPC jak Twitter i Plurk oraz klienta Lazarus Twitter.
1156+
1157+## Inne artykuły internetowe i sieciowe
1158+
1159+- [[Portal:Web Development|Portal na temat tworzenia stron internetowych]]
1160+- [[Networking/pl|Sieć]]
1161+- [[Networking libraries/pl|Biblioteki sieciowe]] - porównanie różnych bibliotek sieciowych
1162+- [[Brook Framework]] - Idealny framework Free Pascal dla Twoich aplikacji internetowych. To czysty Pascal. Nie musisz porzucać preferowanego języka programowania.
1163+- [[Sockets|Gniazda]] - Komponenty gniazd TCP/IP
1164+- [[fcl-net]] - Biblioteka sieciowa dostarczana z FPC
1165+- [[lNet]] - Lekkie komponenty sieciowe
1166+- [[Synapse/pl|Synapse]] - Port szeregowy i synchroniczna biblioteka TCP/IP
1167+- [[XML Tutorial|Poradnik XML]] - XML jest często używany w komunikacji sieciowej
1168+- [[FPC and Apache Modules|FPC i moduły Apache]]
1169+- [[fcl-web]] - Znana również jako fpWeb, jest to biblioteka do tworzenia aplikacji internetowych, które można wdrażać jako moduły cgi, fastcgi lub apache.
1170+- [[Secure programming|Bezpieczne programowanie]]
1171+- [[Internet Tools|Narzędzia internetowe]] - Wrapper wokół komponentów http Synapse/wininet/Android upraszczający korzystanie z https i przekierowań oraz silnik XPath/XQuery/CSS Selector/JSONiq do przetwarzania pobranych stron
1172+
1173+## Zobacz też
1174+
1175+- [[Download from SourceForge/pl|Pobieranie z SourceForge]] Przykład, który używa Synapse do pobierania z serwera HTTP, który stosuje przekierowanie.
1176+- [Wizualny Synapse](https://sourceforge.net/projects/visualsynapse/) wrappery komponentów dla wielu elementów komunikacji szeregowej i sieciowej biblioteki Synapse (TvsComPort, TvsWebClient, TvsSniffer, TvsHTTPServer, TvsFTPServer, TvsAuthentication, TvsVisualDNS, TvsVisualHTTP, TvsVisualDUP, TvsVisualTCP, TvsVisualICMP, TvsSocksProxyInfo, TvsIPHelper, TvsSendMail i TvsSynPing).
1177+- [Komponent TCP/IP oparty na Synapse + mała aplikacja demonstracyjna](https://forum.lazarus.freepascal.org/index.php/topic,48677.0.html)
1178+
1179+## Linki zewnętrzne
1180+
1181+- [Oficjalna strona](http://www.ararat.cz/synapse/)
1182+- [Oficjalna dokumentacja](http://synapse.ararat.cz/doc/help/)
1183+- [Użytkownik malcome stworzył rozwidlenie, aby szybciej poprawić synapse](http://lazarus.freepascal.org/index.php/topic,16032.msg87066.html#msg87066); ta gałąź znajduje się pod adresem ~~[Witryna z kodem Google dla Synapse4Lazarus](http://code.google.com/p/synapse4lazarus/)~~ (aktualnie niedostępna)
1184+
1185+---
1186+*From the Free Pascal wiki, page "Synapse/pl", as it stood on 2022-07-23 after a change by Slawek, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history