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.
409 lines
10 KiB
Plaintext
409 lines
10 KiB
Plaintext
{
|
|
This file is part of R&Q.
|
|
Under same license
|
|
}
|
|
unit history;
|
|
{$I RnQConfig.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, Classes, SysUtils, RDGlobal, DateUtils, ICQCommon, ICQContacts, events, SQLiteDB;
|
|
|
|
{$I NoRTTI.inc}
|
|
|
|
const
|
|
CRYPT_SIMPLE = 0;
|
|
CRYPT_KEY1 = 1;
|
|
|
|
type
|
|
Thistory = class
|
|
private
|
|
hUID: TUID;
|
|
loading: boolean;
|
|
cryptMode: byte;
|
|
hashed: RawByteString;
|
|
function old_FromStream(Str: TStream; const UID: TUID): Boolean;
|
|
public
|
|
ThemeToken, SmilesToken: Cardinal;
|
|
old_EventList: TList;
|
|
|
|
constructor Create(const UID: TUID);
|
|
destructor Destroy; override;
|
|
class function getExistingChats: TUIDS;
|
|
function GetEventCount: Integer;
|
|
function GetAllEvents: Thevents;
|
|
function GetLastEvents(Offset, Cnt: Integer; var NoMoreMessages: Boolean): Thevents;
|
|
function GetLastEvent(Cnt: Integer = 1): Thevent;
|
|
function GetTimeRange(FromTime, ToTime: TDateTime; var NoMoreMessages: Boolean; ToInclusive: Boolean = True): Thevents; overload;
|
|
function GetTimeRange(FromTime, ToTime: TDateTime): Thevents; overload;
|
|
function GetByRowID(RowID: Int64): Thevent;
|
|
function GetByMsgID(MsgID: TMsgID; Recent: Boolean = True): Thevent;
|
|
function GetByTime(Time: TDateTime): Thevent;
|
|
function GetByWID(const WID: String): Thevent;
|
|
function GetBySender(const Sender: TUID): Thevents;
|
|
procedure WriteMsgIDs(ReqID: Integer; MsgID: UInt64; const WID: RawByteString);
|
|
procedure WriteMsgFlags(MsgID: TMsgID; Flags: Integer);
|
|
procedure DeleteFromToTime(St, En: TDateTime);
|
|
procedure DeleteByMsgID(MsgID: TMsgID);
|
|
procedure DeleteBySender(const Sender: TUID);
|
|
function DataSearch(const Txt: String; CaseSensitive: Boolean = False): Thevents;
|
|
function old_Load(Cnt: TICQContact): Boolean;
|
|
end; // Thistory
|
|
|
|
procedure DelHistWith(const UID: TUID);
|
|
function ExistsHistWith(const UID: TUID): Boolean;
|
|
procedure WriteToHistory(ev: Thevent; other: TICQContact = nil; patch: Boolean = False);
|
|
|
|
implementation
|
|
|
|
uses
|
|
RDFileUtil, RQUtil, RnQLangs, globalLib;
|
|
|
|
function Thistory.old_Load(Cnt: TICQContact): Boolean;
|
|
{$IFNDEF DB_ENABLED}
|
|
var
|
|
Str: Tstream;
|
|
MemStream: TMemoryStream;
|
|
{$ENDIF ~DB_ENABLED}
|
|
begin
|
|
Result := False;
|
|
if not Assigned(Cnt) then
|
|
Exit;
|
|
// Result := fromString(loadFile(userPath+historyPath + uid), quite);
|
|
Str := GetStream(Account.ProtoPath + historyPath + LowerCase(cnt.UID));
|
|
if Assigned(Str) then
|
|
begin
|
|
Str.Position := 0;
|
|
// Result := fromSteam(str, quite);
|
|
MemStream := TMemoryStream.Create;
|
|
MemStream.CopyFrom(Str, Str.Size);
|
|
MemStream.Position := 0;
|
|
FreeAndNil(Str);
|
|
Result := old_FromStream(MemStream, LowerCase(Cnt.UID));
|
|
FreeAndNil(MemStream);
|
|
end else
|
|
Result := old_FromStream(nil, LowerCase(Cnt.UID));
|
|
end;
|
|
|
|
constructor Thistory.Create(const UID: TUID);
|
|
begin
|
|
hUID := UID;
|
|
if UID = '' then
|
|
old_EventList := TList.Create
|
|
else
|
|
old_EventList := nil;
|
|
end;
|
|
|
|
destructor Thistory.Destroy;
|
|
begin
|
|
if Assigned(old_EventList) then
|
|
FreeAndNil(old_EventList);
|
|
inherited;
|
|
end;
|
|
|
|
function SortFunc(Item1, Item2: Pointer): Integer;
|
|
begin
|
|
Result := CompareDateTime(Thevent(Item1).when, Thevent(Item2).when);
|
|
end;
|
|
|
|
function Thistory.old_FromStream(Str: TStream; const UID: TUID): Boolean;
|
|
var
|
|
ev: Thevent;
|
|
thisCnt, thisCnt2: TICQContact;
|
|
Cnt1I, Cnt2I: Int64;
|
|
// cur:integer;
|
|
|
|
function GetByte: Byte;
|
|
begin
|
|
Str.Read(Result, 1);
|
|
// inc(cur)
|
|
end;
|
|
|
|
function GetDatetime: TDateTime;
|
|
begin
|
|
Str.Read(Result, 8);
|
|
// inc(cur,8)
|
|
end;
|
|
|
|
function GetInt: Integer;
|
|
begin
|
|
Str.Read(Result, 4);
|
|
// inc(cur,4);
|
|
end;
|
|
|
|
function GetString: RawByteString;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
i := GetInt;
|
|
SetLength(Result, i);
|
|
Str.Read(Result[1], i);
|
|
// inc(cur,length(result))
|
|
end;
|
|
|
|
procedure ParseExtrainfo;
|
|
var
|
|
code, next, extraEnd: integer;
|
|
cur: integer;
|
|
s: AnsiString;
|
|
begin
|
|
cur := 1;
|
|
extraEnd := 4 + getInt;
|
|
inc(cur, 4);
|
|
while cur < extraEnd do
|
|
begin
|
|
code := getInt;
|
|
inc(cur, 4);
|
|
// inc(cur, 4);
|
|
next := cur + getInt + 4;
|
|
case code of
|
|
EI_flags:
|
|
begin
|
|
ev.flags := getInt;
|
|
// inc(cur, 4);
|
|
end;
|
|
EI_UID:
|
|
begin
|
|
// s := str.re
|
|
s := getString;
|
|
if Length(s) > 0 then
|
|
if Assigned(thisCnt) and thisCnt.equals(s) then
|
|
ev.who := thisCnt
|
|
else if Account.AccProto.getMyInfo.equals(s) then
|
|
ev.who := Account.AccProto.getMyInfo
|
|
else
|
|
begin
|
|
thisCnt := Account.AccProto.getContact(s);
|
|
ev.who := thisCnt;
|
|
end;
|
|
end;
|
|
EI_WID:
|
|
begin
|
|
ev.WID := getString;
|
|
end;
|
|
end;
|
|
cur := next;
|
|
end;
|
|
end; // parseExtraInfo
|
|
|
|
var
|
|
len: Int64;
|
|
// iu : TUID;
|
|
i: Integer;
|
|
curPos: Int64;
|
|
begin
|
|
loading := True;
|
|
try
|
|
// cur:=1;
|
|
cryptMode := CRYPT_SIMPLE;
|
|
hashed := '';
|
|
Cnt2I := 0;
|
|
Cnt1I := 0;
|
|
if not Assigned(str) then
|
|
begin
|
|
Result := True;
|
|
Exit;
|
|
end;
|
|
len := str.Size;
|
|
thisCnt := nil;
|
|
thisCnt2 := nil;
|
|
str.Seek(0, 0);
|
|
curPos := 0;
|
|
// while str.Position < len do
|
|
if len > 0 then
|
|
repeat
|
|
ev := Thevent.Create;
|
|
case getInt of
|
|
// case getInt1(str) of
|
|
HI_event:
|
|
begin
|
|
ev.cryptMode := cryptMode;
|
|
ev.kind := getByte;
|
|
begin
|
|
// iu := IntToStr(getInt);
|
|
i := getInt;
|
|
if i > 0 then
|
|
begin
|
|
if Assigned(thisCnt) and thisCnt.equals(i) then
|
|
begin
|
|
inc(Cnt1I);
|
|
ev.who := thisCnt
|
|
end
|
|
else if Account.AccProto.getMyInfo.equals(i) then
|
|
ev.who := Account.AccProto.getMyInfo
|
|
else if Assigned(thisCnt2) and thisCnt2.equals(i) then
|
|
begin
|
|
inc(Cnt2I);
|
|
ev.who := thisCnt2
|
|
end
|
|
else
|
|
begin
|
|
if not Assigned(thisCnt) or (Assigned(thisCnt2) and (Cnt2I > Cnt1I)) then
|
|
begin
|
|
Cnt1I := 0;
|
|
thisCnt := Account.AccProto.getContact(i);
|
|
ev.who := thisCnt;
|
|
end
|
|
else
|
|
begin
|
|
Cnt2I := 0;
|
|
thisCnt2 := Account.AccProto.getContact(i);
|
|
ev.who := thisCnt2;
|
|
end
|
|
end
|
|
end
|
|
else
|
|
begin
|
|
// thisCnt := NIL;
|
|
ev.who := Account.AccProto.getMyInfo;
|
|
end
|
|
end;
|
|
ev.when := getDatetime;
|
|
parseExtrainfo;
|
|
ev.old_decryptInfo(getString);
|
|
old_eventList.add(ev);
|
|
end;
|
|
HI_hashed:
|
|
hashed := getString;
|
|
HI_cryptMode:
|
|
begin
|
|
// getInt; // skip length
|
|
str.Seek(4, soFromCurrent); // skip length
|
|
cryptMode := getByte;
|
|
end;
|
|
else
|
|
begin
|
|
TThread.Queue(nil, procedure
|
|
begin
|
|
msgDlg(getTranslation('The history of %s is corrupted, some data is lost', [uid]), True, mtError);
|
|
end);
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
end;
|
|
curPos := str.Position;
|
|
until (curPos >= len);
|
|
Result := True;
|
|
finally
|
|
loading := false;
|
|
end;
|
|
end; // fromStream
|
|
|
|
class function Thistory.GetExistingChats: TUIDS;
|
|
begin
|
|
Result := SQLDB.GetExistingChats;
|
|
end;
|
|
|
|
function Thistory.GetEventCount: Integer;
|
|
begin
|
|
Result := SQLDB.GetEventCount(hUID);
|
|
end;
|
|
|
|
function Thistory.GetAllEvents: Thevents;
|
|
begin
|
|
Result := SQLDB.GetAllEvents(hUID);
|
|
end;
|
|
|
|
function Thistory.GetLastEvents(Offset, Cnt: Integer; var NoMoreMessages: Boolean): Thevents;
|
|
begin
|
|
Result := SQLDB.GetLastMulti(hUID, Offset, Cnt, NoMoreMessages);
|
|
end;
|
|
|
|
function Thistory.GetLastEvent(Cnt: integer = 1): Thevent;
|
|
begin
|
|
Result := SQLDB.GetLastSingle(hUID, Cnt);
|
|
end;
|
|
|
|
function Thistory.GetTimeRange(FromTime, ToTime: TDateTime; var NoMoreMessages: Boolean; ToInclusive: Boolean = True): Thevents;
|
|
begin
|
|
Result := SQLDB.GetByTimeRange(hUID, FromTime, ToTime, NoMoreMessages, ToInclusive);
|
|
end;
|
|
|
|
function Thistory.getTimeRange(FromTime, ToTime: TDateTime): Thevents;
|
|
var
|
|
Dummy: Boolean;
|
|
begin
|
|
Result := SQLDB.GetByTimeRange(hUID, FromTime, ToTime, Dummy);
|
|
end;
|
|
|
|
function Thistory.GetByRowID(RowID: Int64): Thevent;
|
|
begin
|
|
Result := SQLDB.GetByRowID(hUID, RowID);
|
|
end;
|
|
|
|
function Thistory.GetByMsgID(MsgID: TMsgID; Recent: Boolean = True): Thevent;
|
|
begin
|
|
Result := SQLDB.GetByMsgID(hUID, MsgID, Recent);
|
|
end;
|
|
|
|
function Thistory.GetByTime(Time: TDateTime): Thevent;
|
|
begin
|
|
Result := SQLDB.GetByTime(hUID, Time);
|
|
end;
|
|
|
|
function Thistory.GetByWID(const WID: String): Thevent;
|
|
begin
|
|
Result := SQLDB.GetByWID(hUID, WID);
|
|
end;
|
|
|
|
function Thistory.GetBySender(const Sender: TUID): Thevents;
|
|
begin
|
|
Result := SQLDB.GetBySender(hUID, Sender);
|
|
end;
|
|
|
|
procedure Thistory.WriteMsgIDs(ReqID: Integer; MsgID: TMsgID; const WID: RawByteString);
|
|
begin
|
|
SQLDB.WriteMsgIDs(hUID, ReqID, MsgID, WID);
|
|
end;
|
|
|
|
procedure Thistory.WriteMsgFlags(MsgID: TMsgID; Flags: Integer);
|
|
begin
|
|
SQLDB.WriteMsgFlags(hUID, MsgID, Flags);
|
|
end;
|
|
|
|
procedure Thistory.DeleteFromToTime(St, En: TDateTime);
|
|
begin
|
|
SQLDB.DeleteByTimeRange(hUID, St, En);
|
|
end;
|
|
|
|
procedure Thistory.DeleteByMsgID(MsgID: TMsgID);
|
|
begin
|
|
SQLDB.DeleteByMsgID(hUID, MsgID);
|
|
end;
|
|
|
|
procedure Thistory.DeleteBySender(const Sender: TUID);
|
|
begin
|
|
SQLDB.DeleteBySender(hUID, Sender);
|
|
end;
|
|
|
|
function Thistory.DataSearch(const Txt: String; CaseSensitive: Boolean = False): Thevents;
|
|
begin
|
|
Result := SQLDB.DataSearch(hUID, Txt, CaseSensitive);
|
|
end;
|
|
|
|
procedure DelHistWith(const UID: TUID);
|
|
begin
|
|
SQLDB.DeleteChat(UID);
|
|
end;
|
|
|
|
procedure WriteToHistory(ev: Thevent; other: TICQContact = nil; patch: Boolean = False);
|
|
begin
|
|
ev := ev.clone;
|
|
if other <> nil then
|
|
ev.otherpeer := other;
|
|
if ev.otherpeer = nil then
|
|
ev.otherpeer := ev.chat;
|
|
if ev.otherpeer = nil then
|
|
ev.otherpeer := ev.who;
|
|
ev.WriteToHistory(ev.otherpeer.UID, patch);
|
|
ev.Free;
|
|
end;
|
|
|
|
function ExistsHistWith(const UID: TUID): Boolean;
|
|
begin
|
|
Result := SQLDB.ChatExists(UID);
|
|
end;
|
|
|
|
end.
|