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.
535 lines
14 KiB
Plaintext
535 lines
14 KiB
Plaintext
{
|
|
This file is part of R&Q.
|
|
Under same license
|
|
}
|
|
unit usersDlg;
|
|
{$I RnQConfig.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, ExtCtrls, StdCtrls,
|
|
Sciter, SciterAPI, RnQDialogs, ICQCommon, ICQSession;
|
|
|
|
{$I PubRTTI.inc}
|
|
|
|
type
|
|
PRnQUser = ^TRnQUser;
|
|
TRnQUser = record
|
|
uin: TUID;
|
|
name, // uinStr,
|
|
SubPath, path, prefix: string;
|
|
pwd: String;
|
|
encr: boolean;
|
|
end;
|
|
|
|
{$I NoRTTI.inc}
|
|
|
|
function FindInAvailableUsers(const uin: TUID): integer;
|
|
procedure ClearAvailableUsers;
|
|
procedure RefreshAvailableUsers;
|
|
function GetUserAutoStart(var Pass: String): TUID;
|
|
|
|
procedure GetUsersData(tag: Pointer; argc: UINT; argv: PSciterValue; retval: PSciterValue); cdecl;
|
|
procedure OpenICQReg(tag: Pointer; argc: UINT; argv: PSciterValue; retval: PSciterValue); cdecl;
|
|
procedure ChangeOrAddUser(tag: Pointer; argc: UINT; argv: PSciterValue; retval: PSciterValue); cdecl;
|
|
procedure CheckAccountPass(tag: Pointer; argc: UINT; argv: PSciterValue; retval: PSciterValue); cdecl;
|
|
procedure CreateAccount(tag: Pointer; argc: UINT; argv: PSciterValue; retval: PSciterValue); cdecl;
|
|
procedure DeleteAccount(tag: Pointer; argc: UINT; argv: PSciterValue; retval: PSciterValue); cdecl;
|
|
|
|
var
|
|
AvailableUsers: array of TRnQUser;
|
|
|
|
implementation
|
|
|
|
uses
|
|
StrUtils, ShlObj,
|
|
SciterLib, GlobalLib, UtilLib, LangLib, IniLib,
|
|
{$IFDEF UNICODE}
|
|
AnsiStrings,
|
|
{$ENDIF UNICODE}
|
|
ICQConsts, ICQContacts,
|
|
RnQZip, RDUtils, RnQSysUtils, RnQGlobal, RnQLangs, RQUtil,
|
|
mainDlg, RDGlobal, RDFileUtil;
|
|
|
|
const
|
|
Have2Sel = 'You have to select a user to delete it';
|
|
|
|
function FindInAvailableUsers(const uin: TUID): integer;
|
|
begin
|
|
for Result := 0 to Length(AvailableUsers) - 1 do
|
|
if AvailableUsers[result].uin = uin then
|
|
Exit;
|
|
Result := -1;
|
|
end;
|
|
|
|
procedure ClearAvailableUsers;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := 0 to Length(availableUsers)-1 do
|
|
begin
|
|
SetLength(availableUsers[i].name, 0);
|
|
// SetLength(availableUsers[i].uinStr, 0);
|
|
SetLength(availableUsers[i].SubPath, 0);
|
|
SetLength(availableUsers[i].path, 0);
|
|
SetLength(availableUsers[i].uin, 0);
|
|
SetLength(availableUsers[i].Prefix, 0);
|
|
end;
|
|
SetLength(availableUsers, 0);
|
|
end;
|
|
|
|
procedure RefreshAvailableUsers;
|
|
function getNick_SSI(const path: string; const uid: TUID;
|
|
var nick: String; var isEncripted: Boolean): Boolean;
|
|
function yesno(const l: String): boolean;
|
|
begin result := LowerCase(l)='yes' end;
|
|
var
|
|
db: TRnQCList;
|
|
ini: TStrings;
|
|
zf: TZipFile;
|
|
s: AnsiString;
|
|
cf: String;
|
|
i: Integer;
|
|
// cnt: TRnQcontact;
|
|
save: Boolean;
|
|
begin
|
|
Result := False;
|
|
nick := '';
|
|
save := False;
|
|
isEncripted := False;
|
|
ini := TStringList.create;
|
|
db := nil;
|
|
cf := path + PathDelim + dbFileName + '5';
|
|
if not FileExists(cf) then
|
|
cf := path + PathDelim + dbFileName + '4';
|
|
if FileExists(cf) then
|
|
begin
|
|
zf := TZipFile.Create;
|
|
try
|
|
zf.LoadFromFile(cf);
|
|
i := zf.IndexOf('about.txt');
|
|
if i >= 0 then
|
|
begin
|
|
isEncripted := zf.IsEncrypted(i);
|
|
Result := True;
|
|
if not isEncripted then
|
|
begin
|
|
ini.Text := zf.data[i];
|
|
s := ini.values['account-name'];
|
|
nick := UnUTF(s);
|
|
end;
|
|
end;
|
|
|
|
if not Result then
|
|
begin
|
|
i := zf.IndexOf(configFileName);
|
|
if i >=0 then
|
|
begin
|
|
isEncripted := zf.IsEncrypted(i);
|
|
Result := True;
|
|
if not isEncripted then
|
|
begin
|
|
ini.Text := zf.data[i];
|
|
s := ini.values['account-name'];
|
|
nick := UnUTF(s);
|
|
end;
|
|
end;
|
|
end;
|
|
{
|
|
if not Result then
|
|
begin
|
|
i := zf.IndexOf(dbFileName);
|
|
if i >=0 then
|
|
begin
|
|
isEncripted := zf.IsEncrypted(i);
|
|
Result := True;
|
|
if not isEncripted then
|
|
begin
|
|
s := zf.data[i];
|
|
db := str2db(protoClass._getContactClass, s);
|
|
cnt := db.get(protoClass._getContactClass, uid);
|
|
if Assigned(cnt) then
|
|
nick := cnt.nick;
|
|
freeDB(db);
|
|
end;
|
|
end;
|
|
end;
|
|
}
|
|
except
|
|
s := '';
|
|
end;
|
|
zf.Free;
|
|
end;
|
|
|
|
if not Result then
|
|
begin
|
|
cf := path + PathDelim + configFileName;
|
|
if fileExists(cf) then
|
|
begin
|
|
save := True;
|
|
Result := True;
|
|
try
|
|
ini.LoadFromFile(cf);
|
|
except
|
|
ini.Clear;
|
|
end;
|
|
nick := UnUTF(ini.values['account-name']);
|
|
end
|
|
else
|
|
begin
|
|
cf := path + PathDelim +OldconfigFileName;
|
|
if fileExists(cf) then
|
|
begin
|
|
Result := True;
|
|
save := True;
|
|
ini.LoadFromFile(cf);
|
|
nick := ini.values['account-name'];
|
|
end
|
|
end;
|
|
end;
|
|
|
|
if not Result then
|
|
begin
|
|
// loadDB(path+ PathDelim, db)
|
|
begin
|
|
zf := TZipFile.Create;
|
|
try
|
|
if FileExists(path + PathDelim + dbFileName + '3') then
|
|
zf.LoadFromFile(path + PathDelim + dbFileName + '3');
|
|
i := zf.IndexOf(dbFileName);
|
|
if i >=0 then
|
|
s := zf.data[i];
|
|
except
|
|
s := '';
|
|
end;
|
|
zf.Free;
|
|
end;
|
|
if s = '' then
|
|
s := loadFileA(path+ PathDelim +dbFileName);
|
|
{
|
|
if s > '' then
|
|
begin
|
|
Result := True;
|
|
db:=str2db(protoClass._getContactClass, s);
|
|
cnt := db.get(protoClass._getContactClass, uid);
|
|
if Assigned(cnt) then
|
|
nick := cnt.nick;
|
|
end;
|
|
}
|
|
// if not result then
|
|
// nick := ' ';
|
|
if save then
|
|
begin
|
|
ini.values['account-name']:= UTF(nick);
|
|
ini.saveToFile(cf);
|
|
end;
|
|
FreeDB(db);
|
|
end;
|
|
ini.free;
|
|
end; // getNick
|
|
|
|
procedure addAvailableUser(const UID: TUID; const pPath, pPrefix: String);
|
|
var
|
|
n: Integer;
|
|
begin
|
|
n := length(availableUsers);
|
|
setlength(availableUsers, n + 1);
|
|
// with availableUsers[n] do
|
|
begin
|
|
// availableUsers[n].uinStr:=extractFileName(pPath);
|
|
with availableUsers[n] do
|
|
begin
|
|
// if copy(uinStr, 1, 4) = AIMprefix then
|
|
// uinStr := copy(uinStr, 5, length(uinStr));
|
|
// uinStr:=extractFileName(pPath);
|
|
SubPath := extractFileName(pPath);
|
|
// uinStr := UID;
|
|
uin := UID;
|
|
// uid := uinStr;
|
|
getNick_SSI(pPath, UID, name, encr);
|
|
Prefix := pPrefix;
|
|
path:= ExtractFilePath(pPath);
|
|
end;
|
|
end;
|
|
end; // addAvailableUser
|
|
|
|
procedure searchIn(path: String; const Prefix: String = '');
|
|
var
|
|
sr: TsearchRec;
|
|
s: String;
|
|
s2: TUID;
|
|
begin
|
|
path := includeTrailingPathDelimiter(path);
|
|
ZeroMemory(@sr.FindData, SizeOf(TWin32FindData));
|
|
if FindFirst(path + '*', faDirectory, sr) = 0 then
|
|
repeat
|
|
if (sr.Attr and faDirectory > 0) and (sr.name <> '.')and (sr.name <> '..') then
|
|
begin
|
|
s := ExtractFileName(sr.name);
|
|
s2 := s;
|
|
if TICQSession._isProtoUid(s2) then
|
|
addAvailableUser(s2, path + sr.name, Prefix);
|
|
end;
|
|
until FindNext(sr) > 0;
|
|
FindClose(sr);
|
|
end;
|
|
|
|
var
|
|
s: String;
|
|
i, j, n: Integer;
|
|
found: Boolean;
|
|
ss: TUID;
|
|
// uid: AnsiString;
|
|
begin
|
|
ClearAvailableUsers;
|
|
searchIn(myPath);
|
|
if RnQMainPath > '' then
|
|
searchIn(myPath + RnQMainPath);
|
|
|
|
// s := getSpecialFolder('AppData') + 'R&Q\';
|
|
s := getSpecialFolder(CSIDL_APPDATA) + 'R&Q\';
|
|
searchIn(s, 'App\');
|
|
|
|
if (cmdLinePar.userPath > '') and not AnsiSameText(cmdLinePar.userPath, usersPath) then
|
|
if LowerCase(s) <> LowerCase(cmdLinePar.userPath) then
|
|
searchIn(cmdLinePar.userPath, 'User\');
|
|
|
|
s := usersPath;
|
|
while s > '' do
|
|
searchIn(chop(';',s), 'Users path\');
|
|
|
|
s := mypath + accountsPath;
|
|
if s <> usersPath then
|
|
while s>'' do
|
|
searchIn(chop(';',s));
|
|
|
|
if cmdLinePar.startUser > '' then
|
|
begin
|
|
found := False;
|
|
for n := 0 to length(availableUsers) - 1 do
|
|
begin
|
|
ss := cmdLinePar.startUser;
|
|
if TICQSession._isProtoUid(ss) and (availableUsers[n].uin = ss) then
|
|
found := True;
|
|
end;
|
|
if not found then
|
|
begin
|
|
// fantomWork := True;
|
|
addAvailableUser(cmdLinePar.startUser, myPath + cmdLinePar.startUser, 'CMD\');
|
|
end;
|
|
end;
|
|
|
|
n := length(availableUsers);
|
|
for i := 0 to n - 2 do
|
|
for j := i + 1 to n - 1 do
|
|
swap4(availableUsers[i], availableUsers[j], sizeOf(availableUsers[i]), availableUsers[i].uin > availableUsers[j].uin);
|
|
end; // refreshAvailableUsers
|
|
|
|
function GetUserAutoStart(var Pass: String): TUID;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
RefreshAvailableUsers;
|
|
Result := '';
|
|
Pass := '';
|
|
|
|
if not (CmdLinePar.StartUser = '') then
|
|
Result := ExtractFileName(CmdLinePar.StartUser)
|
|
else
|
|
begin
|
|
I := FindInAvailableUsers(autostartUIN);
|
|
if I >= 0 then
|
|
Result := autostartUIN
|
|
else if Length(AvailableUsers) = 1 then
|
|
Result := AvailableUsers[0].uin;
|
|
end;
|
|
|
|
if not (Result = '') then
|
|
begin
|
|
I := FindInAvailableUsers(Result);
|
|
if I >= 0 then
|
|
begin
|
|
with AvailableUsers[i] do
|
|
if encr and not CheckAccPass(uin, path + SubPath + PathDelim + dbFilename + '5', Pass) then
|
|
Result := ''
|
|
else
|
|
NewAccPass := Pass;
|
|
end else
|
|
Result := '';
|
|
end;
|
|
end;
|
|
|
|
procedure GetUsersData(tag: Pointer; argc: UINT; argv: PSciterValue; retval: PSciterValue); cdecl;
|
|
var
|
|
RnQVer: String;
|
|
I: Integer;
|
|
UsersVar: TParams;
|
|
Data: TParams;
|
|
begin
|
|
RnQVer := IntToStr(RnQBuild) + ' ' + GetTranslation('Build %d', [RnQBuildCustom]);
|
|
{$IFDEF CPUX64}
|
|
RnQVer := RnQVer + ' x64';
|
|
{$ENDIF CPUX64}
|
|
|
|
RefreshAvailableUsers;
|
|
|
|
SetLength(UsersVar, Length(AvailableUsers));
|
|
for I := 0 to Length(AvailableUsers) - 1 do
|
|
UsersVar[I] := UI.RecordToVar(AvailableUsers[I]);
|
|
|
|
SetLength(Data, 4);
|
|
Data[0] := LastUser;
|
|
if Assigned(Account.AccProto) then
|
|
Data[1] := String(Account.AccProto.MyAccNum)
|
|
else
|
|
Data[1] := '';
|
|
Data[2] := UsersVar;
|
|
Data[3] := RnQVer;
|
|
|
|
V2S(Data, retval);
|
|
end;
|
|
|
|
procedure OpenICQReg(tag: Pointer; argc: UINT; argv: PSciterValue; retval: PSciterValue); cdecl;
|
|
begin
|
|
utilLib.OpenURL('https://icq.com/join/');
|
|
end;
|
|
|
|
procedure ChangeOrAddUser(tag: Pointer; argc: UINT; argv: PSciterValue; retval: PSciterValue); cdecl;
|
|
begin
|
|
iniLib.ChangeOrAddUser
|
|
end;
|
|
|
|
procedure CheckAccountPass(tag: Pointer; argc: UINT; argv: PSciterValue; retval: PSciterValue); cdecl;
|
|
var
|
|
I: Integer;
|
|
Res: Boolean;
|
|
Pass: String;
|
|
UID: PWideChar;
|
|
StrLen: Cardinal;
|
|
begin
|
|
UID := '';
|
|
API.ValueStringData(argv, UID, StrLen);
|
|
|
|
if UID = '' then
|
|
begin
|
|
V2S(False, retval);
|
|
Exit;
|
|
end;
|
|
|
|
Res := False;
|
|
I := FindInAvailableUsers(UID);
|
|
if I >= 0 then
|
|
begin
|
|
with AvailableUsers[I] do
|
|
if encr then
|
|
begin
|
|
Res := CheckAccPass(uin, path + SubPath + PathDelim + dbFilename + '5', Pass);
|
|
NewAccPass := Pass;
|
|
end;
|
|
end;
|
|
|
|
V2S(Res, retval);
|
|
end;
|
|
|
|
procedure CreateAccount(tag: Pointer; argc: UINT; argv: PSciterValue; retval: PSciterValue); cdecl;
|
|
var
|
|
UID: PWideChar;
|
|
UIDOnly: TUID;
|
|
StrLen: Cardinal;
|
|
UserPath: String;
|
|
IsProto: Boolean;
|
|
begin
|
|
UID := '';
|
|
API.ValueStringData(argv, UID, StrLen);
|
|
|
|
if CmdLinePar.UserPath > '' then
|
|
UserPath := CmdLinePar.UserPath
|
|
else
|
|
UserPath := MyPath + AccountsPath;
|
|
|
|
UIDOnly := UID;
|
|
IsProto := TICQSession._IsProtoUid(UIDOnly);
|
|
if TICQSession._IsValidUid(UIDOnly) then
|
|
UIDOnly := TICQContact.TrimUID(UIDOnly);
|
|
|
|
if not IsProto then
|
|
begin
|
|
MsgDlg('Not a valid user identifier', True, mtError);
|
|
Exit;
|
|
end;
|
|
|
|
if FindInAvailableUsers(UIDOnly) > -1 then
|
|
begin
|
|
MsgDlg(GetTranslation('%s already exists', [UID]), False, mtError);
|
|
Exit;
|
|
end;
|
|
|
|
UserPath := UserPath + UIDOnly + PathDelim;
|
|
IOresult;
|
|
ForceDirectories(UserPath);
|
|
IOresult;
|
|
LastUser := UIDOnly;
|
|
|
|
UI.ReloadUsers;
|
|
end;
|
|
|
|
procedure DeleteAccount(tag: Pointer; argc: UINT; argv: PSciterValue; retval: PSciterValue); cdecl;
|
|
var
|
|
UIN: PWideChar;
|
|
UINToDelete: TUID;
|
|
StrLen: Cardinal;
|
|
I: Integer;
|
|
Path: String;
|
|
ItsMe, Continue: Boolean;
|
|
begin
|
|
UIN := '';
|
|
API.ValueStringData(argv, UIN, StrLen);
|
|
UINToDelete := UIN;
|
|
|
|
if UINToDelete = '' then
|
|
MsgDlg(Have2Sel, True, mtInformation)
|
|
else
|
|
begin
|
|
I := FindInAvailableUsers(UINToDelete);
|
|
if I = -1 then
|
|
begin
|
|
MsgDlg('Error deleting this user!', True, mtError);
|
|
Exit;
|
|
end;
|
|
|
|
UINToDelete := AvailableUsers[I].uin;
|
|
Path := AvailableUsers[I].path + AvailableUsers[I].SubPath;
|
|
if UINToDelete = '' then
|
|
begin
|
|
MsgDlg(Have2Sel, True, mtInformation);
|
|
Exit;
|
|
end;
|
|
|
|
ItsMe := Assigned(Account.AccProto) and (Account.AccProto.GetMyInfo <> nil) and (Account.AccProto.GetMyInfo.Equals(UINToDelete));
|
|
if ItsMe then
|
|
begin
|
|
Continue := MessageDlg(
|
|
GetTranslation('The user you are trying to delete is the one in use right now.\nIt will be closed to be deleted. Continue?', [UINToDelete]),
|
|
mtConfirmation, [mbYes, mbNo]) = mrYes;
|
|
if Continue then
|
|
begin
|
|
UI.CL.Hide;
|
|
QuitUser;
|
|
end;
|
|
end else
|
|
Continue := MessageDlg(GetTranslation('Are you sure you want to delete %s ?', [UINToDelete]), mtConfirmation, [mbYes, mbNo]) = mrYes;
|
|
|
|
if Continue then
|
|
//if DelSubTree(UINToDelete) then
|
|
if DelTree(Path) then
|
|
begin
|
|
UI.ReloadUsers;
|
|
MsgDlg('User deleted!', True, mtInformation);
|
|
end else
|
|
MsgDlg('Error deleting this user!', True, mtError);
|
|
end
|
|
end;
|
|
|
|
end.
|