diff options
Diffstat (limited to 'protocols/Skype/src')
-rw-r--r-- | protocols/Skype/src/skype_database.cpp | 20 | ||||
-rw-r--r-- | protocols/Skype/src/skype_events.cpp | 149 | ||||
-rw-r--r-- | protocols/Skype/src/skype_proto.cpp | 126 | ||||
-rw-r--r-- | protocols/Skype/src/skype_proto.h | 38 | ||||
-rw-r--r-- | protocols/Skype/src/skype_subclassing.cpp | 27 | ||||
-rw-r--r-- | protocols/Skype/src/skype_subclassing.h | 21 | ||||
-rw-r--r-- | protocols/Skype/src/skype_transfer.cpp | 29 | ||||
-rw-r--r-- | protocols/Skype/src/skype_utils.cpp | 5 |
8 files changed, 401 insertions, 14 deletions
diff --git a/protocols/Skype/src/skype_database.cpp b/protocols/Skype/src/skype_database.cpp index 9d87b9b2c7..50fac3651f 100644 --- a/protocols/Skype/src/skype_database.cpp +++ b/protocols/Skype/src/skype_database.cpp @@ -92,4 +92,24 @@ void CSkypeProto::RaiseMessageSendedEvent( pre.szMessage = (char *)message;
::CallService(MS_PROTO_CHAINSEND, 0, (LPARAM)&ccs);
+}
+
+void CSkypeProto::RaiseFileReceivedEvent(
+ DWORD timestamp,
+ const char* sid,
+ const char* nick,
+ const char* message)
+{
+ PROTORECVFILET pre = {0};
+
+ CCSDATA ccs = {0};
+ ccs.szProtoService = PSR_FILE;
+ ccs.hContact = this->AddContactBySid(sid, nick);
+ ccs.wParam = 0;
+ ccs.lParam = (LPARAM)⪯
+ pre.flags = PREF_UTF;
+ pre.timestamp = timestamp;
+ //pre.szMessage = (char *)message;
+
+ ::CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs);
}
\ No newline at end of file diff --git a/protocols/Skype/src/skype_events.cpp b/protocols/Skype/src/skype_events.cpp index fcacb7117f..ac29ab59e9 100644 --- a/protocols/Skype/src/skype_events.cpp +++ b/protocols/Skype/src/skype_events.cpp @@ -148,6 +148,146 @@ void CSkypeProto::OnMessageReceived(CConversation::Ref conversation, CMessage::R HXML hXml = xi.parseString(xml, &bytesProcessed, NULL);*/
}
+void CSkypeProto::OnTransferChanged(int prop, CTransfer::Ref transfer)
+{
+ if (prop == Transfer::P_STATUS)
+ {
+ Transfer::STATUS status;
+ transfer->GetPropStatus(status);
+
+ /*CConversation::Ref conversation;
+ transfer->GetPropConvoId(conversation);
+
+ SEBinary guid;
+ transfer->GetPropChatmsgGuid(guid);
+ auto ft = this->FindTransfer(guid);*/
+ auto ft = this->FindFileTransfer(transfer);
+
+ SEString sid;
+ transfer->GetPropPartnerHandle(sid);
+ //CParticipant::Refs participants;
+ //conversation->GetParticipants(participants, CConversation::OTHER_CONSUMERS);
+ ////for (uint i = 0; i < participants.size(); i++)
+ //participants[0]->GetPropIdentity(sid);
+
+ HANDLE hContact = this->GetContactBySid(sid);
+
+ switch(status)
+ {
+ /*case CTransfer::NEW:
+ break;*/
+ /*case CTransfer::WAITING_FOR_ACCEPT:
+ break;*/
+ case CTransfer::CONNECTING:
+ this->SendBroadcast(hContact, ACKTYPE_FILE, ACKRESULT_CONNECTING, (HANDLE)ft, 0);
+ break;
+ case CTransfer::TRANSFERRING:
+ case CTransfer::TRANSFERRING_OVER_RELAY:
+ this->SendBroadcast(hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, (HANDLE)ft, 0);
+ break;
+ case CTransfer::FAILED:
+ this->SendBroadcast(hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)ft, 0);
+ break;
+ case CTransfer::COMPLETED:
+ this->SendBroadcast(hContact, ACKTYPE_FILE, ACKRESULT_SUCCESS, (HANDLE)ft, 0);
+ break;
+ case CTransfer::CANCELLED:
+ case CTransfer::CANCELLED_BY_REMOTE:
+ this->SendBroadcast(hContact, ACKTYPE_FILE, ACKRESULT_DENIED, (HANDLE)ft, 0);
+ break;
+ }
+ }
+ if (prop == Transfer::P_BYTESTRANSFERRED)
+ {
+ //PROTOFILETRANSFERSTATUS
+ //this->SendBroadcast(hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)ccid, 0);
+ //SEString transferProgressStr;
+ //transfer->GetPropBytestransferred(transferProgressStr);
+ //uint transferProgress = transferProgressStr.toUInt();
+
+ //SEString fileSizeStr;
+ //transfer->GetPropFilesize(fileSizeStr);
+
+ //// fileSize is float here, to avoid trouble with
+ //// files lessthan 100 bytes in size.
+ //float fileSize = (float)fileSizeStr.toUInt();
+ //float progress = (100 * transferProgress) / fileSize;
+
+ //uint transferRate;
+ //transfer->GetPropBytespersecond(transferRate);
+ //float transferRateInKb = (float)transferRate / 1024;
+
+ //PROTOFILETRANSFERSTATUS pfts = {0};
+ //pfts.cbSize = sizeof(pfts);
+ ////pfts.szCurrentFile
+ //pfts.currentFileProgress = progress;
+ //pfts.
+
+ //this->SendBroadcast(hContact, ACKTYPE_FILE, ACKRESULT_DATA, (HANDLE)ccid, 0);
+ // printf("Progress: %3.0f%% (%1.0f KB/s)\n", progress, transferRateInKb);
+ }
+}
+
+void CSkypeProto::OnFileReceived(CConversation::Ref conversation, CMessage::Ref message)
+{
+ CTransfer::Refs transferList;
+ message->GetTransfers(transferList);
+ Sid::fetch(transferList);
+
+ Transfer::TYPE transferType;
+ Transfer::STATUS transferStatus;
+
+ for (uint i = 0; i < transferList.size(); i++)
+ {
+ auto transfer = transferList[i];
+ transfer.fetch();
+ transfer->SetOnTransferCallback(
+ (CTransfer::OnTransfer)&CSkypeProto::OnTransferChanged,
+ this);
+ //this->transferList.append(transfer);
+
+ // For incomings, we need to check for transfer status, just to be sure.
+ // In some cases, a transfer can appear with STATUS == PLACEHOLDER
+ // As such transfers cannot be accepted, we will need to just store
+ // the reference to Transfer Object and then check for further
+ // status changes in Transfer::OnChange
+ transfer->GetPropType(transferType);
+ transfer->GetPropStatus(transferStatus);
+ if ((transferType == Transfer::INCOMING) && (transferStatus == Transfer::NEW))
+ {
+ //transferList[i]->AutoAccept();
+ SEString name;
+ transfer->GetPropFilename(name);
+
+ wchar_t *path = ::mir_utf8decodeW(name);
+
+ SEString sid;
+ transfer->GetPropPartnerHandle(sid);
+ HANDLE hContact = this->GetContactBySid(sid);
+
+ auto ft = new FileTransfer(this);
+ ft->transfers.append(transfer);
+ transfer->GetPropChatmsgGuid(ft->guid);
+ this->fileTransferList.insert(ft);
+
+ PROTORECVFILET pre = {0};
+ pre.flags = PREF_TCHAR;
+ pre.fileCount = 1;
+ pre.timestamp = time(NULL);
+ pre.tszDescription = L" ";
+ pre.ptszFiles = &path;
+ pre.lParam = (LPARAM)ft;
+ ::ProtoChainRecvFile(hContact, &pre);
+
+ ::mir_free(path);
+ }
+ }
+
+ //SEString bodyXml;
+ //message->GetPropBodyXml(bodyXml);
+ //printf("File transfer msg BodyXML:\n%s\n", (const char*)bodyXml);
+}
+
void CSkypeProto::OnMessage(CConversation::Ref conversation, CMessage::Ref message)
{
CMessage::TYPE messageType;
@@ -156,6 +296,12 @@ void CSkypeProto::OnMessage(CConversation::Ref conversation, CMessage::Ref messa CMessage::SENDING_STATUS sendingStatus;
message->GetPropSendingStatus(sendingStatus);
+ if (messageType == CMessage::POSTED_FILES)
+ {
+ this->OnFileReceived(conversation, message);
+ return;
+ }
+
CMessage::CONSUMPTION_STATUS status;
message->GetPropConsumptionStatus(status);
@@ -179,6 +325,9 @@ void CSkypeProto::OnMessage(CConversation::Ref conversation, CMessage::Ref messa }
break;
+ case CMessage::POSTED_FILES:
+ break;
+
case CMessage::ADDED_CONSUMERS:
{
SEString data;
diff --git a/protocols/Skype/src/skype_proto.cpp b/protocols/Skype/src/skype_proto.cpp index c5014171b4..6b31760df7 100644 --- a/protocols/Skype/src/skype_proto.cpp +++ b/protocols/Skype/src/skype_proto.cpp @@ -1,9 +1,11 @@ -#include "skype_proto.h"
+#include "skype_proto.h"
-CSkypeProto::CSkypeProto(const char* protoName, const TCHAR* userName)
+CSkypeProto::CSkypeProto(const char* protoName, const TCHAR* userName) : fileTransferList(1)
{
ProtoConstructor(this, protoName, userName);
+ //this->fileTransferList = new LIST<FileTransfer>(1);
+
//this->login = NULL;
//this->password = NULL;
this->rememberPassword = false;
@@ -133,17 +135,66 @@ int __cdecl CSkypeProto::AuthRequest(HANDLE hContact, const TCHAR* szMessage) HANDLE __cdecl CSkypeProto::ChangeInfo( int iInfoType, void* pInfoData ) { return 0; }
-HANDLE __cdecl CSkypeProto::FileAllow( HANDLE hContact, HANDLE hTransfer, const TCHAR* szPath ) { return 0; }
-int __cdecl CSkypeProto::FileCancel( HANDLE hContact, HANDLE hTransfer ) { return 0; }
-int __cdecl CSkypeProto::FileDeny( HANDLE hContact, HANDLE hTransfer, const TCHAR* szReason ) { return 0; }
-int __cdecl CSkypeProto::FileResume( HANDLE hTransfer, int* action, const TCHAR** szFilename ) { return 0; }
+HANDLE __cdecl CSkypeProto::FileAllow( HANDLE hContact, HANDLE hTransfer, const TCHAR* szPath )
+{
+ auto ft = (FileTransfer*)hTransfer;
+
+ for (uint i = 0; i < ft->transfers.size(); i++)
+ {
+ bool success;
+ SEString name;
+ wchar_t fullPath[MAX_PATH] = {0};
+ ft->transfers[i]->GetPropFilename(name);
+ ::mir_sntprintf(fullPath, MAX_PATH, L"%s%s", szPath, ::mir_utf8decodeW(name));
+ if (ft->transfers[i]->Accept(::mir_u2a(fullPath), success) && success)
+ {
+ return 0;
+ }
+ }
+
+ return hTransfer;
+}
+
+int __cdecl CSkypeProto::FileCancel( HANDLE hContact, HANDLE hTransfer )
+{
+ auto ft = (FileTransfer*)hTransfer;
+
+ for (uint i = 0; i < ft->transfers.size(); i++)
+ {
+ if (ft->transfers[i]->Cancel())
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int __cdecl CSkypeProto::FileDeny( HANDLE hContact, HANDLE hTransfer, const TCHAR* szReason )
+{
+ auto ft = (FileTransfer*)hTransfer;
+
+ for (uint i = 0; i < ft->transfers.size(); i++)
+ {
+ if (ft->transfers[i]->Cancel())
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+int __cdecl CSkypeProto::FileResume( HANDLE hTransfer, int* action, const TCHAR** szFilename )
+{
+ return 0;
+}
DWORD_PTR __cdecl CSkypeProto:: GetCaps(int type, HANDLE hContact)
{
switch(type)
{
case PFLAGNUM_1:
- return PF1_IM | PF1_BASICSEARCH | PF1_ADDSEARCHRES | PF1_SEARCHBYEMAIL/* | PF1_SEARCHBYNAME*/;
+ return PF1_IM | PF1_FILE | PF1_BASICSEARCH | PF1_ADDSEARCHRES | PF1_SEARCHBYEMAIL/* | PF1_SEARCHBYNAME*/;
case PFLAGNUM_2:
case PFLAGNUM_3:
return PF2_ONLINE | PF2_SHORTAWAY | PF2_HEAVYDND | PF2_INVISIBLE;
@@ -202,7 +253,11 @@ HWND __cdecl CSkypeProto::SearchAdvanced( HWND owner ) { return 0; } HWND __cdecl CSkypeProto::CreateExtendedSearchUI( HWND owner ){ return 0; }
int __cdecl CSkypeProto::RecvContacts( HANDLE hContact, PROTORECVEVENT* ) { return 0; }
-int __cdecl CSkypeProto::RecvFile( HANDLE hContact, PROTORECVFILET* ) { return 0; }
+int __cdecl CSkypeProto::RecvFile( HANDLE hContact, PROTORECVFILET* evt)
+{
+ //db_unset(hContact, "CList", "Hidden");
+ return Proto_RecvFile(hContact, evt);
+}
int __cdecl CSkypeProto::RecvMsg( HANDLE hContact, PROTORECVEVENT* pre)
{
@@ -213,7 +268,60 @@ int __cdecl CSkypeProto::RecvMsg( HANDLE hContact, PROTORECVEVENT* pre) int __cdecl CSkypeProto::RecvUrl( HANDLE hContact, PROTORECVEVENT* ) { return 0; }
int __cdecl CSkypeProto::SendContacts( HANDLE hContact, int flags, int nContacts, HANDLE* hContactsList ) { return 0; }
-HANDLE __cdecl CSkypeProto::SendFile( HANDLE hContact, const TCHAR* szDescription, TCHAR** ppszFiles ) { return 0; }
+
+HANDLE __cdecl CSkypeProto::SendFile( HANDLE hContact, const TCHAR* szDescription, TCHAR** ppszFiles )
+{
+ if (this->IsOnline() && hContact && ppszFiles)
+ {
+ SEStringList targets;
+ char* sid = ::DBGetString(hContact, this->m_szModuleName, "sid");
+ targets.append(sid);
+
+ CConversation::Ref conversation = CConversation::FindBySid(
+ this->skype,
+ ::DBGetString(hContact, this->m_szModuleName, "sid"));
+ conversation.fetch();
+
+ SEFilenameList fileList;
+ for (int i = 0; ppszFiles[i]; i++)
+ {
+ char* file = ::mir_u2a(ppszFiles[i]);
+ fileList.append(file);
+ }
+
+ auto error = TRANSFER_OPEN_SUCCESS;
+ SEFilename errFile; MessageRef msgRef;
+ if ( !conversation->PostFiles(fileList, ::mir_u2a(szDescription), error, errFile, msgRef) || error)
+ {
+ // todo: despair
+ //this->SendBroadcast(hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)ccid, 0);
+ return 0;
+ }
+
+ FileTransfer *ft = new FileTransfer(this);
+ if (msgRef->GetTransfers(ft->transfers))
+ {
+ Sid::fetch(ft->transfers);
+ for (uint i = 0; i < ft->transfers.size(); i++)
+ {
+ auto transfer = ft->transfers[i];
+ transfer.fetch();
+ transfer->SetOnTransferCallback(
+ (CTransfer::OnTransfer)&CSkypeProto::OnTransferChanged,
+ this);
+ //this->transferList.append(transfer);
+ }
+ }
+
+ //auto ft = new FileTransfer(this);
+ msgRef->GetPropGuid(ft->guid);
+ this->fileTransferList.insert(ft);
+
+ return ft;
+ }
+
+ return 0;
+}
int __cdecl CSkypeProto::SendMsg(HANDLE hContact, int flags, const char* msg)
{
diff --git a/protocols/Skype/src/skype_proto.h b/protocols/Skype/src/skype_proto.h index 18c18dfeb4..5e38e73c2a 100644 --- a/protocols/Skype/src/skype_proto.h +++ b/protocols/Skype/src/skype_proto.h @@ -115,6 +115,7 @@ const SettingItem setting[]={ {LPGENT("About"), "About", DBVT_WCHAR, LI_STRING}
};
+
struct HtmlEntity
{
const char *entity;
@@ -179,6 +180,27 @@ struct PasswordChangeBoxParam }
};
+struct FileTransfer +{ + CSkypeProto* ppro; + SEBinary guid; + CTransfer::Refs transfers; + //char *who; + //char *msg; + //char *ftoken; + //char *relay; + //HANDLE hContact; + //int cancel; + //char *url; + //HANDLE hWaitEvent; + //DWORD action; + //int y7; + ////YList *files; + //PROTOFILETRANSFERSTATUS pfts; + + FileTransfer(CSkypeProto* ppro) { this->ppro = ppro; } +};
+
struct CSkypeProto : public PROTO_INTERFACE
{
public:
@@ -273,8 +295,9 @@ protected: CSkype *skype;
CAccount::Ref account;
CContact::Refs contactList;
+// CTransfer::Refs transferList;
CContactGroup::Ref commonList;
- CContactGroup::Ref authWaitList;
+ CContactGroup::Ref authWaitList;
// account
void OnAccountChanged(int prop);
@@ -299,6 +322,14 @@ protected: void OnMessageSended(CConversation::Ref conversation, CMessage::Ref message);
void OnMessageReceived(CConversation::Ref conversation, CMessage::Ref message);
+ // file transfer
+ LIST<FileTransfer> fileTransferList;
+ FileTransfer *FindTransfer(SEBinary guid);
+ FileTransfer *FindFileTransfer(CTransfer::Ref transfer);
+
+ void OnFileReceived(CConversation::Ref conversation, CMessage::Ref message);
+ void OnTransferChanged(int prop, CTransfer::Ref transfer);
+
// chat
static char* Groups[];
@@ -460,6 +491,11 @@ protected: const char* sid,
const char* nick,
const char* message = "");
+ void RaiseFileReceivedEvent(
+ DWORD timestamp,
+ const char* sid,
+ const char* nick,
+ const char* message = "");
void RaiseAuthRequestEvent(
DWORD timestamp,
const char* sid,
diff --git a/protocols/Skype/src/skype_subclassing.cpp b/protocols/Skype/src/skype_subclassing.cpp index 10bdecf9d5..2c24252fa7 100644 --- a/protocols/Skype/src/skype_subclassing.cpp +++ b/protocols/Skype/src/skype_subclassing.cpp @@ -44,6 +44,11 @@ CMessage* CSkype::newMessage(int oid) return new CMessage(oid, this);
}
+CTransfer* CSkype::newTransfer(int oid)
+{
+ return new CTransfer(oid, this);
+}
+
CContactSearch* CSkype::newContactSearch(int oid)
{
return new CContactSearch(oid, this);
@@ -479,4 +484,24 @@ void CConversation::SetOnMessageReceivedCallback(OnMessageReceived callback, CSk // CMessage
-CMessage::CMessage(unsigned int oid, SERootObject* root) : Message(oid, root) { }
\ No newline at end of file +CMessage::CMessage(unsigned int oid, SERootObject* root) : Message(oid, root) { }
+
+// CTransfer
+
+CTransfer::CTransfer(unsigned int oid, SERootObject* root) : Transfer(oid, root)
+{
+ this->proto = NULL;
+ this->transferCallback = NULL;
+}
+
+void CTransfer::SetOnTransferCallback(OnTransfer callback, CSkypeProto* proto)
+{
+ this->proto = proto;
+ this->transferCallback = callback;
+}
+
+void CTransfer::OnChange(int prop)
+{
+ if (this->proto)
+ (proto->*transferCallback)(prop, this->ref());
+}
\ No newline at end of file diff --git a/protocols/Skype/src/skype_subclassing.h b/protocols/Skype/src/skype_subclassing.h index 694fce2c56..b16f7d7e66 100644 --- a/protocols/Skype/src/skype_subclassing.h +++ b/protocols/Skype/src/skype_subclassing.h @@ -12,13 +12,31 @@ class CSkype; class CMessage : public Message
{
public:
-
typedef DRef<CMessage, Message> Ref;
typedef DRefs<CMessage, Message> Refs;
CMessage(unsigned int oid, SERootObject* root);
};
+class CTransfer : public Transfer
+{
+public:
+ typedef void (CSkypeProto::* OnTransfer)(int prop, CTransfer::Ref transfer);
+
+ typedef DRef<CTransfer, Transfer> Ref;
+ typedef DRefs<CTransfer, Transfer> Refs;
+
+ CTransfer(unsigned int oid, SERootObject* p_root);
+
+ void SetOnTransferCallback(OnTransfer callback, CSkypeProto* proto);
+
+private:
+ CSkypeProto* proto;
+ OnTransfer transferCallback;
+
+ void OnChange(int prop);
+};
+
class CParticipant : public Participant
{
public:
@@ -149,6 +167,7 @@ public: CParticipant* newParticipant(int oid);
CContact* newContact(int oid);
CMessage* newMessage(int oid);
+ CTransfer* newTransfer(int oid);
CConversation::Refs inbox;
diff --git a/protocols/Skype/src/skype_transfer.cpp b/protocols/Skype/src/skype_transfer.cpp new file mode 100644 index 0000000000..437d016b6d --- /dev/null +++ b/protocols/Skype/src/skype_transfer.cpp @@ -0,0 +1,29 @@ +#include "skype_proto.h"
+
+//LIST<FileTransfer> CSkypeProto::fileTransferList(1);
+
+FileTransfer *CSkypeProto::FindTransfer(SEBinary guid)
+{
+ for (int i = 0; i < this->fileTransferList.getCount(); i++)
+ {
+ if (this->fileTransferList[i]->guid == guid)
+ {
+ return this->fileTransferList[i];
+ }
+ }
+
+ return NULL;
+}
+
+FileTransfer *CSkypeProto::FindFileTransfer(CTransfer::Ref transfer)
+{
+ for (int i = 0; i < this->fileTransferList.getCount(); i++)
+ {
+ if (this->fileTransferList[i]->transfers.contains(transfer))
+ {
+ return this->fileTransferList[i];
+ }
+ }
+
+ return NULL;
+}
\ No newline at end of file diff --git a/protocols/Skype/src/skype_utils.cpp b/protocols/Skype/src/skype_utils.cpp index 7b66b00386..66e334fbdd 100644 --- a/protocols/Skype/src/skype_utils.cpp +++ b/protocols/Skype/src/skype_utils.cpp @@ -396,7 +396,7 @@ void CSkypeProto::HookEvent(const char* szEvent, SkypeEventFunc handler) int CSkypeProto::SendBroadcast(HANDLE hContact, int type, int result, HANDLE hProcess, LPARAM lParam)
{
- ACKDATA ack = { sizeof(ACKDATA) };
+ /*ACKDATA ack = { sizeof(ACKDATA) };
ack.szModule = this->m_szModuleName;
ack.hContact = hContact;
ack.type = type;
@@ -404,7 +404,8 @@ int CSkypeProto::SendBroadcast(HANDLE hContact, int type, int result, HANDLE hPr ack.hProcess = hProcess;
ack.lParam = lParam;
- return ::CallService(MS_PROTO_BROADCASTACK, 0, (LPARAM)&ack);
+ return ::CallService(MS_PROTO_BROADCASTACK, 0, (LPARAM)&ack);*/
+ return ::ProtoBroadcastAck(this->m_szModuleName, hContact, type, result, hProcess, lParam);
}
DWORD CSkypeProto::SendBroadcastAsync(HANDLE hContact, int type, int hResult, HANDLE hProcess, LPARAM lParam, size_t paramSize)
|