diff options
Diffstat (limited to 'protocols')
-rw-r--r-- | protocols/Skype/src/skype_chat.cpp | 269 | ||||
-rw-r--r-- | protocols/Skype/src/skype_dialogs.cpp | 10 | ||||
-rw-r--r-- | protocols/Skype/src/skype_events.cpp | 79 | ||||
-rw-r--r-- | protocols/Skype/src/skype_proto.cpp | 3 | ||||
-rw-r--r-- | protocols/Skype/src/skype_proto.h | 22 | ||||
-rw-r--r-- | protocols/Skype/src/skype_subclassing.cpp | 9 | ||||
-rw-r--r-- | protocols/Skype/src/skype_subclassing.h | 12 |
7 files changed, 345 insertions, 59 deletions
diff --git a/protocols/Skype/src/skype_chat.cpp b/protocols/Skype/src/skype_chat.cpp index 358c435cc9..25cd462268 100644 --- a/protocols/Skype/src/skype_chat.cpp +++ b/protocols/Skype/src/skype_chat.cpp @@ -1,5 +1,7 @@ #include "skype_proto.h"
#include <m_chat.h>
+#include <m_message.h>
+#include <m_history.h>
bool CSkypeProto::IsChatRoom(HANDLE hContact)
{
@@ -33,7 +35,7 @@ void CSkypeProto::ChatPrepare(HANDLE hItem, HWND hwndList) }
}
-void CSkypeProto::FillChatList(HANDLE hItem, HWND hwndList, SEStringList &chatTargets)
+void CSkypeProto::GetInviteContacts(HANDLE hItem, HWND hwndList, SEStringList &chatTargets)
{
if (hItem == NULL)
hItem = (HANDLE)::SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_ROOT, 0);
@@ -43,7 +45,7 @@ void CSkypeProto::FillChatList(HANDLE hItem, HWND hwndList, SEStringList &chatTa if (IsHContactGroup(hItem))
{
HANDLE hItemT = (HANDLE)SendMessage(hwndList, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem);
- if (hItemT) this->FillChatList(hItemT, hwndList, chatTargets);
+ if (hItemT) this->GetInviteContacts(hItemT, hwndList, chatTargets);
}
else
{
@@ -70,11 +72,11 @@ void CSkypeProto::FillChatList(HANDLE hItem, HWND hwndList, SEStringList &chatTa static const COLORREF crCols[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
-void CSkypeProto::RegisterChat()
+void CSkypeProto::InitChat()
{
GCREGISTER gcr = {0};
gcr.cbSize = sizeof(gcr);
- gcr.dwFlags = GC_TYPNOTIF | GC_CHANMGR;// | GC_TCHAR;
+ gcr.dwFlags = GC_TYPNOTIF | GC_CHANMGR;
gcr.iMaxText = 0;
gcr.nColors = 16;
gcr.pColors = (COLORREF*)crCols;
@@ -82,26 +84,51 @@ void CSkypeProto::RegisterChat() gcr.pszModule = this->m_szModuleName;
CallServiceSync(MS_GC_REGISTER, 0, (LPARAM)&gcr);
- //YHookEvent(ME_GC_EVENT, &CYahooProto::OnGCEventHook);
- //YHookEvent(ME_GC_BUILDMENU, &CYahooProto::OnGCMenuHook);
+ this->HookEvent(ME_GC_EVENT, &CSkypeProto::OnGCEventHook);
+ this->HookEvent(ME_GC_BUILDMENU, &CSkypeProto::OnGCMenuHook);
}
-void CSkypeProto::StartChat(SEStringList &chatTargets)
+void CSkypeProto::StartChat(HANDLE hContact, SEStringList &chatTargets)
{
- CConversation::Ref conference;
- g_skype->CreateConference(conference);
- conference->AddConsumers(chatTargets);
+ char *chatID;
+ SEString data;
+ CConversation::Ref conversation;
- SEString identity;
- conference->GetPropIdentity(identity);
- char *chatID = ::mir_strdup((const char *)identity);
+ if (hContact)
+ {
+ chatID = ::DBGetString(hContact, this->m_szModuleName, "ChatRoomID");
+ g_skype->GetConversationByIdentity(chatID, conversation);
+ conversation->GetJoinBlob(data);
+ char *blob = ::mir_strdup((const char *)data);
+ g_skype->GetConversationByBlob(blob, conversation, false);
+ conversation->Join();
+
+ CParticipant::Refs participants;
+ conversation->GetParticipants(participants, CConversation::OTHER_CONSUMERS);
+ for (uint i = 0; i < participants.size(); i++)
+ {
+ participants[i]->GetPropIdentity(data);
+ chatTargets.append(data);
+ }
+ }
+ else if ( !g_skype->GetConversationByParticipants(chatTargets, conversation))
+ {
+ g_skype->CreateConference(conversation);
+ conversation->SetOption(CConversation::P_OPT_JOINING_ENABLED, true);
+ conversation->AddConsumers(chatTargets);
+
+ conversation->GetPropIdentity(data);
+ chatID = ::mir_strdup((const char *)data);
+ }
+
+ conversation->GetPropDisplayname(data);
+ char *chatName = ::mir_utf8decodeA((const char *)data);
GCSESSION gcw = {0};
gcw.cbSize = sizeof(gcw);
- //gcw.dwFlags = GC_TCHAR;
gcw.iType = GCW_CHATROOM;
- gcw.pszModule = m_szModuleName;
- gcw.pszName = "Chat";
+ gcw.pszModule = this->m_szModuleName;
+ gcw.pszName = chatName;
gcw.pszID = chatID;
::CallServiceSync(MS_GC_NEWSESSION, 0, (LPARAM)&gcw);
@@ -110,13 +137,12 @@ void CSkypeProto::StartChat(SEStringList &chatTargets) GCEVENT gce = {0};
gce.cbSize = sizeof(GCEVENT);
- //gce.dwFlags = GC_TCHAR;
gce.pDest = &gcd;
- gce.pszStatus = Translate("Me");
+ gce.pszStatus = ::Translate("Me");
::CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce);
gcd.iType = GC_EVENT_ADDGROUP;
- gce.pszStatus = Translate("Others");
+ gce.pszStatus = ::Translate("Others");
::CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce);
for (uint i = 0; i < chatTargets.size(); i++)
@@ -133,5 +159,210 @@ void CSkypeProto::StartChat(SEStringList &chatTargets) ::CallServiceSync(MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce);
::CallServiceSync(MS_GC_EVENT, WINDOW_VISIBLE, (LPARAM)&gce);
+ ::mir_free(chatName);
::mir_free(chatID);
+}
+
+void CSkypeProto::ChatEvent(const char *chatID, const char *sid, int evt, const char *msg)
+{
+ char *idt = ::mir_strdup(chatID);
+ char *snt = ::mir_strdup(sid);
+
+ HANDLE hContact = this->GetContactBySid(sid);
+ char *nick = hContact ? (char *)::CallService(MS_CLIST_GETCONTACTDISPLAYNAME, WPARAM(hContact), 0) : snt;
+
+ GCDEST gcd = { m_szModuleName, { NULL }, evt };
+ gcd.pszID = idt;
+
+ GCEVENT gce = {0};
+ gce.cbSize = sizeof(gce);
+ gce.dwFlags = GCEF_ADDTOLOG;
+ gce.pDest = &gcd;
+ gce.pszNick = nick;
+ gce.pszUID = snt;
+ gce.bIsMe = ::stricmp(sid, this->login) == 0;
+ gce.pszStatus = gce.bIsMe ? ::Translate("Me") : ::Translate("Others");
+ gce.pszText = msg;
+ gce.time = time(NULL);
+ ::CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce);
+
+ ::mir_free(snt);
+ ::mir_free(idt);
+}
+
+INT_PTR __cdecl CSkypeProto::OnJoinChat(WPARAM wParam, LPARAM)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ SEStringList list;
+ this->StartChat(hContact, list);
+
+ return 0;
+}
+
+INT_PTR __cdecl CSkypeProto::OnLeaveChat(WPARAM wParam, LPARAM)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ char *chatID = ::DBGetString(hContact, this->m_szModuleName, "ChatID");
+ this->ChatLeave(chatID);
+
+ return 0;
+}
+
+void CSkypeProto::ChatLeave(const char *chatID)
+{
+ char *idt = ::mir_strdup(chatID);
+
+ GCDEST gcd = { m_szModuleName, { NULL }, GC_EVENT_CONTROL };
+ gcd.pszID = idt;
+
+ GCEVENT gce = {0};
+ gce.cbSize = sizeof(GCEVENT);
+ //gce.dwFlags = GCEF_REMOVECONTACT;
+ gce.pDest = &gcd;
+ ::CallServiceSync(MS_GC_EVENT, SESSION_OFFLINE, (LPARAM)&gce);
+ ::CallServiceSync(MS_GC_EVENT, SESSION_TERMINATE, (LPARAM)&gce);
+
+ ::mir_free(idt);
+}
+
+int __cdecl CSkypeProto::OnGCEventHook(WPARAM, LPARAM lParam)
+{
+ GCHOOK *gch = (GCHOOK *)lParam;
+ if (!gch) return 1;
+
+ if (::strcmp(gch->pDest->pszModule, this->m_szModuleName))
+ return 0;
+
+ char *chatID = ::mir_strdup(gch->pDest->pszID);
+ char *sid = ::mir_strdup(gch->pszUID);
+
+ switch (gch->pDest->iType)
+ {
+ case GC_SESSION_TERMINATE:
+ {
+ CConversation::Ref conversation;
+ if (g_skype->GetConversationByIdentity(chatID, conversation, false))
+ {
+ Participant::Refs participants;
+ conversation->GetParticipants(participants, CConversation::MYSELF);
+ participants[0]->Retire();
+ }
+ }
+ break;
+
+ case GC_USER_MESSAGE:
+ if (gch->pszText && gch->pszText[0])
+ {
+ CConversation::Ref conversation;
+ if (g_skype->GetConversationByIdentity(chatID, conversation, false))
+ {
+ CMessage::Ref message;
+ char *text = ::mir_utf8encode(gch->pszText);
+ conversation->PostText(text, message);
+ }
+ }
+ break;
+
+ case GC_USER_CHANMGR:
+ DialogBoxParam(
+ g_hInstance,
+ MAKEINTRESOURCE(IDD_CHATROOM_INVITE),
+ NULL,
+ CSkypeProto::InviteToChatProc,
+ LPARAM(new InviteChatParam(chatID, NULL, this)));
+ break;
+
+ case GC_USER_PRIVMESS:
+ ::CallService(MS_MSG_SENDMESSAGE, (WPARAM)this->GetContactBySid(sid), 0);
+ break;
+
+ case GC_USER_LOGMENU:
+ switch(gch->dwData)
+ {
+ case 10:
+ ::DialogBoxParam(
+ g_hInstance,
+ MAKEINTRESOURCE(IDD_CHATROOM_INVITE),
+ NULL,
+ CSkypeProto::InviteToChatProc,
+ LPARAM(new InviteChatParam(chatID, NULL, this)));
+ break;
+
+ case 20:
+ this->ChatLeave(chatID);
+ break;
+ }
+ break;
+
+ case GC_USER_NICKLISTMENU:
+ switch (gch->dwData)
+ {
+ case 10:
+ ::CallService(MS_USERINFO_SHOWDIALOG, (WPARAM)this->GetContactBySid(sid), 0);
+ break;
+
+ case 20:
+ CallService(MS_HISTORY_SHOWCONTACTHISTORY, (WPARAM)this->GetContactBySid(sid), 0);
+ break;
+
+ case 110:
+ this->ChatLeave(chatID);
+ break;
+ }
+ break;
+
+ case GC_USER_TYPNOTIFY:
+ break;
+ }
+ ::mir_free(sid);
+ ::mir_free(chatID);
+
+ return 0;
+}
+
+int __cdecl CSkypeProto::OnGCMenuHook(WPARAM, LPARAM lParam)
+{
+ GCMENUITEMS *gcmi = (GCMENUITEMS*) lParam;
+
+ if (gcmi == NULL || ::stricmp(gcmi->pszModule, this->m_szModuleName)) return 0;
+
+ if (gcmi->Type == MENU_ON_LOG)
+ {
+ static const struct gc_item Items[] =
+ {
+ { TranslateT("&Invite user..."), 10, MENU_ITEM, FALSE },
+ { TranslateT("&Leave chat session"), 20, MENU_ITEM, FALSE }
+ };
+ gcmi->nItems = SIZEOF(Items);
+ gcmi->Item = (gc_item*)Items;
+ }
+ else if (gcmi->Type == MENU_ON_NICKLIST)
+ {
+ char* id = mir_t2a(gcmi->pszUID);
+ if (!::stricmp(this->login, id))
+ {
+ static const struct gc_item Items[] =
+ {
+ { TranslateT("User &details"), 10, MENU_ITEM, FALSE },
+ { TranslateT("User &history"), 20, MENU_ITEM, FALSE },
+ { _T(""), 100, MENU_SEPARATOR, FALSE },
+ { TranslateT("&Leave chat session"), 110, MENU_ITEM, FALSE }
+ };
+ gcmi->nItems = SIZEOF(Items);
+ gcmi->Item = (gc_item*)Items;
+ }
+ else
+ {
+ static const struct gc_item Items[] =
+ {
+ { TranslateT("User &details"), 10, MENU_ITEM, FALSE },
+ { TranslateT("User &history"), 20, MENU_ITEM, FALSE }
+ };
+ gcmi->nItems = SIZEOF(Items);
+ gcmi->Item = (gc_item*)Items;
+ }
+ mir_free(id);
+ }
+
+ return 0;
}
\ No newline at end of file diff --git a/protocols/Skype/src/skype_dialogs.cpp b/protocols/Skype/src/skype_dialogs.cpp index 1505a08c9f..a2464e6843 100644 --- a/protocols/Skype/src/skype_dialogs.cpp +++ b/protocols/Skype/src/skype_dialogs.cpp @@ -471,13 +471,13 @@ INT_PTR CALLBACK CSkypeProto::InviteToChatProc(HWND hwndDlg, UINT msg, WPARAM wP case CLN_NEWCONTACT:
if (param && (nmc->flags & (CLNF_ISGROUP | CLNF_ISINFO)) == 0)
{
- param->ppro->ChatValidateContact(nmc->hItem, nmc->hdr.hwndFrom);
+ param->ppro->ChatValidateContact(nmc->hItem, nmc->hdr.hwndFrom);
}
break;
case CLN_LISTREBUILT:
if (param)
- param->ppro->ChatPrepare(NULL, nmc->hdr.hwndFrom);
+ param->ppro->ChatPrepare(NULL, nmc->hdr.hwndFrom);
break;
}
}
@@ -514,9 +514,9 @@ INT_PTR CALLBACK CSkypeProto::InviteToChatProc(HWND hwndDlg, UINT msg, WPARAM wP char sid[SKYPE_SID_LIMIT] = "";
HWND hwndList = ::GetDlgItem(hwndDlg, IDC_CCLIST);
- SEStringList chatTargets;
- param->ppro->FillChatList(NULL, hwndList, chatTargets);
- param->ppro->StartChat(chatTargets);
+ SEStringList inviteContacts;
+ param->ppro->GetInviteContacts(NULL, hwndList, inviteContacts);
+ param->ppro->StartChat(NULL, inviteContacts);
}
EndDialog(hwndDlg, IDOK);
diff --git a/protocols/Skype/src/skype_events.cpp b/protocols/Skype/src/skype_events.cpp index 8ceb136173..a3a89b9a6e 100644 --- a/protocols/Skype/src/skype_events.cpp +++ b/protocols/Skype/src/skype_events.cpp @@ -2,7 +2,8 @@ int CSkypeProto::OnModulesLoaded(WPARAM, LPARAM)
{
- this->RegisterChat();
+ this->InitChat();
+
this->HookEvent(ME_OPT_INITIALISE, &CSkypeProto::OnOptionsInit);
this->HookEvent(ME_USERINFO_INITIALISE, &CSkypeProto::OnUserInfoInit);
@@ -28,10 +29,10 @@ int CSkypeProto::OnContactDeleted(WPARAM wParam, LPARAM lParam) void CSkypeProto::OnMessageSended(CConversation::Ref conversation, CMessage::Ref message)
{
- uint timestamp;
- message->GetPropTimestamp(timestamp);
+ SEString data;
- SEString data;
+ uint timestamp;
+ message->GetPropTimestamp(timestamp);
message->GetPropAuthor(data);
char *sid = ::mir_strdup((const char*)data);
@@ -39,43 +40,67 @@ void CSkypeProto::OnMessageSended(CConversation::Ref conversation, CMessage::Ref message->GetPropBodyXml(data);
char *text = ::mir_strdup((const char*)data);
- Participant::Refs participants;
- conversation->GetParticipants(participants, CConversation::OTHER_CONSUMERS);
+ CConversation::TYPE type;
+ conversation->GetPropType(type);
+ if (type == CConversation::DIALOG)
+ {
+ CParticipant::Refs participants;
+ conversation->GetParticipants(participants, CConversation::OTHER_CONSUMERS);
- for (uint i = 0; i < participants.size(); i ++)
- {
- participants[i]->GetPropIdentity(data);
- char *contactSid = ::mir_strdup((const char *)data);
- //todo: get nickname
- this->RaiseMessageSendedEvent(
- timestamp,
- contactSid,
- contactSid,
- text);
+ for (uint i = 0; i < participants.size(); i ++)
+ {
+ participants[i]->GetPropIdentity(data);
+ char *contactSid = ::mir_strdup((const char *)data);
+ //todo: get nickname
+ this->RaiseMessageSendedEvent(
+ timestamp,
+ contactSid,
+ contactSid,
+ text);
+ }
+ }
+ else
+ {
+ conversation->GetPropIdentity(data);
+ char *chatID = ::mir_utf8encode((const char*)data);
+
+ this->ChatEvent(chatID, sid, /*GC_EVENT_MESSAGE*/0x0040, text);
}
}
void CSkypeProto::OnMessageReceived(CConversation::Ref conversation, CMessage::Ref message)
{
+ SEString data;
+
uint timestamp;
message->GetPropTimestamp(timestamp);
- SEString data;
-
message->GetPropAuthor(data);
char *sid = ::mir_strdup((const char*)data);
+
+ message->GetPropBodyXml(data);
+ char *text = ::mir_utf8decodeA((const char*)data);
- message->GetPropAuthorDisplayname(data);
- char *nick = ::mir_strdup((const char*)data);
+ CConversation::TYPE type;
+ conversation->GetPropType(type);
+ if (type == CConversation::DIALOG)
+ {
+ message->GetPropAuthorDisplayname(data);
+ char *nick = ::mir_strdup((const char*)data);
- message->GetPropBodyXml(data);
- char *text = ::mir_strdup((const char*)data);
+ this->RaiseMessageReceivedEvent(
+ (DWORD)timestamp,
+ sid,
+ nick,
+ text);
+ }
+ else
+ {
+ conversation->GetPropIdentity(data);
+ char *chatID = ::mir_strdup((const char*)data);
- this->RaiseMessageReceivedEvent(
- (DWORD)timestamp,
- sid,
- nick,
- text);
+ this->ChatEvent(chatID, sid, /*GC_EVENT_MESSAGE*/ 0x0040, text);
+ }
/*const char *msg = (const char*)propValues[2];
int len = ::strlen(msg) + 8;
diff --git a/protocols/Skype/src/skype_proto.cpp b/protocols/Skype/src/skype_proto.cpp index aba0cc485b..1e33a9a5a7 100644 --- a/protocols/Skype/src/skype_proto.cpp +++ b/protocols/Skype/src/skype_proto.cpp @@ -18,6 +18,9 @@ CSkypeProto::CSkypeProto(const char* protoName, const TCHAR* userName) this->SetAllContactStatus(ID_STATUS_OFFLINE);
this->CreateService(PS_CREATEACCMGRUI, &CSkypeProto::OnAccountManagerInit);
+ // Chat
+ this->CreateService(PS_JOINCHAT, &CSkypeProto::OnJoinChat);
+ this->CreateService(PS_LEAVECHAT, &CSkypeProto::OnLeaveChat);
// Avatar API
this->CreateService(PS_GETAVATARINFOT, &CSkypeProto::GetAvatarInfo);
this->CreateService(PS_GETAVATARCAPS, &CSkypeProto::GetAvatarCaps);
diff --git a/protocols/Skype/src/skype_proto.h b/protocols/Skype/src/skype_proto.h index 6d849abf35..ba35c31fa5 100644 --- a/protocols/Skype/src/skype_proto.h +++ b/protocols/Skype/src/skype_proto.h @@ -63,15 +63,15 @@ const SettingItem setting[]={ struct InviteChatParam
{
- TCHAR *id;
+ char *id;
HANDLE hContact;
CSkypeProto *ppro;
- InviteChatParam(const TCHAR *id, HANDLE hContact, CSkypeProto *ppro)
- : id(mir_tstrdup(id)), hContact(hContact), ppro(ppro) {}
+ InviteChatParam(const char *id, HANDLE hContact, CSkypeProto *ppro)
+ : id(::mir_strdup(id)), hContact(hContact), ppro(ppro) {}
~InviteChatParam()
- { mir_free(id); }
+ { ::mir_free(id); }
};
struct CSkypeProto : public PROTO_INTERFACE, public MZeroedObject
@@ -197,10 +197,18 @@ protected: void ChatValidateContact(HANDLE hItem, HWND hwndList);
void ChatPrepare(HANDLE hItem, HWND hwndList);
- void FillChatList(HANDLE hItem, HWND hwndList, SEStringList &chatTargets);
+ void GetInviteContacts(HANDLE hItem, HWND hwndList, SEStringList &inviteContacts);
- void RegisterChat();
- void StartChat(SEStringList &chatTargets);
+ void InitChat();
+ void StartChat(HANDLE hContact, SEStringList &invitedContacts);
+ void ChatEvent(const char *chatID, const char *sid, int evt, const char* msg);
+ void ChatLeave(const char *chatID);
+
+ INT_PTR __cdecl OnJoinChat(WPARAM wParam, LPARAM);
+ INT_PTR __cdecl OnLeaveChat(WPARAM wParam, LPARAM);
+
+ int __cdecl OnGCMenuHook(WPARAM, LPARAM lParam);
+ int __cdecl OnGCEventHook(WPARAM, LPARAM lParam);
// contacts
void UpdateContactAboutText(HANDLE hContact, CContact::Ref contact);
diff --git a/protocols/Skype/src/skype_subclassing.cpp b/protocols/Skype/src/skype_subclassing.cpp index d8843a800f..5eb2882e4d 100644 --- a/protocols/Skype/src/skype_subclassing.cpp +++ b/protocols/Skype/src/skype_subclassing.cpp @@ -28,6 +28,11 @@ CConversation* CSkype::newConversation(int oid) return new CConversation(oid, this);
}
+CParticipant* CSkype::newParticipant(int oid)
+{
+ return new CParticipant(oid, this);
+}
+
CMessage* CSkype::newMessage(int oid)
{
return new CMessage(oid, this);
@@ -163,6 +168,10 @@ void CContactSearch::SetOnContactFindedCallback(OnContactFinded callback) this->ContactFindedCallback = callback;
}
+// CParticipant
+
+CParticipant::CParticipant(unsigned int oid, SERootObject* root) : Participant(oid, root) { }
+
// CContact
CContact::CContact(unsigned int oid, SERootObject* root) : Contact(oid, root)
diff --git a/protocols/Skype/src/skype_subclassing.h b/protocols/Skype/src/skype_subclassing.h index f2d571ae98..b2798316e9 100644 --- a/protocols/Skype/src/skype_subclassing.h +++ b/protocols/Skype/src/skype_subclassing.h @@ -19,6 +19,15 @@ public: CMessage(unsigned int oid, SERootObject* root);
};
+class CParticipant : public Participant
+{
+public:
+ typedef DRef<CParticipant, Participant> Ref;
+ typedef DRefs<CParticipant, Participant> Refs;
+
+ CParticipant(unsigned int oid, SERootObject* root);
+};
+
class CConversation : public Conversation
{
public:
@@ -135,7 +144,8 @@ public: CContactGroup* newContactGroup(int oid);
CConversation* newConversation(int oid);
CContactSearch* newContactSearch(int oid);
- CContact* newContact(int oid);
+ CParticipant* newParticipant(int oid);
+ CContact* newContact(int oid);
CMessage* newMessage(int oid);
CConversation::Refs inbox;
|