Witam :)
Znalazłem na internecie kod do obsługi gg8. Pozmieniałem go trochę, i oto on:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Sockets, StdCtrls;
type
TFgg = class(TForm)
zaloguj: TButton;
lnumer: TLabel;
lhaslo: TLabel;
numer: TEdit;
haslo: TEdit;
log: TMemo;
llog: TLabel;
procedure zalogujClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Fgg: TFgg;
implementation
{$R *.dfm}
function gg_login_hash(password: PAnsiChar; seed: Cardinal) : Integer;
var
x, y, z: Integer;
begin
y := seed;
x := 0;
while (password^ <> AnsiChar(nil)) do begin
x := (x and $ffffff00) or Ord(password^);
y := y xor x;
y := y + x;
x := x shl 8;
y := y xor x;
x := x shl 8;
y := y - x;
x := x shl 8;
y := y xor x;
z := y and $1f;
y := (y shl z) or (y shr (32 - z));
password := password + 1;
end;
result := y;
end;
procedure connect(gg_id: Integer; gg_pass: PAnsiChar);
type
gg_header = record
t: Integer;
l: Integer;
end;
s_gg_login80 = packed record
uin: Integer;
language: array[1..2] of AnsiChar;
hash_type: Byte;
hash: array [1..64] of AnsiChar;
status: Integer;
flags: Integer;
features: Integer;
local_ip: Integer;
local_port: SmallInt;
external_ip: Integer;
external_port: SmallInt;
image_size: Byte;
unknown2: Byte;
version_len: Integer;
version: array[1..$21] of AnsiChar;
description_size: Integer;
end;
var
socket: TTcpClient;
i_tmp: Integer;
garbage: Pointer; // Tutaj beda tymczasowo odbierane wszystkie smieci
header : gg_header;
out_login: s_gg_login80;
seed: Cardinal;
const GG_WELCOME = $0001;
const GG_LOGIN80 = $0031;
const GG_LOGIN_HASH_GG32 = $01;
const GG_LOGIN_HASH_SHA1 = $02;
const GG_LOGIN80_OK = $0035;
const GG_STATUS_AVAIL = $0002;
const GG_LOGIN_FAILED = $0009;
const GG_DISCONNECTING = $000b;
begin
socket := TTcpClient.Create(nil);
socket.RemoteHost := '91.197.13.35';
socket.RemotePort := '443';
if not socket.Connect then begin
socket.Destroy;
Fgg.log.Lines.Add(TimeTostr(Time)+': Unable to connect');
end;
while socket.ReceiveBuf(header, SizeOf(gg_header)) > 0 do begin
if (header.t = GG_WELCOME) then begin
Fgg.log.Lines.Add(TimeTostr(Time)+': GG Welcome');
socket.ReceiveBuf(i_tmp, SizeOf(i_tmp));
seed := i_tmp;
ZeroMemory(@out_login, SizeOf(out_login));
header.t := GG_LOGIN80;
header.l := SizeOf(out_login);
out_login.uin := gg_id;
out_login.hash_type := GG_LOGIN_HASH_GG32;
out_login.status := GG_STATUS_AVAIL;
out_login.features := $00000007; // Bo tak ma byc
out_login.unknown2 := $64; // Bo tak ma byc
out_login.version_len := SizeOf(out_login.version);
out_login.description_size := 0; // I tak jest wyzerowane, ale to tak dla pamieci, ze nie mamy opisu
CopyMemory(@out_login.language, PAnsiChar('pl'), 2); { Dlaczego tak? A no bo po to, zeby miec pewnosc, z
ze Delphi nie dolozy magicznie na koniec NULLa. }
CopyMemory(@out_login.version, PAnsiChar('Gadu-Gadu Client build 8.0.0.7669'), SizeOf(out_login.version));
i_tmp := gg_login_hash(gg_pass, seed); // Obliczamy hasha
CopyMemory(@out_login.hash, @i_tmp, SizeOf(i_tmp));
socket.SendBuf(header, SizeOf(header));
socket.SendBuf(out_login, SizeOf(out_login));
Fgg.log.Lines.Add(TimeTostr(Time)+': Sent login data');
end else if (header.t = GG_LOGIN80_OK) then begin
Fgg.log.Lines.Add(TimeTostr(Time)+': Logged in');
if (header.l > 0) then begin
GetMem(garbage, header.l);
socket.ReceiveBuf(garbage, header.l, 1);
FreeMem(garbage);
end;
end else if (header.t = GG_LOGIN_FAILED) then begin
Fgg.log.Lines.Add(TimeTostr(Time)+': Wrong password');
socket.Disconnect;
end else if (header.t = GG_DISCONNECTING) then begin
Fgg.log.Lines.Add(TimeTostr(Time)+': Received GG_DISCONNECTING');
socket.Disconnect;
end else begin
Fgg.log.Lines.Add(TimeTostr(Time)+': Unknown header');
// Odbieramy smieci
if (header.l > 0) then begin
GetMem(garbage, header.l);
socket.ReceiveBuf(garbage, header.l);
FreeMem(garbage);
end;
end;
end;
Fgg.log.Lines.Add(TimeTostr(Time)+': Disconnected.');
socket.Destroy;
end;
procedure TFgg.zalogujClick(Sender: TObject);
var
buff_in: AnsiString;
gg_id: Integer;
begin
try
gg_id:=strtoint(numer.Text);
buff_in:=haslo.Text;
connect(gg_id, PAnsiChar(buff_in));
except end;
end;
end.
Kompilowane w Delphi 2009. I teraz problemy:
- "Błąd" podczas kompilowania. Wyskakuje przy linijce:
buff_in:=haslo.Text;
i pisze[DCC Warning] Unit1.pas(159): W1058 Implicit string cast with potential data loss from 'TCaption' to 'AnsiString'
Dlaczego? - Logowanie przebiega prawidłowo do momentu "Logged In". Po tym - program sie zawiesza. Czemu? Gdy np. wprowadzę nieprawidłowe hasło - program wyświetli, że jest błędne hasło, ale się nie zawiesi. Więc co jest źle?
- Program nie zmienia statusu. I teraz pytanie, jak to zrobić? Szukałem na necie, znalazłem, że trzeba wysłać informację o liście kontaktów, a dopiero później działać. Znalazłem także kod, który powinien działać (podobno nie wyświetla poprawnie polskich znaków, no, ale ważne że działa :P):
procedure TBGG1.ChangeStatus;
var
Header: THeader;
OutNewStatus: packed record
Status: Integer;
Flags: Integer;
DescriptionSize: Integer;
end;
Description: Array[1..255]of AnsiChar;
const
C_OUT_NEWSTATUS = $0038;
begin
Header.Typ := C_OUT_NEWSTATUS;
OutNewStatus.DescriptionSize := Length(FDescription);
if OutNewStatus.DescriptionSize > 0 then
begin
FStatusEx := CodeStatus(FStatus,True);
OutNewStatus.Status := FStatusEx;
CopyMemory(@Description,PAnsiChar(FDescription),Length(FDescription));
Header.Length := SizeOf(OutNewStatus)+Length(FDescription);
TCP.WriteBuffer(Header,SizeOf(Header));
TCP.WriteBuffer(OutNewStatus,SizeOf(OutNewStatus));
TCP.WriteBuffer(Description,Length(FDescription));
MessageBox(0,PAnsiChar(string(Description)),'lol',MB_OK);
end else
begin
FStatusEx := CodeStatus(FStatus);
OutNewStatus.Status := FStatusEx;
Header.Length := SizeOf(OutNewStatus);
TCP.WriteBuffer(Header,SizeOf(Header));
TCP.WriteBuffer(OutNewStatus,SizeOf(OutNewStatus));
end;
end;
Moje pytanie - jak dodać ten kod do programu? W które miejsce go wstawić?
4. Jak dodać do programu procedurę odbierania i wysyłania wiadomości? Może ktoś już to robił? Można się posłużyć [url="http://toxygen.net/libgadu/protocol/"][b]tą[/b][/url] dokumentacją.
Z góry za wszelką pomoc dziękuję :)