#include "common.h" #include "proto.h" #include "server_con.h" #include "resource.h" #include "formatting.h" #define FAILED_MESSAGE_HANDLE 99998 int msg_id = 1; int GetCaps(WPARAM wParam,LPARAM lParam) { int ret = 0; switch (wParam) { case PFLAGNUM_1: 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_INVISIBLE; break; case PFLAGNUM_3: break; case PFLAGNUM_4: //ret = PF4_SUPPORTTYPING; break; case PFLAGNUM_5: //ret = PF2_INVISIBLE; break; case PFLAG_UNIQUEIDTEXT: ret = (int) Translate("UserID"); break; case PFLAG_MAXLENOFMESSAGE: ret = MAX_MESSAGE_SIZE; break; case PFLAG_UNIQUEIDSETTING: ret = (int) "UID"; break; } return ret; } int GetName(WPARAM wParam,LPARAM lParam) { mir_snprintf((char *)lParam, wParam, "%s", MODULE); return 0; } int LoadIcon(WPARAM wParam,LPARAM lParam) { UINT id; switch (wParam & 0xFFFF) { case PLI_PROTOCOL: id = IDI_ICON_PROTO; break; case PLI_ONLINE: id = IDI_ICON_PROTO; break; case PLI_OFFLINE: id = IDI_ICON_PROTO; break; default: return (int) (HICON) NULL; } return (int) LoadImage(hInst, MAKEINTRESOURCE(id), IMAGE_ICON, GetSystemMetrics(wParam & PLIF_SMALL ? SM_CXSMICON : SM_CXICON), GetSystemMetrics(wParam & PLIF_SMALL ? SM_CYSMICON : SM_CYICON), 0); return 0; } int GetInfo(WPARAM wParam,LPARAM lParam) { CCSDATA *ccs = ( CCSDATA* )lParam; int uid; if((uid = DBGetContactSettingDword(ccs->hContact, MODULE, "UID", 0)) == 0) return 1; // fail LookupUID(uid); return 0; } int SetStatus(WPARAM wParam,LPARAM lParam) { if(wParam == status) return 0; SetServerStatus(wParam); return 0; } int GetStatus(WPARAM wParam,LPARAM lParam) { return status; } typedef struct tag_TFakeAckParams { HANDLE hEvent; HANDLE hContact; LPARAM lParam; } TFakeAckParams; static DWORD CALLBACK sttFakeAckMessageSuccess( LPVOID param ) { TFakeAckParams *tParam = ( TFakeAckParams* )param; WaitForSingleObject( tParam->hEvent, INFINITE ); Sleep( 100 ); ProtoBroadcastAck(MODULE, tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, ( HANDLE )tParam->lParam, 0 ); CloseHandle( tParam->hEvent ); delete tParam; return 0; } static DWORD CALLBACK sttFakeAckMessageFailed( LPVOID param ) { TFakeAckParams *tParam = ( TFakeAckParams* )param; WaitForSingleObject( tParam->hEvent, INFINITE ); Sleep( 100 ); ProtoBroadcastAck(MODULE, tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)FAILED_MESSAGE_HANDLE, tParam->lParam); CloseHandle( tParam->hEvent ); delete tParam; return 0; } int ProtoSendMessage(WPARAM wParam, LPARAM lParam) { CCSDATA *ccs = (CCSDATA *) lParam; char *message = (char *)ccs->lParam; char msg_utf[MAX_MESSAGE_SIZE], msg_fmt[MAX_MESSAGE_SIZE]; int uid; if((uid = DBGetContactSettingDword(ccs->hContact, MODULE, "UID", 0)) == 0 || status == ID_STATUS_OFFLINE) { HANDLE hEvent; TFakeAckParams *tfap; hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); tfap = new TFakeAckParams; tfap->hContact = ccs->hContact; tfap->hEvent = hEvent; tfap->lParam = 0; CloseHandle( CreateThread( NULL, 0, sttFakeAckMessageFailed, tfap, 0, 0 )); SetEvent( hEvent ); return FAILED_MESSAGE_HANDLE; } // TODO: process 'message' and/or 'messagew' below if(ccs->wParam & PREF_UNICODE) { wchar_t *messagew = (wchar_t *)&message[strlen(message)+1]; WideCharToMultiByte(CP_UTF8, 0, messagew, -1, msg_utf, MAX_MESSAGE_SIZE, 0, 0); } else { //} else if(ccs->wParam & PREF_UTF) { // message is utf8 encoded - you can use mir_utf8decode (m_system.h) to make it wide strncpy(msg_utf, message, MAX_MESSAGE_SIZE); } msg_utf[MAX_MESSAGE_SIZE-1] = 0; entitize(msg_utf, MAX_MESSAGE_SIZE); mir_snprintf(msg_fmt, MAX_MESSAGE_SIZE, "

%s

", msg_utf); ClientNetMessage msg; msg.add_int("bm", 1); msg.add_int("sesskey", sesskey); msg.add_int("t", uid); msg.add_int("f", my_uid); msg.add_int("cv", CLIENT_VER); msg.add_string("msg", msg_fmt); SendMessage(msg); HANDLE hEvent; TFakeAckParams *tfap; hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); int ret = msg_id++; tfap = new TFakeAckParams; tfap->hContact = ccs->hContact; tfap->hEvent = hEvent; tfap->lParam = (LPARAM)ret; CloseHandle( CreateThread( NULL, 0, sttFakeAckMessageSuccess, tfap, 0, 0 )); SetEvent( hEvent ); return ret; } int ProtoSendMessageW(WPARAM wParam, LPARAM lParam) { CCSDATA *ccs = (CCSDATA *) lParam; ccs->wParam |= PREF_UNICODE; return ProtoSendMessage(wParam, lParam); } int ProtoRecvMessage(WPARAM wParam, LPARAM lParam) { DBEVENTINFO dbei; CCSDATA* ccs = (CCSDATA*)lParam; PROTORECVEVENT* pre = (PROTORECVEVENT*)ccs->lParam; DBDeleteContactSetting(ccs->hContact, "CList", "Hidden"); ZeroMemory(&dbei, sizeof(dbei)); dbei.cbSize = sizeof(dbei); dbei.szModule = MODULE; dbei.timestamp = pre->timestamp; dbei.flags = (pre->flags & PREF_CREATEREAD) ? DBEF_READ : 0; dbei.flags |= (pre->flags & PREF_RTL) ? DBEF_RTL : 0; dbei.flags |= (pre->flags & PREF_UTF) ? DBEF_UTF : 0; dbei.eventType = EVENTTYPE_MESSAGE; dbei.cbBlob = strlen(pre->szMessage) + 1; if ( pre->flags & PREF_UNICODE ) dbei.cbBlob *= ( sizeof( wchar_t )+1 ); dbei.pBlob = (PBYTE)pre->szMessage; CallService(MS_DB_EVENT_ADD, (WPARAM)ccs->hContact, (LPARAM)&dbei); return 0; } 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; } int AddToList(WPARAM wParam, LPARAM lParam) { MYPROTOSEARCHRESULT *mpsr = (MYPROTOSEARCHRESULT *)lParam; bool temp = (wParam & PALF_TEMPORARY) != 0; HANDLE hContact = FindContact(mpsr->uid); if(!hContact) { hContact = CreateContact(mpsr->uid, mpsr->psr.nick, mpsr->psr.email, true); } 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}; pd.cbSize = sizeof(pd); pd.szName = MODULE; pd.type = PROTOTYPE_PROTOCOL; CallService(MS_PROTO_REGISTERMODULE,0,(LPARAM)&pd); } #define NUM_FILTER_SERVICES 13 HANDLE hServices[NUM_FILTER_SERVICES]; HANDLE hEventContactDeleted; void CreateProtoServices() { // create our services int i = 0; hServices[i++] = CreateProtoServiceFunction(MODULE, PSS_MESSAGE, ProtoSendMessage); hServices[i++] = CreateProtoServiceFunction(MODULE, PSS_MESSAGE"W", ProtoSendMessageW); hServices[i++] = CreateProtoServiceFunction(MODULE, PSR_MESSAGE, ProtoRecvMessage); hServices[i++] = CreateProtoServiceFunction(MODULE, PS_GETCAPS, GetCaps); hServices[i++] = CreateProtoServiceFunction(MODULE, PS_GETNAME, GetName); hServices[i++] = CreateProtoServiceFunction(MODULE, PS_LOADICON,LoadIcon); hServices[i++] = CreateProtoServiceFunction(MODULE, PSS_GETINFO,GetInfo); 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); //my_space_server_running = false; } void DeinitProto() { UnhookEvent(hEventContactDeleted); for(int i = 0; i < NUM_FILTER_SERVICES; i++) DestroyServiceFunction(hServices[i]); }