Sign in Join
Wiki copytemporary

Synapse/pl: what changed

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

OldNewLine
11Synapse ułatwia użycie portu szeregowego i dostarcza synchroniczną bibliotekę TCP/IP.
22
33## Przegląd
44
55Synapse 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.
66
77Zobacz dokumentację na oficjalnej stronie (link poniżej), aby uzyskać więcej informacji.
88
99## Instalacja
1010
1111Instalacja może być tak prosta, jak po prostu skopiowanie wszystkich plików do katalogu aplikacji i dodanie odpowiednich modułów Synapse do klauzuli *uses*.
1212
1313Bardziej 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.
1414
1515Strona informacyjna pobierania/SVN Synapse: [Strona pobierania Synapse](http://www.ararat.cz/synapse/doku.php/download)
1616
1717## Wsparcie i zgłaszanie błędów
1818
1919Projekt Synapse posiada listę mailingową, na której udzielane jest wsparcie i można przesyłać łatki.
2020
2121Raporty o błędach można również przesyłać pocztą na listę dyskusyjną.
2222
2323Zobacz [strona pomocy Synapse](http://www.ararat.cz/synapse/doku.php/support)
2424
2525## Obsługa SSL/TLS
2626
2727Z Synapse możesz korzystać z obsługi OpenSSL, CryptLib, StreamSecII lub OpenStreamSecII SSL. Domyślnie nie jest używana obsługa SSL.
2828
2929Wsparcie 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).
3030
3131Synapse ładuje pliki bibliotek SSL w środowisku wykonawczym jako biblioteki dynamiczne.
3232
3333- Szczegółowe informacje można znaleźć na stronie [Architektura wtyczek SSL/TLS](http://www.ararat.cz/synapse/doku.php/public:howto:sslplugin)
3434- Niektóre biblioteki kryptograficzne można uzyskać pod adresem: <http://synapse.ararat.cz/files/crypt/>
3535
3636### Brakująca biblioteka
3737
3838W 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:
3939
40-`/usr/bin/ld: cannot find -lcl`
40+```text
41+/usr/bin/ld: cannot find -lcl
42+```
4143
4244Podobny komunikat zostanie wyświetlony podczas korzystania z innych bibliotek dynamicznych.
4345
4446## Przykład serwera WWW
4547
4648Zobacz ten [[Networking|przykład serwera internetowego (www)]].
4749
4850## Przykład zapytania serwera QOTD
4951
5052Zobacz ten [[QOTD|przykład zapytania serwera - Cytat dnia]].
5153
5254## Wysyłanie email
5355
5456Artykuł opisujący wysyłanie e-maili wraz z załącznikami za pomocą Synapse: <http://www.freepascal.org/~michael/articles/lazmail/lazmail-en.pdf>
5557
5658Przykł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?):
5759
5860``` pascal
5961{Ten kod obsługuje szyfrowanie TLS/SSL; jeśli wysyłasz do portu 25, SMTP używa zwykłego tekstu.}
6062
6163uses
6264 ..., smtpsend,ssl_openssl; //prawdopodobnie można użyć również inne moduły SSL.
6365
6466// MailData to tekst wiadomości.
6567function SendMail(
6668 User, Password,
6769 MailFrom, MailTo,
6870 SMTPHost, SMTPPort: string;
6971 MailData: string): Boolean;
7072var
7173 SMTP: TSMTPSend;
7274 sl:TStringList;
7375begin
7476 Result:=False;
7577 SMTP:=TSMTPSend.Create;
7678 sl:=TStringList.Create;
7779 try
7880 sl.text:=Maildata;
7981 SMTP.UserName:=User;
8082 SMTP.Password:=Password;
8183 SMTP.TargetHost:=SMTPHost;
8284 SMTP.TargetPort:=SMTPPort;
8385 SMTP.AutoTLS:=true;
8486 if Trim(SMTPPort)<>'25' then
8587 SMTP.FullSSL:=true; // jeśli wysyłasz na port 25, nie używaj szyfrowania
8688 if SMTP.Login then
8789 begin
8890 result:=SMTP.MailFrom(MailFrom, Length(MailData)) and
8991 SMTP.MailTo(MailTo) and
9092 SMTP.MailData(sl);
9193 SMTP.Logout;
9294 end;
9395 finally
9496 SMTP.Free;
9597 sl.Free;
9698 end;
9799end;
98100```
99101
100102### Wysyłanie załączników
101103
102104Proszę zapoznać się z tą [dokumentacją Synapse](http://synapse.ararat.cz/doku.php/public:howto:tmimepart).
103105
104106## Pobieranie plików
105107
106108### Z serwera FTP
107109
108110Po 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:
109111
110112``` pascal
111113FtpGetFile
112114```
113115
114116zaprowadzi cię bardzo daleko.
115117
116118``` pascal
117119function DownloadFTP(URL, TargetFile: string): boolean;
118120const
119121 FTPPort=21;
120122 FTPScheme='ftp://'; //Nazwa schematu URI dla adresów URL FTP
121123var
122124 Host: string;
123125 Port: integer;
124126 Source: string;
125127 FoundPos: integer;
126128begin
127129 // Usuń informacje o schemacie:
128130 if LeftStr(URL, length(FTPScheme))=FTPScheme then URL:=Copy(URL, length(FTPScheme)+1, length(URL));
129131
130132 // Surowa analiza; można użyć kodu parsującego URI z pakietów FPC...
131133 FoundPos:=pos('/', URL);
132134 Host:=LeftStr(URL, FoundPos-1);
133135 Source:=Copy(URL, FoundPos+1, Length(URL));
134136
135137 //Sprawdź numery portów:
136138 FoundPos:=pos(':', Host);
137139 Port:=FTPPort;
138140 if FoundPos>0 then
139141 begin
140142 Host:=LeftStr(Host, FoundPos-1);
141143 Port:=StrToIntDef(Copy(Host, FoundPos+1, Length(Host)),21);
142144 end;
143145 Result:=FtpGetFile(Host, IntToStr(Port), Source, TargetFile, 'anonymous', 'fpc@example.com');
144146 if result=false then writeln('DownloadFTP: error downloading '+URL+'. Details: host: '+Host+'; port: '+Inttostr(Port)+'; remote path: '+Source+' to '+TargetFile);
145147end;
146148```
147149
148150Przykład pobrania listy plików dostępnych w podanej ścieżce
149151
150152``` pascal
151153//Użyj modułu ftpsend
152154
153155function FtpGetDir(const IP, Port, Path, User, Pass: string; DirList: TStringList): Boolean;
154156var
155157 i: Integer;
156158 s: string;
157159begin
158160 Result := False;
159161 with TFTPSend.Create do
160162 try
161163 Username := User;
162164 Password := Pass;
163165 TargetHost := IP;
164166 TargetPort := Port;
165167 if not Login then
166168 Exit;
167169 Result := List(Path, False);
168170 for i := 0 to FtpList.Count -1 do
169171 begin
170172 s := FTPList[i].FileName;
171173 DirList.Add(s);
172174 end;
173175 Logout;
174176 finally
175177 Free;
176178 end;
177179end;
178180```
179181
180182### Z serwera HTTP
181183
182184Po 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.
183185
184186#### Wersja prosta
185187
186188``` pascal
187189...
188190uses httpsend,
189191...
190192function DownloadHTTP(URL, TargetFile: string): Boolean;
191193var
192194 HTTPGetResult: Boolean;
193195 HTTPSender: THTTPSend;
194196begin
195197 Result := False;
196198 HTTPSender := THTTPSend.Create;
197199 try
198200 HTTPGetResult := HTTPSender.HTTPMethod('GET', URL);
199201 if (HTTPSender.ResultCode >= 100) and (HTTPSender.ResultCode<=299) then begin
200202 HTTPSender.Document.SaveToFile(TargetFile);
201203 Result := True;
202204 end;
203205 finally
204206 HTTPSender.Free;
205207 end;
206208end;
207209```
208210
209211#### Wersja zaawansowana
210212
211213``` pascal
212214...
213215uses httpsend
214216...
215217function DownloadHTTP(URL, TargetFile: string): Boolean;
216218// Pobieranie pliku; w razie potrzeby spróbuj ponownie.
217219// Można próbować użyć funkcji Synapse HttpGetBinary, ale to nie działa
218220// z kodami wyników (tzn. szczęśliwie pobiera dokument błędu 404)
219221const
220222 MaxRetries = 3;
221223var
222224 HTTPGetResult: Boolean;
223225 HTTPSender: THTTPSend;
224226 RetryAttempt: Integer;
225227begin
226228 Result := False;
227229 RetryAttempt := 1;
228230 HTTPSender := THTTPSend.Create;
229231 try
230232 try
231233 // Spróbuj pobrać plik
232234 HTTPGetResult := HTTPSender.HTTPMethod('GET', URL);
233235 while (HTTPGetResult = False) and (RetryAttempt < MaxRetries) do
234236 begin
235237 Sleep(500 * RetryAttempt);
236238 HTTPSender.Clear;
237239 HTTPGetResult := HTTPSender.HTTPMethod('GET', URL);
238240 RetryAttempt := RetryAttempt + 1;
239241 end;
240242 // Jeśli mamy odpowiedź z serwera, sprawdź, czy plik został do nas wysłany.
241243 case HTTPSender.Resultcode of
242244 100..299:
243245 begin
244246 HTTPSender.Document.SaveToFile(TargetFile);
245247 Result := True;
246248 end; //informational, success
247249 300..399: Result := False; // przekierowanie. Nie zaimplementowano, ale może się zdarzyć.
248250 400..499: Result := False; // błąd klienta; 404 nie znaleziono itp.
249251 500..599: Result := False; // wewnętrzny błąd serwera
250252 else Result := False; // kod nieznany
251253 end;
252254 except
253255 // Nie obchodzi nas przyczyna tego błędu; pobieranie nie powiodło się.
254256 Result := False;
255257 end;
256258 finally
257259 HTTPSender.Free;
258260 end;
259261end;
260262```
261263
262264#### Prosta wersja z paskiem postępu
263265
264266Poniż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.
265267
266268> **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
267269
268270``` pascal
269271unit uhttpdownloader;
270272
271273{$mode objfpc}{$H+}
272274
273275interface
274276
275277uses
276278 Classes, SysUtils, httpsend, blcksock, typinfo;
277279
278280type
279281 IProgress = interface
280282 procedure ProgressNotification(Text: String; CurrentProgress : integer; MaxProgress : integer);
281283 end;
282284
283285type
284286 { THttpDownloader }
285287
286288 THttpDownloader = class
287289 public
288290 function DownloadHTTP(URL, TargetFile: string; ProgressMonitor : IProgress): Boolean;
289291 private
290292 Bytes : Integer;
291293 MaxBytes : Integer;
292294 HTTPSender: THTTPSend;
293295 ProgressMonitor : IProgress;
294296 procedure Status(Sender: TObject; Reason: THookSocketReason; const Value: String);
295297 function GetSizeFromHeader(Header: String):integer;
296298 end;
297299
298300implementation
299301
300302function THttpDownloader.DownloadHTTP(URL, TargetFile: string; ProgressMonitor : IProgress): Boolean;
301303var
302304 HTTPGetResult: Boolean;
303305begin
304306 Result := False;
305307 Bytes:= 0;
306308 MaxBytes:= -1;
307309 Self.ProgressMonitor:= ProgressMonitor;
308310
309311 HTTPSender := THTTPSend.Create;
310312 try
311313 HTTPSender.Sock.OnStatus:= Status;
312314 HTTPGetResult := HTTPSender.HTTPMethod('GET', URL);
313315 if (HTTPSender.ResultCode >= 100) and (HTTPSender.ResultCode<=299) then begin
314316 HTTPSender.Document.SaveToFile(TargetFile);
315317 Result := True;
316318 end;
317319 finally
318320 HTTPSender.Free;
319321 end;
320322end;
321323
322324procedure THttpDownloader.Status(Sender: TObject; Reason: THookSocketReason; const Value: String);
323325var
324326 V, currentHeader: String;
325327 i: integer;
326328begin
327329 //spróbuj pobrać rozmiar pliku z nagłówków
328330 if (MaxBytes = -1) then
329331 begin
330332 for i:= 0 to HTTPSender.Headers.Count - 1 do
331333 begin
332334 currentHeader:= HTTPSender.Headers[i];
333335 MaxBytes:= GetSizeFromHeader(currentHeader);
334336 if MaxBytes <> -1 then break;
335337 end;
336338 end;
337339
338340 V := GetEnumName(TypeInfo(THookSocketReason), Integer(Reason)) + ' ' + Value;
339341
340342 if Reason = THookSocketReason.HR_ReadCount then
341343 begin
342344 Bytes:= Bytes + StrToInt(Value);
343345 ProgressMonitor.ProgressNotification(V, Bytes, MaxBytes);
344346 end;
345347end;
346348
347349function THttpDownloader.GetSizeFromHeader(Header: String): integer;
348350var
349351 item : TStringList;
350352begin
351353 Result:= -1;
352354
353355 if Pos('Content-Length:', Header) <> 0 then
354356 begin
355357 item:= TStringList.Create();
356358 item.Delimiter:= ':';
357359 item.StrictDelimiter:=true;
358360 item.DelimitedText:=Header;
359361 if item.Count = 2 then
360362 begin
361363 Result:= StrToInt(Trim(item[1]));
362364 end;
363365 end;
364366end;
365367
366368end.
367369```
368370
369371Co my tu robimy?
370372
371373Przede 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.
372374
373375Po 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.
374376
375377„HR_ReadCount” dostarcza nam informacji ile bajtów zostało odczytanych od ostatniego zdarzenia.
376378
377379Postęp jest następnie zgłaszany do interfejsu użytkownika:
378380
379381``` pascal
380382procedure TMainForm.ProgressNotification(Text: String; CurrentProgress: integer; MaxProgress: integer);
381383begin
382384 if (MaxProgress <> -1) then
383385 begin
384386 ProgressBar.Max:= MaxProgress;
385387 end;
386388
387389 ProgressBar.Position:= CurrentProgress;
388390 memoStatus.Lines.Add(Text);
389391 Application.ProcessMessages;
390392end;
391393```
392394
393395Tak więc ostatecznym głównym modułem będzie:
394396
395397``` pascal
396398unit uMain;
397399
398400{$mode objfpc}{$H+}
399401
400402interface
401403
402404uses
403405 Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls, httpsend, blcksock, typinfo,
404406 uhttpdownloader;
405407
406408type
407409
408410 { TMainForm }
409411
410412 TMainForm = class(TForm, IProgress)
411413 btnStartDownload: TButton;
412414 edtUrl: TEdit;
413415 labelUrl: TLabel;
414416 memoStatus: TMemo;
415417 ProgressBar: TProgressBar;
416418 SaveDialog: TSaveDialog;
417419 procedure btnStartDownloadClick(Sender: TObject);
418420 private
419421 { private declarations }
420422 function GetFileNameFromURL(url: String):string;
421423 public
422424 { public declarations }
423425 procedure ProgressNotification(Text: String; CurrentProgress : integer; MaxProgress : integer);
424426 end;
425427
426428var
427429 MainForm: TMainForm;
428430
429431implementation
430432
431433{$R *.lfm}
432434
433435{ TMainForm }
434436
435437procedure TMainForm.btnStartDownloadClick(Sender: TObject);
436438var
437439 fileName: String;
438440 downloader: THttpDownloader;
439441 success: boolean;
440442begin
441443 fileName:= GetFileNameFromURL(edtUrl.Text);
442444 SaveDialog.FileName:=fileName;
443445 if (SaveDialog.Execute) then
444446 begin
445447 memoStatus.Lines.Clear;
446448 ProgressBar.Position:=0;
447449 downloader:= THttpDownloader.Create();
448450 success:= downloader.DownloadHTTP(edtUrl.Text, SaveDialog.FileName, Self);
449451
450452 ProgressBar.Position:=0;
451453 if Success then
452454 memoStatus.Lines.Add('Download successful')
453455 else
454456 memoStatus.Lines.Add('Error during download');
455457
456458 end;
457459end;
458460
459461function TMainForm.GetFileNameFromURL(url: String): string;
460462var i, l : integer;
461463 fileName, current : String;
462464begin
463465 fileName:= '';
464466 l:= Length(url);
465467 for i:= l downto 0 do begin
466468 current:= url[i];
467469 if current <> '/' then
468470 begin
469471 fileName:= current + fileName;
470472 end else begin
471473 Result:= fileName;
472474 break;
473475 end;
474476 end;
475477end;
476478
477479procedure TMainForm.ProgressNotification(Text: String; CurrentProgress: integer; MaxProgress: integer);
478480begin
479481 if (MaxProgress <> -1) then ProgressBar.Max:= MaxProgress;
480482 ProgressBar.Position:= CurrentProgress;
481483 memoStatus.Lines.Add(Text);
482484 Application.ProcessMessages;
483485end;
484486
485487end.
486488```
487489
488490Odnosnik: <https://andydunkel.net/2015/09/09/lazarus_synapse_progress/>
489491
490492#### Z serwera HTTP przez parsowanie adresów URL: Sourceforge
491493
492494Zobacz [[Download from SourceForge|Pobieranie z SourceForge]], aby zapoznać się z przykładem pobierania z sourceforge.net.
493495
494496### Z serwera HTTPS
495497
496498Jest 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://>**.
497499
498500## Przykładowy program klienta SSH/Telnet
499501
500502Poniż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.
501503
502504### Wymagania
503505
504506Opró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.
505507
506508Istnieją 2 możliwości:
507509
508510- 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.
509511- 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).
510512
511513#### Cryptlib
512514
513515- 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.
514516- 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.
515517
516518Będziesz także potrzebował dowiązań (cryptlib.pas), obecnych w źródłach dystrybucji cryptlib.
517519
518520Wersje pliku binarnego cryptlib i dowiązania muszą być zgodne.
519521
520522> **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.
521523
522524#### LibSSH2
523525
524526- 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.
525527- W systemach Linux i macOS zainstaluj libssh2 za pomocą menedżera pakietów lub z innych środków. Ponadto dystrybuując swoją aplikację:
526528 - Linux: oznacz libssh2 jako wymaganie w swoim pakiecie .deb/.rpm/inny.
527529 - macOS: dołącz libssh2 do katalogu zasobów [[Application Bundle|Pakietu aplikacji]].
528530
529531Bę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.
530532
531533### Wtyczka Synapse libssh2 SSL
532534
533535> **Note:** Wtyczka nie jest ukończona.
534536
535537``` pascal
536538{
537539 ssl_libssh2.pas wersja 0.2
538540
539541 Wtyczka obsługi SSH2 (zarys) dla biblioteki Synapse (http://www.ararat.cz/synapse) do LibSSH2 (http://libssh2.org)
540542 Wymaga: interfejsu libssh2 pascal - http://www.lazarus.freepascal.org/index.php/topic,15935.msg86465.html#msg86465 oraz
541543 libssh2.dll z OpenSSL.
542544
543545 (С) Alexey Suhinin http://x-alexey.narod.ru
544546}
545547
546548{$IFDEF FPC}
547549 {$MODE DELPHI}
548550{$ENDIF}
549551{$H+}
550552
551553unit ssl_libssh2;
552554
553555interface
554556
555557uses
556558 SysUtils,
557559 blcksock, synsock,
558560 libssh2;
559561
560562type
561563 {:@abstract(klasa implementująca wtyczkę CryptLib SSL/SSH.)
562564 Instancja tej klasy zostanie utworzona dla każdego @link(TTCPBlockSocket).
563565 Nie musisz tworzyć instancji tej klasy, wszystko robi sam Synapse!}
564566 TSSLLibSSH2 = class(TCustomSSL)
565567 protected
566568 FSession: PLIBSSH2_SESSION;
567569 FChannel: PLIBSSH2_CHANNEL;
568570 function SSHCheck(Value: integer): Boolean;
569571 function DeInit: Boolean;
570572 public
571573 {:Zobacz @inherited}
572574 constructor Create(const Value: TTCPBlockSocket); override;
573575 destructor Destroy; override;
574576 function Connect: boolean; override;
575577 function LibName: String; override;
576578 function Shutdown: boolean; override;
577579 {:Zobacz @inherited}
578580 function BiShutdown: boolean; override;
579581 {:Zobacz @inherited}
580582 function SendBuffer(Buffer: TMemory; Len: Integer): Integer; override;
581583 {:Zobacz @inherited}
582584 function RecvBuffer(Buffer: TMemory; Len: Integer): Integer; override;
583585 {:Zobacz @inherited}
584586 function WaitingData: Integer; override;
585587 {:Zobacz @inherited}
586588 function GetSSLVersion: string; override;
587589 published
588590 end;
589591
590592implementation
591593
592594{==============================================================================}
593595function TSSLLibSSH2.SSHCheck(Value: integer): Boolean;
594596var
595597 PLastError: PAnsiChar;
596598 ErrMsgLen: Integer;
597599begin
598600 Result := true;
599601 FLastError := 0;
600602 FLastErrorDesc := '';
601603 if Value<0 then
602604 begin
603605 FLastError := libssh2_session_last_error(FSession, PLastError, ErrMsglen, 0);
604606 FLastErrorDesc := PLastError;
605607 Result := false;
606608 end;
607609end;
608610
609611function TSSLLibSSH2.DeInit: Boolean;
610612begin
611613 if Assigned(FChannel) then
612614 begin
613615 libssh2_channel_free(FChannel);
614616 FChannel := nil;
615617 end;
616618 if Assigned(FSession) then
617619 begin
618620 libssh2_session_disconnect(FSession,'Goodbye');
619621 libssh2_session_free(FSession);
620622 FSession := nil;
621623 end;
622624 FSSLEnabled := False;
623625 Result := true;
624626end;
625627
626628constructor TSSLLibSSH2.Create(const Value: TTCPBlockSocket);
627629begin
628630 inherited Create(Value);
629631 FSession := nil;
630632 FChannel := nil;
631633end;
632634
633635destructor TSSLLibSSH2.Destroy;
634636begin
635637 DeInit;
636638 inherited Destroy;
637639end;
638640
639641function TSSLLibSSH2.Connect: boolean;
640642begin
641643 Result := False;
642644 if SSLEnabled then DeInit;
643645 if (FSocket.Socket <> INVALID_SOCKET) and (FSocket.SSL.SSLType = LT_SSHv2) then
644646 begin
645647 FSession := libssh2_session_init();
646648 if not Assigned(FSession) then
647649 begin
648650 FLastError := -999;
649651 FLastErrorDesc := 'Cannot initialize SSH session';
650652 exit;
651653 end;
652654 if not SSHCheck(libssh2_session_startup(FSession, FSocket.Socket)) then
653655 exit;
654656 if (FSocket.SSL.PrivateKeyFile<>'') then
655657 begin
656658 if (not SSHCheck(libssh2_userauth_publickey_fromfile(FSession, PChar(FSocket.SSL.Username), nil, PChar(FSocket.SSL.PrivateKeyFile), PChar(FSocket.SSL.KeyPassword)))) then
657659 exit;
658660 end
659661 else
660662 if (FSocket.SSL.Username<>'') and (FSocket.SSL.Password<>'') then
661663 begin
662664 if (not SSHCheck(libssh2_userauth_password(FSession, PChar(FSocket.SSL.Username), PChar(FSocket.SSL.Password)))) then
663665 exit;
664666 end;
665667 FChannel := libssh2_channel_open_session(FSession);
666668 if not assigned(FChannel) then
667669 begin
668670 SSHCheck(-1); // get error
669671 if FLastError = 0 then
670672 begin
671673 FLastError := -999; // unknown error
672674 FLastErrorDesc := 'Cannot open session';
673675 end;
674676 exit;
675677 end;
676678 if not SSHCheck(libssh2_channel_request_pty(FChannel, 'vanilla')) then
677679 exit;
678680 if not SSHCheck(libssh2_channel_shell(FChannel)) then
679681 exit;
680682 FSSLEnabled := True;
681683 Result := True;
682684 end;
683685end;
684686
685687function TSSLLibSSH2.LibName: String;
686688begin
687689 Result := 'ssl_libssh2';
688690end;
689691
690692function TSSLLibSSH2.Shutdown: boolean;
691693begin
692694 Result := DeInit;
693695end;
694696
695697function TSSLLibSSH2.BiShutdown: boolean;
696698begin
697699 Result := DeInit;
698700end;
699701
700702function TSSLLibSSH2.SendBuffer(Buffer: TMemory; Len: Integer): Integer;
701703begin
702704 Result:=libssh2_channel_write(FChannel, PChar(Buffer), Len);
703705 SSHCheck(Result);
704706end;
705707
706708function TSSLLibSSH2.RecvBuffer(Buffer: TMemory; Len: Integer): Integer;
707709begin
708710 result:=libssh2_channel_read(FChannel, PChar(Buffer), Len);
709711 SSHCheck(Result);
710712end;
711713
712714function TSSLLibSSH2.WaitingData: Integer;
713715begin
714716 if libssh2_poll_channel_read(FChannel, Result) <> 1 then Result := 0;
715717end;
716718
717719function TSSLLibSSH2.GetSSLVersion: string;
718720begin
719721 Result:=libssh2_version(0);
720722end;
721723
722724initialization
723725 if libssh2_init(0)=0 then
724726 SSLImplementation := TSSLLibSSH2;
725727
726728finalization
727729 libssh2_exit;
728730
729731end.
730732```
731733
732734### Klasa klienta terminala
733735
734736Poniższy moduł telnetsshclient.pas wykorzystuje moduł Synapse tlntsend.pas i opisuje logowanie, wysyłanie poleceń, odbieranie danych wyjściowych i wylogowywanie.
735737
736738Jeś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.
737739
738740To urządzenie zostało lekko przetestowane na serwerze Linux ssh/telnet. Dodatkowe testy mile widziane.
739741
740742``` pascal
741743unit telnetsshclient;
742744
743745{ Wrapper wokół bibliotek Synapse i biblioteki SSL (obecnie używane są libssh2+libssl)
744746Pobierz skompilowaną bibliotekę Windows dll, np. z
745747http://alxdm.dyndns-at-work.com:808/files/windll_libssh2.zip
746748Pobierz pliki interfejsu FreePascal:
747749http://www.lazarus.freepascal.org/index.php/topic,15935.msg86465.html#msg86465
748750
749751Ten moduł umożliwia użytkownikowi wysyłanie poleceń Telnet lub SSH i uzyskiwanie danych wyjściowych
750752Dzięki Leonardo Rame
751753http://leonardorame.blogspot.com/2010/01/synapse-based-ssh-client.html
752754i Ludo Brands.
753755
754756Napisany przez Reiniera Olislagersa 2011.
755757Zmodyfikowany dla libssh2 przez Alexeya Suhinina 2012.
756758
757759Licencja kodu:
758760* MIT
759761* LGPLv2 lub nowszy (z wyjątkiem statycznego linkowania FreePascal)
760762* GPLv2 lub nowszy
761763zgodnie z twoim wyborem.
762764Dozwolone jest bezpłatne korzystanie, ale proszę nie pozywać mnie ani nie obwiniać.
763765
764766Korzysta z innych bibliotek/komponentów, dla których mogą obowiązywać różne licencje, które również mogą wpływać na skompilowaną pracę.
765767}
766768
767769{$mode objfpc}{$H+}
768770{$DEFINE HAS_SSH_SUPPORT} //zakomentuj, jeśli wymagana jest tylko obsługa telnet
769771{$DEFINE LIBSSH2}
770772
771773interface
772774
773775uses
774776 Classes, SysUtils,
775777 tlntsend
776778 {$IFDEF HAS_SSH_SUPPORT}
777779 {ssl - a właściwie teraz ssh - biblioteki wymagane przez tlntsend}
778780 {$IFDEF LIBSSH2}
779781 ssl_libssh2
780782 {$ELSE}
781783 ssl_cryptlib
782784 {$ENDIF}
783785 {$ENDIF HAS_SSH_SUPPORT} ;
784786
785787type
786788 TProtocolType = (Telnet, SSH); //Różne sposoby łączenia
787789 TServerType = (Unix, Windows); //głównie dotyczy zakończenia linii tekstu
788790 { TelnetSSHClient }
789791
790792 { TTelnetSSHClient }
791793
792794 TTelnetSSHClient = class(TTelnetSend)
793795 protected
794796 FConnected: boolean;
795797 FOutputPosition: integer; //Śledzi pozycję w strumieniu wyjściowym
796798 FProtocolType: TProtocolType;
797799 FServerLineEnding: string; //zależy od FServerType
798800 FServerType: TServerType;
799801 FWelcomeMessage, FTelnetLoginPrompt, FTelnetPasswordPrompt: string;
800802 procedure SetPrivateKeyFile(Value: string);
801803 function GetPrivateKeyFile: string;
802804 { Na podstawie protokołu i typu serwera ustaw oczekiwane zakończenie linii po stronie serwera}
803805 procedure DetermineLineEnding;
804806 { Ustawia port, jeśli portu nie ustawiono jawnie. Używa protokołu typu: SSH lub telnet}
805807 procedure DeterminePort;
806808 function GetSessionLog: string;
807809 procedure ProtocolTypeChange(Value: TProtocolType);
808810 function ReceiveData: string; //Może być używany do odbierania wiadomości powitalnej itp.
809811 procedure SendData(Data: string);
810812 procedure ServerTypeChange(Value: TServerType);
811813 public
812814 {Wszystkie dane wyjściowe wygenerowane podczas całej sesji do tej pory}
813815 property AllOutput: string read GetSessionLog;
814816 {Ma wartość True, jeśli jest podłączony do serwera}
815817 property Connected: boolean read FConnected;
816818 {Nazwa lub adres IP hosta, z którym chcesz się połączyć}
817819 property HostName: string read FTargetHost write FTargetHost;
818820 {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}
819821 property Port: String read FTargetPort write FTargetPort;
820822 {Lokalizacja pliku klucza prywatnego}
821823 property PrivateKeyFile: string read GetPrivateKeyFile write SetPrivateKeyFile;
822824 {Pytanie o login Telnet}
823825 property TelnetLoginPrompt: string read FTelnetLoginPrompt write FTelnetLoginPrompt;
824826 {Pytanie o hasło Telnet}
825827 property TelnetPasswordPrompt: string read FTelnetPasswordPrompt write FTelnetPasswordPrompt;
826828 {Nazwa użytkownika używana podczas łączenia}
827829 property UserName: string read FUserName write FUserName;
828830 {Hasło używane podczas łączenia. Używane jako hasło (passphrase), jeśli używany jest klucz prywatny}
829831 property Password: string read FPassword write FPassword;
830832 {Czy powinniśmy rozmawiać z serwerem przez Telnet czy SSH? Domyślnie jest to SSH}
831833 property ProtocolType: TProtocolType read FProtocolType write ProtocolTypeChange;
832834 {Serwer Windows czy Unix/Linux? Ma to wpływ na końcówki linii. Domyślnie jest to Unix. UWAGA: nieprzetestowane}
833835 property Servertype: TServerType read FServerType write ServerTypeChange;
834836 {Pierwsza wiadomość wyświetlana przy logowaniu}
835837 property WelcomeMessage: string read FWelcomeMessage;
836838 {Połącz/zaloguj się do serwera. Wymaga poprawnych wszystkich opcji uwierzytelniania, protokołu i nazwy hosta/portu.
837839 Zwraca opisowy wynik. Następnie możesz użyć właściwości Connected.}
838840 function Connect: string;
839841 {Jeśli połączony, wyloguj się z serwera}
840842 procedure Disconnect;
841843 {Wyślij polecenie do serwera i odbierz wynik}
842844 function CommandResult(Command: string): string; //Wyślij polecenie i uzyskaj wyniki
843845 constructor Create;
844846 destructor Destroy; override;
845847 end;
846848
847849implementation
848850
849851
850852{ TelnetSSHClient }
851853procedure TTelnetSSHClient.SetPrivateKeyFile(value: string);
852854begin
853855 Sock.SSL.PrivateKeyFile := value;
854856end;
855857
856858function TTelnetSSHClient.GetPrivateKeyFile: string;
857859begin
858860 Result := Sock.SSL.PrivateKeyFile;
859861end;
860862
861863procedure TTelnetSSHClient.DetermineLineEnding;
862864begin
863865 case FProtocolType of
864866 SSH:
865867 begin
866868 if FServerType = Unix then
867869 FServerLineEnding := #10 //Unix
868870 else
869871 FServerLineEnding := #13 + #10; //windows
870872 end;
871873 Telnet:
872874 begin
873875 if FServerType = Unix then
874876 FServerLineEnding := #10 //Unix
875877 else
876878 FServerLineEnding := #13 + #10; //windows
877879 end;
878880 else
879881 raise Exception.Create('Nieznany typ protokołu.');
880882 end;
881883end;
882884
883885procedure Ttelnetsshclient.DeterminePort;
884886begin
885887 if FTargetPort = '' then
886888 //Ustaw domyślny port dla protokołu
887889 begin
888890 case FProtocolType of
889891 Telnet: FTargetPort := '23';
890892 SSH: FTargetPort := '22';
891893 else
892894 raise Exception.Create('Nieznany typ protokołu.');
893895 end;
894896
895897 end;
896898end;
897899
898900procedure TTelnetSSHClient.ServerTypeChange(Value: Tservertype);
899901begin
900902 FServerType := Value;
901903 DetermineLineEnding;
902904end;
903905
904906function TTelnetSSHClient.Connect: string;
905907var
906908 Received: string;
907909begin
908910 result:='Nieznany błąd podczas łączenia';
909911 FOutputPosition := 1; //Pierwszy znak w strumieniu wyjściowym
910912 FWelcomeMessage := '';
911913 //Tylko dla pewności:
912914 DetermineLineEnding;
913915 DeterminePort;
914916 if FTargetPort='0' then
915917 begin
916918 result:='Port nie może być równy 0.';
917919 exit; //wyskoczyć z funkcji
918920 end;
919921 case FProtocolType of
920922 Telnet:
921923 begin
922924 try
923925 if Login then
924926 begin
925927 FConnected := True;
926928 result:='Połączono z serwerem telnet.';
927929 end
928930 else
929931 if Sock.LastError<>0 then raise Exception.Create(Sock.LastErrorDesc);
930932 except
931933 on E: Exception do
932934 begin
933935 FConnected:=false;
934936 result:='Błąd połączenia z serwerem telnet '+FTargetHost+':'+
935937 FTargetPort+' jako użytkownik ' + FUserName +
936938 '. Szczegóły techniczne: '+E.Message;
937939 end;
938940 end;
939941 end;
940942 SSH:
941943 begin
942944 {$IFNDEF HAS_SSH_SUPPORT}
943945 raise Exception.Create(
944946 'Obsługa SSH nie została skompilowana do biblioteki telnetsshclient.');
945947 {$ENDIF HAS_SSH_SUPPORT}
946948 try
947949 if (PrivateKeyFile <> '') and (FPassword <> '') then
948950 Sock.SSL.KeyPassword:=FPassword;
949951 if SSHLogin then
950952 begin
951953 FConnected := True;
952954 result:='Connected to SSH server.';
953955 end
954956 else
955957 begin
956958 if Sock.LastError<>0 then raise Exception.Create(Sock.LastErrorDesc);
957959 if Sock.SSL.LastError<0 then raise Exception.Create(Sock.SSL.LastErrorDesc);
958960 end;
959961 except
960962 on E: Exception do
961963 begin
962964 FConnected:=false;
963965 result:='Błąd połączenia z serwerem SSH '+FTargetHost+':'+
964966 FTargetPort+' jako użytkownik ' + FUserName +
965967 '. Szczegóły techniczne: '+E.Message;
966968 end;
967969 end;
968970 end;
969971 else
970972 raise Exception.Create('Nieznany typ protokołu.');
971973 end;
972974 if FConnected = True then
973975 begin
974976 FWelcomeMessage := ReceiveData;
975977 if FProtocolType=Telnet then
976978 begin
977979 //Niestety, będziemy musieli sami wyodrębnić login
978980 //Mam nadzieję, że dotyczy to wszystkich typów serwerów.
979981 if (AnsiPos(AnsiLowerCase(FTelnetLoginPrompt),AnsiLowerCase(FWelcomeMessage))>0) then
980982 begin
981983 SendData(UserName);
982984 end;
983985 Received:=ReceiveData;
984986 if (AnsiPos(AnsiLowerCase(FTelnetPasswordPrompt),AnsiLowerCase(Received))>0) then
985987 begin
986988 SendData(Password);
987989 end;
988990 //Otrzymuj dodatkową wiadomość powitalną/wiadomość dnia
989991 FWelcomeMessage:=FWelcomeMessage+LineEnding+ReceiveData;
990992 end;
991993 end;
992994end;
993995
994996procedure TTelnetSSHClient.Disconnect;
995997begin
996998 Logout;
997999 FConnected := False;
9981000end;
9991001
10001002function TTelnetSSHClient.ReceiveData: string;
10011003begin
10021004 Result := '';
10031005 while Sock.CanRead(1000) or (Sock.WaitingData > 0) do
10041006 begin
10051007 Sock.RecvPacket(1000);
10061008 Result := Result + Copy(SessionLog, FOutputPosition,
10071009 Length(SessionLog));
10081010 FOutputPosition := Length(SessionLog) + 1;
10091011 end;
10101012end;
10111013
10121014procedure Ttelnetsshclient.SendData(Data: String);
10131015begin
10141016 Data := Data + FServerLineEnding; //Może to być linux, może być Windows
10151017 Send(Data);
10161018end;
10171019
10181020function TTelnetSSHClient.GetSessionLog: string;
10191021begin
10201022 // Do tej pory uzyskuje pełne dane wyjściowe
10211023 Result := SessionLog;
10221024end;
10231025
10241026procedure TTelnetSSHClient.ProtocolTypeChange(Value: Tprotocoltype);
10251027begin
10261028 FProtocolType := Value;
10271029 //W razie potrzeby automatycznie określ port i zakończenie linii
10281030 DeterminePort;
10291031 DetermineLineEnding;
10301032end;
10311033
10321034function TTelnetSSHClient.CommandResult(Command: string): string;
10331035begin
10341036 Result := '';
10351037 if FConnected then
10361038 begin
10371039 SendData(Command);
10381040 Result := ReceiveData; //dostaje za dużo
10391041 end
10401042 else
10411043 begin
10421044 //podnieś wyjątek
10431045 Result := '';
10441046 raise Exception.Create('Polecenie można uruchomić tylko po podłączeniu');
10451047 end;
10461048end;
10471049
10481050constructor TTelnetSSHClient.Create;
10491051begin
10501052 inherited;
10511053 FConnected := False;
10521054 FProtocolType := SSH; //Może to też być telnet
10531055 FServerType := Unix; //Prawdopodobnie bezpieczna wartość domyślna.
10541056 FTelnetLoginPrompt := 'login:';
10551057 FTelnetPasswordPrompt := 'password:';
10561058 DetermineLineEnding;
10571059 DeterminePort;
10581060end;
10591061
10601062destructor TTelnetSSHClient.Destroy;
10611063begin
10621064 if FConnected then
10631065 Disconnect;
10641066 inherited Destroy;
10651067end;
10661068
10671069end.
10681070```
10691071
10701072### Przykładowy kod klienta
10711073
10721074Aby 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:
10731075
10741076``` pascal
10751077program sshtest;
10761078
10771079{Program testowy dla telnetsshclient
10781080
10791081Napisany przez Reiniera Olislagersa 2011.
10801082Zmodyfikowany dla libssh2 przez Alexeya Suhinina 2012.
10811083
10821084Licencja kodu:
10831085* MIT
10841086* LGPLv2 lub nowszy (z wyjątkiem statycznego linkowania FreePascal)
10851087* GPLv2 lub nowszy
10861088zgodnie z twoim wyborem.
10871089Dozwolone jest bezpłatne korzystanie, ale proszę nie pozywać mnie ani nie obwiniać.
10881090
10891091Korzysta z innych bibliotek/komponentów, dla których mogą obowiązywać różne licencje, które również mogą wpływać na skompilowaną pracę.
10901092
10911093Uruchamianie: sshtest <serverIPorhostname> [PrivateKeyFile]
10921094}
10931095{$mode objfpc}{$H+}
10941096{$APPTYPE CONSOLE}
10951097
10961098uses
10971099 telnetsshclient;
10981100var
10991101 comm: TTelnetSSHClient;
11001102 Command: string;
11011103begin
11021104 writeln('Start.');
11031105 comm:=TTelnetSSHClient.Create;
11041106 comm.HostName:= ParamStr(1); //Pierwszy argument w wierszu poleceń
11051107 if comm.HostName='' then
11061108 begin
11071109 writeln('Proszę podać nazwę hosta w wierszu poleceń.');
11081110 halt(1);
11091111 end;
11101112
11111113 comm.PrivateKeyFile := ParamStr(2);
11121114
11131115 comm.TargetPort:='0'; //automatyczne określanie na podstawie typu protokołu
11141116 comm.UserName:='root'; //zmień dla swojej sytuacji
11151117 comm.Password:='password'; //zmień dla swojej sytuacji
11161118 comm.ProtocolType:=SSH; //Telnet lub SSH
11171119 writeln(comm.Connect); //Pokaż wynik połączenia
11181120 if comm.Connected then
11191121 begin
11201122 writeln('Serwer: ' + comm.HostName + ':'+comm.TargetPort+', użytkownik: '+comm.UserName);
11211123 writeln('Wiadomość powitalna:');
11221124 writeln(comm.WelcomeMessage);
11231125 Command:='ls -al';
11241126 writeln('*** Wysyłanie ' + Command);
11251127 writeln('*** Początek wyniku****');
11261128 writeln(comm.CommandResult(Command));
11271129 writeln('*** Koniec wyniku****');
11281130 writeln('');
11291131 writeln('');
11301132 Command:='df -h';
11311133 writeln('*** Wysyłanie ' + Command);
11321134 writeln('*** Początek wyniku****');
11331135 writeln(comm.CommandResult(Command));
11341136 writeln('*** Koniec wyniku****');
11351137 writeln('');
11361138 writeln('');
11371139 writeln('Wszystkie wyjścia:');
11381140 writeln('*** Początek wyniku****');
11391141 writeln(comm.AllOutput);
11401142 writeln('*** Koniec wyniku****');
11411143 comm.Disconnect;
11421144 end
11431145 else
11441146 begin
11451147 writeln('Połączenie z ' +
11461148 comm.HostName + ':' +
11471149 comm.TargetPort + ' nie udało się.');
11481150 end;
11491151 comm.Free;
11501152end.
11511153```
11521154
11531155## Integracja z OAuth v1/Twitter/Plurk
11541156
11551157Biblioteka 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.
11561158
11571159## Inne artykuły internetowe i sieciowe
11581160
11591161- [[Portal:Web Development|Portal na temat tworzenia stron internetowych]]
11601162- [[Networking/pl|Sieć]]
11611163- [[Networking libraries/pl|Biblioteki sieciowe]] - porównanie różnych bibliotek sieciowych
11621164- [[Brook Framework]] - Idealny framework Free Pascal dla Twoich aplikacji internetowych. To czysty Pascal. Nie musisz porzucać preferowanego języka programowania.
11631165- [[Sockets|Gniazda]] - Komponenty gniazd TCP/IP
11641166- [[fcl-net]] - Biblioteka sieciowa dostarczana z FPC
11651167- [[lNet]] - Lekkie komponenty sieciowe
11661168- [[Synapse/pl|Synapse]] - Port szeregowy i synchroniczna biblioteka TCP/IP
11671169- [[XML Tutorial|Poradnik XML]] - XML jest często używany w komunikacji sieciowej
11681170- [[FPC and Apache Modules|FPC i moduły Apache]]
11691171- [[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.
11701172- [[Secure programming|Bezpieczne programowanie]]
11711173- [[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
11721174
11731175## Zobacz też
11741176
11751177- [[Download from SourceForge/pl|Pobieranie z SourceForge]] Przykład, który używa Synapse do pobierania z serwera HTTP, który stosuje przekierowanie.
11761178- [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).
11771179- [Komponent TCP/IP oparty na Synapse + mała aplikacja demonstracyjna](https://forum.lazarus.freepascal.org/index.php/topic,48677.0.html)
11781180
11791181## Linki zewnętrzne
11801182
11811183- [Oficjalna strona](http://www.ararat.cz/synapse/)
11821184- [Oficjalna dokumentacja](http://synapse.ararat.cz/doc/help/)
11831185- [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)
11841186
11851187---
11861188*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