Маленькая аська :) https://rnq.ru
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

12214 lines
364 KiB

{
This file is part of R&Q.
Under same license
}
unit ICQv9;
{$I RnQConfig.inc}
{$DEFINE usesVCL}
{ $DEFINE usesDC}
interface
uses
windows, sysutils, classes, types,
RnQGlobal, RnQNet,
WinSock,
ICQflap,
RnQProtocol,
ICQContacts, strutils,
RQThemes, RDGlobal, RQUtil,
RnQPrefsLib,
ICQConsts, OverbyteIcsUtils;
{$I NoRTTI.inc}
type
TwpResult=packed record
nick,first,last,email:string;
StsMSG : String;
BDay : TDateTime;
uin : TUID;
authRequired:boolean;
// status:byte; // 0=offline 1=online 2=don't know
gender : byte;
status : word; // 0=offline 1=online 2=don't know
age : word;
BaseID : Word;
end; // TwpResult
TwpSearch=packed record
nick,first,last,email,city,state, keyword:string;
uin:TUID;
Token : RawByteString;
gender, lang:byte;
onlineOnly:boolean;
country:word;
wInterest : Word;
age:integer;
end; // TwpSearch
TOSSIItem = class(TObject)
public
ItemType : Byte;
FAuthorized: boolean;
ItemID, GroupID: integer;
ItemName : AnsiString;
// ItemNameU : String;
FInfoToken : RawByteString;
FProto : RawByteString; // may be "facebook" or "gtalk"
ExtData : RawByteString;
// Debug : String;
// ExtInfo: string;
// FNick,
Caption : String;
Fnote : String;
FCellular : String;
FCellular2 : String;
FCellular3 : String;
FMail : String;
FFirstMsg: TDateTime;
isNIL : Boolean; // In Not-In-List group
function Clone : TOSSIItem;
end;
Tssi = record
itemCnt: integer;
modTime: TDateTime;
items: TStringList;
end;
type
TsplitProc=procedure(const s: RawByteString) of object;
TsplitSSIProc=procedure(items: array of TOSSIItem) of object;
PSSIEvent = ^TSSIEvent;
TSSIEvent = class(TObject)
public
// ack fields
timeSent:TdateTime;
ID : Int64;
NUM : Integer;
kind: integer;
// uin:integer;
// flags : Cardinal;
// UID : TUID;
Item : TOSSIItem;
// email : string;
// info : string;
// cl:TRnQCList;
// wrote,lastmodify:Tdatetime;
// filepos:integer;
constructor Create;// override;
destructor Destroy; override; final;
// function toString:string;
// procedure fromString(s:string);
function Clone : TSSIEvent;
end; // TSSIEvent
TSSIacks = class(Tlist)
// function toString:string;
// procedure fromString(s:string);
function empty:boolean;
destructor Destroy; override; final;
procedure Clear; override; final;
// procedure clearU;
// function add(kind: Integer; dest:TUID; flags:integer=0; const info:string=''):TSSIEvent; overload;
// function add(kind: Integer; dest:TUID; flags:integer; cl:TRnQCList):TSSIEvent; overload;
// function add(ref : Int64; Num : Integer; kind: Integer; dest:TUID):TSSIEvent; overload;
function add(ref : Int64; Num : Integer; kind: Integer; item : TOSSIItem):TSSIEvent; overload;
function getAt(const idx:integer):TSSIEvent;
function findID(id:Integer; NUM:Integer = -1):integer;
// function remove(ev:TSSIEvent):boolean; overload;
// function stFor(who:Tcontact):boolean;
// procedure updateScreenFor(uin: TUID);
end; // TSSIacks
TmsgID = int64;
TicqEvent= (
IE_error = Byte(RnQProtocol.IE_error),
IE_online,
IE_offline,
IE_incoming,
IE_outgoing,
IE_msg,
IE_buzz,
IE_userinfo = Byte(High(RnQProtocol.TProtoEvent))+20,
IE_userinfoCP,
IE_email,
IE_webpager,
IE_fromMirabilis,
IE_contacts,
IE_numOfContactsChanged,
IE_wpEnd,
IE_userSimpleInfo,
IE_statusChanged,
IE_authReq,
IE_auth,
IE_authDenied,
IE_url,
IE_gcard,
IE_wpResult,
IE_addedYou,
IE_visibilityChanged,
IE_toofast,
IE_connecting,
IE_connected,
IE_loggin,
IE_redirecting,
IE_redirected,
IE_almostOnline,
// IE_serverConnecting,
IE_serverConnected,
IE_serverDisconnected,
IE_serverSent,
IE_serverGot,
IE_ProxySent,
IE_ProxyGot,
IE_dcConnected,
IE_dcDisconnected,
IE_dcSent,
IE_dcGot,
IE_dcError,
IE_creatingUIN,
IE_newUin,
//s@x
IE_ackImage,
IE_getImage,
//\\
IE_uinDeleted,
IE_myinfoACK,
IE_pwdChanged,
IE_pause,
IE_ack,
IE_automsgreq,
IE_sendingAutomsg,
IE_endOfOfflineMsgs,
IE_serverAck,
IE_msgError,
IE_Missed_MSG,
IE_sendingXStatus,
IE_ackXStatus,
IE_XStatusReq,
IE_fileReq,
IE_fileOk,
IE_fileDenied,
IE_fileack,
IE_fileabort,
IE_fileDone,
IE_contactupdate,
IE_contactSelfDeleted,
IE_redraw,
IE_typing,
IE_getAvtr,
IE_avatar_changed,
IE_srvSomeInfo
);
TicqPhase=(
null_, // offline
{$IFDEF USE_REGUIN}
creating_uin_, // asking for a new uin
{$ENDIF USE_REGUIN}
connecting_, // trying to reach the login server
login_, // performing login on login server
reconnecting_, // trying to reach the service server
relogin_, // performing login on service server
settingup_, // setting up things
online_
);
TicqSession=class;
TicqNotify=procedure (Sender:TicqSession; event:TicqEvent) of object;
TicqDCmode=(DC_NONE, DC_UPONAUTH, DC_ROSTER, DC_EVERYONE, DC_FAKE );
TrefKind=(
REF_null,
REF_wp,
REF_query,
REF_simplequery,
REF_savemyinfo,
REF_file,
REF_status,
REF_msg,
REF_contacts,
REF_auth,
REF_sms,
REF_login
);
{$IFDEF usesDC}
TICQdirect=class(TProtoDirect)
{ private
P_host, P_port: AnsiString;
public
sock : TRnQSocket;
eventID : TmsgID;
contact : TICQContact;
directs : Tdirects;
imserver : boolean;
imSender : Boolean;
needResume : Boolean;
Directed : Boolean;
UseLocProxy : Boolean;
mode : TDirectMode;
stage : byte;
kind :(DK_none, DK_file);
fileDesc : String;
// fileName :string;
// fileData :string;
buf : RawByteString;
fileCntReceived, fileCntTotal:integer;
fileSizeReceived, fileSizeTotal: Int64;
transferChkSum, fileChkSum : Cardinal;
receivedChkSum : Cardinal;
// Received : Int64;
fileName: String;
myspeed :integer;
hisVer :integer;
AOLProxy : record
ip : Cardinal;
port : word;
end;
data :pointer;}
constructor Create; Override;
// destructor Destroy; override;
private
// FOnDataAvailable, FOnDisconnect : TDirectDataAvailable;
// FOnDataNext : TDirectDataNext;
// FOnNotification : TDirectNotification;
procedure connected(Sender: TObject; Error: Word);
procedure received(Sender: TObject; Error: Word);
procedure sended(Sender: TObject; Error: Word);
procedure disconnected(Sender: TObject; Error: Word);
// function myPort:integer;
function myinfo:TICQContact;
// procedure sendPkt(const s: RawByteString);
function sendProxyCMD(cmd, flags :word; const data: RawByteString):boolean;
procedure connected2cli;
// procedure sendACK1;
// procedure sendACK2;
// procedure sendACK3;
// procedure sendVcard;
// procedure sendSpeed;
// procedure parseFileDC0101(s : RawByteString);
function parseFileDC0101(s : RawByteString) : Boolean;
function parseFileDC0205(s : RawByteString) : Boolean; // Resume request
procedure sendFilePrompt; // 0101
procedure sendACK_File; // 0202
procedure sendDone_File; // 0204
// procedure parseVcard(s : RawByteString);
public
// destructor Destroy;
procedure connect;
procedure connect2proxy;
procedure listen;
procedure close;
procedure Failed;
// procedure ProcessSend;
procedure DoneTransfer;
// procedure logMsg(err : Word; const msg : String);
// property ICQ : TicqSession read TicqSession(fproto);
end; // TICQdirect
{$ENDIF usesDC}
TICQSessionSubType = (SESS_IM=0, SESS_AVATARS=1, SESS_NEW_UIN=2);
// TicqSession = class(TRnQProtocol, IRnQProtocol)
TicqSession = class(TRnQProtocol)
public
// const ContactType : TRnQContactType = TICQContact;
// type ContactType = TICQContact;
const ContactType : TClass = TICQContact;
private
phase : TicqPhase;
wasUINwp : boolean; // trigger a last result at first result
// creatingUIN : boolean; // this is a special session, to create uin
// isAvatarSession : boolean; // this is a special session, to get avatars
protoType : TICQSessionSubType; // main session; to create uin; to get avatars
previousInvisible : boolean;
P_webaware : boolean;
P_authneeded : boolean;
P_showInfo : byte;
// startingInvisible : boolean;
startingVisibility : Tvisibility;
startingStatus : TICQstatus;
curStatus : TICQstatus;
fVisibility : Tvisibility;
Q : TflapQueue;
FLAPseq : word;
SNACref : TmsgID;
cookie : RawByteString;
waitingNewPwd : RawByteString;
cookieTime : TDateTime;
P_DCmode : TicqDCmode;
fDC_Fake_ip : TInAddr;
fDC_Fake_port : word;
fSSLServer : String;
fOscarProxyServer : String;
refs :array [1..maxRefs] of record
kind:TrefKind;
uid : TUID;
end;
SSIacks : TSSIacks;
// SSI_InServerTransaction : Boolean;
SSI_InServerTransaction : Integer;
savingMyInfo :record
running:boolean;
ACKcount:integer;
c:TICQContact;
end;
fRoster :TRnQCList;
fVisibleList :TRnQCList;
fInvisibleList :TRnQCList;
{$IFDEF UseNotSSI}
fIntVisibleList :TRnQCList;
fIntInvisibleList :TRnQCList;
fUseSSI, fUseLSI : Boolean;
{$ENDIF UseNotSSI}
tempVisibleList :TRnQCList;
spamList :TRnQCList;
fPwd : String;
fPwdHash : ShortString;
fSessionSecret : String;
fSessionToken : String;
fSessionTokenExpIn : Integer;
fSessionTokenTime : Integer;
buzzedLastTime : TDateTime;
// getAvatarFor : Integer;
procedure setWebaware(value:boolean);
procedure setAuthNeeded(value:boolean);
procedure setDCmode(v:TicqDCmode);
procedure set_DCfakeIP(ip : TInAddr);
procedure setDCfakePort(port: Word);
procedure setVisibility(v: Tvisibility);
procedure proxy_connected;
{$IFDEF UseNotSSI}
procedure sendAddContact(const buinlist:AnsiString); overload;
procedure sendRemoveContact(const buinlist:AnsiString); overload;
procedure sendAddVisible(const buinlist:AnsiString); overload;
procedure sendRemoveVisible(const buinlist:AnsiString); overload;
procedure sendAddInvisible(const buinlist:AnsiString); overload;
procedure sendRemoveInvisible(const buinlist:AnsiString); overload;
{$ENDIF UseNotSSI}
//procedure sendAddTempContact(cl:TRnQCList); overload;
//procedure sendRemoveTempContact(const buinlist:AnsiString); // 0310
public
{$IFDEF RNQ_AVATARS}
mainICQ : TicqSession; // Is PROTO_ICQ
avt_icq : TicqSession;
{$ENDIF RNQ_AVATARS}
// localSSI,
serverSSI: Tssi;
localSSI_modTime : TDateTime;
localSSI_itemCnt : Integer;
// listener : TicqNotify;
// MyInfo0 : TICQcontact;
birthdayFlag : boolean;
curXStatus : byte;
curXStatusStr : TXStatStr;
serviceServerAddr : AnsiString;
serviceServerPort : AnsiString;
// used to pass valors to listeners
eventError :TicqError;
eventOldStatus :TICQstatus;
eventOldInvisible :boolean;
eventUrgent :boolean;
eventAccept :TicqAccept;
eventContact :TICQContact;
eventContacts :TRnQCList;
eventWP :TwpResult;
eventMsgA : RawByteString;
eventAddress : string;
eventNameA : AnsiString;
eventData : RawByteString;
// eventFilename : string;
eventInt :integer; // multi-purpose
eventFlags :dword;
// eventFileSize :LongWord;
eventTime :TdateTime; // in local time
eventMsgID :TmsgID;
eventStream: TMemoryStream;
{$IFDEF usesDC}
eventDirect :TICQDirect;
{$ENDIF usesDC}
// acceptKey: string;
uploadAvatarFN : String;
// ConnectSSL : Boolean;
pPublicEmail,
showClientID,
offlineMsgsChecked,
SupportUTF,
SendingUTF,
UseCryptMsg,
UseAdvMsg,
{$IFDEF ICQ_OLD_STATUS}
// UseOldXSt,
{$ENDIF ICQ_OLD_STATUS}
{$IFDEF UseNotSSI}
LoginMD5,
useSSI2, useLSI2,
{$ENDIF UseNotSSI}
saveMD5Pwd,
AvatarsSupport,
AvatarsAutoGet,
AvatarsAutoGetSWF : Boolean;
myAvatarHash : RawByteString;
class function NewInstance: TObject; override; final;
// class function GetId: Word; override;
class function _GetProtoName: string; OverRide; final;
// class function _isValidUid(var uin:TUID):boolean; OverRide; final;
class function _isProtoUid(var uin:TUID):boolean; OverRide; final;
class function _isValidUid1(const uin:TUID):boolean; OverRide; final;
class function _getDefHost : Thostport; OverRide; final;
class function _getContactClass : TRnQCntClass; OverRide; final;
class function _getProtoServers : String; OverRide; final;
class function _getProtoID : Byte; OverRide; final;
class function _CreateProto(const uid : TUID) : TRnQProtocol; OverRide; final;
class function _RegisterUser(var pUID : TUID; var pPWD : String) : Boolean; OverRide; final;
class function _MaxPWDLen: Integer; OverRide; final;
// class function isValidUid(var uin:TUID):boolean;
// function isValidUid(var uin:TUID):boolean;
// function getContact(uid : TUID) : TRnQContact;
// class function getICQContact(const uid : TUID) : TICQContact; OverLoad;
// class function getICQContact(uin : Integer) : TICQContact; OverLoad;
function getICQContact(const uid : TUID) : TICQContact; OverLoad;
function getICQContact(uin : Integer) : TICQContact; OverLoad;
function getContact(const UID : TUID) : TRnQContact; OverRide; final;
function getContactClass : TRnQCntClass; OverRide; final;
function pwdEqual(const pass : String) : Boolean; OverRide; final;
property DCmode:TicqDCmode read P_dcmode write setDCmode;
property DCfakeIP:TInAddr read fDC_Fake_ip write set_DCfakeIP;
property DCfakePort:word read fDC_Fake_port write setDCfakePort;
{$IFDEF UseNotSSI}
property UseSSI: boolean read fUseSSI;
property UseLSI3: boolean read fUseLSI;
{$ENDIF UseNotSSI}
procedure setDCfakeIP(ip : AnsiString);
// procedure setStatusStr(s : String; Pic : AnsiString = '');
procedure setStatusStr(xSt : byte; stStr : TXStatStr);
procedure setStatusFull(st: byte; xSt : byte; stStr : TXStatStr);
// constructor Create; override;
// destructor Destroy; override;
constructor Create(const id : TUID; subType : TICQSessionSubType);
destructor Destroy; OverRide; final;
procedure ResetPrefs; OverRide; final;
procedure GetPrefs(var pp : TRnQPref); OverRide; final;
procedure SetPrefs(pp : TRnQPref); OverRide; final;
procedure Clear; OverRide; final;
procedure connect;
// procedure connect(createUIN:boolean; avt_session : Boolean = false); overload;
procedure disconnect; OverRide; final;
// procedure setStatus(s:Tstatus; inv:boolean);
procedure setStatus(st: byte); overload; OverRide; final;
procedure setStatus(s:TICQstatus; vis: Tvisibility); overload;
function getPwd : String; OverRide; Final;
function getPwdOnly : String; OverRide; Final;
procedure setPwd(const value:String); OverRide; Final;
procedure refreshSessionSecret();
function getSession: TSessionParams; OverRide; Final;
function getStatus: byte; OverRide; final;
function getVisibility : byte; OverRide; final;
function IsInvisible : Boolean; OverRide; final;
function isOnline:boolean; OverRide; final;
function isOffline:boolean; OverRide; final;
function isReady:boolean; OverRide; final; // we can send commands
function isConnecting:boolean; OverRide; final;
function isSSCL:boolean; OverRide; final;
function imVisibleTo(c:TRnQContact):boolean; OverRide; final;
function getStatusName: String; OverRide; final;
function getStatusImg : TPicName; OverRide; final;
function getXStatus:byte; OverRide; final;
public
// manage contact lists
function readList(l : TLIST_TYPES) : TRnQCList; OverRide; final;
procedure AddToList(l : TLIST_TYPES; cl:TRnQCList); OverLoad; OverRide; final;
procedure RemFromList(l : TLIST_TYPES; cl:TRnQCList); OverLoad; OverRide; final;
// manage contacts
// function validUid(var uin:TUID):boolean; inline;
// function validUid1(const uin:TUID):boolean; inline;
// class function isValidUid(var uin:TUID):boolean; Static;
procedure AddToList(l : TLIST_TYPES; cnt:TRnQContact); OverLoad; OverRide; final;
procedure RemFromList(l : TLIST_TYPES; cnt:TRnQContact); OverLoad; OverRide; final;
function isInList(l : TLIST_TYPES; cnt:TRnQContact) : Boolean; OverRide; final;
function addContact(c:TRnQContact; isLocal : Boolean = false):boolean; overload;OverRide; final;
function removeContact(cnt:TRnQContact):boolean;OverRide; final;
procedure InputChangedFor(cnt :TRnQContact; InpIsEmpty : Boolean; timeOut : boolean = false); OverRide; final;
procedure UpdateGroupOf(cnt : TRnQContact); OverRide; final;
procedure getClientPicAndDesc4(cnt:TRnQContact; var pPic : TPicName; var CliDesc : String); OverRide; final;
function maxCharsFor(const c:TRnQContact; isBin : Boolean = false):integer; OverRide; final;
function compareStatusFor(cnt1, Cnt2 : TRnqContact) : Smallint; OverRide; final;
procedure sendkeepalive;OverRide; final;
function canAddCntOutOfGroup : Boolean; OverRide; final;
{$IFDEF UNICODE}
// procedure notificationForMsgW(msgtype:byte; flags:byte; urgent:boolean;
// msg:string{; offline:boolean = false});
{$ENDIF UNICODE}
procedure notificationForMsg(msgtype:byte; flags:byte; urgent:boolean;
const msg: RawByteString{; offline:boolean = false});
function getLocalIPstr:string;
{$IFDEF usesDC}
function getNewDirect : TProtoDirect; OverRide; final;
function directTo(c:TICQContact):TICQDirect;
{$ENDIF usesDC}
public // ICQ Only
property SSLserver : String read fSSLServer;
property ProxyServer : String read fOscarProxyServer;
property getProtoType: TICQSessionSubType read protoType;
property webaware:boolean read P_webaware write setWebaware;
property authNeeded:boolean read P_authNeeded write setAuthNeeded;
property showInfo : Byte read P_showInfo write P_showInfo;
property pwd: String read getPwd write setPwd;
property visibility : Tvisibility read fVisibility write setVisibility;
{$IFDEF UseNotSSI}
procedure updateVisibility;
{$ENDIF UseNotSSI}
private
function getLocalIP:integer;
function serverPort:word;
function serverStart:word;
//procedure sendAddTempContact(const buinlist: RawByteString); overload; // 030F
function sendFLAP(ch:word; const data: RawByteString):boolean;
function sendSNAC(fam,sub:word; const data: RawByteString):boolean; OverLoad;
//function sendSNAC(fam,sub, flags:word; const data: RawByteString):boolean; OverLoad;
public // ICQ Only
procedure SSIdeleteContact(cnt : TRnQContact);
procedure SSIAddContact(c : TICQContact);
procedure SSI_DeleteItem(gID, iID, Tp : word; const iName : AnsiString = ''; const pExtData : RawByteString = '');
procedure SSI_UpdateContact(c : TICQContact);
procedure SSI_UpdateGroup(c : TICQContact);
procedure SSIdeleteGroup(gID:integer);
function SSI_deleteAvatar : Boolean;
procedure SSIUpdateGroup(const args:array of integer);
procedure addContact(cl:TRnQCList; SendIt : Boolean = True); overload;
{$IFDEF UseNotSSI}
procedure setVisibleList(cl:TRnQCList);
procedure setInvisibleList(cl:TRnQCList);
{$ENDIF UseNotSSI}
procedure clearTemporaryVisible;
procedure RequestContactList(isImp : Boolean = True);
function useMsgType2for(c:TICQContact):boolean;
procedure sendWPsearch(wp:TwpSearch; idx : Integer);
procedure sendWPsearch2(wp:TwpSearch; idx : Integer; IsWP : Boolean = True);
procedure sendAuthReq(const uin:TUID; const msg:string);
procedure sendAuth(const uin:TUID);
procedure sendAuthDenied(const uin:TUID; const msg:string='');
function getDCModeStr : AnsiString;
function getDCfakeIP : AnsiString;
function getDCfakePort : Integer;
function getUINStatus( const uin : TUID ) : Integer;
function CheckInvisibility2( const uin : TUID ) : Integer;
function CheckInvisibility3( const uin : TUID ) : Integer;
// procedure CheckInvisibility( uin : dword );
procedure SendTYPING(cnt : TRnQContact; notif_type : Word);
procedure RemoveMeFromHisCL(const uin : TUID);
procedure sendCreateUIN(const acceptKey : RawByteString);
procedure sendDeleteUIN;
procedure sendsaveMyInfoNew(c:TICQContact);
// procedure sendPermsNew;//(c:Tcontact);
procedure sendSticker(uin: TUID; const sticker: String);
procedure sendInfoStatus(const s : String);
procedure sendPrivacy(em : Word; ShareWeb : Boolean; authReq : Boolean);
procedure sendReqOfflineMsgs;
procedure sendDeleteOfflineMsgs;
procedure sendContacts(cnt : TRnQContact;flags:dword; cl:TRnQCList);
procedure sendQueryInfo(uin: Integer);
procedure sendSimpleQueryInfo(const uin: TUID);
procedure sendAdvQueryInfo(const uin: TUID);
procedure sendFullQueryInfo(const uin: TUID);
procedure sendNewQueryInfo(const uin: TUID);
procedure sendAddedYou(const uin: TUID);
procedure sendStatusCode(sendVis : Boolean = True);
procedure sendXStatusCodeOnly();
procedure sendCapabilities;
procedure resetStatusCode;
procedure SSIAuth_REPLY(const uin : TUID; isAccept : Boolean; const msg : String = '');
function sendAutoMsgReq(const uin:TUID):integer;
function RequestIcon(c : TICQContact) : Boolean;
function uploadAvatar(const fn : String) : Boolean;
procedure RequestXStatus(const uin : TUID);
{$IFDEF usesDC}
// function sendFileReq(uin:TUID; msg,fn:string; size:integer):integer; // returns handle
procedure sendFileAbort(cnt : TICQContact; msgID:TmsgID);
procedure sendFileAck(msgID:TmsgID);
function sendFileReq(const uin:TUID; const msg:string; fa : TFileAbout; useProxy : Boolean):integer;
function sendFileReq2(drct : TICQDirect):integer;
function sendFileReqPro(drct : TICQDirect):integer;
procedure sendFileOk(Drct : TICQDirect; SendMsg : Boolean = False;
isListen : Boolean = false; useProxy : Boolean = false);
// function sendFileTest(msgID:TmsgID; c:Tcontact; fn:string; size:integer) : Integer;
procedure ProcessReceiveFile(dirct : TICQDirect);
{$ENDIF usesDC}
procedure add2visible(cl:TRnQCList; OnlyLocal : Boolean = false); overload;
procedure add2invisible(cl:TRnQCList; OnlyLocal : Boolean = false); overload;
protected
// event managing
procedure notifyListeners(ev:TicqEvent);
// send packets
procedure sendMSGsnac(const uin : TUID; const sn : RawByteString);
procedure sendCryptMSGsnac(const uin : TUID; const sn : RawByteString);
// procedure sendPermissions;
{$IFDEF UseNotSSI}
procedure sendAddContact(cl:TRnQCList; OnlyLocal : Boolean = False); overload;
procedure sendRemoveContact(cl:TRnQCList); overload;
{$ENDIF UseNotSSI}
procedure sendRemoveVisible(cl:TRnQCList); overload;
procedure sendRemoveInvisible(cl:TRnQCList); overload;
procedure sendAddInvisible(cl:TRnQCList); overload;
procedure sendAddVisible(cl:TRnQCList); overload;
procedure sendACK(cont : TICQContact; status:integer; const msg:string; DownCnt: word = $FFFF);
procedure sendVisibility;
procedure parseTYPING_NOTIFICATION(const pkt : RawByteString);
{$IFDEF RNQ_AVATARS}
procedure parse0121(const pkt : RawByteString; flags : Word);
procedure iconUploadAck(const pkt : RawByteString);
// procedure RequestIcon(uin : Integer; hash : String);
procedure parseIcon(const pkt: RawByteString);
procedure initAvatarSess;
{$ENDIF RNQ_AVATARS}
procedure sendMyXStatus(cont : TICQContact; msgID : Int64);
procedure SSIreqRoster;
// function SSI_Item2packet(item : TOSSIItem) : String;
// procedure SSIUpdateGroup( grID : Integer);
procedure SSI_UpdateGroups(const args:array of integer);
// procedure SSIRenameGroup(gID:integer; gName:string);
// procedure renameSSIGroup(gID:integer; gName:string);
private
function add2visible(c:TICQContact):boolean; overload;
function add2ignore(c:TICQContact):boolean; //overload;
function remFromIgnore(c:TICQContact):boolean;
function add2invisible(c:TICQContact):boolean; overload;
function addTemporaryVisible(c:TICQContact):boolean; overload;
function addTemporaryVisible(cl:TRnQCList):boolean; overload;
function removeTemporaryVisible(c:TICQContact):boolean; overload;
function removeTemporaryVisible(cl:TRnQCList):boolean; overload;
function removeFromVisible(c:TICQContact):boolean; overload;
procedure removeFromVisible(const cl:TRnQCList); overload;
function removeFromInvisible(c:TICQContact):boolean; overload;
procedure removeFromInvisible(const cl:TRnQCList); overload;
procedure SSIsendAddTempVisible(const buid : AnsiString);
procedure SSIsendDelTempVisible(const buid : AnsiString);
procedure SSI_AddVisItem(const UID : TUID; iType : Word);
procedure SSI_DelVisItem(const UID : TUID; iType : Word);
procedure SSI_UpdateItem(const iName, iExtData : RawByteString; gID, iID, Tp : word);
Function SSI_CreateItem(const iName, iExtData : RawByteString; gID, iID, Tp : word) : word;
procedure SSI_CreateItems(Items : array of TOSSIItem);
procedure SSI_DeleteItems(Items : array of TOSSIItem);
{$IFDEF USE_REGUIN}
procedure send170c;
procedure parse170d(const snac: RawByteString);
{$ENDIF USE_REGUIN}
procedure sendChangePwd(const newPwd: RawByteString);
procedure parseGCdata(const snac:RawByteString; offline:boolean=FALSE);
// procedure parseStatus(snac:string; ofs:integer);
procedure parseOnlineInfo(const snac: RawByteString; pOfs: Integer; cont : TICQContact; isSt : Boolean;
isMsg : Boolean = True; ShowCntSts : Boolean = True);
procedure parseStatus(const snac: RawByteString; ofs:integer; cont : TICQContact;
isInvis : Boolean = false; Status_changed : Boolean = False);
{$IFDEF USE_REGUIN}
procedure parseNewUIN(const snac: RawByteString);
{$ENDIF USE_REGUIN}
procedure parseCookie(const flap : RawByteString);
procedure parseREDIRECTxSERVICE(const pkt : RawByteString); // 0105
procedure parseOncomingUser(const snac : RawByteString);
procedure parseOffgoingUser(const snac : RawByteString);
procedure parseMsgError(const snac : RawByteString; ref:integer);
procedure parseServerAck(const snac : RawByteString; ref:integer);
procedure parseSRV_LOCATION_ERROR(const snac : RawByteString; ref:integer);
procedure parseAuthKey(const snac : RawByteString);
procedure parse1503(const snac : RawByteString; ref:integer; flags : word);
procedure parse1501error(const snac : RawByteString; ref:integer; flags : word);
procedure parse040A(const snac : RawByteString);
procedure parse040B(const snac : RawByteString);
procedure parse0107(const snac : RawByteString);
procedure parse010A(const snac : RawByteString);
procedure parse010F(const snac : RawByteString);
procedure parse0206(snac : RawByteString);
procedure parse020C(const snac : RawByteString; ref : Integer);
procedure parseIncomingMsg(snac : RawByteString);
procedure goneOffline; // called going offline
{$IFDEF usesDC}
procedure dc_connected(Sender: TObject; Error: Word);
{$ENDIF usesDC}
procedure connected(Sender: TObject; Error: Word);
procedure OnProxyTalk(Sender : TObject; isReceive : Boolean; Data : RawByteString);
procedure OnProxyError(Sender : TObject; Error : Integer; Msg : String);
procedure onDataAvailable(Sender: TObject; Error: Word);
procedure received(Sender: TObject; Error: Word; pkt : RawByteString);
procedure disconnected(Sender: TObject; Error: Word);
procedure parseContactsString(s: RawByteString);
procedure parseAuthString(s: RawByteString);
procedure parsePagerString(s: RawByteString);
procedure parseAuthReq(const pkt : RawByteString);
procedure newLogin;
procedure SSIreqLimits;
procedure SSIchkRoster;
procedure SSIsendReady;
procedure SSIstart();
procedure SSIstop(needSend : Boolean = false);
// procedure SSIUpdate(ID : String);
procedure SplitCL2SSI_DelItems(proc:TsplitSSIProc; cl:TRnQCList; Tp : word);
// procedure SSInewGroup(gID:integer; gName:string; iID : integer = 0);
// procedure SSIAddContact(vUIN, vName: String;
// vMail: String=''; vSMS: String=''; cmnt: String='');
// procedure SSInewContact(gID,cID:integer; nUIN,cName, vMail, vSMS, cmnt:string);
function SSI_sendAddContact(cnt : TICQContact; needAuth : Boolean = false; pItem : TOSSIItem = NIL) : Word;
// procedure SSInewContactauth(gID,cID:integer; nUIN,cName:string);
// procedure SSIdeleteContact(gID,cID:integer; nUIN,cName:string);
procedure parse131b(const pkt : RawByteString);
procedure parse131C(const pkt : RawByteString);
procedure parse1308090A(const snac:RawByteString; ref:integer; iType : Word);
// procedure parse1308(snac:string; ref:integer);
// procedure parse1309(snac:string; ref:integer);
// procedure parse130A(snac:string; ref:integer);
procedure parse130E(const snac: RawByteString; ref:integer); //SSIackParse(Pkt: String); // #$13#$0E
procedure ProcessSSIacks;
procedure parse1311(const snac: RawByteString; ref: Integer); // SSI_Begin transaction
procedure parse1312(const snac: RawByteString; ref: Integer); // SSI_END transaction
procedure sendLogin;
procedure sendImICQ;
procedure sendCookie;
procedure SendReqBuddy(Second: Boolean = False);
procedure sendIMparameter(chn : AnsiChar);
procedure sendClientReady;
function addRef(k: TRefKind; const uin: TUID): Integer;
function dontBotherStatus:boolean;
function myUINle: RawByteString;
function getFullStatusCode:dword;
public // All
function sendMsg(cnt : TRnQContact; var flags:dword; const msg:string; var requiredACK:boolean):integer; OverRide; final; // returns handle
function sendBuzz(cnt: TRnQContact): Boolean;
procedure SetListener(l : TProtoNotify); OverRide; final;
procedure AuthGrant(Cnt : TRnQContact); OverRide; final;
procedure AuthRequest(cnt : TRnQContact; const reason : String); OverRide; final;
function isMyAcc(c : TRnQContact) : Boolean; OverRide; final;
function getMyInfo : TRnQContact; OverRide; final;
// procedure setMyInfo(cnt : TRnQContact);
function getStatuses : TStatusArray; OverRide; final;
function getVisibilitis : TStatusArray; OverRide; final;
function getStatusMenu : TStatusMenu; OverRide; final;
function getVisMenu : TStatusMenu; OverRide; final;
function getStatusDisable : TOnStatusDisable; OverRide; final;
function getPrefPage : TPrefFrameClass; OverRide; final;
function GenSSID : Integer;
procedure applyBalloon;
// property statuses : TStatusArray read getStatuses;
property MyInfo :TRnQContact read getMyInfo;
procedure sendSMS(dest, msg: String; ack: Boolean);
procedure sendSMS2(dest, msg: String; ack: Boolean);
end; // TicqSession
TICQProtoClass = class of TICQSession;
{$IFNDEF ICQ_OLD_STATUS}
const
UseOldXSt = False;
{$ENDIF ICQ_OLD_STATUS}
{$IFNDEF UseNotSSI}
const
LoginMD5 = True;
{$ENDIF UseNotSSI}
var
// My_proto_ver : Byte = 10;
// ICQ_TCP_VERSION := My_proto_ver;
// sendInterests,
supportInvisCheck,
addTempVisMsg,
showInvisSts,
AvatarsNotDnlddInform,
avtSessInit : Boolean;
ToUploadAvatarFN : String;
ToUploadAvatarHash : RawByteString;
ExtClientCaps : RawByteString;
AddExtCliCaps : Boolean;
sendBalloonOn :integer;
sendBalloonOnDate :Tdatetime;
{$IFDEF RNQ_FULL}
// SendedFlaps : LongWord;
// ICQMaxFlaps : LongWord = 70;
{$ENDIF}
// onStatusDisable :array [SC_ONLINE..pred(SC_OFFLINE)] of record
// onStatusDisable :array [SC_ONLINE..pred(SC_)] of record
// onStatusDisable :array [TICQstatus] of TOnStatusDisable;
var
ICQstatuses, icqVis : TStatusArray;
statMenu, icqVisMenu : TStatusMenu;
implementation
uses
Controls, dateUtils,
{$IFDEF UNICODE}
AnsiStrings,
{$ENDIF UNICODE}
RnQZip, OverbyteIcsZLibHigh, OverbyteIcsZLibObj,
OverbyteIcsMD5, OverbyteIcsWSocket,
// ElAES,
aes_type, aes_ecb,
RnQDialogs, RnQLangs, RDUtils, RnQBinUtils,
Base64, //ZLibEx,
RDFileUtil, RnQCrypt,
// rtf2html,
{$IFDEF RNQ_AVATARS}
RnQ_Avatars,
{$ENDIF}
globalLib, UtilLib,
RQ_ICQ, ICQClients, history, events,
themesLib, prefDlg, chatDlg,
RnQStrings, outboxLib, icq_fr,
Protocol_ICQ, Stickers;//, outboxLib;
const
DT2100miliseconds=1/(SecsPerDay*10);
var
lastSendedFlap : TDateTime;
procedure splitCL(proc:TsplitProc; cl:TRnQCList);
var
i,cnt:integer;
s: RawByteString;
begin
if TList(cl).count=0 then
begin
proc('');
exit;
end;
i:=0;
while (i< TList(cl).count) do
begin
if i > 0 then
sleep(1000);
cnt:=600;
s:='';
while (i< TList(cl).count) and (cnt>0) do
begin
s:=s + TICQContact(cl.getAt(i)).buin;
inc(i);
dec(cnt);
end;
proc(s);
end;
end;
procedure splitSSICL(proc:TsplitProc; cl:TRnQCList; OnlyLocal : Boolean);
var
i,cnt:integer;
s: RawByteString;
begin
if TList(cl).count=0 then
begin
proc('');
exit;
end;
i:=0;
while (i< TList(cl).count) do
begin
if i > 0 then
sleep(1000);
cnt:=100;
s:='';
while (i< TList(cl).count) and (cnt>0) do
begin
with TICQContact(cl.getAt(i)) do
if CntIsLocal or (not OnlyLocal and not Authorized) then
begin
s:=s + buin;
dec(cnt);
end;
inc(i);
end;
proc(s);
end;
end;
procedure splitSSICL60(proc:TsplitProc; cl:TRnQCList; OnlyLocal : Boolean);
var
i,cnt:integer;
s: RawByteString;
begin
if TList(cl).count=0 then
begin
proc('');
exit;
end;
i:=0;
while (i< TList(cl).count) do
begin
if i > 0 then
sleep(1000);
cnt:=10;
s:='';
while (i< TList(cl).count) and (cnt>0) do
begin
with TICQContact(cl.getAt(i)) do
if CntIsLocal or (not OnlyLocal and not Authorized) then
begin
s:=s + buin;
dec(cnt);
end;
inc(i);
end;
proc(s);
end;
end;
function SSI_Item2packet(item : TOSSIItem) : RawByteString;
begin
if Assigned(item) and (item is TOSSIItem) then
with item do
Result := Length_BE(ItemName) + word_BEasStr(GroupID) +
word_BEasStr(ItemID) + word_BEasStr(ItemType) +
Length_BE(ExtData)
else
Result := '';
end;
procedure SplitCL2SSI_Items(proc:TsplitSSIProc; cl:TRnQCList;
iExtData : RawByteString; gID, iID, Tp : word);
var
i, len1, LenAll:integer;
k : Integer;
arr : array of TOSSIItem;
// s:string;
begin
if TList(cl).count=0 then
begin
proc([]);
exit;
end;
i:=0;
while (i< TList(cl).count) do
begin
if i > 0 then
sleep(1000);
LenAll := 0;
SetLength(arr, 0);
// s:='';
while (i< TList(cl).count) and (LenAll<6000) do
begin
with cl.getAt(i) do
begin
// s:=s + buin;
k := length(arr);
SetLength(arr, k + 1);
arr[k] := TOSSIItem.Create;
with arr[k] do
begin
ItemType := Tp;
ItemName := UID;
ItemID := 0;
ExtData := '';
Len1 := Length(SSI_Item2packet(arr[k]));
end;
Inc(LenAll, len1);
end;
inc(i);
// dec(cnt);
end;
proc(arr);
end;
end;
function code2status(code:dword):TICQstatus;
begin
code:=code and ($FFFF-8-flag_invisible);
case code of
$10: begin result:=SC_OCCUPIED; exit end;
4: begin result:=SC_NA; exit end;
2: begin result:=SC_DND; exit end;
end;
for result:=low(result) to high(result) do
if status2code[result] = code then
exit;
result:= SC_ONLINE;
end; // code2status
function sameMethods(a,b:TicqNotify):boolean;
begin result:= double((@a)^) = double((@b)^) end;
function encrypted(const s: RawByteString): RawByteString;
const
cryptData:array [1..16] of byte=($F3,$26,$81,$C4,$39,$86,$DB,$92,$71,$A3,$B9,$E6,$53,$7A,$95,$7C);
var
i:integer;
begin
i:=length(s);
setLength(result,i);
while i > 0 do
begin
byte(result[i]):=byte(s[i]) xor cryptData[i];
dec(i);
end;
end; // encrypted
{
function str2url(const s:string):string;
var
i:integer;
ss:string;
begin
result:='';
for i:=1 to length(s) do
begin
case s[i] of
' ':ss:='%20';
'A'..'Z','a'..'z','0'..'9':ss:=s[i];
else ss:='%'+intToHex(ord(s[i]),2);
end;
result:=result+ss;
end;
end; // str2url}
function str2url(const s: AnsiString): AnsiString;
var
i:integer;
ss: AnsiString;
begin
result:='';
for i:=1 to length(s) do
begin
case s[i] of
' ':ss:='%20';
'A'..'Z','a'..'z','0'..'9':ss:=s[i];
else ss:='%'+IntToHexA(Byte(s[i]),2);
end;
result:=result+ss;
end;
end; // str2url
function str2html(const s: AnsiString): AnsiString;
var
i: integer;
ss: AnsiString;
begin
Result := '';
for i := 1 to length(s) do
begin
case s[i] of
{ 'à':ss:='&egrave;';
'è':ss:='&egrave;';
'é':ss:='&eacute;';
'ì':ss:='&igrave;';
'ò':ss:='&ograve;';
'ù':ss:='&ugrave;';
'É':ss:='&Eacute;';}
'<': ss := '&lt;';
'>': ss := '&gt;';
'"': ss := '&quot;';
'&': ss := '&amp;';
else ss:=s[i];
end;
Result := Result + ss;
end;
end; // str2html
{
function str2html2(const s:string):string;
begin
result:=template(s, [
'<', '&lt;',
'>', '&gt;'
// CRLF, '<br/>',
// #13, '<br/>',
// #10, '<br/>',
// '&', '&amp;'
]);
end; // str2html
}
function str2html2(const s: AnsiString): AnsiString;
begin
result := template(s, [
AnsiString('<'), AnsiString('&lt;'),
AnsiString('>'), AnsiString('&gt;')
// CRLF, '<br/>',
// #13, '<br/>',
// #10, '<br/>',
// '&', '&amp;'
]);
end; // str2html
function xml_sms(me: TRnQcontact; const dest, msg: AnsiString; ack: boolean): AnsiString;
const
yesno: array [boolean] of AnsiString = ('No', 'Yes');
begin
result :=
'<icq_sms_message>' +
'<destination>' + dest + '</destination>' +
'<text>' + str2html(msg) + '</text>' +
'<codepage>1251</codepage>' +
//'<encoding>utf8</encoding>' +
'<senders_UIN>' + me.uid + '</senders_UIN>' +
'<senders_name>' + AnsiString(me.displayed) + '</senders_name>' +
'<delivery_receipt>' + yesno[ack] + '</delivery_receipt>' +
'<time>' + AnsiString(FormatDatetime('ddd, dd mmm yyyy hh:nn:ss', now - gmtoffset)) + ' GMT</time>' +
'</icq_sms_message>';
end; // xml_sms
/////////////////////////////////////////////////////////
{$IFDEF usesDC}
constructor TICQDirect.create;
begin
{ sock:=TRnQSocket.create(NIL);
sock.tag:=integer(@self);
sock.OnDataAvailable:=received;
sock.OnSessionClosed:=disconnected;
//sock.OnSocksError := OnProxyError;
imserver:=TRUE;
kind:=DK_none;
stage := 0;
mode := dm_bin_direct;
Directed := False;
needResume := False;
AOLProxy.ip := 0;
AOLProxy.port := 0;
UseLocProxy := True;
myspeed:=100;}
Inherited;
sock.OnDataAvailable:=received;
sock.OnSessionClosed:=disconnected;
end; // create
procedure TICQDirect.listen;
var
i : Integer;
s : Boolean;
begin
sock.OnSessionAvailable:=connected;
imserver := TRUE;
Directed := False;
// mode := dm_init;
sock.addr:='0.0.0.0';
sock.Port:= '0';
s := false;
for I := 0 to portsListen.PortsCount do
try
sock.Port := IntToStr(portsListen.getRandomPort);
sock.listen;
s := True;
Break;
except
S := false;
end;
if not s then
begin
// sock.getFreePort;
sock.Port:= '0';
sock.listen;
end;
logMsg(0, getTranslation('Listening port: %s', [sock.Port]));
// sock.port:='20000';
if (mode = dm_bin_direct) and (not imSender)and (kind = DK_file) then
TicqSession(directs.proto).sendFileOk(Self, True);
end; // listen
function TICQdirect.sendProxyCMD(cmd, flags :word; const data: RawByteString):boolean;
var
s: RawByteString;
begin
result:=FALSE;
if sock.State <> wsConnected then exit;
s:=word_BEasStr((Length(Data) + 10)) // Len
+#$04#$4A // PackVer
+word_BEasStr(cmd) // CmdType
+z // Unknown
+word_BEasStr(flags) // Flags
+data;
sendPkt(s);
s:='';
result:=TRUE;
end; // sendFLAP
procedure TICQDirect.connect;
begin
sock.OnSessionConnected:=connected;
imserver:=FALSE;
mode := dm_bin_direct;
//sock.addr:=dword_LE2ip(contact.connection.ip);
Directed := False;
if (sock.State = wsConnected)or
(sock.State = wsListening)
then
begin
sock.Close;
sock.WaitForClose; // prevent to change properties while the socket is open
end;
if UseLocProxy then
sock.proxySettings(directs.proto.aProxy)
else
sock.DisableProxy;
if (TICQcontact(contact).connection.internal_ip > 0)
and (TICQcontact(contact).connection.ft_port > 0) then
begin
// sock.addr := dword_LE2ip(contact.connection.internal_ip);
sock.addr := dword_LE2ipU(TICQcontact(contact).connection.internal_ip);
sock.port := intToStr(TICQcontact(contact).connection.ft_port);
sock.connect;
end;
end; // connect
procedure TICQDirect.connect2proxy;
begin
sock.OnSessionConnected:=connected;
imserver:=FALSE;
mode := dm_bin_proxy;
//sock.addr:=dword_LE2ip(contact.connection.ip);
Directed := False;
if (sock.State = wsConnected)or
(sock.State = wsListening)
then
begin
sock.Close;
sock.WaitForClose; // prevent to change properties while the socket is open
end;
// if UseLocProxy then
sock.proxySettings(directs.proto.aProxy)
// else
// DisableProxy(sock)
;
if stage = 1 then
begin
if imSender then
sock.addr := TicqSession(directs.proto).ProxyServer
else
sock.addr := dword_LE2ipU(AOLProxy.ip);
sock.port := '5190';//TicqSession(directs.proto).serviceServerPort;
end
else
if stage = 2 then
begin
if not imSender then
sock.addr := TicqSession(directs.proto).ProxyServer
else
sock.addr := dword_LE2ipU(AOLProxy.ip)
;
sock.port := '5190';//TicqSession(directs.proto).serviceServerPort;
end
else
if stage = 3 then
begin
if imSender then
sock.addr := TicqSession(directs.proto).ProxyServer
else
sock.addr := dword_LE2ipU(AOLProxy.ip)
;
sock.port := '5190';//TicqSession(directs.proto).serviceServerPort;
end;
try
// Need make asynchronized call
sock.Connect
except
on E:Exception do
begin
{ eventMsgA := E.Message;
eventError:=EC_cantconnect;
eventInt:=WSocket_WSAGetLastError;
notifyListeners(IE_error);}
// goneOffline;
end
else
begin
{ eventMsgA := '';
eventError:=EC_cantconnect;
eventInt:=WSocket_WSAGetLastError;
eventMsgA := WSocketErrorDesc(eventInt);
notifyListeners(IE_error);}
// goneOffline;
end;
end;
end;
procedure TICQDirect.connected2cli;
begin
Directed := True;
begin
if (not imSender)and (kind = DK_file) then
TicqSession(directs.proto).sendFileOk(Self, True);
if imSender and (kind = DK_file) then
sendFilePrompt;
end;
end;
procedure TICQDirect.Failed;
begin
sock.close
end;
procedure TICQDirect.close;
begin sock.close end;
procedure TICQDirect.connected(Sender: TObject; Error: Word);
var
icq:TicqSession;
a : Word;
begin
icq:= TicqSession(directs.proto);
icq.eventDirect:=self;
if error<>0 then
begin
icq.eventMsgA := '';
a := WSocket_WSAGetLastError;
if a <> 0 then
begin
error:= a;
icq.eventMsgA := WSocketErrorDesc(error);
end;
icq.eventInt:=error;
icq.eventError:=EC_cantconnect_dc;
icq.notifyListeners(IE_error);
exit;
end;
if imserver then
sock.dup(sock.accept);
P_host:=sock.GetPeerAddr;
P_port:=sock.GetPeerPort;
icq.notifyListeners(IE_dcConnected);
if mode = dm_bin_proxy then
if (((stage=1)or(stage=3))and(not imSender))or
((stage=2)and imSender) then
begin
sendProxyCMD(4, 0, myinfo.buin + word_BEasStr(AOLProxy.port) + qword_LEasStr(eventID) +
TLV($01, CAPS_sm2big(CAPS_sm_FILE_TRANSFER)));
end
else
begin
sendProxyCMD(2, 0, myinfo.buin + qword_LEasStr(eventID) +
TLV($01, CAPS_sm2big(CAPS_sm_FILE_TRANSFER)));
end
else
Connected2Cli;
end; // connected
procedure TICQDirect.disconnected(Sender: TObject; Error: Word);
begin
with TicqSession(directs.proto) do
begin
eventDirect:=self;
notifyListeners(IE_dcDisconnected);
end;
if Assigned(OnDisconnect) then
OnDisconnect(self, 0);
end; // disconnected
procedure TICQDirect.sended(Sender: TObject; Error: Word);
var
b : Boolean;
begin
SetLength(buf, 0);
b := false;
if Assigned(OnDataNext) then
OnDataNext(self, buf, b);
if Length(buf)>0 then
sendPkt(buf);
if b then
sock.Close;
end;
procedure TICQDirect.received(Sender: TObject; Error: Word);
const
Z=#0#0#0#0;
var
s, s1: RawByteString;
l, ofs:integer;
msg_type : word;
begin
// queue in buf
//buf:=buf+sock.receiveStr;
{$IFDEF UNICODE}
s := sock.ReceiveStrA;
{$ELSE nonUNICODE}
s := sock.ReceiveStr;
{$ENDIF UNICODE}
// extract the packet from buf
{if length(buf) < 2 then exit;
l:=word_LEat(@buf[1]);
if length(buf) < l+2 then exit;
s:=copy(buf,1,l+2);
delete(buf,1,l+2);}
// log
if not (Directed and not imSender and (mode = dm_bin_direct)) then
with TicqSession(directs.proto) do
begin
eventData := s;
eventDirect:=self;
notifyListeners(IE_dcGot);
end;
if mode= dm_bin_proxy then
begin
l := word_BEat(s, 1);
msg_type := word_BEat(s, 5);
case msg_type of
1: begin
Failed;
Exit;
end;
3: begin
if l > 15 then
begin
AOLProxy.port := word_BEat(s, 13);
ofs := 15;
// AOLProxy.ip := readBEDWORD(s, ofs);
AOLProxy.ip := readDWORD(s, ofs);
if not imSender then
TicqSession(directs.proto).sendFileOk(self, True, false, True)
else
TicqSession(directs.proto).sendFileReqPro(self);
end
else
Failed;
Exit;
end;
5: begin
mode := dm_bin_direct;
connected2cli;
end;
end;
exit;
end;
//delete(s,1,2);
// reply
if imSender then
begin
if kind = DK_file then
if (Length(s) >4)and(AnsiStartsText(AnsiString('OFT2'), s)) then
begin
msg_type := word_BEat(s, 7);
case msg_type of
{ $0101 : // Prompt. This is sent by the file sender to indicate that the client is ready to begin sending data.
begin
s1 := Copy(s, 1, 6) + #02#02 + Copy(s, 9, MAXSHORT);
// Self.fileTotal := 0;
sendPkt(s1);
mode := dm_bin_direct;
// sendACK_File;
end;
$0106 : // Sender Resume. The sender has agreed to begin the transfer at the point the receiver specified.
begin
s1 := Copy(s, 1, 6) + #02#07 + Copy(s, 9, MAXSHORT);
sendPkt(s1);
end;
}
$0202, $0207:
begin
if msg_type=$0202 then
fileSizeReceived := 0
else
;
with TicqSession(directs.proto) do
begin
eventcontact := TICQcontact(contact);
eventMsgID := eventID;
eventDirect := self;
notifyListeners(IE_fileack);
end;
end;
$0204:
begin
// mode :=
close;
with TicqSession(directs.proto) do
begin
// directs.icq.eventcontact := contact;
eventMsgID := eventID;
notifyListeners(IE_fileDone);
end;
end;
$0205:
begin
s1 := Copy(s, 1, 6) + #01#06 + Copy(s, 9, MAXSHORT);
parseFileDC0205(s);
sendPkt(s1);
// sendACK_File;
end
end;
// разбираем инфу!
end;
end
else // not imSender
if (kind = DK_file) then
begin
if //(mode <> dm_bin_receive)and
(Length(s) >4)and(AnsiStartsText(AnsiString('OFT2'), s)) then
begin
msg_type := word_BEat(s, 7);
case msg_type of
$0101 : // Prompt. This is sent by the file sender to indicate that the client is ready to begin sending data.
begin
parseFileDC0101(s);
sendACK_File;
// s1 := Copy(s, 1, 6) + #02#02 + Copy(s, 9, MAXSHORT);
// sendPkt(s1);
if not needResume then
mode := dm_bin_direct;
// sendACK_File;
end;
$0106 : // Sender Resume. The sender has agreed to begin the transfer at the point the receiver specified.
begin
s1 := Copy(s, 1, 6) + #02#07 + Copy(s, 9, MAXSHORT);
sendPkt(s1);
mode := dm_bin_direct;
end;
end;
// Filename := 'data5.txt';
// разбираем инфу!
end
else
begin
if mode = dm_bin_direct then
begin
buf := s;
if Assigned(OnDataAvailable) then
OnDataAvailable(self, 0);
end;
end;
end;
// case s[1] of
// #$FF:sendACK1;
// end;
s:='';
end; // received
procedure TICQdirect.DoneTransfer;
begin
sendDone_File;
if (fileCntTotal=1) or
((fileCntTotal >0) and (fileCntReceived >= fileCntTotal)) then
close;
end;
function TICQDirect.myinfo:TICQcontact;
begin result:= TICQcontact(directs.proto.getMyInfo) end;
function TICQDirect.parseFileDC0101(s : RawByteString) : Boolean;
var
evID : Int64;
encrypted : Word;
compressed : Word;
errStr : String;
ofs : Integer;
ptype : Word;
enc : byte;
begin
ofs := 7;
pType := readWORD(s, ofs);
// ofs := 9;
evID := //qword_LEat(@s[9]);
readQWORD(s, ofs);
Result := True;
encrypted := readBEWORD(s, ofs); //$10);
if encrypted <> 0 then
begin
errStr := 'Unknown encryption';
result := false;
Exit;
end;
compressed := readBEWORD(s, ofs); //$12);
if compressed <> 0 then
begin
errStr := 'Unknown compression';
result := false;
Exit;
end;
fileCntTotal := readBEWORD(s, ofs); //$14);
if fileCntTotal = 0 then
begin
errStr := 'No files';
result := false;
Exit;
end;
if readBEWORD(s, ofs) = 0 then
begin
errStr := 'No files left';
result := false;
Exit;
end;
readBEWORD(s, ofs); // Total Parts (TotPrts)
readBEWORD(s, ofs); // Parts Left (PrtsLeft)
fileSizeTotal := readBEDWORD(s, ofs); // Total Size (TotSz)
if fileSizeTotal = 0 then
begin
errStr := 'File size is zero';
result := false;
Exit;
end;
readBEDWORD(s, ofs); // The size (Size)
readINT(s, ofs); // Modification Time (ModTime)
transferChkSum := readBEDWORD(s, ofs); // Checksum (Checksum)
readBEDWORD(s, ofs); // The Received Resource Fork Checksum (RfrcvCsum)
readBEDWORD(s, ofs); // The Resource Fork Size (RfSize)
readBEDWORD(s, ofs); // The Creation Time (CreTime)
readBEDWORD(s, ofs); // The Resource Fork Checksum (RfCsum)
readBEDWORD(s, ofs); // The Bytes Received (nRecvd)
readBEDWORD(s, ofs); // The Received Checksum (RecvCsum)
inc(ofs, 32); // The Identification String (IDString)
readBYTE(s, ofs); // The Flags (Flags)
readBYTE(s, ofs); // The List Name Offset (NameOff) defaults to 0x1C (Decimal: 28)
readBYTE(s, ofs); // The List Size Offset (SizeOff) default is 0x11(Decimal: 17)
inc(ofs, 69); // The “Dummy” block (Dummy)
inc(ofs, 16); // The Macintosh File Information (MacFileInfo)
enc := readWORD(s, ofs);
readWORD(s, ofs); // The Encoding Subcode (Subcode) observed to be only 0x0000
if enc <> 2 then
begin
end
else // Unicode
begin
end;
if not Result then
logMsg(99, errStr);
// пишем тута!
// word_BEat(s, 7);
;
end;
function TICQDirect.parseFileDC0205(s : RawByteString) : Boolean;
var
evID : Int64;
// encrypted : Word;
// compressed : Word;
errStr : String;
ofs : Integer;
ptype : Word;
// enc : byte;
begin
ofs := 7;
pType := readWORD(s, ofs);
// ofs := 9;
evID := //qword_LEat(@s[9]);
readQWORD(s, ofs);
Result := True;
// encrypted :=
readBEWORD(s, ofs); //$10);
{ if encrypted <> 0 then
begin
errStr := 'Unknown encryption';
result := false;
Exit;
end;}
// compressed :=
readBEWORD(s, ofs); //$12);
{ if copressed <> 0 then
begin
errStr := 'Unknown compression';
result := false;
Exit;
end;}
// fileCntTotal :=
readBEWORD(s, ofs); //$14);
{ if fileCntTotal = 0 then
begin
errStr := 'No files';
result := false;
Exit;
end;}
if readBEWORD(s, ofs) = 0 then
begin
errStr := 'No files left';
result := false;
Exit;
end;
readBEWORD(s, ofs); // Total Parts (TotPrts)
readBEWORD(s, ofs); // Parts Left (PrtsLeft)
// fileSizeTotal :=
readBEDWORD(s, ofs); // Total Size (TotSz)
{ if fileSizeTotal = 0 then
begin
errStr := 'File size is zero';
result := false;
Exit;
end;}
readBEDWORD(s, ofs); // The size (Size)
readINT(s, ofs); // Modification Time (ModTime)
// transferChkSum :=
readBEDWORD(s, ofs); // Checksum (Checksum)
readBEDWORD(s, ofs); // The Received Resource Fork Checksum (RfrcvCsum)
readBEDWORD(s, ofs); // The Resource Fork Size (RfSize)
readBEDWORD(s, ofs); // The Creation Time (CreTime)
readBEDWORD(s, ofs); // The Resource Fork Checksum (RfCsum)
self.fileSizeReceived := readBEDWORD(s, ofs); // The Bytes Received (nRecvd)
Self.receivedChkSum := readBEDWORD(s, ofs); // The Received Checksum (RecvCsum)
{ inc(ofs, 32); // The Identification String (IDString)
readBYTE(s, ofs); // The Flags (Flags)
readBYTE(s, ofs); // The List Name Offset (NameOff) defaults to 0x1C (Decimal: 28)
readBYTE(s, ofs); // The List Size Offset (SizeOff) default is 0x11(Decimal: 17)
inc(ofs, 69); // The “Dummy” block (Dummy)
inc(ofs, 16); // The Macintosh File Information (MacFileInfo)
enc := readWORD(s, ofs);
readWORD(s, ofs); // The Encoding Subcode (Subcode) observed to be only 0x0000
if enc <> 2 then
begin
end
else // Unicode
begin
end;}
if not Result then
logMsg(99, errStr);
// пишем тута!
// word_BEat(s, 7);
;
end;
procedure TICQDirect.sendACK_File; // 0202 , 0205
var
s : RawByteString;
data : RawByteString;
i : Integer;
begin
data := #02;
if needResume then
data := data + #05
else
begin
data := data + #02;
fileSizeReceived := 0;
receivedChkSum := $FFFF0000;
end;
data := data +
qword_LEasStr(eventID) + // Cookie
#00#00 + // Encrypt
#00#00 + // Comp
word_BEasStr(1)+ // TotFil
word_BEasStr(1)+ // FilLft
word_BEasStr(1*1)+ // TotPrts
word_BEasStr(1*1)+ // PrtsLft
dword_BEasStr(fileSizeTotal)+// TotSz
dword_BEasStr(fileSizeTotal)+// Size
dword_BEasStr(0)+ // ModTime
dword_BEasStr(fileChkSum)+ // Checksum
dword_BEasStr($FFFF0000)+ // RfrcvCsum
dword_BEasStr(0)+ //RfSize
dword_BEasStr(0)+ //CreTime
dword_BEasStr($FFFF0000)+ //RfcSum
dword_BEasStr(fileSizeReceived)+ //nRecvd
dword_BEasStr(receivedChkSum)+ //RecvCsum
'CoolFileXfer'+z+ //IDString
z+z+z+z+ //IDString
#$20+ //Flags: $20 – Negotiation, $01 – Done
#$1C+ //NameOff
#$11+ //SizeOff
z+z+z+z+z+ //Dummy
z+z+z+z+z+ //Dummy
z+z+z+z+z+ //Dummy
z+z+#00+ //Dummy
z+z+z+z+ // MacFileInfo
word_BEasStr(2)+ // Encoding: 0000-ASCII, 0002 - UTF-16BE or UCS-2BE, 0003 - ISO-8859-1
word_BEasStr(0)+ // Subcode
StrToUnicode(fileName + #00);
i := Length(data);
if i < $100-6 then
begin
SetLength(data, $100-6);
FillMemory(@data[i+1], ($100-6-i), 0);
end;
s := 'OFT2' + word_BEasStr(length(data)+6)+data;
sendPkt(s);
end;
procedure TICQDirect.sendDone_File; // 0204
var
s : RawByteString;
data : RawByteString;
i : Integer;
begin
data := #02#04 +
qword_LEasStr(eventID) + // Cookie
#00#00 + // Encrypt
#00#00 + // Comp
word_BEasStr(1)+ // TotFil
word_BEasStr(1)+ // FilLft
word_BEasStr(1*1)+ // TotPrts
word_BEasStr(1*1)+ // PrtsLft
dword_BEasStr(fileSizeTotal)+// TotSz
dword_BEasStr(fileSizeTotal)+// Size
dword_BEasStr(0)+ // ModTime
dword_BEasStr(fileChkSum)+ // Checksum
dword_BEasStr($FFFF0000)+ // RfrcvCsum
dword_BEasStr(0)+ //RfSize
dword_BEasStr(0)+ //CreTime
dword_BEasStr($FFFF0000)+ //RfcSum
dword_BEasStr(fileSizeTotal)+ //nRecvd
dword_BEasStr(fileChkSum)+ //RecvCsum
'CoolFileXfer'+z+ //IDString
z+z+z+z+ //IDString
#$20+ //Flags: $20 – Negotiation, $01 – Done
#$1C+ //NameOff
#$11+ //SizeOff
z+z+z+z+z+ //Dummy
z+z+z+z+z+ //Dummy
z+z+z+z+z+ //Dummy
z+z+#00+ //Dummy
z+z+z+z+ // MacFileInfo
word_BEasStr(2)+ // Encoding: 0000-ASCII, 0002 - UTF-16BE or UCS-2BE, 0003 - ISO-8859-1
word_BEasStr(0)+ // Subcode
StrToUnicode(fileName + #00);
i := Length(data);
if i < $100-6 then
begin
SetLength(data, $100-6);
FillMemory(@data[i+1], ($100-6-i), 0);
end;
s := 'OFT2' + word_BEasStr(length(data)+6)+data;
sendPkt(s);
end;
procedure TICQDirect.sendFilePrompt; // 0101
var
s : RawByteString;
data : RawByteString;
i : Integer;
begin
data := #01#01 +
qword_LEasStr(eventID) + // Cookie
#00#00 + // Encrypt
#00#00 + // Comp
word_BEasStr(1)+ // TotFil
word_BEasStr(1)+ // FilLft
word_BEasStr(1*1)+ // TotPrts
word_BEasStr(1*1)+ // PrtsLft
dword_BEasStr(fileSizeTotal)+// TotSz
dword_BEasStr(fileSizeTotal)+// Size
dword_BEasStr(0)+ // ModTime
dword_BEasStr(fileChkSum)+ // Checksum
dword_BEasStr($FFFF0000)+ // RfrcvCsum
dword_BEasStr(0)+ //RfSize
dword_BEasStr(0)+ //CreTime
dword_BEasStr($FFFF0000)+ //RfcSum
dword_BEasStr(0)+ //nRecvd
dword_BEasStr($FFFF0000)+ //RecvCsum
'CoolFileXfer'+z+ //IDString
z+z+z+z+ //IDString
#$20+ //Flags: $20 – Negotiation, $01 – Done
#$1C+ //NameOff
#$11+ //SizeOff
z+z+z+z+z+ //Dummy
z+z+z+z+z+ //Dummy
z+z+z+z+z+ //Dummy
z+z+#00+ //Dummy
z+z+z+z+ // MacFileInfo
word_BEasStr(2)+ // Encoding: 0000-ASCII, 0002 - UTF-16BE or UCS-2BE, 0003 - ISO-8859-1
word_BEasStr(0)+ // Subcode
StrToUnicode(fileName + #00);
i := Length(data);
if i < $100-6 then
begin
SetLength(data, $100-6);
FillMemory(@data[i+1], ($100-6-i), 0);
end;
s := 'OFT2' + word_BEasStr(length(data)+6)+data;
sendPkt(s);
end;
{
procedure TICQDirect.parseVcard(s:string);
begin
hisVer:=ord(s[2]);
if contact=NIL then
begin
contact:=contactsDB.get(dword_LEat(@s[16]));
contact.connection.port:=word_LEat(@s[29]);
end;
end; // parseVcard
procedure TICQDirect.sendACK1;
begin sendPkt(#1#0#0#0) end;
procedure TICQDirect.sendACK2;
begin sendPkt(#1+dword_LEasStr(myspeed)+WNTS(myinfo.displayed)) end;
procedure TICQDirect.sendACK3;
begin sendPkt(#3+Z+Z+dword_LEasStr(myspeed)+#1#0#0) end;
procedure TICQDirect.sendVcard;
begin
sendPkt(
#$FF+char(6)+#0#$2B#0+dword_LEasStr(contact.uid)+#0#0+
dword_LEasStr(directs.icq.serverPort)+directs.icq.myUINle+
dword_LEasStr(directs.icq.getLocalIP)+#127#0#0#1+#4+
dword_LEasStr(directs.icq.serverPort)+dword_LEasStr(contact.dc_cookie)+
#$50#0#0#0#3#0#0#0#0#0#0#0
);
end;
procedure TICQDirect.sendSpeed;
begin sendPkt(#5+dword_LEasStr(myspeed)) end;
}
///////////////////////////////////////////////////////////////////////
{$ENDIF usesDC}
///////////////////////////////////////////////////////////////////////
class function TicqSession._RegisterUser(var pUID : TUID; var pPWD : String) : Boolean;
begin
{$IFDEF USE_REGUIN}
newaccountFrm:=TnewaccountFrm.create(NIL);
translateWindow(newaccountFrm);
if newaccountFrm.showModal = mrOk then
begin
Result := True;
pUID := ...
// pUID :=
end;
// ForceForegroundWindow(handle);
freeAndNIL(newaccountFrm);
{$ELSE}
Result := False;
openURL('http://www.icq.com/join/');
{$ENDIF USE_REGUIN}
end;
class function TicqSession._CreateProto(const uid : TUID) : TRnQProtocol;
begin
Result := TicqSession.Create(uid, SESS_IM);
end;
constructor TicqSession.create(const id : TUID; subType : TICQSessionSubType);
begin
protoType := subType;
fContactClass := TICQcontact;
inherited create;
phase:=null_;
listener:=NIL;
avt_icq := NIL;
if id='' then
begin
MyAccount := '';
// myinfo0:=NIL
end
else
begin
// myinfo0 := getICQContact(id);
// MyAccount := myinfo0.UID2cmp;
MyAccount := TICQContact.trimUID(id);
end;
if (MyAccount <> '') and
(pos(AnsiChar('@'), MyAccount) > 1) then
Attached_login_email := MyAccount
else
Attached_login_email := '';
fPwd := '';
fPwdHash := '';
fSessionTokenExpIn := 86400;
SNACref:=1;
// FLAPseq:=$6700+random($100);
// FLAPseq := Flap_start;
// FLAPseq := Flap_start+random($100);
// FLAPseq := Flap_Start1; // 20090122 - из-за ICQ 6.5
FLAPseq := getFirstFlap;
lastSendedFlap := now;
curStatus := SC_OFFLINE;
fVisibility := VI_normal;
curXStatus := 0;
startingStatus := SC_ONLINE;
sock:=TRnQSocket.create(NIL);
sock.OnSessionConnected:=connected;
sock.OnDataAvailable:= onDataAvailable;
sock.OnDataReceived := received;
sock.OnSessionClosed:= disconnected;
sock.OnSocksError := OnProxyError;
sock.OnProxyTalk := OnProxyTalk;
//sock.FlushTimeout
//sock.http.enabled:=FALSE;
cookie := '';
cookieTime := 0;
with _getDefHost do
begin
loginServerAddr := host;
loginServerPort := IntToStrA(port);
end;
Q:=TflapQueue.create;
if subType = SESS_IM then
begin
{$IFDEF usesDC}
directs := Tdirects.create(self);
{$ENDIF usesDC}
DCmode := DC_none;
showInfo := 2;
webaware := True;
fRoster := TRnQCList.create;
fVisibleList := TRnQCList.create;
fInvisibleList:= TRnQCList.create;
{$IFDEF UseNotSSI}
fIntVisibleList := TRnQCList.create;
fIntInvisibleList:= TRnQCList.create;
fUseSSI := True;
fUseLSI := False;
{$ENDIF UseNotSSI}
tempVisibleList:=TRnQCList.create;
spamList := TRnQCList.Create;
SSIacks := TSSIacks.Create;
savingmyinfo.running:=FALSE;
uploadAvatarFN := '';
avtSessInit := False;
{$IFDEF RNQ_AVATARS}
avt_icq := TicqSession.create('', SESS_AVATARS);
// avt_icq.listener := RnQmain.avticqEvent;
avt_icq.listener:= self.listener;
avt_icq.mainICQ := self;
{$ENDIF RNQ_AVATARS}
{$IFDEF usesDC}
// server:=Twsocket.create(NIL);
// server.OnSessionAvailable:=dc_connected;
{$ENDIF usesDC}
end;
end; // create
procedure TicqSession.ResetPrefs;
var
i : Integer;
begin
// ICQ.readList(LT_VISIBLE).clear;
// ICQ.readList(LT_INVISIBLE).clear;
inherited ResetPrefs;
fVisibleList.clear;
fInvisibleList.Clear;
DCmode := DC_NONE;
setDCfakeIP('6.6.6.0');
DCfakePort := 666;
curXStatus := 0;
authNeeded:=True;
with aProxy do
begin
// enabled:=FALSE;
// for pp:=low(pp) to high(pp) do addr[pp].host:='';
addr.host:='';
// addr[PP_SOCKS4].port:='1080';
// addr[PP_SOCKS5].port:='1080';
// addr[PP_HTTPS].port:='3128';
addr.port:=1080;
proto:=PP_NONE;
auth:=FALSE;
NTLM := False;
serv := TicqSession._getDefHost;
ssl := False;
end;
pPublicEmail := False;
showClientID := True;
offlineMsgsChecked := TRUE;
supportInvisCheck := false;
{$IFDEF CHECK_INVIS}
CheckInvis.ShowInvisibility:=TRUE;
CheckInvis.AutoCheck:=false;
CheckInvis.AutoCheckInterval:=180;
CheckInvis.ChkInvisInterval :=3.5;
CheckInvis.AutoCheckOnSend := false;
CheckInvis.AutoCheckGoOfflineUsers := false;
CheckInvis.Method := 0;
showCheckedInvOfl := True;
// CheckInvis.AutoCheckOnSend := false;
{$ENDIF}
AddExtCliCaps := False;
ExtClientCaps := '';
typingInterval := 5;
SupportUTF := True;
SendingUTF := True;
UseCryptMsg := True;
UseAdvMsg := True;
useFBcontacts := false;
AvatarsSupport := True;
AvatarsAutoGet := True;
{$IFDEF RNQ_LITE}
AvatarsAutoGetSWF := False;
AvatarsNotDnlddInform := True;
{$ELSE RNQ_FULL}
AvatarsAutoGetSWF := True;
AvatarsNotDnlddInform := False;
{$ENDIF RNQ_LITE}
myAvatarHash := '';
saveMD5Pwd:=False;
// icq.myInfo.Icon_hash_safe := '';
// useSSI := True;
{$IFDEF ICQ_OLD_STATUS}
// UseOldXSt := False;
{$ENDIF ICQ_OLD_STATUS}
{$IFDEF UseNotSSI}
LoginMD5:=True;
useSSI2 := masterUseSSI;
{$ENDIF UseNotSSI}
// serverSSI.itemCnt := 0;
// serverSSI.modTime := 0;
// serverSSI.items := nil;
clearSSIList(serverSSI);
localSSI_itemCnt := 0;
localSSI_modTime := 0;
{ localSSI.itemCnt := 0;
localSSI.modTime := 0;
localSSI.items := nil;}
showInvisSts := True;
addTempVisMsg := False;
sendBalloonOn:=BALLOON_NEVER;
onStatusDisable[byte(SC_dnd)].blinking:=TRUE;
onStatusDisable[byte(SC_dnd)].sounds:=TRUE;
for I := low(XStatusArray) to High(XStatusArray) do
begin
ExtStsStrings[i].Cap := getTranslation(XStatusArray[i].Caption);
ExtStsStrings[i].Desc := '';
end;
end;
procedure TicqSession.GetPrefs(var pp : TRnQPref);
var
i : Integer;
s : String;
sR : RawByteString;
begin
if (MyAccount <> '') and
(pos(AnsiChar('@'), MyAccount) <= 0) then
pp.addPrefStr('oscar-uid', MyAccount);
pp.addPrefBool('add-to-vislist-before-msg', addTempVisMsg);
pp.addPrefBool('add-client-caps', AddExtCliCaps);
pp.addPrefStr('add-client-caps-str', Str2hex(ExtClientCaps));
pp.addPrefInt('send-balloon-on', sendBalloonOn);
pp.addPrefDate('send-balloon-on-date', sendBalloonOnDate);
try
pp.addPrefBool('public-email', pPublicEmail);
pp.addPrefBool('login-md5', LoginMD5);
pp.addPrefBool('save-md5-pass', saveMD5Pwd);
except
// msgDlg('Какая-то глупая ошибка :(((', mtError);
end;
// pp.addPrefStr('server-host', MainProxy.serv.host);
// pp.addPrefInt('server-port', MainProxy.serv.port);
pp.addPrefBool('connection-ssl', MainProxy.ssl);
pp.addPrefInt('typing-notify-interval', typingInterval);
pp.addPrefBool('support-utf8', SupportUTF);
pp.addPrefBool('sending-utf8', SendingUTF);
pp.addPrefBool('use-crypt-msg', useCryptMsg);
pp.addPrefBool('use-adv-msg', useAdvMsg);
pp.addPrefBool('use-xmpp-contacts', useFBcontacts);
pp.addPrefBool('avatars-flag', AvatarsSupport);
pp.addPrefBool('avatars-auto-load-flag', AvatarsAutoGet);
pp.addPrefBool('avatars-auto-swf-flag', AvatarsAutoGetSWF);
pp.addPrefBool('avatars-not-downloaded-inform-flag', AvatarsNotDnlddInform);
pp.addPrefStr('avatar-my', Str2hex(myAvatarHash));
{$IFDEF CHECK_INVIS}
pp.addPrefBool('invisibility-flag', CheckInvis.ShowInvisibility);
pp.addPrefBool('check-invisibility-every', CheckInvis.AutoCheck);
pp.addPrefInt('check-invisibility-interval', CheckInvis.AutoCheckInterval);
pp.addPrefInt('check-invis-interval', Round(CheckInvis.ChkInvisInterval*10));
pp.addPrefBool('support-invis-check', supportInvisCheck);
pp.addPrefBool('check-invisibility-on-send', CheckInvis.AutoCheckOnSend);
pp.addPrefBool('check-invisibility-on-offl', CheckInvis.AutoCheckGoOfflineUsers);
pp.addPrefInt('check-invisibility-method', CheckInvis.Method);
pp.addPrefBool('show-checked-offlines', showCheckedInvOfl);
{$ENDIF}
pp.addPrefBool('show-invis-status', showInvisSts);
{$IFDEF UseNotSSI}
pp.addPrefBool('use-ssi', useSSI2);
pp.addPrefBool('use-lsi', useLSI2);
{$ELSE UseNotSSI}
pp.addPrefBool('use-lsi', False);
pp.addPrefBool('use-ssi', True);
{$ENDIF UseNotSSI}
// pp.addPrefTime('local-ssi-time', localSSI.modTime);
// pp.addPrefInt('local-ssi-count', localSSI.itemCnt);
pp.addPrefTime('local-ssi-time', localSSI_modTime);
pp.addPrefInt('local-ssi-count', localSSI_itemCnt);
//for st:=SC_ONLINE to pred(SC_OFFLINE) do
for i in self.getStatusMenu do
// for i := byte(low(tICQStatus)) to byte(high(tICQstatus)) do
if i <> byte(SC_OFFLINE) then
begin
s := status2Img[i]+'-disable-';
pp.addPrefBool( s+'blinking', onStatusDisable[i].blinking);
pp.addPrefBool( s+'tips', onStatusDisable[i].tips);
pp.addPrefBool( s+'sounds', onStatusDisable[i].sounds);
pp.addPrefBool( s+'openchat', onStatusDisable[i].OpenChat);
end;
// icq := TicqSession(mainproto.ProtoElem);
pp.addPrefBool('auth-needed', self.authneeded);
pp.addPrefStr('dc-mode', self.getDCModeStr);
pp.addPrefStr('dc-fake-ip', self.getDCfakeIP);
pp.addPrefInt('dc-fake-port', self.getDCfakePort);
pp.addPrefBool('webaware', self.webaware);
pp.addPrefBool('show-client-id', showClientID);
// pp.addPrefBool('use-old-xstatus', useOldxSt);
pp.addPrefInt('xstatus', self.curXStatus);
pp.addPrefInt('icq-showinfo', self.showInfo);
// +'proxy='+yesno[ICQ.proxy.enabled]+CRLF
// +'proxy='+yesno[false]+CRLF // for old R&Q
;
//for pp:=low(pp) to high(pp) do result:=result
// +'proxy-'+proxyproto2str[pp]+'-host='+proxy.addr[pp].host+CRLF
// +'proxy-'+proxyproto2str[pp]+'-port='+proxy.addr[pp].port+CRLF;
if not (RnQstartingStatus in [Low(status2Img)..High(status2Img)]) then
pp.addPrefStr('starting-status', 'last_used')
else
pp.addPrefStr('starting-status', status2Img[RnQstartingStatus]);
pp.addPrefStr('starting-visibility', visib2str[TVisibility(RnQstartingVisibility)]);
pp.addPrefStr('last-set-status', status2Img[lastStatusUserSet]);
inherited GetPrefs(pp);
if not dontSavePwd //and not locked
then
begin
if saveMD5Pwd then
sR := fPwdHash
else
sR := StrToUTF8(fPwd);
// pp.addPrefBlob('crypted-password', passCrypt(sR));
pp.addPrefBlob64('crypted-password64', passCrypt(sR))
end
else
begin
pp.DeletePref('crypted-password64');
end;
pp.DeletePref('crypted-password');
end;
function String2Hex(const Buffer: Ansistring): string;
begin
SetLength(result, 2*Length(Buffer));
BinToHex(@Buffer[1], PWideChar(@result[1]), Length(Buffer));
end;
procedure TicqSession.SetPrefs(pp : TRnQPref);
var
i : Integer;
sU, sU2 : String;
st: Byte;
l : RawByteString;
// myInf : TRnQContact;
begin
inherited SetPrefs(pp);
pp.getPrefStr('oscar-uid', sU);
if sU > '' then
MyAccount := sU;
pp.getPrefBool('public-email', pPublicEmail);
pp.getPrefBool('add-client-caps', AddExtCliCaps);
ExtClientCaps := hex2str(pp.getPrefBlobDef('add-client-caps-str'));
case pp.getPrefIntDef('dc-mode') of
0 : dcMode := DC_NONE;
1 : dcMode := DC_UPONAUTH;
2 : dcMode := DC_ROSTER;
3 : dcMode := DC_EVERYONE;
end;
setDCfakeIP(pp.getPrefBlobDef('dc-fake-ip'));
DCfakePort := pp.getPrefIntDef('dc-fake-port', DCfakePort);
authneeded := pp.getPrefBoolDef('auth-needed', authneeded);
webaware := pp.getPrefBoolDef('webaware', webaware);
showInfo := pp.getPrefIntDef('icq-showinfo', showInfo);
i := pp.getPrefIntDef('xstatus');
if i >= 0 then
begin
// if i > High(XStatus6) then
if (i in [low(XStatusArray)..High(XStatusArray)])
// and (xsf_6 in XStatusArray[i].flags)
then
curXStatus := i
else
curXStatus := 0;
end;
pp.getPrefInt('send-balloon-on', sendBalloonOn);
pp.getPrefDate('send-balloon-on-date', sendBalloonOnDate);
{$IFDEF ICQ_OLD_STATUS}
// pp.getPrefBool('use-old-xstatus', useOldxSt);
{$ENDIF ICQ_OLD_STATUS}
{$IFDEF UseNotSSI}
pp.getPrefBool('login-md5', LoginMD5);
{$ENDIF UseNotSSI}
{$IFDEF UseNotSSI}
pp.getPrefBool('use-ssi', useSSI2);
pp.getPrefBool('use-lsi', useLSI2);
{$ENDIF UseNotSSI}
// pp.getPrefInt('local-ssi-count', localSSI.itemCnt);
// pp.getPrefDateTime('local-ssi-time', localSSI.modTime);
pp.getPrefInt('local-ssi-count', localSSI_itemCnt);
pp.getPrefDateTime('local-ssi-time', localSSI_modTime);
for st := Byte(low(tICQstatus)) to Byte(high(tICQstatus)) do
// for st:=SC_ONLINE to pred(SC_OFFLINE) do
with onStatusDisable[byte(st)] do
begin
// sU2 := status2Img[st];
sU2 := status2Img[st] + '-disable-';
// sU := sU2+'-disable-blinking';
sU := sU2+'blinking';
pp.getPrefBool(sU, blinking);
// sU := sU2+'-disable-tips';
sU := sU2+'tips';
pp.getPrefBool(sU, tips);
// sU := sU2+'-disable-sounds';
sU := sU2+'sounds';
pp.getPrefBool(sU, sounds);
// sU := sU2+'-disable-openchat';
sU := sU2+'openchat';
pp.getPrefBool(sU, OpenChat);
end;
pp.getPrefBool('add-to-vislist-before-msg', addTempVisMsg);
{$IFDEF CHECK_INVIS}
pp.getPrefBool('support-invis-check', supportInvisCheck);
pp.getPrefBool('invisibility-flag', CheckInvis.ShowInvisibility);
pp.getPrefBool('check-invisibility-every', CheckInvis.AutoCheck);
pp.getPrefInt('check-invisibility-interval', CheckInvis.AutoCheckInterval);
CheckInvis.ChkInvisInterval := pp.getPrefIntDef('check-invis-interval', trunc(CheckInvis.ChkInvisInterval * 10)) / 10;
pp.getPrefBool('check-invisibility-on-send', CheckInvis.AutoCheckOnSend);
pp.getPrefBool('check-invisibility-on-offl', CheckInvis.AutoCheckGoOfflineUsers);
CheckInvis.Method := pp.getPrefIntDef('check-invisibility-method', CheckInvis.Method);
pp.getPrefBool('show-checked-offlines', showCheckedInvOfl);
{$ENDIF}
pp.getPrefBool('save-md5-pass', saveMD5Pwd);
if pp.prefExists('crypted-password64') then
l := passDecrypt(pp.getPrefBlob64Def('crypted-password64'))
else
l := passDecrypt(pp.getPrefBlobDef('crypted-password'));
if saveMD5pwd then
begin
pwd := '';
if (length(l) < 16) and (length(l) > 0) then
fPwdHash := MD5Pass(l)
else
fPwdHash := l;
end
else
begin
pwd:= UnUTF(l);
fPwdHash := '';
end;
l := '';
pp.getPrefInt('typing-notify-interval', typingInterval);
pp.getPrefBool('support-utf8', SupportUTF);
pp.getPrefBool('use-crypt-msg', useCryptMsg);
pp.getPrefBool('sending-utf8', SendingUTF);
pp.getPrefBool('use-adv-msg', useAdvMsg);
pp.getPrefBool('use-xmpp-contacts', useFBcontacts);
pp.getPrefBool('avatars-flag', AvatarsSupport);
pp.getPrefBool('avatars-auto-load-flag', AvatarsAutoGet);
pp.getPrefBool('avatars-auto-swf-flag', AvatarsAutoGetSWF);
pp.getPrefBool('avatars-not-downloaded-inform-flag', AvatarsNotDnlddInform);
pp.getPrefBool('show-invis-status', showInvisSts);
pp.getPrefBool('show-client-id', showClientID);
pp.getPrefBool('connection-ssl', MainProxy.ssl);
pp.getPrefStr('server-host', MainProxy.serv.host);
pp.getPrefInt('server-port', MainProxy.serv.port);
l := pp.getPrefBlobDef('starting-status');
if l='last_used' then
RnQstartingStatus:=-1
else
RnQstartingStatus:= str2status(l);
l := pp.getPrefBlobDef('starting-visibility');
RnQstartingVisibility:= Byte(str2visibility(l));
l := pp.getPrefBlobDef('last-set-status');
lastStatusUserSet := str2status(l);
// setVisibility(self, byte(RnQstartingVisibility));
visibility:=Tvisibility(RnQstartingVisibility);
{$IFDEF UseNotSSI}
updateVisibility;
{$ENDIF UseNotSSI}
myAvatarHash := hex2str(pp.getPrefBlobDef('avatar-my'));
if contactsDB.idxOf(TICQContact, MyAccount)>=0 then
with TICQcontact(getMyInfo) do
begin
// status := ticqStatus(SC_OFFLINE);
ICQIcon.hash_safe := myAvatarHash;
end;
applyBalloon();
fSSLServer := pp.getPrefStrDef('oscar-ssl-server',
ICQ_SECURE_LOGIN_SERVER0);
fOscarProxyServer := pp.getPrefStrDef('oscar-proxy-server',
AOL_FILE_TRANSFER_SERVER0);
end;
procedure TicqSession.Clear;
begin
// myinfo0:=NIL;
readList(LT_ROSTER).clear;
readList(LT_VISIBLE).Clear;
readList(LT_INVISIBLE).Clear;
readList(LT_TEMPVIS).Clear;
readList(LT_SPAM).Clear;
{$IFDEF UseNotSSI}
fIntVisibleList.clear;
fIntInvisibleList.clear;
{$ENDIF UseNotSSI}
FreeAndNil(eventContacts);
eventContact := NIL;
end;
destructor TicqSession.destroy;
begin
{$IFDEF usesDC}
directs.free;
// server.Free;
{$ENDIF usesDC}
{$IFDEF RNQ_AVATARS}
if Assigned(avt_icq) then
freeAndNIL(avt_icq);
{$ENDIF RNQ_AVATARS}
Q.free;
sock.free;
fRoster.free;
fVisibleList.free;
fInvisibleList.free;
{$IFDEF UseNotSSI}
fIntVisibleList.free;
fIntInvisibleList.free;
{$ENDIF UseNotSSI}
tempvisibleList.free;
spamList.Free;
SSIacks.Free;
// imageStream.Free;
inherited destroy;
end; // destroy
function TicqSession.myUINle: RawByteString;
begin result:=dword_LEasStr(StrToIntDef(myAccount, 0)) end;
function TicqSession.getMyInfo : TRnQcontact;
begin
// result := MyInfo0;
Result := contactsDB.add(Self, MyAccount);
end;
{procedure TicqSession.setMyInfo(cnt : TRnQContact);
begin
myInfo := TICQContact(cnt);
end;}
function TicqSession.isMyAcc(c : TRnQContact) : Boolean;
begin
// result := MyInfo0.equals(c);
Result := Assigned(c) and c.equals(MyAccount)
end;
function TicqSession.canAddCntOutOfGroup : Boolean;
begin
{$IFDEF UseNotSSI}
Result := not (UseSSI);
{$ELSE UseNotSSI}
result := false;
{$ENDIF UseNotSSI}
end;
function TicqSession.pwdEqual(const pass : String) : Boolean;
begin
Result := ((pass<>'')and(pass = fPwd)) or (MD5Pass(pass) = fPwdHash);
end;
function TicqSession.getPwd: String;
begin
if saveMD5Pwd then
Result := fPwdHash
else
Result := fPwd;
end;
function TicqSession.getPwdOnly: String;
begin
Result := fPwd;
end;
function TicqSession.getSession: TSessionParams;
var
params: TSessionParams;
begin
if (fSessionToken = '') or
(fSessionTokenTime = 0) or
(fSessionTokenTime + fSessionTokenExpIn > DateTimeToUnix(Now, False)) then
refreshSessionSecret();
params.secret := fSessionSecret;
params.token := fSessionToken;
params.tokenExpIn := fSessionTokenExpIn;
params.tokenTime := fSessionTokenTime;
Result := params;
end;
procedure TicqSession.setPwd(const value:String);
procedure chg(const v : String);
begin
if saveMD5pwd and LoginMD5 then
begin
fPwd := '';
if v > '' then
fPwdHash := MD5Pass(v)
else
fPwdHash := '';
// For login by mail
if (MyAccount <> '') and
(pos(AnsiChar('@'), MyAccount) > 1) then
fPwd := v;
end
else
begin
fPwd := v;
fPwdHash := '';
end;
end;
begin
if not pwdEqual(Value) and (length(value) <= maxPwdLength) then
if isOnline and (value > '') then
begin
// if (not saveMD5Pwd) and (MD5Pass(fpwd)=Value) then ;
if messageDlg(getTranslation('Really want to change password on server?'), mtConfirmation, [mbYes,mbNo],0, mbNo, 20) = mrYes then
begin
sendChangePwd(value);
chg(value);
end
end
else
chg(value);
end; // setPwd
function TicqSession.sendFLAP(ch: word; const data: RawByteString): boolean;
var
s: RawByteString;
begin
Result := False;
if sock.State <> wsConnected then Exit;
s := RawByteString('*') + AnsiChar(ch) + word_BEasStr(FLAPseq) + word_BEasStr(length(data)) + data;
try
while abs(now - lastSendedFlap) < DT2100miliseconds do
// Application.ProcessMessages
;
sock.sendStr(RawByteString(s));
lastSendedFlap := now;
{ if phase=online_ then
begin
inc(SendedFlaps);
if (SendedFlaps > ICQMaxFlaps)and (phase=online_) then
sock.Pause;
end;}
eventData := s;
notifyListeners(IE_serverGot);
inc(FLAPseq);
if FLAPseq >= $8000 then FLAPseq := 0;
except
end;
s:='';
result:=TRUE;
end; // sendFLAP
function TicqSession.sendSNAC(fam, sub: word; const data: RawByteString): boolean;
begin
Result := sendFLAP(SNAC_CHANNEL, SNAC(fam, sub, SNACref) + data)
end;
//function TicqSession.sendSNAC(fam,sub, flags:word; const data: RawByteString):boolean;
//begin result:=sendFLAP(SNAC_CHANNEL, SNAC(fam,sub,flags, SNACref)+data) end;
procedure TicqSession.sendKeepalive;
begin
sendFLAP(KEEPALIVE_CHANNEL,'');
{$IFDEF RNQ_AVATARS}
// if (not isAvatarSession) and avt_icq.isOnline then
if (protoType = SESS_IM) and avt_icq.isOnline then
avt_icq.sendFLAP(KEEPALIVE_CHANNEL,'')
{$ENDIF RNQ_AVATARS}
end;
procedure TicqSession.notifyListeners(ev:TicqEvent);
begin
if assigned(listener) then
// listener(self,ev);
listener(self, Integer(ev));
end; // notifyListeners
function TicqSession.isOffline: boolean;
begin
Result := phase = null_
end;
function TicqSession.isOnline: boolean;
begin
Result := phase = online_
end;
function TicqSession.isConnecting: boolean;
begin
// Result := not (isOffline or isOnline)
Result := (phase <> online_) and (phase <> null_)
end;
{$IFDEF usesDC}
procedure TicqSession.dc_connected(Sender: TObject; Error: Word);
var
a : Word;
begin
if error<>0 then
begin
a := WSocket_WSAGetLastError;
if a <> 0 then
begin
error := a;
eventMsgA := WSocketErrorDesc(error)
end;
eventInt := error;
eventError:=EC_cantconnect_dc;
notifyListeners(IE_error);
exit;
end;
//eventDirect:=directs.newFor(NIL);
//eventDirect.sock.dup(server.accept);
notifyListeners(IE_dcConnected);
end; // dc_connected
{$ENDIF usesDC}
procedure TicqSession.goneOffline;
var
i:integer;
begin
if phase=null_ then exit;
phase:=null_;
// if not isAvatarSession then
if protoType = SESS_IM then
begin
tempvisibleList.clear;
clearSSIList(serverSSI);
{$IFDEF usesDC}
// if DCmode <> DC_none then
// if Assigned(server) then
// server.close;
{$ENDIF usesDC}
curStatus := SC_OFFLINE;
with fRoster, TList(fRoster) do
for i:=0 to count-1 do
with TICQContact(getAt(i)) do
begin
OfflineClear;
status:= SC_UNK;
end;
end;
notifyListeners(IE_offline);
end; // goneOffline
procedure TicqSession.disconnect;
begin
sendFLAP(LOGOUT_CHANNEL, ''); // Посылаем серверу отключение
q.reset;
sock.close;
goneOffline;
end;
procedure TicqSession.connected(Sender: TObject; Error: Word);
begin
eventTime := now;
if error <> 0 then
begin
goneOffline;
eventInt:=WSocket_WSAGetLastError;
if eventInt=0 then
eventInt:=error;
eventMsgA := WSocketErrorDesc(eventInt);
eventError:=EC_cantconnect;
notifyListeners(IE_error);
exit;
end;
eventAddress:=sock.Addr;
if sock.SslEnable then
eventAddress := eventAddress + ' '+ crlf + sock.SslVersion +'; '+ sock.SslCipher;
notifyListeners(IE_serverConnected);
proxy_connected;
end; // connected
procedure TicqSession.proxy_connected;
begin
{$IFDEF USE_REGUIN}
//if creatingUIN then
if protoType = SESS_NEW_UIN then
begin
phase:=creating_uin_;
notifyListeners(IE_connected);
end
else
{$ENDIF USE_REGUIN}
case phase of
connecting_:
begin
// FLAPseq := Flap_Start1; // 20090122 - èç-çà ICQ 6.5
FLAPseq := getFirstFlap;
phase:=login_;
notifyListeners(IE_connected);
end;
reconnecting_:
begin
// FLAPseq := Flap_Start2; // 20090122 - èç-çà ICQ 6.5
FLAPseq := getFirstFlap;
phase:=relogin_;
notifyListeners(IE_redirected);
end;
end
end; // proxy_connected
procedure TicqSession.disconnected(Sender: TObject; Error: Word);
begin
q.reset;
eventAddress:=sock.addr;
eventMsgA := '';
notifyListeners(IE_serverDisconnected);
if error <> 0 then
begin
goneOffline;
eventInt:=WSocket_WSAGetLastError;
// GetWinsockErr
if eventInt=0 then eventInt:=error;
eventMsgA := WSocketErrorDesc(eventInt);
eventError:=EC_socket;
notifyListeners(IE_error);
exit;
end;
if (phase<>login_)or(cookie='') then
goneOffline;
end; // disconnected
function TicqSession.isReady:boolean;
begin
Result := phase in [SETTINGUP_, ONLINE_]
end;
function TicqSession.isSSCL:boolean;
begin
Result :=
{$IFDEF UseNotSSI}
self.useSSI
{$ELSE ~UseNotSSI}
True;
{$ENDIF UseNotSSI}
end;
procedure TicqSession.sendVisibility;
var
i : Integer;
s : RawByteString;
begin
if isReady then
begin
s := TLV($CA, AnsiChar(visibility2SSIcode[visibility]))+ // PD_MODE
TLV($D0, #1)+ //
TLV($D1, #1)+
TLV($D2, #1)+
TLV($D3, #1)+
TLV($CB, AnsiString(#$FF#$FF#$FF#$FF))
// +TLV($15F, 0) // WEB_PD_MODE
; // PD_MASK
i := FindSSIItemType(serverSSI, FEEDBAG_CLASS_ID_PDINFO);
if i >= 0 then
begin
// serverSSI.items
with TOSSIItem(serverSSI.items.Objects[i]) do
begin
// s := getTLVSafe($CA, ExtInfo);
// s := replaceAddTLV($CA, ExtInfo, 1, Char(visibility2SSIcode[visibility]));
// s := TLV($CA, Char(visibility2SSIcode[visibility]))+
// TLV($D0, #1)+TLV($D1, #1)+TLV($D2, #1)+TLV($D3, #1)+
// TLV($CB, #$FF#$FF#$FF#$FF);
SSI_UpdateItem(ItemName, s, GroupID, ItemID, FEEDBAG_CLASS_ID_PDINFO);
end;
end
else
begin
// s := TLV($CA, Char(visibility2SSIcode[visibility]))+
// TLV($D0, #1)+TLV($D1, #1)+TLV($D2, #1)+TLV($D3, #1)+
// TLV($CB, #$FF#$FF#$FF#$FF);
SSI_CreateItem('', S, 0, 0, FEEDBAG_CLASS_ID_PDINFO);
end;
end;
end;
procedure TicqSession.resetStatusCode; //011E
begin
if not isReady then Exit;
sendSNAC(ICQ_SERVICE_FAMILY, $1E, TLV($06, dword_Zero));
addRef(REF_status, '');
end;
procedure TicqSession.sendStatusCode(sendVis: Boolean); //011E
const
vcookie = #1#2#3#4;
var
dc : RawByteString;
// i : Integer;
i : Cardinal;
StFirst : Boolean;
xStsTLV : RawByteString;
Pck : RawByteString;
begin
if not isReady then Exit;
if DCmode = DC_none then
dc := Z + dword_BEasStr(0)
else if DCmode = DC_FAKE then
dc := dword_LEasStr(fDC_Fake_ip.S_addr) + dword_BEasStr(fDC_Fake_port)
else
dc := dword_LEasStr(getLocalIP) +
// server.GetXAddr + //#127#0#0#1+
dword_BEasStr(serverPort);
if sock.http.enabled then
dc := dc + #1#0
else
if sock.SocksServer <> '' then
dc := dc + #2#0
else
dc := dc + #4#0;
dc := dc + AnsiChar(ICQ_TCP_VERSION) + vcookie + dword_BEasStr($50)
// + #0#0#0#3+dword_BEasStr(myinfo.lastUpdate_dw)+dword_BEasStr(myinfo.lastInfoUpdate_dw)+Z+#0#0;
+ #0#0#0#1;
if showClientID then
begin
i := RnQBuild;
if LiteVersion then
i:= $40000000 or i;
if TestVersion then
i:= $80000000 or i;
dc := dc + dword_BEasStr(RnQclientID) + dword_BEasStr(i)
end
else
dc := dc + dword_BEasStr(Random($40FFFFFF)) + dword_BEasStr(Random($40FFFFFF));
dc := dc + dword_BEasStr(Random($40FFFFFF)) + #0#0;
StFirst := True;
if previousInvisible <> isInvisible then
begin
{$IFDEF UseNotSSI}
if not useSSI then
sendAddVisible(fIntVisibleList);
{$ENDIF UseNotSSI}
if isInvisible then
StFirst := False;
end;
// else
{
if UseOldXSt then
xStsTLV := TLV($1D, word_BEasStr($02) + AnsiChar(#$04) + BUIN( Length_BE('')+Length_BE('') // 'iso-8859-1'
)+
TLV(BART_TYPE_STATUS_MOOD, ''))
else
xStsTLV := TLV($1D, word_BEasStr($02) + AnsiChar(#$04) + BUIN( Length_BE(StrToUTF8(ExtStsStrings[curXStatus].Desc))+
Length_BE('') // 'iso-8859-1'
)+
TLV(BART_TYPE_STATUS_MOOD, XStatusArray[curXStatus].pid6));
}
xStsTLV := TLV($1D,
word_BEasStr(BART_TYPE_STATUS_STR) +
AnsiChar(BART_FLAGS_DATA) +
// Length_B(Length_BE(StrToUTF8(ExtStsStrings[curXStatus].Desc))+
Length_B(Length_BE(StrToUTF8(curXStatusStr.Desc)) + Length_BE('')) + // 'iso-8859-1'
word_BEasStr(BART_TYPE_STATUS_MOOD) +
Length_BE(XStatusArray[curXStatus].pid6)
);
Pck := TLV(6, getFullStatusCode)
// + TLV(8, #0#0)
+ TLV(8, #$0A#$07) // From ICQ7.6 beta
// + TLV(8, #$22#01)
+ TLV($C, dc)
// + TLV($11, #1#$2C#$35#$FB#$3B)
// + TLV($12, #0#0)
+ TLV($1F, #0#0)
+ xStsTLV;
if StFirst then
begin
sendSNAC(ICQ_SERVICE_FAMILY, $1E, Pck);
addRef(REF_status, '');
sleep(100);
end;
// else
if
{$IFDEF UseNotSSI}
useSSI and
{$ENDIF UseNotSSI}
sendVis
then
sendVisibility;
if not StFirst then
begin
sleep(100);
sendSNAC(ICQ_SERVICE_FAMILY, $1E, Pck);
addRef(REF_status, '');
end;
// ssi_
{pkt.createSNAC(1,$11,0);
pkt.addDword_BE(0);
pkt.send(sock);
addRef(REF_null,0);}
if previousInvisible <> isInvisible then
begin
{$IFDEF UseNotSSI}
if not useSSI and not isInvisible then
sendAddInvisible(fIntInvisibleList);
{$ENDIF UseNotSSI}
eventContact := nil;
notifyListeners(IE_visibilityChanged);
end;
previousInvisible := isInvisible;
end; // sendStatusCode
procedure TicqSession.sendXStatusCodeOnly(); //011E
var
xStsTLV : RawByteString;
begin
if not isReady then Exit;
xStsTLV := TLV($1D,
word_BEasStr(BART_TYPE_XSTATUS) +
AnsiChar(BART_FLAGS_DATA) +
// Length_B(Length_BE(StrToUTF8(ExtStsStrings[curXStatus].Desc))+
Length_B(Length_BE(StrToUTF8(curXStatusStr.Desc)) + Length_BE('')) + // 'iso-8859-1'
word_BEasStr(BART_TYPE_STATUS_MOOD) +
Length_BE(XStatusArray[curXStatus].pid6)
);
sendSNAC(ICQ_SERVICE_FAMILY, $1E, xStsTLV);
addRef(REF_status, '');
end; // sendStatusCode
//procedure TicqSession.setStatusStr(s : String; Pic : String = '');
procedure TicqSession.setStatusStr(xSt : byte; stStr : TXStatStr);
var
s : String;
begin
eventContact := NIL;
if not (xSt in [Low(XStatusArray)..High(XStatusArray)]) then
Exit;
curXStatus := xSt;
eventInt := xSt;
curXStatusStr.Cap := stStr.Cap;
curXStatusStr.Desc := stStr.Desc;
eventNameA := StrToUTF8(stStr.Cap);
eventMsgA := StrToUTF8(stStr.Desc);
// eventMsg := AnsiToUtf8(stStr.Desc);
notifyListeners(IE_sendingXStatus);
// title := eventName;
// s := eventMsg;
s := UTF8ToStr(eventNameA);
if //(eventName > '') and
(curXStatusStr.Cap <> s) then
curXStatusStr.Cap := s;
s := UTF8ToStr(eventMsgA);
if //(eventMsg > '') and
(curXStatusStr.Desc <> s) then
curXStatusStr.Desc := s;
if isReady then
begin
// if UseOldXSt then
sendCapabilities;
// else
sendStatusCode(false);
// sendSNAC(ICQ_SERVICE_FAMILY, $1E, TLV($1D, word_BEasStr($02) + #$04 + BUIN( Length_BE(StrToUTF8(s))+
// Length_BE('') // 'iso-8859-1'
// )+
// TLV($0E, Pic))
// );
// sendSNAC(ICQ_SERVICE_FAMILY, $1E, TLV($1D, TLV($0E, Pic))
// );
end;
end;
procedure TicqSession.setStatusFull(st: byte; xSt : byte; stStr : TXStatStr);
var
s : String;
ChangedSts, ChangedXStsID, ChangedXStsDesc : Boolean;
begin
eventContact := NIL;
if not (xSt in [0.. High(XStatusArray)]) then
xSt := 0;
ChangedXStsID := curXStatus <> xSt;
ChangedXStsDesc := curXStatusStr.Desc <> stStr.Desc;
if ChangedXStsID or ChangedXStsDesc then
begin
curXStatus := xSt;
eventInt := xSt;
curXStatusStr.Desc := stStr.Desc;
eventNameA := StrToUTF8(stStr.Cap);
eventMsgA := StrToUTF8(stStr.Desc);
// eventMsg := AnsiToUtf8(stStr.Desc);
notifyListeners(IE_sendingXStatus);
// title := eventName;
// s := eventMsg;
s := UTF8ToStr(eventNameA);
if //(eventName > '') and
(curXStatusStr.Cap <> s) then
curXStatusStr.Cap := s;
s := UTF8ToStr(eventMsgA);
if //(eventMsg > '') and
(curXStatusStr.Desc <> s) then
curXStatusStr.Desc := s;
end;
if st = byte(SC_OFFLINE) then
begin
disconnect;
exit;
end;
//if (s = myinfo.status) and (inv = myinfo.invisible) then exit;
// if (st = byte(myinfo.status)) then exit;
ChangedSts := st <> byte(curStatus);
if not (ChangedSts or ChangedXStsID or ChangedXStsDesc) then
Exit;
if ChangedSts then
begin
eventOldStatus := curStatus;
eventOldInvisible := IsInvisible;
startingStatus := TICQStatus(st);
end;
if isReady then
begin
curStatus := TICQStatus(st);
if ChangedSts or ChangedXStsDesc then
sendStatusCode(False);
// eventContact:=myinfo;
eventContact:= NIL;
notifyListeners(IE_statuschanged);
if ChangedXStsID then
sendCapabilities;
end
else
connect;
end;
{$IFDEF UseNotSSI}
procedure TicqSession.sendAddVisible(const buinlist:RawByteString);
begin
if not isReady or not isInvisible then exit;
sendSNAC(ICQ_BOS_FAMILY, 5, buinlist);
end; // sendAddVisible
procedure TicqSession.sendRemoveVisible(const buinlist:RawByteString);
begin
if not isReady or not isInvisible then exit;
sendSNAC(ICQ_BOS_FAMILY, 6, buinlist);
end; // sendRemoveVisible
procedure TicqSession.sendAddInvisible(const buinlist:RawByteString);
begin
if not isReady or isInvisible then exit;
sendSNAC(ICQ_BOS_FAMILY, 7, buinlist);
end; // sendAddInvisible
procedure TicqSession.sendRemoveInvisible(const buinlist:RawByteString);
begin
if not isReady or isInvisible then exit;
sendSNAC(ICQ_BOS_FAMILY, 8, buinlist);
end; // sendRemoveInvisible
procedure TicqSession.sendRemoveContact(cl:TRnQCList);
begin
if not useSSI then
splitCL(sendRemoveContact,cl)
// else
// SplitCL2SSI_Items(SSI, cl, '', 0, 0, FEEDBAG_CLASS_ID);
end;
{$ENDIF UseNotSSI}
procedure TicqSession.sendAddVisible(cl:TRnQCList);
begin
{$IFDEF UseNotSSI}
if not useSSI then
splitCL(sendAddVisible,cl)
else
{$ENDIF UseNotSSI}
SplitCL2SSI_Items(SSI_CreateItems, cl, '', 0, 0, FEEDBAG_CLASS_ID_PERMIT);
end;
procedure TicqSession.sendAddInvisible(cl:TRnQCList);
begin
{$IFDEF UseNotSSI}
if not useSSI then
splitCL(sendAddInvisible,cl)
else
{$ENDIF UseNotSSI}
SplitCL2SSI_Items(SSI_CreateItems, cl, '', 0, 0, FEEDBAG_CLASS_ID_DENY);
end;
procedure TicqSession.sendRemoveVisible(cl:TRnQCList);
begin
{$IFDEF UseNotSSI}
if not useSSI then
splitCL(sendRemoveVisible,cl)
else
{$ENDIF UseNotSSI}
SplitCL2SSI_DelItems(SSI_DeleteItems, cl, FEEDBAG_CLASS_ID_PERMIT);
end;
procedure TicqSession.sendRemoveInvisible(cl:TRnQCList);
begin
{$IFDEF UseNotSSI}
if not useSSI then
splitCL(sendRemoveInvisible,cl)
else
{$ENDIF UseNotSSI}
SplitCL2SSI_DelItems(SSI_DeleteItems, cl, FEEDBAG_CLASS_ID_DENY);
end;
{$IFDEF UseNotSSI}
procedure TicqSession.sendAddContact(cl:TRnQCList; OnlyLocal : Boolean);
begin
if not useSSI then
splitCL(sendAddContact,cl)
else
// msgDlg(Str_unsupported, mtError);
splitSSICL(sendAddContact,cl, OnlyLocal)
end;
procedure TicqSession.sendAddContact(const buinlist:RawByteString);
begin
if (buinlist = '') or not isReady then exit;
sendSNAC(ICQ_BUDDY_FAMILY, $04, buinlist);
end; // sendAddContact
procedure TicqSession.sendRemoveContact(const buinlist:RawByteString);
begin
if (buinlist = '') or not isReady then exit;
sendSNAC(ICQ_BUDDY_FAMILY, $05, buinlist);
end; // sendRemoveContact
{$ENDIF UseNotSSI}
{
procedure TicqSession.sendAddTempContact(const buinlist: RawByteString); // 030F
begin
if (buinlist='') or not isReady then exit;
sendSNAC(ICQ_BUDDY_FAMILY, $0F, buinlist);
addRef(REF_null, '');
end; // sendAddTempContact
procedure TicqSession.sendAddTempContact(cl:TRnQCList);
begin
// msgDlg(Str_unsupported, mtError);
splitSSICL60(sendAddTempContact,cl, True)
end;
procedure TicqSession.sendRemoveTempContact(const buinlist:AnsiString); // 0310
begin
if (buinlist='') or not isReady then exit;
sendSNAC(ICQ_BUDDY_FAMILY, $10, buinlist);
end; // sendRemoveTempContact
}
{$IFDEF usesDC}
//function TicqSession.sendFileReq(uin:TUID; msg,fn:string; size:integer):integer;
function TicqSession.sendFileReq(const uin:TUID; const msg:string; fa : TFileAbout; useProxy : Boolean):integer;
var
c:TICQcontact;
proxyIP : Integer;
proxyPort : Integer;
s : RawByteString;
begin
result:=-1;
if not isReady then exit;
c := getICQContact(uin);
if not imVisibleTo(c) then
if addTempVisMsg then
addTemporaryVisible(c);
{
sendSNAC(ICQ_MSG_FAMILY, CLI_META_MSG, qword_LEasStr(SNACref)+#0#2
+BUIN(uin)
+TLV(5, #0#0
+qword_LEasStr(SNACref)+CAPS_sm2big(CAPS_sm_ICQSERVERRELAY)+TLV($A,#0#1)
+TLV($F,'')+TLV(3, dword_BEasStr(getLocalIP))+TLV(5,word_BEasStr(serverPort))
+TLV($2711, header2711+char(MTYPE_FILEREQ)+#0
+word_LEasStr(word(status2code[myinfo.status]))+#1#0+WNTS(msg)
+Z+WNTS(fn)+dword_LEasStr(size)+Z )
)
+TLV(3,'')
);
}
{ if sock.http.enabled then
begin
proxyIP := WSocketResolveHost(sock.http.addr).S_addr;
s := TLV($10, '');
port := 0;
end
else}
begin
eventDirect:=directTo(c);
eventDirect.imserver := True;
eventDirect.imsender := True;
eventDirect.kind := DK_file;
eventDirect.fileName := fa.fName;
eventDirect.fileChkSum := fa.CheckSum;
eventDirect.stage := 1;
eventDirect.fileSizeTotal := fa.Size;
eventDirect.eventID := SNACref;
// eventDirect.fi
if not useProxy then
eventDirect.listen
else
begin
eventDirect.stage := 1;
eventDirect.connect2proxy;
exit;
end;
// port := serverStart;
proxyPort := //StrToInt(eventDirect.port);
eventDirect.myPort;
proxyIP := getLocalIP;
s := '';
end;
sendSNAC(ICQ_MSG_FAMILY, CLI_META_MSG, qword_LEasStr(SNACref)+#0#2
+ Length_B(uin)
+TLV(5, #0#0 // Request
+ qword_LEasStr(eventDirect.eventID)
+ CAPS_sm2big(CAPS_sm_FILE_TRANSFER)
+ TLV($0A, #0#1) // Request Number
+ TLV($0F, '') // Mystery Block
// + TLV($0E, 'en')
+ TLV($0D, 'utf-8')
+ TLV($0C, str2html2(StrToUtf8('<ICQ_COOL_FT><FS>' + eventDirect.fileName +'</FS><S>'
+ IntToStr(eventDirect.fileSizeTotal) + '</S>'
// + '<SID>1</SID><DESC></DESC></ICQ_COOL_FT>'
+ '<SID>1</SID></ICQ_COOL_FT>'
)))
// + TLV($0D, 'unicode-2-0')
// + TLV($0C, StrToUnicode(str2html2('<ICQ_COOL_FT><FS>' + fn+'</FS><S>' + intToStr(size) + '</S>'
// + '<SID>1</SID><DESC></DESC></ICQ_COOL_FT>'
// + '<SID>1</SID></ICQ_COOL_FT>'
// )))
+ TLV($02, dword_LEasStr(proxyIP)) //proxy ip or my IP
+ TLV($16, dword_LEasStr(not proxyIP)) //proxy ip or my IP check
+ s // has proxy flag
+ TLV($03, dword_LEasStr(getLocalIP)) // Proxy IP
+ TLV($05, word_BEasStr(proxyPort))
// + TLV($17, word_LEasStr(not proxyPort)) //word_BEasStr(serverPort)
+ TLV($17, word_LEasStr($FFFF)) //word_BEasStr(serverPort)
+ TLV($2711, word_BEasStr(1) // Multiple Files Flag. A value of 0x0001 indicates - only one file; while a value of 0x0002 indicates that more than one file is being transferred
+ word_BEasStr(1) // File Count, the total number of files that will be transmitted during this file transfer
+ dword_BEasStr(eventDirect.fileSizeTotal)// Total Bytes, the sum of the size in bytes of all files to be transferred
+ StrToUTF8(eventDirect.fileName)+ #00)
+ TLV($2712, 'utf-8')));
Result := addRef(REF_file, uin);
end; // sendFileReq
function TicqSession.sendFileReqPro(drct : TICQDirect):integer;
var
c:TRnQContact;
proxyIP, myIP : Integer;
ProxyPort : Integer;
s : RawByteString;
begin
result:=-1;
if not isReady then exit;
c:= drct.contact;
if not imVisibleTo(c) then
if addTempVisMsg then
addTemporaryVisible(TICQcontact(c));
eventDirect := drct;
if eventDirect.eventID <= 0 then
eventDirect.eventID := SNACref;
Result := eventDirect.eventID;
if drct.mode = dm_bin_proxy then
if drct.AOLProxy.port > 0 then
begin
s := TLV($10, '');
proxyIP := drct.AOLProxy.ip;
proxyPort := drct.AOLProxy.port;
myIP := 0;
end
else
begin
eventDirect.stage := 1;
eventDirect.connect2proxy;
exit;
end
else
begin
s := '';
if drct.stage = 1 then
drct.listen;
proxyIP := getLocalIP;
proxyPort := drct.myPort;
myIP := proxyIP;//getLocalIP;
end;
if drct.fileDesc = '' then
drct.fileDesc := '<ICQ_COOL_FT><FS>' + drct.fileName +'</FS><S>' + intToStr(drct.fileSizeTotal) + '</S>'
// + '<SID>1</SID><DESC></DESC></ICQ_COOL_FT>'
+ '<SID>1</SID></ICQ_COOL_FT>';
sendSNAC(ICQ_MSG_FAMILY, CLI_META_MSG, qword_LEasStr(drct.eventID)+#0#2
+ c.buin
+TLV(5, #0#0 // Request
+ qword_LEasStr(drct.eventID)
+ CAPS_sm2big(CAPS_sm_FILE_TRANSFER)
+ TLV($0A, word_BEasStr(eventDirect.stage)) // Request Number
+ TLV($0F, '') // Mystery Block
// + TLV($0E, 'en')
+ TLV($0D, 'utf-8')
+ TLV($0C, str2html2(StrToUTF8(drct.fileDesc)))
// + TLV($0D, 'unicode-2-0')
// + TLV($0C, StrToUnicode(str2html2('<ICQ_COOL_FT><FS>' + fn+'</FS><S>' + intToStr(size) + '</S>'
// + '<SID>1</SID><DESC></DESC></ICQ_COOL_FT>'
// + '<SID>1</SID></ICQ_COOL_FT>'
// )))
+ TLV($02, dword_LEasStr(proxyIP)) //proxy ip or my IP
+ TLV($16, dword_LEasStr(not proxyIP)) //proxy ip or my IP check
// + TLV($03, dword_LEasStr(getLocalIP)) // Client IP Address
+ TLV($03, dword_LEasStr(myIP)) // Client IP Address
+ TLV($05, word_BEasStr(proxyPort))
// + TLV($17, word_LEasStr(not proxyPort)) //word_BEasStr(serverPort)
+ TLV($17, word_BEasStr(not proxyPort)) // in ICQ6 it seems BE
// + TLV($17, word_LEasStr($FFFF)) //word_BEasStr(serverPort)
+ s // has proxy flag
+ TLV($2711, word_BEasStr(1) // Multiple Files Flag. A value of 0x0001 indicates - only one file; while a value of 0x0002 indicates that more than one file is being transferred
+ word_BEasStr(1) // File Count, the total number of files that will be transmitted during this file transfer
+ dword_BEasStr(drct.fileSizeTotal)// Total Bytes, the sum of the size in bytes of all files to be transferred
+ StrToUtf8(drct.fileName)+ AnsiChar(#00))
+ TLV($2712, 'utf-8')));
Result := addRef(REF_file, c.UID);
end; // sendFileReq
function TicqSession.sendFileReq2(drct : TICQDirect):integer;
var
// c:Tcontact;
proxyIP : Integer;
port : Integer;
s : RawByteString;
begin
result:=-1;
if not isReady then exit;
// c:=contactsDB.get(uin);
if not imVisibleTo(drct.contact) then
if addTempVisMsg then
addTemporaryVisible(TICQcontact(drct.contact));
if sock.http.enabled then
begin
proxyIP := WSocketResolveHost(sock.http.addr).S_addr;
s := TLV($10, '');
port := 0;
end
else
begin
// eventDirect:=directTo(c);
drct.imserver := True;
// eventDirect.kind := DK_file;
drct.listen;
// eventDirect.fileTotal := size;
// port := serverStart;
port := //StrToInt(eventDirect.port);
drct.myPort;
proxyIP := getLocalIP;
s := '';
end;
sendSNAC(ICQ_MSG_FAMILY, CLI_META_MSG, qword_LEasStr(SNACref)+#0#2
+ (drct.contact.buin)
+TLV(5, #0#0 // Request
+ qword_LEasStr(SNACref)+CAPS_sm2big(CAPS_sm_FILE_TRANSFER)
+ TLV($0A, #00#02) // Request Number
+ TLV($02, dword_LEasStr(proxyIP)) //proxy ip or my IP
+ TLV($16, dword_LEasStr(not proxyIP)) //proxy ip or my IP check
+ s // has proxy flag
+ TLV($03, dword_LEasStr(getLocalIP)) // Proxy IP
+ TLV($05, word_BEasStr(port))
// + TLV($17, word_LEasStr(not port)) //word_BEasStr(serverPort)
+ TLV($17, word_BEasStr($FFFF)) //word_BEasStr(serverPort)
)
);
Result := addRef(REF_file, drct.contact.UID);
end; // sendFileReq
procedure TicqSession.sendFileOk(Drct : TICQDirect; SendMsg : Boolean = False;
isListen : Boolean = false; useProxy : Boolean = false);
begin
//if not isReady then exit;
//if not imVisibleTo(c) then
// if addTempVisMsg then
// addTemporaryVisible(c);
if not SendMsg then
begin
// eventDirect:=directTo(c);
eventDirect := Drct;
// eventDirect.kind := DK_file;
// eventDirect.eventID := msgID;
// eventDirect.fileName := eventFilename;
// eventDirect.fileTotal := eventFileSize;
if isListen then
begin
// eventDirect.port := 20000;
eventDirect.listen;
end
else
eventDirect.connect;
end;
if SendMsg then
begin
if useProxy then
sendSNAC(ICQ_MSG_FAMILY, CLI_META_MSG, qword_LEasStr(Drct.eventID)+#0#2
+ Drct.contact.buin// BUIN(drсt.contact.UID)
// + TLV(5, #0#0 // Request
+ TLV(5, #0#2 // Accept
+ qword_LEasStr(Drct.eventID)+CAPS_sm2big(CAPS_sm_FILE_TRANSFER)
+ TLV($0A, #00#02) // Request Number
+ TLV($02, dword_LEasStr(Drct.AOLProxy.ip)) //proxy ip or my IP
+ TLV($16, dword_LEasStr(not Drct.AOLProxy.ip)) //proxy ip or my IP check
// + TLV($03, dword_LEasStr(getLocalIP)) // Proxy IP
+ TLV($05, word_LEasStr(Drct.AOLProxy.port))
+ TLV($17, word_LEasStr(not Drct.AOLProxy.port)) //word_BEasStr(serverPort)
// + TLV($17, word_LEasStr($FFFF)) //word_BEasStr(serverPort)
+ TLV($10, '') // has proxy flag
)
)
// sendSNAC(ICQ_MSG_FAMILY, CLI_META_MSG, qword_LEasStr(msgID)+#0#2
// +BUIN(c.uid)
// +TLV(5, #0#2+qword_LEasStr(msgID)+CAPS_sm2big(CAPS_sm_FILE_TRANSFER)//+TLV($A,#0#2)
// )
// );
else
// Send File OK
sendSNAC(ICQ_MSG_FAMILY, CLI_META_MSG, qword_LEasStr(Drct.eventID)+#0#2
+Drct.contact.buin // BUIN(c.uid)
+ TLV(5, #0#2 // Accept
+qword_LEasStr(Drct.eventID)
+CAPS_sm2big(CAPS_sm_FILE_TRANSFER)//+TLV($A,#0#2)
)
);
end;
end; // sendFileOK
procedure TicqSession.ProcessReceiveFile(dirct : TICQDirect);
begin
// if not isReady then exit;
if not imVisibleTo(dirct.contact) then
if addTempVisMsg then
addTemporaryVisible(TICQcontact(dirct.contact));
eventDirect := dirct;
if (dirct.mode = dm_bin_direct) then
begin
if ((dirct.imSender)and (dirct.stage = 1))or
((not dirct.imSender)and (dirct.stage = 2)) then
dirct.listen
else
dirct.connect
end
else
if dirct.stage = 1 then
dirct.connect2proxy
else
sendSNAC(ICQ_MSG_FAMILY, CLI_META_MSG, qword_LEasStr(dirct.eventID)+#0#2
+ dirct.contact.buin// BUIN(drct.contact.UID)
+ TLV(5, #0#0 // Request
// + TLV(5, #0#2 // Accept
+ qword_LEasStr(dirct.eventID)+CAPS_sm2big(CAPS_sm_FILE_TRANSFER)
+ TLV($0A, #00#02) // Request Number
+ TLV($02, dword_LEasStr(0)) //proxy ip or my IP
+ TLV($16, dword_LEasStr($FFFFFFFF)) //proxy ip or my IP check
+ TLV($03, dword_LEasStr(0)) // Client IP
// + TLV($05, word_BEasStr(Drct.AOLProxy.port))
// + TLV($17, word_LEasStr(not Drct.AOLProxy.port)) //word_BEasStr(serverPort)
// + TLV($17, word_LEasStr($FFFF)) //word_BEasStr(serverPort)
// + TLV($10, '') // has proxy flag
)
)
end; // sendFileOK
procedure TicqSession.sendFileAbort(cnt : TICQcontact; msgID:TmsgID);
//var
// c:Tcontact;
begin
if not isReady then exit;
//c:=contactsDB.get(refs[msgID].uid);
if not imVisibleTo(cnt) then
if addTempVisMsg then
addTemporaryVisible(cnt);
sendSNAC(ICQ_MSG_FAMILY, CLI_META_MSG, qword_LEasStr(msgID)+#0#2
+ cnt.buin
+TLV(5, #0#0+qword_LEasStr(msgID)+CAPS_sm2big(CAPS_sm_FILE)+TLV($B,#0#1) )
);
end; // sendFileAbort
procedure TicqSession.sendFileAck(msgID:TmsgID);
var
c:TICQcontact;
begin
if not isReady then exit;
c:= getICQContact(refs[msgID].uid);
if not imVisibleTo(c) then
if addTempVisMsg then
addTemporaryVisible(c);
sendSNAC(ICQ_MSG_FAMILY, CLI_META_MSG, qword_LEasStr(msgID)+#0#2
+ Length_B(refs[msgID].uid)
+TLV(5, #0#2+qword_LEasStr(msgID) + CAPS_sm2big(CAPS_sm_ICQSERVERRELAY ))
);
end; // sendFileAck
{$ENDIF usesDC}
procedure TicqSession.sendAuthReq(const uin:TUID; const msg:string);
var
c:TICQcontact;
iam : TRnQContact;
begin
c:=getICQContact(uin);
if not imVisibleTo(c) then
if addTempVisMsg then
addTemporaryVisible(c);
iam := getMyInfo;
sendSNAC(ICQ_MSG_FAMILY, CLI_META_MSG, qword_LEasStr(SNACref)+#0#4
+ Length_B(uin)
+TLV(5, myUINle+ AnsiChar(MTYPE_AUTHREQ)+ AnsiChar(#0)
// +WNTS(getMyInfo.nick+#$FE+getMyInfo.first+#$FE+getMyInfo.last+#$FE+ MyInfo0.email+#$FE#0#$FE+msg)
+WNTS(StrToUTF8(iam.nick)+AnsiChar(#$FE)+
StrToUTF8(iam.first)+AnsiChar(#$FE)+
StrToUTF8(iam.last)+AnsiChar(#$FE)+
''+AnsiString(#$FE#0#$FE)+
StrToUTF8(msg))
)
);
end; // sendAuthReq
procedure TicqSession.sendMSGsnac(const uin : TUID; const sn : RawByteString);
begin
sendSNAC(ICQ_MSG_FAMILY, CLI_META_MSG, qword_LEasStr(SNACref)+#0#2
+ Length_B(uin)
+TLV(5, #0#0+qword_LEasStr(SNACref)+ CAPS_sm2big(CAPS_sm_ICQSERVERRELAY)
+TLV($A,#0#1)
+TLV($F,'')
+TLV($2711, header2711 + sn )
)
{ /*
* Set the Buddy Icon Requested flag.
* XXX - Every time? Surely not...
*/
if (args->flags & AIM_IMFLAGS_BUDDYREQ) {
byte_stream_put16(&data, 0x0009);
byte_stream_put16(&data, 0x0000);
}
// +TLV(3,'')
);
end;
procedure TicqSession.sendCryptMSGsnac(const uin : TUID; const sn : RawByteString);