About

It's a small component showing how it's easy to implement basic functions of ICQ v8 (used in 2002a) protocol. Sources are quite good commented so it's very simply to extend functionality of this component. You have to install component from unit ICQClient.pas. Hope you enjoy it ;)

Some source references used in component:

  • Main ICQ v8 proto. site and login sequence, by Douglas McLaughlin
  • Alternative ICQ Protocol Specification, by Rudiger Kuhlmann
  • Some specific info about v8 protocol, by Massimo Melina
  • Encrypting/Decrypting functions(in direct packets) were converted from C++ mICQ clone, by Matthew D. Smith
  • Xorkeygen sources for decrypting database passwords, by covertD
  • Unofficial ICQ database specification, by Derek Soeder
  • ICQ database specification, by Martin Öberg.
  • SOCKS protocol description, by NEC USA, Inc.
  • Miranda-icq sources for database specs (also it's the best ICQ clone ever made!)

    Contact info
    For updates checkout: http://www.cobans.net.
    If you want to receive mails about TICQClient updates, mailto: mailto:alex@ritlabs.com?subject=join_ticqclient_update.
    Have you got any questions, offers, bugreports? Then mail me: alex@ritlabs.com, ICQ: #4024781.
    If someone would like to join the developing of TICQClient, please, do not hesitate to contact me.


Units & Installation

Units:
ICQWorks.pas - contains all low level parsing functions & constants.
MySocket.pas - small and fast TCP socket used in TICQClient.
ICQDb.pas - TICQDb component, helps to import contacts, messages & self info in our own applications.
ICQDb.dcr - component's icon.
ICQDirect.pas - objects providing direct connection support.
ICQClient.pas - TICQClient component itself.
ICQClient.dcr - component's icon.

Installation:
First of all you have to install TICQClient component.
Start Delphi, then Component > Install Component > here you have to choose file ICQClient.pas and press OK button, then in new window press Compile button.
If you had previous versions installed, please reinstall(do the same) component to include new events.

Note: TICQDb and TICQClient components were tested in Delphi5, Delphi6, but can be easily conveted for using in Delphi3 & older versions.


Some important notes about ICQ protocol

  • ICQ protocol consists of two parts:
    • Server protocol, used for exchanging information with server, the last known version is v8 (used in ICQ2001b, ICQ2002a)
    • Direct protocol, used between two ICQ clients and does not depend from server protocol.
    Sometimes direct connection cannot be estabilished between clients: possible one of theese clients uses proxy, some network problems & other unknown reasons.
    TICQClient implements both of theese protocols!
  • All direct connection functions & procedures in this help are marked with "(DC)".
  • If user requests authorization then it will be granted automaticly.


Features

  • Logging to server & status changing
  • Managing contact, visible, invisible, ignore lists
  • Retrieving/uploading server side contact lists
  • Searching users by UIN, Email, Nick or Random Group
  • 'White Pages'
  • Getting user's info
  • Setting info about yourself
  • Registering a new UIN
  • Unregistering the existing UIN
  • Changing the current password
  • Sending/receiving various types of messages and URLs
  • Sending/receiving SMS messages
  • Auto-away messages support
  • Supporting direct connections
  • Sending/receiving contacts & contact requests
  • Importing messages, urls, contacts & owner's info(including password) from ICQ(2000x, 2001x, 2002a) and Miranda-icq 1.2.1
  • Dumping all incoming/outgoing packets
  • Help in English and Russian languages
  • Native Delphi code, fully freeware!


Server Side List
In one of the last versions of ICQ client was added a feature allowing to save a copy of client's contact list on the server. It's very usefull when you are using ICQ from different places. From version 1.17 TICQClient component supports Server Side List (SSL) uploads.

  • Before adding/modifying users and groups you have to call SSLChangeStart procedure.
  • To add a new group call SSLAddGroup procedure, to delete call procedure SSLDelGroup.
  • To add a new user into a group call procedure SSLAddUser to delete call procedure SSLDelUser.
  • To add user into ignore or server side visible/invisible list call SSLAddUserIntoList, to delete call SSLDelUserFromList procedure.
  • To rename the group use procedure SSLUpdateGroup.
  • After modifiyng users and groups you have to call procedure SSLChangeEnd.
  • To retrieve SSL from server call procedure RequestContactList.


property ICQServer: String
ICQ server to connect to, you may use 'login.icq.com'.


property ICQPort: Word
ICQ port to connect to, you may use '5190'.


property UIN: LongWord
Property allows to read/set current client's UIN, used on login.


property Password: String
Property allows to read/set current client's Password, used on login.


property Status: LongWord
Property allows to read/set client's status after logging to server.
Status can be one of(declared in ICQWorks.pas):
S_ONLINE
S_INVISIBLE
S_AWAY
S_NA
S_OCCUPIED
S_DND
S_FFC (Free for Chat)


property ContactList: TStrings
Client's contact list *sent only on login*. Each line indicates UIN number. If you want to add user into contact list after login take a look on AddContact procedure.


property InvisibleList: TStrings
Client's invisible list. Each line indicates UIN number. Invisible list is sent to the server when you are logging/changing status to other then invisible, you can add user while you are online & offline.


property VisibleList: TStrings
Client's visible list. Each line indicates UIN number. Visible list is sent to the server when you are logging/changing status to invisible, you can add user while you are online & offline.


property LoggedIn: Boolean
If client has logged to server the property will return True.


property ConvertToPlaintext: Boolean
If you set this property to True, then text received in RTF(RichText) format will be automaticly converted into plain.


property AutoAwayMessage: String
Client's auto-away message. It's sent as a special typed message when someone requests it(e.g. a response to 'Read Away-message').


property ProxyUserID: String
Sets proxy user's ID. For more info see property ProxyAuth.


property ProxyAuth: Boolean
Set to True if you are using proxy authorization. In this case SOCKS4 will require only ProxyUserID, SOCKS5 will require ProxyUserID and ProxyPass properties to be set.


property ProxyHost: String
Sets your proxy host.


property ProxyPass: String
Sets proxy password. For more info see property ProxyAuth.


property ProxyPort: Word
Sets your proxy port. Usually 1080.


property ProxyResolve: Boolean
Resolve hostnames (ICQServer property) from proxy. Works only with SOCKS5 proxies. Use it when you haven't access to DNS servers.


property ProxyType: TProxyType
Sets your current proxytype. Where ProxyType can take following values (declared in ICQWorks.pas):

  • P_NONE - do not use proxy server, connect direcly
  • P_SOCKS4 - use socks4 server
  • P_SOCKS5 - use socks5 server

    Warning: change this property before logging to server!


property DisableDirectConnections: Boolean
If you set this property to True you will not able conneting to other ICQ clients directly.

Warning: change this property before logging to server!


property ConnectionTimeout: Byte
Set connection timeout (in seconds). If you don't use timeouts set it to 0.
If you haven't connected to ICQ server and ConnectionTimeout seconds elapsed you will receive OnError event with ErrorType = ERR_CONNTIMEOUT.

Note: connection timeout stops after login and disconnect.


procedure Login(Status: LongWord = S_ONLINE)
This procedure logges to server with Status, default set to S_ONLINE, can be used other(listed in property Status). After successfull login you will receive OnLogin event


procedure Disconnect
Disconnect from server.


function AddContact(UIN: LongWord): Boolean
Adds UIN to contact list after logon(when you are online), UIN automaticly added to ContactList TStrings. After adding the UIN you will receive status notifications. Returns True when UIN is added to the list(it wasn't there before).


procedure SendMessage(UIN: LongWord; Msg: String)
Send a message to UIN.


procedure RemoveContact(UIN: LongWord)
Removes UIN from contact list. Use while you are online.


procedure RemoveContactInvisible(UIN: LongWord)
Removes UIN from the invisible list. Use while you are online.


procedure RemoveContactVisible(UIN: LongWord)
Removes UIN from the visible list. Use while you are online.


function SendContacts(UIN: LongWord; Contacts: TStringList): Word; (DC)
Sends contacts to UIN. Each line in Contacts TStringList has the following format: User's UIN=User's NickName, User's NickName can be empty.
Returns ID of the packet if direct connection with UIN has been estabilished, otherwise it returns 0. As a response you will receive OnDirectPacketAck event with this ID.
Example:

  procedure TMainForm.Button2Click(Sender: TObject);
  var
    List: TStringList;
  begin
    List := TStringList.Create;
    List.Add('52341243=Monica');
    List.Add('12333391=Britney');
    List.Add('8213876=');
    List.Add('1234333=Bob');
    List.Add('925464568=');
    ICQClient1.SendContacts(4024781, List);
    List.Free;
  end;


procedure SendMessageAdvanced(UIN: LongWord; const Msg: String; ID: Word; RTFFormat: Boolean)
Sends Msg to UIN with advanced options, after UIN has got your message you will receive confirmation. ID - randomly generated value, may be used for packet acknowledgements (see OnAdvancedMsgAck event). If your Msg is in the RTF(RichText Format), then RTFFormat parameter should be True, otherwise - False. Beware of using the RTF Format, some clients(old versions of ICQ, linux & windows clones) don't support it.


function SendMessageDirect(UIN: LongWord; const Msg: String; RTFFormat: Boolean): Word; (DC)
For more info please see SendMessageAdvanced procedure. This function doesn't yet support confirmations. Returns ID of the packet if direct connection with UIN has been estabilished, otherwise it returns 0. As a response you will receive OnDirectPacketAck event with this ID.


procedure SendSMS(const Destination, Text: String)
Sends SMS message to Destination with Text.
Example:

  ICQClient1.SendSMS('+3739401111', 'Hello, World!');
If evrything is okay you will receive OnSMSAck event, otherwise OnSMSRefused event.


procedure SendURL(UIN: LongWord; const URL, Description: String);
Send an URL message to UIN.


procedure RegisterNewUIN(const Password: String)
Registers a new UIN number, Password parameter -- it's a password which you want to use with new UIN. Procedure should be called when you are not connected to server. If UIN is granted you will receive OnNewUINRegistered event, otherwise - OnNewUINRefused event(if you are trying to register new numbers too often and for other reasons).


procedure UnregisterUIN(const Password: String)
Unregister current UIN. You should call this procedure when you are online, Password variable it's your current password. If password is wrong then you will receive OnUnregisterBadPassword event, otherwise OnUnregisterOk event(after OnUnregisterOk event you are automaticly disconnected from server).


procedure ChangePassword(const NewPassword: String)
Changes current user's password to NewPassword. Should be called when you are online. Doesn't affect on Password property(you have to change it manualy). After successfull change you will receive OnChangePasswordOk event, otherwise OnChangePasswordError event.


procedure DestroyUINList(var List: TList)
Releases memory used while parsing the server side contact list.


procedure RequestAwayMsg(UIN: LongWord; ID: Word; ReqStatus: Byte)
Requests UIN's auto-away message, you can pass random values through ID parameter to devide packets one from other when you receive answers.
ReqStatus - type of auto-away message to request for, can be one of theese (declared in ICQWorks.pas):
GET_AWAY, - request away message
GET_OCCUPIED, - request occupied message
GET_NA, - request NA message
GET_DND, - request DND message
GET_FFC - request FFC(Free For Chat) message.
In other words ReqStatus it's a current UIN's status.
As a reply you will receive OnAutoMsgResponse event.


procedure RequestContactList
Requests server side contact list. For more info look at OnServerListRecv event.


function RequestContacts(UIN: LongWord; const Reason: String): Word; (DC)
Request contact from UIN.
Returns ID of the packet if direct connection with UIN has been estabilished, otherwise it returns 0. As a response you will receive OnDirectPacketAck event with this ID.
Example:

  procedure TMainForm.Button1Click(Sender: TObject);
  begin
    ICQClient1.RequestContacts(4024781, 'Send me some contacts pleease! I''m so bored with you :)');
  end;


procedure RequestInfo(UIN: LongWord)
Query info about UIN. As answer you will recieve theese events: OnUserWorkInfo, OnUserInfoMore, OnUserInfoAbout, OnUserInfoInterests, OnUserInfoMoreEmails.


procedure SetSelfInfoAbout(About: String)
Set info about yourself.
As a result you will receive OnInfoChanged event.


procedure SetSelfInfoGeneral(NickName, FirstName, LastName, Email, City, State, Phone, Fax, Street, Cellular, Zip, Country: String; TimeZone: Byte; PublishEmail: Boolean)
Set general info about yourself. You can skip some parameters (eg. use '' - empty strings) to unspecify some info.
As a result you will receive OnInfoChanged event.


procedure SetSelfInfoMore(Age: Word; Gender: Byte; HomePage: String; BirthYear: Word; BirthMonth, BirthDay: Byte; Language1, Language2, Language3: String)
Set more info about yourself.
As a result you will receive OnInfoChanged event.


procedure SearchByMail(Email: String)
Searches user by Mail.
As answer you will receive OnUserFound event when at least one user found or OnUserNotFound event if such user does not exist.


procedure SearchByName(FirstName, LastName, NickName, Email: String)
Searches user by Other info.
As answer you will receive OnUserFound event when at least one user found or OnUserNotFound event if such user does not exist.


procedure SearchRandom(Group: Word)
Searches random user from Group, where Group id could be found in RandGroups: array[1..11](declared in ICQWorks.pas) constant.
As answer you will receive OnUserFound event when at least one user found or OnUserNotFound event if such user does not exist.

Note: only one user will be found.


procedure SearchByUIN(UIN: LongWord)
Searches user by UIN.
As answer you will receive OnUserFound event when at least one user found or OnUserNotFound event if such user does not exist.


procedure SearchWhitePages(First, Last, Nick, Email: String; MinAge, MaxAge: Word; Gender: Byte; Language, City, State: String; Country, Company, Department, Position: String; Occupation, Past, PastDesc, Interests, InterDesc, Affiliation, AffiDesc, HomePage: String; Online: Boolean)
Searches user in 'White Pages'.
As answer you will receive OnUserFound event when at least one user found or OnUserNotFound event if such user does not exist.


function DirectConnectionEstabilished(UIN: LongWord): Boolean; (DC)
Returns True if direct connection with UIN has been estabilished already.


procedure SendKeepAlive
Sends single keep alive packet to the icq server.

  • it is safe to send keepalive packets.
  • it is safe to never send keepalive packets.
  • keepalive packets are sent by official icq clients, when the checkbox "keep the connection alive" is turned on.
  • it is safe to send keepalive packets with an interval of 30 or more seconds between keepalive packets. It is unknown if they can be sent more frequently.


procedure SetAuthorization(AuthorizationRequired, WebAware: Boolean)
Set your AuthorizationRequired and WebAware options. As result you will receive OnAuthorizationChangedOk event .


procedure SendAuthRequest(UIN: LongWord; Msg: String)
Request authorization. As answer you will receive OnAuthResponse.
Example:

procedure TMainForm.Button1Click(Sender: TObject);
begin
  ICQClient1.SendAuthRequest(4024781, 'Authorize me please!!');
end;


procedure SSLChangeStart(FirstUpload: Boolean)
Notifies server that you will start changing the server side lists. Set FirstUpload to True if you want to add users without authorization.


procedure SSLChangeEnd
Notifies server that you finished changing the server side lists.


procedure SSLAddGroup(GroupName: String; GroupID: Word)
Add a group to the server side list.
GroupName -- name of this group
GroupID -- random value (from interval: 1 to 32767) associated with this group
As answer you will receive OnSSLChangeResponse event.


procedure SSLDelGroup(GroupName: String; GroupID: Word)
Delete group from SSL.
GroupName should be equal to the last passed in procedure SSLAddGroup or procedure SSLUpdateGroup with this GroupID.
As answer you will receive OnSSLChangeResponse event.
Example:

procedure TMainForm.Button3Click(Sender: TObject);
begin
  ICQClient1.SSLAddGroup('General', 0008);
  ICQClient1.SSLDelGroup('General', 0008);
end;
Note: delete all users from the group before deleting the group.


procedure SSLUpdateGroup(GroupName: String; GroupID: Word; UserIDs: TStringList)
Update group.
UserIDs - this parameter should contain a string list of all UserID values which belogs to this GroupID.
Can be used to rename any SSL group. (official clones send this command also when adding/removing users from SSL).
As answer you will receive OnSSLChangeResponse event.
Example:

procedure TMainForm.Button1Click(Sender: TObject);
var
  List: TStringList;
begin
  ICQClient1.SSLChangeStart(False);
  ICQClient1.SSLAddGroup('My Good Friends', 0010);                                  //Create group 'My Good Friends' with id 0010
  ICQClient1.SSLAddGroup('Me lovers', 0011);                                        //Create group 'Me lovers' with id 0011
  ICQClient1.SSLAddUser(0010, 0020, '4024781', 'Coban', '', False, False);          //Add user Coban with UIN 4024781 in 'My Good Friends' group
  ICQClient1.SSLAddUser(0010, 0021, '98384233', 'Animal Killer', '', False, False); //Add user Animal Killer in 'My Good Friends' group
  ICQClient1.SSLAddUser(0011, 0015, '848382', 'Britney', '', False, False);         //Add user Britney in 'Me lovers' group
  ICQClient1.SSLAddUser(0011, 0015, '848382', 'Britney my Love!', '', False, True); //Rename 'Britney' to 'Britney my Love!' ;)

  List := TStringList.Create;   //Create temporary list
  List.Add(0020);               //Add Coban's UserID to list
  List.Add(0021);               //Add Animal Killer's UserID to list

  ICQClient1.SSLUpdateGroup('My Bad Friends', 0010, List);                          //Rename group 'My Good Friends' to 'My Bad Friends'

  List.Free;

  ICQClient1.SSLChangeEnd;
end;


procedure SSLAddUser(GroupID, UserID: Word; UIN, Name, SMSNumber: String; Authorize, UpdateUser: Boolean)
Adds user to server side list.
GroupID - id of the group user belongs to (passed in the second parameter in SSLAddGroup procedure)
UserID - random value (from interval: 1 to 32767) associated with this user
UIN - UIN of the user
Name - Nick name of this user (can be empty)
SMSNumber - localy assigned user's SMS number (can be empty)
Authorize - set to True if you are awaiting authorization from this user
UpdateUser - set to True if you are updating user's info: when you want to change Name or SMSNumber
As answer you will receive OnSSLChangeResponse event.

Notes:
If user requires authorization before adding him in your contact list you have to request authorization wait untill OnAuthResponse event is called and if authorization is granted -- add UIN to SSL, otherwise you will receive OnSSLChangeResponse with ErrorCode = ERRSSL_AUTH (User not authorized).

Also, there is another way to add user with authorization required -- set FirstUpload parameter in SSLChangeStart procedure to True. But if you do it often server will stop adding users to SSL. Do it when uploading the whole contact list for the first time.

To delete user you have to use procedure SSLDelUser. Example:

procedure TMainForm.Button1Click(Sender: TObject);
begin
  ICQClient1.SSLChangeStart(False);
  ICQClient1.SSLAddGroup('My Good Friends', 0010);                                  //Create group 'My Good Friends' with id 0010
  ICQClient1.SSLAddGroup('Me lovers', 0011);                                        //Create group 'Me lovers' with id 0011
  ICQClient1.SSLAddUser(0010, 0020, '4024781', 'Coban', '', False, False);          //Add user Coban with UIN 4024781 in 'My Good Friends' group
  ICQClient1.SSLAddUser(0010, 0021, '98384233', 'Animal Killer', '', False, False); //Add user Animal Killer in 'My Good Friends' group
  ICQClient1.SSLAddUser(0011, 0015, '848382', 'Britney', '', False, False);         //Add user Britney in 'Me lovers' group
  ICQClient1.SSLAddUser(0011, 0015, '848382', 'Britney my Love!', '', False, True); //Rename 'Britney' to 'Britney my Love!' ;)
  ICQClient1.SSLDelUser(0011, 0015, '848382', 'Britney my Love!', '', False);       //Remove user 'Britney my Love!' from 'Me lovers' group
  ICQClient1.SSLChangeEnd;
end;
Another example, UIN 398712 uses authorization:
{First stage - send authorization request:}
procedure TMainForm.Button1Click(Sender: TObject);
begin
  ICQClient1.SendAuthRequest(398712, 'Authorize me, please, we met at school!');
end;

{Second stage - add user to SSL:}
procedure TMainForm.ICQClient1AuthResponse(Sender: TObject; UIN: String;
  Granted: Boolean; Reason: String);
begin
  ICQClient1.SSLChangeStart(False);
  if Granted then
    ICQClient1.SSLAddUser(0010, 0025, '398712', '', '', False, False)               //Add user(ID: 0025) to group(ID: 0010) after we've been authorized
  else
    ICQClient1.SSLAddUser(0010, 0025, '398712', '', '', False, True);               //Add user(ID: 0025) to group(ID: 0010), user refused to authorize us (may be you lie ;), so add him in SSL with authorization awaiting status
  ICQClient1.SSLChangeEnd;
end;
Another example, UIN 398712 uses authorization:
{Add user without authorization.}
procedure TMainForm.ICQClient1AuthResponse(Sender: TObject; UIN: String;
  Granted: Boolean; Reason: String);
begin
  ICQClient1.SSLChangeStart(True);                                                  //Now it's not require to request authorization
  ICQClient1.SSLAddUser(0010, 0025, '398712', '', '', False, False);                //Add user(ID: 0025) to group(ID: 0010)
  ICQClient1.SSLChangeEnd;
end;


procedure SSLDelUser(GroupID, UserID: Word; UIN, Name, SMSNumber: String; Authorize: Boolean)
Delete user from the server side list.
For more info see procedure SSLAddUser.
Parameters in this procedure should be equal to last params passed in procedure SSLAddUser with this GroupID.
As answer you will receive OnSSLChangeResponse event.


procedure SSLAddUserIntoList(UserID: Word; UIN: String; BuddyType: Word)
UserID - random value (from interval: 1 to 32767) associated with the user
UIN - UIN of the user
BuddyType (declared in ICQWorks.pas) can be one of:

  • BUDDY_IGNORE //Add contact to the ignore list
  • BUDDY_INVISIBLE //Add contact to the server side invisible list
  • BUDDY_VISIBLE //Add contact to the server side visible list
    As answer you will receive OnSSLChangeResponse event.
    To delete user from one of theese server side lists use SSLDelUserFromList procedure.

    Notes:
    If you add user to the ignore list this user will stop receiving any notifications from you. Also this UIN will not be able to send you messages.

    You should not use SSLChangeStart & SSLChangeEnd procedures!


procedure SSLDelUserFromList(UserID: Word; UIN: String; BuddyType: Word)
Remove user from the visible, invisible, ignore list.
For more info see SSLAddUserIntoList.
As answer you will receive OnSSLChangeResponse event.

Note: you should not use SSLChangeStart & SSLChangeEnd procedures!


OnLogin(Sender: TObject)
Called after successfull login.


OnConnectionFailed(Sender: TObject)
Called when you cannot connect or server has disconnected you in other reasons.


OnAddedYou(Sender: TObject; UIN: String)
Called when someone adds you to his contact list.


OnAdvancedMsgAck(Sender: TObject; UIN: String; ID: Word; AcceptType: Byte; AcceptMsg: String)
A response to SendMessageAdvanced procedure.
It's a confirmation that client received your message successfully. If you haven't received this event for some time you can resend your message.
ID - id passed in SendMessageAdvanced procedure.
AcceptType may be one of (declared in ICQWorks.pas):
ACC_NORMAL - normally accepted
ACC_NO_OCCUPIED - not accepted, occupied status
ACC_NO_DND - not accepted, dnd status
ACC_AWAY - accepted but away status
ACC_NA - accepted in NA status
ACC_CONTACTLST - accepted to contact list (no blink in tray)
AcceptMsg is an away message, such as: "User is currently N/A. You can leave him/her a message".


OnDirectPacketAck(Sender: TObject; ID: Word); (DC)
A response to every direct packet(SendMessageDirect, RequestContacts, etc) you've sent and which was received successfully by the other side.
ID = return value in DC (Direct Connection) functions.


OnAutoMsgResponse(Sender: TObject; UIN: String; ID: Word; RespStatus: Byte; Msg: String)
A response to RequestAwayMsg procedure.
ID & RespStatus are the same you've passed in RequestAwayMsg procedure, Msg -- it's an user's auto-away message.


OnChangePasswordOk(Sender: TObject)
A response to ChangePassword procedure. It means that your password has been changed.


OnChangePasswordError(Sender: TObject)
A response to ChangePassword procedure. It means that your password cannot be changed, possible new password is too long or too short.


OnContactListRecv(Sender: TObject; UIN: String; ContactList: TStringList); (DC)
Called when UIN sends you his contacts. Each line in ContactList has the folling format: User's UIN=User's NickName. After using the ContactList TStringList you *must* destroy it (ContactList.Free).


OnContactListRequest(Sender: TObject; UIN, Reason: String); (DC)
Called when UIN requests from you some contacts, don't let him die :)


OnMessageRecv(Sender: TObject; Msg, UIN: String);
Called when you receive a message(through server or dirrectly).


OnURLRecv(Sender: TObject; Description, URL, UIN: String)
Called when you receive URL (through server or dirrecly).


OnOfflineMsgRecv(Sender: TObject; Msg, UIN: String)
Called when you receive a message, which was sent when you were offline.


OnOfflineURLRecv(Sender: TObject; Description, URL, UIN: String)
Called when you receive an URL, which was sent when you were offline.


OnNewUINRegistered(Sender: TObject; UIN: String)
A response to RegisterNewUIN procedure. New UIN is granted to you! Now you can use this UIN to login to the server.


OnNewUINRefused(Sender: TObject)
A response to RegisterNewUIN procedure. It means that server cannot give you a new UIN, possible you are trying to register numbers too often or there are other reasons.


OnServerListRecv(Sender: TObject; SrvContactList: TList)
A response to RequestContactList procedure.
After using the SrvContactList you *must* call DestroyUINList procedure with SrvContactList as a parameter, required to free allocated data, otherwise you'll have memory leaks. Each SrvContactList is a pointer on a TUINEntry stucture (declared in ICQClient.pas).

  TUINEntry = record
    UIN: LongWord;            //UIN in contact list
    Nick: ShortString;        //Nick of this UIN, can be null(empty)
    CType: Word;              //Type, can be U_NORMAL(Normal contact list entry), U_VISIBLE_LIST(user is in visible list)
                              //, U_INVISIBLE_LIST(user is in invisible list), U_IGNORE_LIST(user is in ignore list)
    CGroupID: Word;           //Group's ID user belongs to
    CTag: Word;               //ID of the user
    CGroup: ShortString;      //Group name, UIN belongs to
  end;

  Example:
  procedure TMainForm.ICQClient1ServerListRecv(Sender: TObject;
    SrvContactList: TList);
  var
    i: Word;
    UserInfo: TUINEntry;
  begin
     if SrvContactList.Count > 0 then
       for i := 0 to SrvContactList.Count - 1 do
       begin
         UserInfo := PUINEntry(SrvContactList.Items[i])^;
         Memo1.Lines.Add(UserInfo.Nick + ' is in group ' + UserInfo.CGroup
           + ' and his uin is ' + IntToStr(UserInfo.UIN));
       end;
     ICQClient1.DestroyUINList(SrvContactList);
  end;


OnStatusChange(Sender: TObject; UIN: String; Status: Cardinal)
Called when user from your contact list changes status or goes online. Statuses are listed in property Status. Also you can use StatusToStr(Value: LongWord): String function from ICQWorks for converting the numberic representation into the string value.


OnUserOffline(Sender: TObject; UIN: String)
Called when user from your contact list goes offline.


OnUnregisterBadPassword(Sender: TObject)
A response to UnregisterUIN procedure. Called when the password passed in UnregisterUIN was incorrect.


OnUnregisterOk(Sender: TObject)
A response to UnregisterUIN procedure. Called when you have been unregistered. After this event you are automaticly disconnected from server.


OnUserFound(Sender: TObject; UIN, Nick, FirstName, LastName, Email: String; Status: Word; Gender, Age: Byte; SearchComplete, Authorize: Boolean)
A reponse to SearchByMail, SearchByUIN, SearchByName, SearchRandom, SearchWhitePages procedures. SearchComplete is set to TRUE when there are no more such users (so this user is last in search response list).


OnUserNotFound(Sender: TObject)
A reponse to SearchByMail, SearchByUIN, SearchByName, SearchRandom, SearchWhitePages procedures.
Called when there are no users found.


OnUserGeneralInfo(Sender: TObject; UIN, NickName, FirstName, LastName, Email, City, State, Phone, Fax, Street, Cellular, Zip, Country: String; TimeZone: Byte; PublishEmail: Boolean)
A response to RequestInfo procedure.
To convert TimeZone to normal format(eg. +2:00) you have to do the following:

  var
    S: String;
  <....>
  S := IntToStr(- ShortInt(TimeZone) div 2) + ':' + IntToStr(Abs(ShortInt(TimeZone) mod 2 * 30));


OnUserInfoMore(Sender: TObject; UIN: String; Age: Word; Gender: Byte; HomePage: String; BirthYear, BirthMonth, BirthDay: Word; Lang1, Lang2, Lang3: String)
A response to RequestInfo procedure.


OnUserInfoAbout(Sender: TObject; UIN, About: String)
A response to RequestInfo procedure.


OnUserWorkInfo(Sender: TObject; UIN, WCity, WState, WPhone, WFax, FAddress, WZip, WCountry, WCompany, WDepartment, WPosition, WOccupation, WHomePage: String)
A response to RequestInfo procedure.


OnUserInfoInterests(Sender: TObject; UIN: String; Interests: TStringList)
A response to RequestInfo procedure.
If you have set this event, you *must* destroy Interests StringList afrer using it(Interests.Free).


OnUserInfoMoreEmails(Sender: TObject; UIN: String; Emails: TStringList)
A response to RequestInfo procedure.
If you have set this event, you *must* destroy Emails StringList after using it(Emails.Free).


OnUserInfoBackground(Sender: TObject; UIN: String; Pasts, Affiliations: TStringList)
A response to RequestInfo procedure.
If you have set this event, you *must* destroy Pasts and Affilattions StringLists after using of them.


OnPktDirectParse(Sender: TObject; Buffer: Pointer; BufLen: Cardinal; Incoming: Boolean); (DC)
Called every time TICQClient sends or receives packet through direct protocal. Used by developers.

Note: packets can be encrypted.


OnPktParse(Sender: TObject; Buffer: Pointer; BufLen: Cardinal; Incoming: Boolean)
Called every time TICQClient sends or receives packet. Used by developers.


OnSMSAck(Sender: TObject; Source, Network, MsgId: String; Deliverable: Boolean)
A response to SendSMS procedure.
Called when SMS message was successfully added to the cellular provider's(Network param) que. This means that the SMS message will be soon delivered.


OnSMSRefused(Sender: TObject)
A response to SendSMS procedure.
Called when SMS cannot be delivered. Possible you've set wrong cellular number.


OnSMSReply(Sender: TObject; Source, SmsSender, Time, Text: String)
Called when someone replied to your SMS message through mobile phone.


OnOnlineInfo(Sender: TObject; UIN: String; Port: Word; InternalIP, ExternalIP: String; ProtoVer: Byte)
Called after OnStatusChange event. Provides advances info about UIN.


OnError(Sender: TObject; ErrorType: TErrorType; ErrorMsg: String)
Called when happened an error or warning.
ErrorType can be one of:

  • ERR_SOCKET - error happened in socket
  • ERR_INTERNAL - unknown internal component error
  • ERR_WARNING - just a warning
  • ERR_PROXY - error related with proxy server
  • ERR_PROTOCOL - icq protocol related error
  • ERR_CONNTIMEOUT - connection timeout (see ConnectionTimeout property for more info)
  • ERR_LOGIN - error during login, ErrorMsg can be: 'Bad password' or 'Too often logins'


OnInfoChanged(Sender: TObject; InfoType: TInfoType)
A response to SetSelfInfoGeneral, SetSelfInfoAbout, SetSelfInfoMore.
InfoType -- info you've uploaded, can be one of:

  • INFO_GENERAL
  • INFO_MORE
  • INFO_ABOUT

    Note: it's safe to upload one info type to server, wait untill OnInfoChanged event is called and upload the next info type


OnAuthorizationChangedOk(Sender: TObject)
A response to SetAuthoriation procedure.


OnAuthResponse(Sender: TObject; UIN: String; Granted: Boolean; Reason: String)
A response to SendAuthRequest procedure.
If authorization isn't granted (Granted parameter is set to False) reason can be filled with the answer.


OnSSLChangeResponse(Sender: TObject; ErrorCode: Word)
A response to all SSL procedures.
ErrorCode can be one of (declared in ICQWorks.pas):

  • ERRSSL_NOTFOUND //User not found
  • ERRSSL_EXISTS //Added buddy already exists
  • ERRSSL_AUTH //User not authorized
  • ERRSSL_OTHER //Other SSL error
  • ERRSSL_NOERROR //No error (changed successfully)


property DatFile: String
Set user's .dat file.

See also: property IdxFile.


property IdxFile: String
Set user's .idx file.
Eg. if my UIN is 4024781, then in C:\Program Files\ICQ\2002a\ there two files: 4024781.dat and 4024781.idx which should be used for importing.

See also: property DatFile

Note: This property should not be used if the DbType property is DB_MIRANDA.


property DbVersion: LongWord
Get current ICQ database version, can be one of:
DB_99A - 99a
DB_99B - 99b
DB_2000a - 2000a
DB_2000b - 2000b
DB_2001a - 2001a, 2001b, 2002a
DB_MIRANDA121 - Miranda 1.2.1

This property is set after calling StartParsing procedure.


propety DbType: TDbType
Set user's .dat file type, can be DB_ICQ, DB_MIRANDA (declared in ICQWorks.pas).


procedure StartParsing
This procedure opens .idx and .dat files & parses their contents.
Should be called after IdxFile property and DatFile property are set
As a result you will receive OnParsingStarted event or OnError event if there is an error.


OnAdvMessageFound(Sender: TObject; UIN: Cardinal; Incoming: Boolean; PlainText, RichText, UTF8Text, RecvTime: String; RecvTimeStamp: Cardinal)
Called when message with advanced properties was found in .dat file.

Note: called when DbType property is DB_ICQ only.


OnContactFound(Sender: TObject; UIN: Cardinal; NickName, FirstName, LastName, Email: String; Age, Gender: Byte; LastUpdate: String; LastUpdateStamp: Cardinal)
Called when contact list entry was found in .dat file.

Note: LastUpdate and LastUpdateStamp parameters are not set if DbType property is DB_MIRANDA.


OnError(Sender: TObject; Reason: Word)
Called when the error occured.
Reason can be one of:
ERR_FILEOPEN - Could not open .idx or .dat file
ERR_NOTICQDB - Not an ICQ database
ERR_DBVERNOTSUPPORTED - Database version not supported

Note: you can use function DbErrorToStr(Error: Word): String for converting the Reason into it's string representation.


OnMessageFound(Sender: TObject; UIN: Cardinal; Incoming: Boolean; Msg, RecvTime: String; RecvTimeStamp: Cardinal)
Called when message was found in .dat file.


OnURLFound(Sender: TObject; UIN: Cardinal; Incoming: Boolean; Description, URL, RecvTime: String; RecvTimeStamp: Cardinal)
Called when URL was found in .dat file.


OnParsingFinished(Sender: TObject)
Called when parsing of .dat & .idx files has been finished.


OnParsingStarted(Sender: TObject)
Called when parsing of .dat & .idx files started successfully.


OnProgress(Sender: TObject; Progress: Byte)
While parsing the .idx and .dat files you will receive OnProgress event. Progress it's a percent (%) of work has been already done.

Note: doesn't work if the DbType property is DB_MIRANDA.


OnSelfInfoFound(Sender: TObject; UIN: Cardinal; NickName, FirstName, LastName, Email, Password: String; Age, Gender: Byte; LastUpdate: String; LastUpdateStamp: Cardinal)
Called when self info (in other words owner's info) has been found.