You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
422 lines
9.3 KiB
Plaintext
422 lines
9.3 KiB
Plaintext
{
|
|
This file is part of R&Q.
|
|
Under same license
|
|
}
|
|
unit outboxLib;
|
|
{$I RnQConfig.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, RnQStrings, RDGlobal, ICQContacts;
|
|
|
|
{$I NoRTTI.inc}
|
|
|
|
const
|
|
OE_msg = 1;
|
|
OE_contacts = 2;
|
|
OE_addedYou = 3;
|
|
OE_auth = 4;
|
|
OE_authDenied = 5;
|
|
|
|
OEvent2ShowStr: array [OE_msg .. OE_authDenied] of string = (Str_message, 'Contacts', 'Added you', 'Authorization given',
|
|
'Authorization denied');
|
|
|
|
type
|
|
POEvent = ^TOEvent;
|
|
TOEvent = class
|
|
public
|
|
kind: integer;
|
|
flags: Cardinal;
|
|
whom: TICQContact;
|
|
info: string;
|
|
cl: TRnQCList;
|
|
wrote, lastmodify: Tdatetime;
|
|
// ack fields
|
|
timeSent: Tdatetime;
|
|
ID: Integer;
|
|
sID: String;
|
|
filepos: integer;
|
|
constructor Create(pKind: Integer); // override;
|
|
destructor Destroy; override;
|
|
function ToString: RawByteString;
|
|
function FromString(const s: RawByteString): Boolean;
|
|
function Clone: TOEvent;
|
|
end;
|
|
|
|
Toutbox = class(Tlist)
|
|
public
|
|
// destructor Destroy; override;
|
|
|
|
function ToString: RawByteString;
|
|
procedure FromString(s: RawByteString);
|
|
|
|
function Empty: Boolean;
|
|
function Pop: TOEvent;
|
|
|
|
procedure Clear; override;
|
|
procedure ClearU;
|
|
protected
|
|
procedure Notify(Ptr: Pointer; Action: TListNotification); OverRide;
|
|
public
|
|
function Add(kind: integer; dest: TICQContact; flags: integer = 0; const info: string = ''): TOEvent; overload;
|
|
function Add(kind: integer; dest: TICQContact; flags: integer; cl: TRnQCList): TOEvent; overload;
|
|
function GetAt(idx: integer): TOEvent;
|
|
function Remove(ev: TOEvent): Boolean; overload;
|
|
function StFor(who: TICQContact): Boolean;
|
|
function FindID(const sID: String): Integer;
|
|
|
|
procedure UpdateScreenFor(cnt: TICQContact);
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
SciterLib, globalLib, mainDlg, utilLib, roasterLib,
|
|
RnQCrypt, RQUtil, RnQDialogs, RDUtils, RnQBinUtils, ICQCommon;
|
|
|
|
{ destructor Toutbox.Destroy;
|
|
begin
|
|
clear;
|
|
inherited
|
|
end; // destroy
|
|
}
|
|
|
|
function Toutbox.ToString: RawByteString;
|
|
var
|
|
s: RawByteString;
|
|
res: RawByteString;
|
|
i: integer;
|
|
begin
|
|
res := ''; // file version
|
|
if count > 0 then
|
|
begin
|
|
for i := 0 to count - 1 do
|
|
begin
|
|
s := getAt(i).ToString;
|
|
res := res + int2str(Length(s)) + s;
|
|
end;
|
|
i := StrToIntDef(TICQContact.TrimUID(Account.AccProto.MyAccNum), 0);
|
|
critt(res, i);
|
|
end;
|
|
Result := 'VER' + int2str(1) + res;
|
|
end;
|
|
|
|
procedure Toutbox.FromString(s: RawByteString);
|
|
var
|
|
i, l: integer;
|
|
ev: TOEvent;
|
|
begin
|
|
i := StrToIntDef(String(TICQContact.TrimUID(Account.AccProto.MyAccNum)), 0);
|
|
s := decritted(Copy(s, 8, Length(s)), i);
|
|
ClearU;
|
|
i := 1;
|
|
if Length(s) < 4 then
|
|
Exit;
|
|
try
|
|
while i < Length(s) do
|
|
begin
|
|
l := Integer((@s[i])^);
|
|
Inc(i, 4);
|
|
ev := TOEvent.Create(OE_msg);
|
|
if ev.FromString(copy(s, i, l)) then
|
|
add(ev)
|
|
else
|
|
ev.Free;
|
|
inc(i, l);
|
|
end;
|
|
UpdateScreenFor(nil);
|
|
except
|
|
msgDlg('Error on load outbox', True, mtError);
|
|
end;
|
|
end;
|
|
|
|
procedure Toutbox.Clear;
|
|
begin
|
|
inherited;
|
|
ActionManager.Execute(AK_SAVEOUTBOX, SaveDelay);
|
|
end;
|
|
|
|
procedure Toutbox.ClearU;
|
|
var
|
|
i: integer;
|
|
oe: TOEvent;
|
|
begin
|
|
for i := count - 1 downto 0 do
|
|
begin
|
|
oe := getAt(i);
|
|
if oe <> nil then
|
|
with oe do
|
|
try
|
|
UpdateScreenFor(whom);
|
|
Items[i] := nil;
|
|
except end;
|
|
end;
|
|
inherited;
|
|
ActionManager.Execute(AK_SAVEOUTBOX, SaveDelay);
|
|
end;
|
|
|
|
function Toutbox.add(kind: integer; dest: TICQContact; flags: integer; cl: TRnQCList): TOEvent;
|
|
begin
|
|
result := add(kind, dest, flags);
|
|
result.cl := TRnQCList.Create;
|
|
result.cl.assign(cl);
|
|
end;
|
|
|
|
function Toutbox.add(kind: integer; dest: TICQContact; flags: integer = 0; const info: string = ''): TOEvent;
|
|
var
|
|
found: Boolean;
|
|
i: integer;
|
|
begin
|
|
Result := nil;
|
|
Found := False;
|
|
if (kind in [OE_addedYou, OE_auth, OE_authDenied]) then
|
|
for i := 0 to count - 1 do
|
|
begin
|
|
result := getAt(i);
|
|
if (kind = result.kind) and (dest.equals(result.whom)) then
|
|
begin
|
|
found := True;
|
|
Break;
|
|
end;
|
|
end;
|
|
if not found then
|
|
begin
|
|
Result := TOEvent.Create(kind);
|
|
add(result);
|
|
end;
|
|
Result.kind := kind;
|
|
Result.flags := flags;
|
|
Result.whom := dest;
|
|
Result.info := info;
|
|
Result.wrote := now;
|
|
Result.lastmodify := now;
|
|
Result.cl := nil;
|
|
UpdateScreenFor(result.whom);
|
|
ActionManager.Execute(AK_SAVEOUTBOX, SaveDelay);
|
|
end;
|
|
|
|
function Toutbox.getAt(idx: integer): TOEvent;
|
|
begin
|
|
if (idx >= 0) and (idx < count) then
|
|
result := list[idx]
|
|
else
|
|
result := nil;
|
|
end;
|
|
|
|
procedure Toutbox.Notify(Ptr: Pointer; Action: TListNotification);
|
|
begin
|
|
inherited;
|
|
if (Action = lnDeleted) and (Ptr <> nil) then
|
|
TOEvent(Ptr).Free;
|
|
end;
|
|
|
|
function Toutbox.remove(ev: TOEvent): Boolean;
|
|
var
|
|
i: integer;
|
|
begin
|
|
// Result := inherited remove(ev)>=0;
|
|
i := IndexOf(ev);
|
|
if i >= 0 then
|
|
begin
|
|
result := True;
|
|
list[i] := nil;
|
|
Delete(i);
|
|
UpdateScreenFor(ev.whom);
|
|
ActionManager.Execute(AK_SAVEOUTBOX, SaveDelay);
|
|
end else
|
|
Result := False;
|
|
end;
|
|
|
|
function Toutbox.Pop: TOEvent;
|
|
begin
|
|
Result := nil;
|
|
if Count > 0 then
|
|
begin
|
|
Result := getAt(0);
|
|
List[0] := nil;
|
|
Delete(0);
|
|
UpdateScreenFor(result.whom);
|
|
ActionManager.Execute(AK_SAVEOUTBOX, SaveDelay);
|
|
end;
|
|
end;
|
|
|
|
function Toutbox.Empty: Boolean;
|
|
begin
|
|
Result := Count = 0
|
|
end;
|
|
|
|
function Toutbox.stFor(who: TICQContact): Boolean;
|
|
var
|
|
i: integer;
|
|
ev: TOEvent;
|
|
begin
|
|
Result := False;
|
|
if Assigned(who) and (who is TICQContact) then
|
|
for i := 0 to count - 1 do
|
|
begin
|
|
ev := getAt(i);
|
|
if Assigned(ev) and Assigned(ev.whom) and who.equals(ev.whom) then
|
|
begin
|
|
Result := True;
|
|
Exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure Toutbox.UpdateScreenFor(cnt: TICQContact);
|
|
begin
|
|
UI.CL.UpdateAdditionalImage;
|
|
|
|
if (cnt = nil) or (cnt.UID = '0') then
|
|
Exit;
|
|
|
|
if Assigned(UI.Chat) then
|
|
with UI.Chat do
|
|
if Assigned(CurrentContact) and CurrentContact.Equals(cnt) then
|
|
UpdateStatusBar;
|
|
|
|
roasterLib.UpdateInPlace(cnt);
|
|
end;
|
|
|
|
function Toutbox.FindID(const sID: String): Integer;
|
|
var
|
|
e: TOEvent;
|
|
begin
|
|
for Result := Count - 1 downto 0 do
|
|
begin
|
|
e := GetAt(Result);
|
|
if Assigned(e) and (e.sID = sID) then
|
|
Exit;
|
|
end;
|
|
Result := -1;
|
|
end;
|
|
|
|
/// /////////////////////////////////////////////////////////////////////
|
|
|
|
const
|
|
OEK_kind = 1;
|
|
OEK_flags = 2;
|
|
OEK_email = 3;
|
|
OEK_uin = 4;
|
|
OEK_info = 5;
|
|
OEK_wrote = 6;
|
|
OEK_cl = 7;
|
|
OEK_lastmod = 8;
|
|
OEK_UID = 10;
|
|
|
|
function TOEvent.ToString: RawByteString;
|
|
|
|
procedure WriteDown(Code: integer; const Data: RawByteString);
|
|
begin
|
|
Result := Result + int2str(Length(data)) + int2str(code) + Data
|
|
end;
|
|
|
|
begin
|
|
Result := '';
|
|
WriteDown(OEK_kind, int2str(kind));
|
|
WriteDown(OEK_flags, int2str(flags));
|
|
if Assigned(whom) then
|
|
WriteDown(OEK_UID, UTF(whom.UID));
|
|
WriteDown(OEK_info, UTF(info));
|
|
WriteDown(OEK_wrote, dt2str(wrote));
|
|
WriteDown(OEK_lastmod, dt2str(lastmodify));
|
|
if Assigned(cl) then
|
|
WriteDown(OEK_cl, cl.toString);
|
|
end;
|
|
|
|
function TOEvent.FromString(const s: RawByteString): Boolean;
|
|
var
|
|
i, l, code, next: integer;
|
|
uid: TUID;
|
|
begin
|
|
i := 1;
|
|
Result := True;
|
|
try
|
|
while i+8 < Length(s) do
|
|
begin
|
|
l := Integer((@s[i])^);
|
|
Inc(i, 4);
|
|
code := Integer((@s[i])^);
|
|
Inc(i, 4);
|
|
next := i + l;
|
|
case code of
|
|
OEK_kind:
|
|
kind := Integer((@s[i])^);
|
|
OEK_flags:
|
|
flags := Integer((@s[i])^);
|
|
OEK_wrote:
|
|
wrote := TDateTime((@s[i])^);
|
|
OEK_lastmod:
|
|
lastmodify := TDateTime((@s[i])^);
|
|
OEK_info:
|
|
info := UnUTF(Copy(s, i, l));
|
|
OEK_uin:
|
|
begin
|
|
{$IFDEF UID_IS_UNICODE}
|
|
uid := IntToStr(Integer((@s[i])^));
|
|
{$ELSE ansi}
|
|
uid := IntToStr(Integer((@s[i])^));
|
|
{$ENDIF UID_IS_UNICODE}
|
|
whom := Account.AccProto.GetContact(uid);
|
|
end;
|
|
OEK_UID:
|
|
begin
|
|
{$IFDEF UID_IS_UNICODE}
|
|
uid := UnUTF(Copy(s, i, l));
|
|
{$ELSE ansi}
|
|
uid := Copy(s, i, l);
|
|
{$ENDIF UID_IS_UNICODE}
|
|
whom := Account.AccProto.getContact(uid);
|
|
end;
|
|
OEK_cl:
|
|
begin
|
|
if cl = nil then
|
|
cl := TRnQCList.Create;
|
|
cl.FromString(Copy(s, i, l), Account.AccProto.contactsDB);
|
|
end;
|
|
end;
|
|
i := next;
|
|
end;
|
|
except
|
|
Result := False;
|
|
end;
|
|
end;
|
|
|
|
function TOEvent.Clone: TOEvent;
|
|
begin
|
|
Result := TOEvent.Create(Self.kind);
|
|
result.flags := Self.flags;
|
|
result.whom := Self.whom;
|
|
result.info := Self.info;
|
|
if Self.cl <> nil then
|
|
result.cl := cl.Clone
|
|
else
|
|
result.cl := nil;
|
|
result.wrote := Self.wrote;
|
|
result.lastmodify := lastmodify;
|
|
result.timeSent := timeSent;
|
|
result.ID := ID;
|
|
result.filepos := filepos;
|
|
end;
|
|
|
|
destructor TOEvent.Destroy;
|
|
begin
|
|
if Assigned(cl) then
|
|
FreeAndNil(cl);
|
|
whom := nil;
|
|
SetLength(info, 0);
|
|
inherited;
|
|
end;
|
|
|
|
constructor TOEvent.Create(pKind: Integer);
|
|
begin
|
|
kind := pKind;
|
|
flags := 0;
|
|
whom := nil;
|
|
info := '';
|
|
cl := nil;
|
|
end;
|
|
|
|
end.
|