1 /*
2  * This file is part of Licq, an instant messaging client for UNIX.
3  * Copyright (C) 2010-2013 Licq developers <licq-dev@googlegroups.com>
4  *
5  * Licq is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * Licq is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Licq; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 
20 #ifndef LICQ_EVENT_H
21 #define LICQ_EVENT_H
22 
23 #include <pthread.h>
24 #include <string>
25 
26 #include "userid.h"
27 
28 namespace LicqIcq
29 {
30 class COscarService;
31 class IcqProtocol;
32 void* ProcessRunningEvent_Client_tep(void* p);
33 void* ProcessRunningEvent_Server_tep(void* p);
34 void* OscarServiceSendQueue_tep(void* p);
35 }
36 
37 namespace LicqMsn
38 {
39 class CMSN;
40 }
41 
42 namespace LicqJabber
43 {
44 class Plugin;
45 }
46 
47 namespace LicqDaemon
48 {
49 class PluginManager;
50 }
51 
52 namespace Licq
53 {
54 class Packet;
55 class ProtocolSignal;
56 class UserEvent;
57 
58 //-----CExtendedAck----------------------------------------------------------
59 
60 /*! \brief Information on file and chat request responses.
61 
62     This class will provide information on what the result of a chat or file
63     transfer request was.
64 */
65 class ExtendedData
66 {
67 public:
68   // Accessors
69 
70   //!Returns true if the remote end accepted the request, otherwise false.
accepted()71   bool accepted() const { return myAccepted; }
72   //!The port to connect to if the request was accpeted.
port()73   unsigned short port() const { return myPort; }
74   //!The reason for declining the request.
response()75   const std::string& response() const { return myResponse; }
76 
77 protected:
ExtendedData(bool accepted,unsigned short port,const std::string & response)78   ExtendedData(bool accepted, unsigned short port, const std::string& response)
79     : myAccepted(accepted), myPort(port), myResponse(response)
80   { /* Empty */ }
81 
82   bool myAccepted;
83   unsigned short myPort;
84   std::string myResponse;
85 
86   friend class LicqIcq::IcqProtocol;
87 };
88 
89 
90 //-----CSearchAck------------------------------------------------------------
91 /*! \brief The response to a search request.
92 
93     Each search result is passed to the plugin as a CSearchAck.  If there
94     was no search results, then a single CSearchAck is passed on with
95     Result() returning EVENT_SUCCESS, which also signifies the search is
96     complete.
97 */
98 class SearchData
99 {
100 public:
101   enum Status
102   {
103     StatusOffline = 0,  // User is offline
104     StatusOnline = 1,   // User is online
105     StatusDisabled = 2, // User has disabled online awareness
106   };
107 
108   // Accessors
109   //! Returns the alias (nickname) of the search result.
alias()110   const std::string& alias() const { return myAlias; }
111   //! Returns the first name of the search result.
firstName()112   const std::string& firstName() const { return myFirstName; }
113   //! Returns the last name of the search result.
lastName()114   const std::string& lastName() const { return myLastName; }
115   //! Returns the e-mail address of the search result.
email()116   const std::string& email() const { return myEmail; }
117 
118   /**
119    * Get the user id
120    *
121    * @return User id of search match
122    */
userId()123   const UserId& userId() const { return myUserId; }
124 
125   //! If non-zero, the number of search results that were found that could not
126   //! be displayed.  The server has a 40 user limit on search results.  This
127   //! is valid when Result() is EVENT_SUCCESS.
more()128   unsigned long more() const { return myMore; }
129   //! The online status of the search result.
status()130   char status() const { return myStatus; }
131   //! The gender of the search result.  Female = 1, Male = 2, Unknown = 3.
gender()132   char gender() const { return myGender; }
133   //! The age of the serach result.
age()134   char age() const { return myAge; }
135   //! Non-zero if authorization is required to add this user.
auth()136   char auth() const { return myAuth; }
137 
138 protected:
SearchData(const UserId & userId)139   SearchData(const UserId& userId)
140     : myUserId(userId)
141   { /* Empty */ }
142 
143   UserId myUserId;
144   std::string myAlias;
145   std::string myFirstName;
146   std::string myLastName;
147   std::string myEmail;
148   unsigned long myMore;
149   char myStatus;
150   char myGender;
151   char myAge;
152   char myAuth;
153 
154   friend class LicqIcq::IcqProtocol;
155 };
156 
157 
158 /*! \brief Plugin event messages
159 
160     This class is the main event class for talking to the ICQ server and to
161     plugins.  Internally all messages/urls... become ICQEvents with the
162     relevant data fields set.  A plugin will receive an event in response
163     to any asynchronous function call (such as icqSendMessage) eventually.
164 */
165 class Event
166 {
167 public:
168   enum ConnectType
169   {
170     ConnectNone         = 0,
171     ConnectServer       = 1,
172     ConnectUser         = 2,
173   };
174 
175   enum ResultType
176   {
177     ResultAcked         = 1,    // Event acked by reciepient
178     ResultSuccess       = 2,    // Event successfully sent
179     ResultFailed        = 3,    // Event failed
180     ResultTimedout      = 4,    // Time out while communicating with remote socket
181     ResultError         = 5,    // Other error
182     ResultCancelled     = 6,    // Event cancelled by the user
183     ResultUnsupported   = 7,    // Event is unsupported
184   };
185 
186   enum SubResultType
187   {
188     SubResultAccept     = 1,    // Event was accepted by recipient
189     SubResultRefuse     = 2,    // Event was rejected by recipient
190     SubResultReturn     = 3,    // Recipient is DND/Occupied, message needs to be resent with flags for urgent or to contact list
191   };
192 
193   enum Commands
194   {
195     CommandOther        = 0,            // Command not in this list
196     CommandMessage      = 1,            // Plain text message
197     CommandUrl          = 2,            // URL message
198     CommandFile         = 3,            // File transfer proposal
199     CommandChatInvite   = 4,            // Chat invitation
200     CommandSearch       = 5,            // Search (last event)
201     CommandSecureOpen   = 6,            // Open secure channel
202   };
203 
204   enum Flags
205   {
206     FlagDirect          = 0x0001,       // Message/Url/... was sent direct
207     FlagSearchDone      = 0x0002,       // This is the last search result
208   };
209 
210   // Accessors
211 
212   /// One of CommandType above
command()213   unsigned command() const { return myCommand; }
214 
215   /// Bitmask from Flags above
flags()216   unsigned flags() const { return myFlags; }
217 
218   //!This is the result of the event.
Result()219   ResultType Result() const { return m_eResult; }
220 
221   /// One of SubResultType above. This field is only relevant if the command
222   /// was ICQ_CMDxTCP_START (ie the message was sent direct).
subResult()223   unsigned subResult() const { return mySubResult; }
224 
225   //!The SNAC returned as an unsigned long.  The upper 2 bytes is the family
226   //!and the lower 2 bytes is the subtype.  To compare SNAC's use the SNAC
227   //!macro to convert it to an unsigned long: MAKESNAC(family, subtype).
SNAC()228   unsigned long SNAC() const { return m_nSNAC; }
229 
230   //!This is used to identify events internally, but is necessary for
231   //!accepting/rejecting chat or file requests.
Sequence()232   unsigned short Sequence() const { return m_nSequence; }
233 
234   //!This is used to identify events internally, is are necessary for
235   //!accepting/rejecting chat or file requests.
SubSequence()236   unsigned short SubSequence() const { return m_nSubSequence; }
237 
238   /**
239    * Get user id the event was destined for.
240    *
241    * @return User id for event if relevant
242    */
userId()243   const UserId& userId() const { return myUserId; }
244 
245   //!Special structure containing information relevant if this is a
246   //!search event.
SearchAck()247   const SearchData* SearchAck() const { return m_pSearchAck; }
248 
249   //!Special structure containing information relevant if this is a
250   //!chat or file transfer accept or reject.
ExtendedAck()251   const ExtendedData* ExtendedAck() const { return m_pExtendedAck; }
252 
253   //!Contains the actual CUserEvent containing the message/url...that was
254   //!sent to Uin().  Can be used to resend the event.
userEvent()255   const UserEvent* userEvent() const { return m_pUserEvent; }
256 
257   // Returns the event and transfers ownership to the calling function
258   UserEvent* GrabUserEvent();
259   SearchData* GrabSearchAck();
260 
261   //!Compare this event to the id to see if the plugin matches a waiting
262   //!event with the event that the daemon has signaled to the plugin.
263   bool Equals(unsigned long) const;
264 
265   ~Event();
266 
267 protected:
268   Event(const ProtocolSignal* ps, ResultType result = ResultSuccess, UserEvent* ue = NULL);
269   Event(pthread_t caller, unsigned long id, int _nSocketDesc, Packet* p, ConnectType _eConnect,
270       const UserId& userId = UserId(), UserEvent* e = NULL);
271   Event(int _nSocketDesc, Packet* p, ConnectType _eConnect, const UserId& userId = UserId(),
272       UserEvent* e = NULL);
273   Event(const Event* e);
274 
275   // Daemon only
SubType()276   unsigned short SubType() const     { return m_nSubType; }
ExtraInfo()277   unsigned short ExtraInfo() const   { return m_nExtraInfo; }
SetSubType(unsigned short nSubType)278   void SetSubType(unsigned short nSubType) { m_nSubType = nSubType; }
NoAck()279   bool NoAck() const           { return m_NoAck; }
SetNoAck(bool NoAck)280   void SetNoAck(bool NoAck)    { m_NoAck = NoAck; }
IsCancelled()281   bool IsCancelled() const     { return m_bCancelled; }
282 
283   void AttachPacket(Packet* p);
284 
285   // Compare this event to another one
286   bool CompareEvent(int, unsigned short) const;
287   bool CompareEvent(unsigned short) const;
288   bool CompareSubSequence(unsigned long) const;
289   unsigned long EventId() const;
290 
291   ConnectType    m_eConnect;
292   unsigned myCommand;
293   unsigned myFlags;
294   ResultType m_eResult;
295   unsigned mySubResult;
296   bool           m_bCancelled : 1;
297   bool           m_Deleted : 1;
298   bool           m_NoAck : 1;
299   unsigned long  m_nSNAC;
300   unsigned short m_nSequence;
301   unsigned short m_nSubSequence;
302   unsigned short m_nSubType;
303   unsigned short m_nExtraInfo;
304   int            m_nSocketDesc;
305   UserId myUserId;
306   Packet* m_pPacket;
307   pthread_t      thread_send;
308   bool           thread_running;
309   pthread_t      thread_plugin;
310 
311   UserEvent* m_pUserEvent;
312   ExtendedData* m_pExtendedAck;
313   SearchData* m_pSearchAck;
314 
315   unsigned long  m_nEventId;
316 
317   friend class LicqIcq::COscarService;
318   friend class LicqIcq::IcqProtocol;
319   friend void* LicqIcq::ProcessRunningEvent_Client_tep(void* p);
320   friend void* LicqIcq::ProcessRunningEvent_Server_tep(void* p);
321   friend void* LicqIcq::OscarServiceSendQueue_tep(void* p);
322   friend class LicqMsn::CMSN;
323   friend class LicqJabber::Plugin;
324   friend class LicqDaemon::PluginManager;
325 };
326 
327 } // namespace Licq
328 
329 #endif
330