Witam. Pytanie do MisiekD, ale może ktoś z Was też tak jak my lubi i preferuje Synapse,
to będzie umiał odpowiedzieć. Podesłałęm jednej osobie program stwrzony w Delphi 7 - z
użyciem Synapse konkretnie THttpSend. Program w oryginalnej postaci działa, ale jeżeli
ta osoba go przekompilowała pod Delphi 2010 to przestał działać, uruchamia się, ale jak
w momencie logowania ma wysłać dane POSTem do strony www to nic się nie dzieje, no
i pytanie do Was spotkaliście się z problemami z Synapse pod Delphi 2010? Pobrałem dla
pewności najnowszą dostępną wersję 39 i efekt ten sam. Ponoc Indy działa i tutaj pewnie
zwolennicy Indy triumfują i mówią "a do d**y te olesiowe Synapse, Indy rulez", ale ja do
tej pory nie miałem pojęcia że nowsze wersje Delphi mają problem - z kompatybilnością
wstecz, bo kod który działa ok pod Delphi 7 w nowszych wersjach Delphi i jeżeli, nic tam
z UAC nie koliduje to w nowszych Windowsach również. Jakie są wasze doświadczenia, z
pewnością Misiekd tworzyl już coś pod Delphi 2010 z Synapse, a może i ktoś iunny też?
Dodam, że w "Requirements" przy downloadzie napisano "experimental Delphi 2009+".
Delphi 2010 i Synapse - program nie działa prawidłowo
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Szczecin
- Postów: 4191
- Rejestracja: dni
- Ostatnio: dni
- Postów: 7923
problem jest od D2k9 gdzie string zamienił się w UnicodeString. Co prawda nie musiałem kompilować nic pod d2k9> ale próbowałem i potwierdzam, że nie działało :(.
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Szczecin
- Postów: 4191
Ok, dziękuję za informację, a i jak rozumiem - zamiana w źródłach
wszystkich typów String na UnicodeString nie rozwiąże problemu?
- Rejestracja: dni
- Ostatnio: dni
zamiana string na unicodestring na pewno nie pomoże, bo w Delphi 2009+ jest właśnie
type string=unicodestring;
więc to NIC nie zmieni ;-)
za to może zmienić zamiana wszystkich string na ansistring, char na ansichar, pchar na pansichar – czyli przywrócenie starego porządku rzeczy.
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Szczecin
- Postów: 4191
Dziękuję za informację. Jak dla mnie Synapse nadal jest ok, ale pewnie autor jak nie porzuci projektu, a chyba raczej
nie zrobił tego, to pewnie wyda może wkrótce wersję działającą - tak, jak należy z wersjami Delphi 2009 i nowszymi.
- Rejestracja: dni
- Ostatnio: dni
Nie mam jak sprawdzić bo pracuje na leciwym Turbo, ale może Synapse pobrana bezpośrednio z SVN zahula, tymbardziej że jest jakas wzmianka o zmianach w niektórych unitach pod D2009 (a Synapse pobrana z zipa oznaczona jako 39 wygląda na starszą)
jeżeli ktoś ma ochotę posprawdzać
http://synalist.svn.sourceforge.net/viewvc/synalist/trunk/
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Szczecinek
- Postów: 12
Witam. Zdaję sobie sprawę, że ostatnia wypowiedź była 6 lat temu, a Synapse od 4 lat chyba nie jest rozwijane. Ale...
...mam ten sam problem. Postanowiłem przejść ze swoim kodem z Delphi 7 na Delphi 2010 w celu lepszej obsługi Unicode.
Wszystko poszło łatwo i pięknie dopóki nie musiałem wysłać POSTu.
Problem pojawia się tutaj, a dokładniej w Document.Write(Pointer(URLData)^, Length(URLData)) :
Address := strona_www;
Command := '/jakas_komenda';
URLData := 'jakies_dane';
Document.Write(Pointer(URLData)^, Length(URLData));
HTTPMethod('POST', Address + Command);
Document.Write odwołuje się do Classes.pas i funkcji function TMemoryStream.Write(const Buffer; Count: Longint): Longint;
W Delphi 7 i Delphi 2010, funkcja ta wygląda tak samo.
function TMemoryStream.Write(const Buffer; Count: Longint): Longint;
var
Pos: Longint;
begin
if (FPosition >= 0) and (Count >= 0) then
begin
Pos := FPosition + Count;
if Pos > 0 then
begin
if Pos > FSize then
begin
if Pos > FCapacity then
SetCapacity(Pos);
FSize := Pos;
end;
System.Move(Buffer, Pointer(Longint(FMemory) + FPosition)^, Count);
FPosition := Pos;
Result := Count;
Exit;
end;
end;
Result := 0;
end;
Następnie System.Move(Buffer, Pointer(Longint(FMemory) + FPosition)^, Count) odwołuje się do System.pas i procedury** procedure Move**(const Source; var Dest; count : Integer). A ta już inaczej wygląda w Delphi 7 i Delphi 2010.
Dla Delphi 7:
procedure Move( const Source; var Dest; count : Integer );
{$IFDEF PUREPASCAL}
var
S, D: PChar;
I: Integer;
begin
S := PChar(@Source);
D := PChar(@Dest);
if S = D then Exit;
if Cardinal(D) > Cardinal(S) then
for I := count-1 downto 0 do
D[I] := S[I]
else
for I := 0 to count-1 do
D[I] := S[I];
end;
{$ELSE}
asm
{ ->EAX Pointer to source }
{ EDX Pointer to destination }
{ ECX Count }
PUSH ESI
PUSH EDI
MOV ESI,EAX
MOV EDI,EDX
MOV EAX,ECX
CMP EDI,ESI
JA @@down
JE @@exit
SAR ECX,2 { copy count DIV 4 dwords }
JS @@exit
REP MOVSD
MOV ECX,EAX
AND ECX,03H
REP MOVSB { copy count MOD 4 bytes }
JMP @@exit
@@down:
LEA ESI,[ESI+ECX-4] { point ESI to last dword of source }
LEA EDI,[EDI+ECX-4] { point EDI to last dword of dest }
SAR ECX,2 { copy count DIV 4 dwords }
JS @@exit
STD
REP MOVSD
MOV ECX,EAX
AND ECX,03H { copy count MOD 4 bytes }
ADD ESI,4-1 { point to last byte of rest }
ADD EDI,4-1
REP MOVSB
CLD
@@exit:
POP EDI
POP ESI
end;
{$ENDIF}
Dla Delphi 2010:
procedure Move(const Source; var Dest; count : Integer);
{$IFDEF PUREPASCAL}
var
S, D: PAnsiChar;
I: Integer;
begin
S := PAnsiChar(@Source);
D := PAnsiChar(@Dest);
showmessage('move');
if S = D then Exit;
if Cardinal(D) > Cardinal(S) then
for I := count-1 downto 0 do
D[I] := S[I]
else
for I := 0 to count-1 do
D[I] := S[I];
end;
{$ELSE}
asm
cmp eax, edx
je @@Exit {Source = Dest}
cmp ecx, 32
ja @@LargeMove {Count > 32 or Count < 0}
sub ecx, 8
jg @@SmallMove
@@TinyMove: {0..8 Byte Move}
jmp dword ptr [@@JumpTable+32+ecx*4]
@@SmallMove: {9..32 Byte Move}
fild qword ptr [eax+ecx] {Load Last 8}
fild qword ptr [eax] {Load First 8}
cmp ecx, 8
jle @@Small16
fild qword ptr [eax+8] {Load Second 8}
cmp ecx, 16
jle @@Small24
fild qword ptr [eax+16] {Load Third 8}
fistp qword ptr [edx+16] {Save Third 8}
@@Small24:
fistp qword ptr [edx+8] {Save Second 8}
@@Small16:
fistp qword ptr [edx] {Save First 8}
fistp qword ptr [edx+ecx] {Save Last 8}
@@Exit:
ret
nop {4-Byte Align JumpTable}
nop
@@JumpTable: {4-Byte Aligned}
dd @@Exit, @@M01, @@M02, @@M03, @@M04, @@M05, @@M06, @@M07, @@M08
@@LargeForwardMove: {4-Byte Aligned}
push edx
fild qword ptr [eax] {First 8}
lea eax, [eax+ecx-8]
lea ecx, [ecx+edx-8]
fild qword ptr [eax] {Last 8}
push ecx
neg ecx
and edx, -8 {8-Byte Align Writes}
lea ecx, [ecx+edx+8]
pop edx
@FwdLoop:
fild qword ptr [eax+ecx]
fistp qword ptr [edx+ecx]
add ecx, 8
jl @FwdLoop
fistp qword ptr [edx] {Last 8}
pop edx
fistp qword ptr [edx] {First 8}
ret
@@LargeMove:
jng @@LargeDone {Count < 0}
cmp eax, edx
ja @@LargeForwardMove
sub edx, ecx
cmp eax, edx
lea edx, [edx+ecx]
jna @@LargeForwardMove
sub ecx, 8 {Backward Move}
push ecx
fild qword ptr [eax+ecx] {Last 8}
fild qword ptr [eax] {First 8}
add ecx, edx
and ecx, -8 {8-Byte Align Writes}
sub ecx, edx
@BwdLoop:
fild qword ptr [eax+ecx]
fistp qword ptr [edx+ecx]
sub ecx, 8
jg @BwdLoop
pop ecx
fistp qword ptr [edx] {First 8}
fistp qword ptr [edx+ecx] {Last 8}
@@LargeDone:
ret
@@M01:
movzx ecx, [eax]
mov [edx], cl
ret
@@M02:
movzx ecx, word ptr [eax]
mov [edx], cx
ret
@@M03:
mov cx, [eax]
mov al, [eax+2]
mov [edx], cx
mov [edx+2], al
ret
@@M04:
mov ecx, [eax]
mov [edx], ecx
ret
@@M05:
mov ecx, [eax]
mov al, [eax+4]
mov [edx], ecx
mov [edx+4], al
ret
@@M06:
mov ecx, [eax]
mov ax, [eax+4]
mov [edx], ecx
mov [edx+4], ax
ret
@@M07:
mov ecx, [eax]
mov eax, [eax+3]
mov [edx], ecx
mov [edx+3], eax
ret
@@M08:
fild qword ptr [eax]
fistp qword ptr [edx]
end;
{$ENDIF}
Główna róznica to deklaracja zmiennych jako PChar (Delphi 7) i PAnsiChar (Delphi 2010). I moim skromnym zdaniem tutaj jest sedno problemu - ale pamiętajcie, że jestem początkującym programistą.
Sekcja application/x-www-form-urlencoded pakietu wysłanego za pomocą POST w Delphi 7 ma w HEX postać (przykład):
ab de cd da efa to samo w Delphi 2010 wygląda już tak:
ab 00 de 00 cd 00 da 00 ef 00i w tym momencie serwer już nie przyjmuje takiego zapytania.
Pokusiłem się o zamianę kodu w System.pas, na ten z Delphi 7. Za pomocą komend dokonałem rekompilacji zmienionego System.pas
dcc32.exe -M -Y -$D+ System.pas
dcc32.exe -M -Y -$D- System.pas
Podmieniłem odpowiednio pliki w katalogach /lib, /lib/debug, /lib/release. Projekt skompilowany ponownie, ale efektu zero.
To tyle moich wypocin. Czy macie jakiś sposób na ten problem ? Czy trzeba się pożegnać z Synapse ?
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Szczecin
- Postów: 4191
Nie wiem czy klasa TStringList nie jest też w unicode. Ale ja bym zrobił lamerskie rozwiązanie, skoro deklarowanie AnsiString nie pomaga. Zresztą robiłem tak, gdy nie wiedziałem sam jak zapisać string do TMemoryString, a co kiedyś w jakimś starym kodzie pokazał mi MisiekD.
Zrób więc może tak na próbę. Utwórz TStringList, ustaw jego właściwosć Text na żądany AnsiString. Usuń ostatnie dwa znaki (czyli CR LF - znak nowej linii, bo zawsze on jest na końcu, powinno pomóc samo Delete). Teraz zrób TwojaStringLista.SaveToSreeam(Document). Może zadziała ok.
Jeżeli nie, to ktoś inny może doradzi coś lepszego. Ja później już korzystałem na ogól z Synapse pod Delphi 7.
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Gorlice
Wersja rozwojowa Synapse jest kompatybilna z Unicode (nie wiem czy w 100% ale to co ja robiłem na pewno i do tego należało wysyłanie POST)
https://sourceforge.net/p/synalist/code/HEAD/tree/trunk/
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Szczecinek
- Postów: 12
Jestem już po próbach i testach.
Na obecną chwilę sprawdził się sposób podany przez olesio. Zrobiłem to tak:
Address := strona_www;
Command := '/action/License/DownloadContext';
URLData := 'fileId=' + id_pliku + '&__RequestVerificationToken=' + token;
// sposób od olesio
Params := TStringList.Create;
Params.Text := URLData;
Params.SaveToStream(Document);
HTTPMethod('POST', Address + Command);
Próbowałem się pozbyć znaku ostatniej linii, ale nie wychodzi mi. Jak to zrobić, bez wyciągania tekstu z TStringList, modyfikacji wyciągniętego tekstu i ponownego wpisania do TStringList - bo to co przed chwilą napisałem nie ma sensu. Po wpisaniu do TStringList, znak nowej linii znowu powraca. Próbowałem Delete, Trim i inne nietrafione sposoby znalezione w sieci. Trzeba by to zapewne robić bezpośrednio na danym tekście w TStringList - jest to możliwe, czyżbym coś przeoczył ?
Dzięki kAzek za link do rozwojowego Synapse. Rzeczywiście są różnice, ale po zastosowaniu tej wersji Synapse, bez zmian, problem nadal występował.
PS. Mimo znaku nowej linii w wysyłanym pakiecie, serwer go akceptuje i odpowiada poprawnie. Ale kto wie jak będzie z innymi serwerami.
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Szczecin
- Postów: 4191
Sorry, nie do końca dobrze podpowiedziałem. Z klasą TStringList się chyba nie da, zawsze dojdzie ten znak nowej lini, nawet przy operacjach na właściwości Text. Ale jest też przecież jeszcze klasa TStringStream. Pod Delphi 7 mi poniższy kod działa ok.
Utworzony plik D:\test.bin ma rozmiar dokładnie czterech bajtów, czyli długość słowa Test. A jak widać zapisuje TMemoryStream, a takiego samego typu jest pod Synapse właściwość Document. Także raczej będzie pewne, że nic nie zostanie namieszane w nagłowku niezgodnie z protokołem HTTP(S). I serwer raczej powinien otrzymać to czego oczekuje, ale sprawdź.
//...
var
SS : TStringStream;
MS : TMemoryStream;
begin
SS := TStringStream.Create('Test');
MS := TMemoryStream.Create;
MS.LoadFromStream(SS);
MS.SaveToFile('D:\test.bin');
SS.Free;
MS.Free;
end;
Innego sposobu nie znam. Chociaż kto wie jak nowsze Delphi czy FPC/Lazarus odniesie się do konstruktora. To też sprawdź, bo wszędzie te narzucanie nam UNICODE. Niby wymóg czasów, ale to tak jakby nagle wywalić z Windowsa wszelkie funkcje WinAPI z końcowką A, zamiast W, bo po co komu przecież wstępna kompatybilność i uproszczenie? ;)
EDIT: pod Delphi XE 8, więc w miarę nowym. Powyższy kod zachowuje się tak samo. Także może to skuteczny sposób.
- Rejestracja: dni
- Ostatnio: dni
- Postów: 2196
A nie lepiej czasami poprawić kawałek kodu aby "było po ludzku" ?
I najlepiej w tym co jest już w IDE ?
http://docwiki.embarcadero.com/RADStudio/XE8/en/Using_an_HTTP_Client
Koncepcja poprawiania move w System.pas to tez proszenie sie o kłopoty , a po drugie to nie mialo prawa zadzialac lepiej , bo niby dlaczego, jak w obydwu wersjach działały te funkcje tak samo ?
- Rejestracja: dni
- Ostatnio: dni
- Lokalizacja: Szczecinek
- Postów: 12
Do @olesio : oczywiście Twój sposób działa, nie ma znaku końca linii w wysyłanym pakiecie. I można chyba uznać to za rozwiązanie zaistniałego problemu. Chyba że ktoś ma jeszcze zgrabniejszy pomysł.
Do @Adamek Adam : oczywiście, że można i tak, może i też za pomocą Indy, ale temat postu to Delphi 2010 i Synapse... i na tym się skupiamy.