From 16827df7bc4a82d74f89dc81631bd2a7d05f3121 Mon Sep 17 00:00:00 2001 From: sje Date: Fri, 29 Jun 2007 06:41:47 +0000 Subject: can add and remove contacts git-svn-id: https://server.scottellis.com.au/svn/mim_plugs@220 4f64403b-2f21-0410-a795-97e2b3489a10 --- MySpace/NetMessage.cpp | 139 +++++++++++++++++++++++++++---- MySpace/NetMessage.h | 45 ++++++---- MySpace/proto.cpp | 218 ++++++++++++++++++++++++++++++++++++++++++++++++- MySpace/proto.h | 6 ++ MySpace/server_con.cpp | 94 ++++++++++++++++++--- MySpace/server_con.h | 12 +++ 6 files changed, 467 insertions(+), 47 deletions(-) (limited to 'MySpace') diff --git a/MySpace/NetMessage.cpp b/MySpace/NetMessage.cpp index 023a459..45b9159 100644 --- a/MySpace/NetMessage.cpp +++ b/MySpace/NetMessage.cpp @@ -39,6 +39,102 @@ NMString::~NMString() { delete[] text; } +Dictionary::Dictionary(): LinkedList< KeyValue >() { +} + +Dictionary::~Dictionary() { +} + +int Dictionary::parse(char *data, int size) { + int pos = 0; + char *key, *value; + int start, end = 0; + while(end < size) { + start = end; + end = start; + while(end < size && data[end] != '=') end++; + if(end < size) { + data[end] = 0; + key = &data[start]; + + start = end + 1; + end = start; + while(end < size && data[end] != '\x1c' && data[end] != 0) end++; + if(end <= size) { + data[end] = 0; + value = &data[start]; + end++; + } else + value = 0; + } else { + key = value = 0; + } + + if(key && value) { + KeyValue kv = KeyValue(NMString(key), NMString(value)); + add(kv); + } + } + return pos; +} + +bool Dictionary::get_string(char *key, char *buff, int buffsize) { + NMString strkey(key); + for(Iterator i = start(); i.has_val(); i.next()) { + KeyValue kv = i.val(); + if(kv.first == strkey) { + mir_snprintf(buff, buffsize, "%s", kv.second.text); + return true; + } + } + return false; +} + +int Dictionary::get_int(char *key) { + NMString strkey(key); + for(Iterator i = start(); i.has_val(); i.next()) { + KeyValue kv = i.val(); + if(kv.first == strkey) { + return atoi(kv.second.text); + } + } + return 0; +} + +void Dictionary::add_string(char *key, char *buff) { + KeyValue dat = KeyValue(NMString(key), NMString(buff)); + add(dat); +} + +void Dictionary::add_int(char *key, int i) { + char buff[254]; + KeyValue dat(NMString(key), NMString(_itoa(i, buff, 10))); + add(dat); +} + +int Dictionary::make_body(char *buff, int size) { + int pos = 0, key_len, val_len, len; + bool first = true; + for(Iterator i = start(); i.has_val() && pos < size; i.next()) { + KeyValue v = i.val(); + + key_len = strlen(v.first.text); + val_len = strlen(v.second.text); + len = key_len + val_len + 2; + + if(size - pos - len > 0) { + if(first) { + mir_snprintf(buff + pos, size - pos, "%s=%s", v.first.text, v.second.text); + first = false; + } else + mir_snprintf(buff + pos, size - pos, "\x1c%s=%s", v.first.text, v.second.text); + } + pos += len; + } + + return pos; +} + NetMessage::NetMessage(): Map() { } @@ -108,6 +204,14 @@ bool NetMessage::get_string(char *key, char *buff, int buffsize) { return false; } +int NetMessage::get_int(char *key) { + NMString val; + if(get(NMString(key), val)) { + return atoi(val.text); + } + return 0; +} + bool NetMessage::get_data(char *key, char *buff, int *size) { NMString val; if(get(NMString(key), val)) { @@ -126,25 +230,20 @@ bool NetMessage::get_data(char *key, char *buff, int *size) { return false; } -int NetMessage::get_int(char *key) { - NMString val; - if(get(NMString(key), val)) { - return atoi(val.text); +Dictionary NetMessage::get_dict(char *key) { + Dictionary d; + char t[4096]; + if(get_string(key, t, 4096)) { + d.parse(t, strlen(t)); } - return 0; + return d; } -ClientNetMessage::ClientNetMessage(): LinkedList< KeyValue >() { -} -ClientNetMessage::~ClientNetMessage() { +ClientNetMessage::ClientNetMessage(): Dictionary() { } -void ClientNetMessage::add_string(char *key, char *buff) { - char *temp = escape(buff); - KeyValue dat = KeyValue(NMString(key), NMString(temp)); - delete temp; - add(dat); +ClientNetMessage::~ClientNetMessage() { } bool ClientNetMessage::add_data(char *key, char *data, int size) { @@ -169,12 +268,20 @@ bool ClientNetMessage::add_data(char *key, char *data, int size) { return false; } -void ClientNetMessage::add_int(char *key, int i) { - char buff[254]; - KeyValue dat(NMString(key), NMString(_itoa(i, buff, 10))); +void ClientNetMessage::add_string(char *key, char *buff) { + char *temp = escape(buff); + KeyValue dat = KeyValue(NMString(key), NMString(temp)); + delete temp; add(dat); } +void ClientNetMessage::add_dict(char *key, Dictionary &d) { + char t[4096]; + if(d.make_body(t, 4096)) { + add_string(key, t); + } +} + //static char *ClientNetMessage::escape(char *val) { int len = strlen(val); diff --git a/MySpace/NetMessage.h b/MySpace/NetMessage.h index bae4ad7..4989f55 100644 --- a/MySpace/NetMessage.h +++ b/MySpace/NetMessage.h @@ -17,6 +17,32 @@ public: char *text; }; +class KeyValue: public Pair { +public: + KeyValue(const NMString &k, const NMString &v): Pair(k, v) {} + KeyValue &operator=(const KeyValue &other) { + first = other.first; + second = other.second; + return *this; + } +}; + +class Dictionary: public LinkedList< KeyValue > { +public: + Dictionary(); + virtual ~Dictionary(); + + virtual int parse(char *data, int size); + + bool get_string(char *key, char *buff, int buffsize); + int get_int(char *key); + + virtual void add_string(char *key, char *buff); + void add_int(char *key, int i); + + int make_body(char *buff, int size); +}; + class NetMessage: public Map { public: NetMessage(); @@ -25,32 +51,23 @@ public: int parse(char *data, int size); bool get_string(char *key, char *buff, int buffsize); - bool get_data(char *key, char *buff, int *size); int get_int(char *key); + bool get_data(char *key, char *buff, int *size); + Dictionary get_dict(char *key); static char *unescape_inplace(char *val); }; -class KeyValue: public Pair { -public: - KeyValue(const NMString &k, const NMString &v): Pair(k, v) {} - KeyValue &operator=(const KeyValue &other) { - first = other.first; - second = other.second; - return *this; - } -}; - -class ClientNetMessage: public LinkedList< KeyValue > { +class ClientNetMessage: public Dictionary { public: ClientNetMessage(); virtual ~ClientNetMessage(); - int ClientNetMessage::make_packet(char *buff, int size); + int make_packet(char *buff, int size); void add_string(char *key, char *buff); bool add_data(char *key, char *buff, int size); - void add_int(char *key, int i); + void add_dict(char *key, Dictionary &d); static char *escape(char *val); }; diff --git a/MySpace/proto.cpp b/MySpace/proto.cpp index 55b31c0..60577b1 100644 --- a/MySpace/proto.cpp +++ b/MySpace/proto.cpp @@ -9,8 +9,7 @@ int GetCaps(WPARAM wParam,LPARAM lParam) { int ret = 0; switch (wParam) { case PFLAGNUM_1: - //ret = PF1_IM | PF1_BASICSEARCH | PF1_ADDSEARCHRES | PF1_MODEMSG | PF1_FILE | PF1_CHAT; - ret = PF1_IM;// | PF1_BASICSEARCH | PF1_EXTSEARCHUI | PF1_ADDSEARCHRES | PF1_MODEMSG | PF1_FILE | PF1_CHAT; + ret = PF1_NUMERICUSERID | PF1_IM | PF1_BASICSEARCH | PF1_SEARCHBYEMAIL | PF1_SEARCHBYNAME | PF1_ADDSEARCHRES | PF1_SERVERCLIST; break; case PFLAGNUM_2: ret = PF2_ONLINE;// | PF2_SHORTAWAY | PF2_HEAVYDND; @@ -119,7 +118,210 @@ int ProtoRecvMessage(WPARAM wParam, LPARAM lParam) { return CallService(MS_PROTO_CHAINRECV, wParam, lParam); } +int BasicSearch(WPARAM wParam, LPARAM lParam) { + if(status <= ID_STATUS_OFFLINE) return 0; + char *szId = (char *)lParam; + ClientNetMessage msg; + msg.add_int("persist", 1); + msg.add_int("sesskey", sesskey); + msg.add_int("uid", DBGetContactSettingDword(0, MODULE, "UID", 0)); + + msg.add_int("cmd", 1); + msg.add_int("dsn", 4); + msg.add_int("lid", 3); + + int req = req_id++; + msg.add_int("rid", req); + + char body[512]; + mir_snprintf(body, 512, "UserID=%s", szId); + msg.add_string("body", body); + + SendMessage(msg); + + return req; +} + +int SearchByEmail(WPARAM wParam, LPARAM lParam) { + if(status <= ID_STATUS_OFFLINE) return 0; + char *email = (char*)lParam; + + ClientNetMessage msg; + msg.add_int("persist", 1); + msg.add_int("sesskey", sesskey); + msg.add_int("uid", DBGetContactSettingDword(0, MODULE, "UID", 0)); + + msg.add_int("cmd", 1); + msg.add_int("dsn", 5); + msg.add_int("lid", 7); + + int req = req_id++; + msg.add_int("rid", req); + + char body[512]; + mir_snprintf(body, 512, "Email=%s", email); + msg.add_string("body", body); + + SendMessage(msg); + return req; +} + +int SearchByName(WPARAM wParam, LPARAM lParam) { + if(status <= ID_STATUS_OFFLINE) return 0; + PROTOSEARCHBYNAME *sbn = (PROTOSEARCHBYNAME *)lParam; + if(!sbn->pszNick) return 0; + + ClientNetMessage msg; + msg.add_int("persist", 1); + msg.add_int("sesskey", sesskey); + msg.add_int("uid", DBGetContactSettingDword(0, MODULE, "UID", 0)); + + msg.add_int("cmd", 1); + msg.add_int("dsn", 5); + msg.add_int("lid", 7); + + int req = req_id++; + msg.add_int("rid", req); + + char body[512]; + mir_snprintf(body, 512, "UserName=%s", sbn->pszNick); + msg.add_string("body", body); + + SendMessage(msg); + return req; +} + +HANDLE FindContact(int uid) { + char *proto; + DBVARIANT dbv; + int cuid; + HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 ); + while ( hContact != NULL ) + { + proto = ( char* )CallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM )hContact,0 ); + if ( proto && !strcmp( MODULE, proto)) { + cuid = DBGetContactSettingDword(hContact, MODULE, "UID", (DWORD)-1); + if(cuid != (DWORD)-1) { + return hContact; + } + } + hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 ); + } + + return 0; +} + +int AddToList(WPARAM wParam, LPARAM lParam) { + MYPROTOSEARCHRESULT *mpsr = (MYPROTOSEARCHRESULT *)lParam; + bool temp = (wParam & PALF_TEMPORARY) != 0; + + HANDLE hContact = FindContact(mpsr->uid); + bool new_contact = (hContact == 0); + if(!hContact) { + hContact = (HANDLE)CallService(MS_DB_CONTACT_ADD, 0, 0); + } else if(!temp) { + DBDeleteContactSetting(hContact, "CList", "NotOnList"); + DBDeleteContactSetting(hContact, "CList", "Hidden"); + } + + if(hContact) { + // add to miranda + if(new_contact) { + DBWriteContactSettingDword(hContact, MODULE, "UID", mpsr->uid); + + ClientNetMessage msg_add; + msg_add.add_string("addbuddy", ""); + msg_add.add_int("sesskey", sesskey); + msg_add.add_int("newprofileid", mpsr->uid); + msg_add.add_string("reason", ""); + + SendMessage(msg_add); + + ClientNetMessage msg_block; + msg_block.add_string("blocklist", ""); + msg_block.add_int("sesskey", sesskey); + + char idlist[1024]; + mir_snprintf(idlist, 1024, "b-|%d|a+|%d", mpsr->uid, mpsr->uid); + msg_block.add_string("idlist", idlist); + + SendMessage(msg_block); + + // update contact details? + ClientNetMessage msg_persist; + msg_persist.add_int("persist", 1); + msg_persist.add_int("sesskey", sesskey); + + msg_persist.add_int("cmd", 514); + msg_persist.add_int("dsn", 0); + msg_persist.add_int("uid", DBGetContactSettingDword(0, MODULE, "UID", 0)); + msg_persist.add_int("lid", 9); + msg_persist.add_int("rid", req_id++); + char body[4096]; + mir_snprintf(body, 4096, "ContactID=%d\x1cGroupName=\x1cPosition=1000\x1cVisibility=1\x1cNickName=\x1cNameSelect=0", mpsr->uid); + msg_persist.add_string("body", body); + SendMessage(msg_persist); + } + + if(mpsr->psr.nick && strlen(mpsr->psr.nick)) { + DBWriteContactSettingStringUtf(hContact, MODULE, "Nick", mpsr->psr.nick); + } + if(mpsr->psr.email && strlen(mpsr->psr.email)) { + DBWriteContactSettingStringUtf(hContact, MODULE, "email", mpsr->psr.email); + } + + if(new_contact) { + CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)MODULE); + } + + if(temp) { + DBWriteContactSettingByte(hContact, "CList", "NotOnList", 1); + DBWriteContactSettingByte(hContact, "CList", "Hidden", 1); + } else { + DBDeleteContactSetting(hContact, "CList", "NotOnList"); + DBDeleteContactSetting(hContact, "CList", "Hidden"); + } + } + + return (int)hContact; +} + +int ContactDeleted(WPARAM wParam, LPARAM lParam) { + HANDLE hContact = (HANDLE)wParam; + int uid = DBGetContactSettingDword(hContact, MODULE, "UID", 0); + if(uid) { + ClientNetMessage msg_del; + msg_del.add_string("delbuddy", ""); + msg_del.add_int("sesskey", sesskey); + msg_del.add_int("delprofileid", uid); + SendMessage(msg_del); + + ClientNetMessage msg_persist; + msg_persist.add_int("persist", 1); + msg_persist.add_int("sesskey", sesskey); + msg_persist.add_int("cmd", 515); + msg_persist.add_int("dsn", 0); + msg_persist.add_int("uid", DBGetContactSettingDword(0, MODULE, "UID", 0)); + msg_persist.add_int("lid", 8); + msg_persist.add_int("rid", req_id++); + char body[1024]; + mir_snprintf(body, 1024, "ContactID=%d", uid); + msg_persist.add_string("body", body); + SendMessage(msg_persist); + + ClientNetMessage msg_block; + msg_block.add_string("blocklist", ""); + msg_block.add_int("sesskey", sesskey); + + char idlist[1024]; + mir_snprintf(idlist, 1024, "a-|%d|b-|%d", uid, uid); + msg_block.add_string("idlist", idlist); + + SendMessage(msg_block); + } + return 0; +} void RegisterProto() { PROTOCOLDESCRIPTOR pd = {0}; @@ -129,9 +331,10 @@ void RegisterProto() { CallService(MS_PROTO_REGISTERMODULE,0,(LPARAM)&pd); } -#define NUM_FILTER_SERVICES 9 +#define NUM_FILTER_SERVICES 12 HANDLE hServices[NUM_FILTER_SERVICES]; +HANDLE hEventContactDeleted; void CreateProtoServices() { // create our services int i = 0; @@ -146,10 +349,17 @@ void CreateProtoServices() { hServices[i++] = CreateProtoServiceFunction(MODULE, PS_SETSTATUS, SetStatus); hServices[i++] = CreateProtoServiceFunction(MODULE, PS_GETSTATUS, GetStatus); + hServices[i++] = CreateProtoServiceFunction(MODULE, PS_BASICSEARCH, BasicSearch); + hServices[i++] = CreateProtoServiceFunction(MODULE, PS_SEARCHBYEMAIL, SearchByEmail); + hServices[i++] = CreateProtoServiceFunction(MODULE, PS_SEARCHBYNAME, SearchByName); + hServices[i++] = CreateProtoServiceFunction(MODULE, PS_ADDTOLIST, AddToList); // remember to modify the NUM_FILTER_SERVICES #define above if you add more services! + + hEventContactDeleted = HookEvent(ME_DB_CONTACT_DELETED, ContactDeleted); } void DeinitProto() { + UnhookEvent(hEventContactDeleted); for(int i = 0; i < NUM_FILTER_SERVICES; i++) DestroyServiceFunction(hServices[i]); -} \ No newline at end of file +} diff --git a/MySpace/proto.h b/MySpace/proto.h index d45c485..008c9f5 100644 --- a/MySpace/proto.h +++ b/MySpace/proto.h @@ -1,6 +1,12 @@ #ifndef _PROTO_INC #define _PROTO_INC +typedef struct user { + int uin; + char *email; + char *username; +} UserType; + void RegisterProto(); void CreateProtoServices(); void DeinitProto(); diff --git a/MySpace/server_con.cpp b/MySpace/server_con.cpp index 79f20b8..0aa577c 100644 --- a/MySpace/server_con.cpp +++ b/MySpace/server_con.cpp @@ -4,8 +4,6 @@ #include "arc4.h" #include "options.h" -#include "NetMessage.h" - #define SERVER_READ_BUFFER_SIZE (1024 * 32) /* TODO: obtain IPs of network interfaces from user's machine, instead of @@ -26,7 +24,14 @@ int status = ID_STATUS_OFFLINE; bool server_running = false, server_stop = false; HANDLE server_connection = 0; -int sesskey; +int sesskey = 0, req_id = 1; + + +void SendMessage(ClientNetMessage &msg) { + char packet[4096]; + int packet_size = msg.make_packet(packet, 4096); + if(server_connection) Netlib_Send(server_connection, packet, packet_size, MSG_DUMPASTEXT); +} void CALLBACK sttMainThreadStatusCallback( ULONG dwParam ) { if(status != dwParam) { @@ -98,9 +103,7 @@ void try_login(NetMessage &msg, HANDLE connection) { delete[] ch_resp; - char packet[4096]; - int packet_size = reply.make_packet(packet, 4096); - Netlib_Send(server_connection, packet, packet_size, MSG_DUMPASTEXT); + SendMessage(reply); } else { PUShowMessage("Nonce format error", SM_NOTIFY); } @@ -170,16 +173,81 @@ void __cdecl ServerThreadFunc(void*) { try_login(msg, server_connection); } else if(msg.get_int("lc") == 2) { sesskey = msg.get_int("sesskey"); + DBWriteContactSettingDword(0, MODULE, "UID", msg.get_int("userid")); + char nick[256]; + if(msg.get_string("uniquenick", nick, 256)) + DBWriteContactSettingStringUtf(0, MODULE, "Nick", nick); QueueUserAPC(sttMainThreadStatusCallback, mainThread, ID_STATUS_ONLINE); } else if(msg.exists(NMString("persistr"))) { - /* - NMString cmd, dsn, lid; - msg.get(NMString("cmd"), cmd); - msg.get(NMString("dsn"), dsn); - msg.get(NMString("lid"), lid); - mir_snprintf(mt, 256, "Peristr message: type is %s,%s,%s", cmd.text, dsn.text, lid.text); + + int cmd, dsn, lid, req; + cmd = msg.get_int("cmd") & 255; + dsn = msg.get_int("dsn"); + lid = msg.get_int("lid"); + req = msg.get_int("rid"); + + mir_snprintf(mt, 256, "Peristr message: type is %d,%d,%d", cmd, dsn, lid); PUShowMessage(mt, SM_NOTIFY); - */ + if(cmd == 1 && dsn == 5 && lid == 7) { + Dictionary body = msg.get_dict("body"); + char email[256], nick[256]; + int uid = body.get_int("UserID"); + if(uid != 0) { + MYPROTOSEARCHRESULT mpsr = {sizeof(mpsr)}; + + if(body.get_string("UserName", nick, 256)) + mpsr.psr.nick = nick; + else if(body.get_string("DisplayName", nick, 256)) + mpsr.psr.nick = nick; + if(body.get_string("Email", email, 256)) + mpsr.psr.email = email; + mpsr.uid = uid; + + ProtoBroadcastAck(MODULE, 0, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)req, (LPARAM)&mpsr); + } else + ProtoBroadcastAck(MODULE, 0, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)req, 0); + } else + if(cmd == 1 && dsn == 4 && lid == 3) { + Dictionary body = msg.get_dict("body"); + char errmsg[256]; + if(body.get_string("ErrorMessage", errmsg, 256)) { + PUShowMessage(errmsg, SM_WARNING); + ProtoBroadcastAck(MODULE, 0, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)req, 0); + } else { + char email[256], nick[256]; + int uid = body.get_int("UserID"); + if(uid != 0) { + MYPROTOSEARCHRESULT mpsr = {sizeof(mpsr)}; + + if(body.get_string("DisplayName", nick, 256)) + mpsr.psr.nick = nick; + else if(body.get_string("UserName", nick, 256)) + mpsr.psr.nick = nick; + + if(body.get_string("Email", email, 256)) + mpsr.psr.email = email; + mpsr.uid = uid; + + ProtoBroadcastAck(MODULE, 0, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)req, (LPARAM)&mpsr); + } else + ProtoBroadcastAck(MODULE, 0, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)req, 0); + } + } else + if(cmd == 2 && dsn == 0 && lid == 9) { + Dictionary body = msg.get_dict("body"); + char errmsg[256]; + if(body.get_string("ErrorMessage", errmsg, 256)) { + PUShowMessage(errmsg, SM_WARNING); + } else { + char nick[256]; + int uid = body.get_int("ContactID"); + if(uid != 0) { + if(body.get_string("NickName", nick, 256)) { + DBWriteContactSettingStringUtf(0, MODULE, "Nick", nick); + } + } + } + } } } } diff --git a/MySpace/server_con.h b/MySpace/server_con.h index e051f87..9bbacf0 100644 --- a/MySpace/server_con.h +++ b/MySpace/server_con.h @@ -1,9 +1,21 @@ #ifndef _SERVER_CON_INC #define _SERVER_CON_INC +#include "NetMessage.h" +#include "m_protosvc.h" + extern int status; +extern int sesskey; +extern int req_id; void InitServerConnection(); void DeinitServerConnection(); +void SendMessage(ClientNetMessage &msg); + +typedef struct { + PROTOSEARCHRESULT psr; + int uid; +} MYPROTOSEARCHRESULT; + #endif -- cgit v1.2.3