From 6ad2fdede0ae25dc0d56b5e45f6b9aa876e93b68 Mon Sep 17 00:00:00 2001 From: sje Date: Tue, 3 Jul 2007 06:26:19 +0000 Subject: don't strip links in tags get avatars! woohoo :) git-svn-id: https://server.scottellis.com.au/svn/mim_plugs@248 4f64403b-2f21-0410-a795-97e2b3489a10 --- MySpace/MySpace.cpp | 3 + MySpace/common.h | 3 + MySpace/formatting.cpp | 13 ++- MySpace/net.cpp | 2 +- MySpace/proto.cpp | 153 ++++++++-------------------- MySpace/server_con.cpp | 270 ++++++++++++++++++++++++++++++++++++++++++++++++- MySpace/server_con.h | 1 + MySpace/version.h | 2 +- 8 files changed, 328 insertions(+), 119 deletions(-) diff --git a/MySpace/MySpace.cpp b/MySpace/MySpace.cpp index 87eb600..741ae3f 100644 --- a/MySpace/MySpace.cpp +++ b/MySpace/MySpace.cpp @@ -18,6 +18,8 @@ int code_page; char MODULE[256]; +MM_INTERFACE mmi; + PLUGININFOEX pluginInfo={ sizeof(PLUGININFOEX), __PLUGIN_NAME, @@ -111,6 +113,7 @@ extern "C" __declspec (dllexport) int Load(PLUGINLINK *link) { code_page = (int)CallService(MS_LANGPACK_GETCODEPAGE, 0, 0); + mir_getMMI(&mmi); // Get module name from DLL file name { char* str1; diff --git a/MySpace/common.h b/MySpace/common.h index 36a072c..0a9db69 100644 --- a/MySpace/common.h +++ b/MySpace/common.h @@ -39,6 +39,7 @@ #include #include #include +#include #include // for m_utils #include // for FD_SETSIZE #include @@ -49,6 +50,8 @@ #include #include +extern MM_INTERFACE mmi; + //////////// // included for backward compatibility #ifndef CMIF_UNICODE diff --git a/MySpace/formatting.cpp b/MySpace/formatting.cpp index e66d0f6..130e703 100644 --- a/MySpace/formatting.cpp +++ b/MySpace/formatting.cpp @@ -81,9 +81,20 @@ void unentitize_nick(char *buff) { void strip_tags(char *buff) { int in = 0, out = 0; while(buff[in]) { - if(buff[in] == '<' && buff[in + 1] != 'i') { + if(buff[in] == '<' && buff[in + 1] != 'i' && buff[in + 1] != 'a') { while(buff[in] && buff[in] != '>') in++; in++; + } else if(buff[in] == '<' && buff[in + 1] == 'a') { + // link + while(buff[in] && buff[in] != '\'' && buff[in] != '\"') in++; + in++; + while(buff[in] && buff[in] != '\'' && buff[in] != '\"') + buff[out++] = buff[in++]; + while(buff[in] && buff[in] != '>') in++; + in++; + // add a space after a link in case there's something inside the tags + if(buff[in] && buff[in] != ' ' && buff[in] != '\r' && buff[in] != '\n' && buff[in] != '\t') + buff[out++] = ' '; } else buff[out++] = buff[in++]; } diff --git a/MySpace/net.cpp b/MySpace/net.cpp index 998e3cf..1613946 100644 --- a/MySpace/net.cpp +++ b/MySpace/net.cpp @@ -10,7 +10,7 @@ void InitNetlib() { nl_user.flags = NUF_OUTGOING | NUF_HTTPCONNS; char buff[512]; - mir_snprintf(buff, 512, "%s server connection", MODULE); + mir_snprintf(buff, 512, "%s connections", MODULE); nl_user.szDescriptiveName = buff; hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nl_user); diff --git a/MySpace/proto.cpp b/MySpace/proto.cpp index c7133a3..48d65ad 100644 --- a/MySpace/proto.cpp +++ b/MySpace/proto.cpp @@ -24,7 +24,7 @@ int GetCaps(WPARAM wParam,LPARAM lParam) { ret = PF2_ONLINE | PF2_SHORTAWAY | PF2_INVISIBLE; break; case PFLAGNUM_4: - ret = PF4_SUPPORTTYPING; + ret = PF4_SUPPORTTYPING | PF4_AVATARS; break; case PFLAGNUM_5: //ret = PF2_INVISIBLE; @@ -92,37 +92,18 @@ int GetStatus(WPARAM wParam,LPARAM lParam) { return status; } -typedef struct tag_TFakeAckParams -{ - HANDLE hEvent; - HANDLE hContact; - LPARAM lParam; -} TFakeAckParams; +void __cdecl sttFakeAckMessageSuccess(void *param) { + HANDLE hContact = (HANDLE)param; -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; + SleepEx( 10, TRUE ); + ProtoBroadcastAck(MODULE, hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)1, 0 ); } -static DWORD CALLBACK sttFakeAckMessageFailed( LPVOID param ) -{ - TFakeAckParams *tParam = ( TFakeAckParams* )param; - WaitForSingleObject( tParam->hEvent, INFINITE ); +void __cdecl sttFakeAckMessageFailed(void *param) { + HANDLE hContact = (HANDLE)param; - Sleep( 100 ); - ProtoBroadcastAck(MODULE, tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)FAILED_MESSAGE_HANDLE, tParam->lParam); - - CloseHandle( tParam->hEvent ); - delete tParam; - return 0; + SleepEx( 10, TRUE ); + ProtoBroadcastAck(MODULE, hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, (HANDLE)FAILED_MESSAGE_HANDLE, 0); } int ProtoSendMessage(WPARAM wParam, LPARAM lParam) { @@ -132,18 +113,7 @@ int ProtoSendMessage(WPARAM wParam, LPARAM lParam) { 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 ); + mir_forkthread(sttFakeAckMessageFailed, ccs->hContact); return FAILED_MESSAGE_HANDLE; } @@ -153,7 +123,6 @@ int ProtoSendMessage(WPARAM wParam, LPARAM lParam) { 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; @@ -171,22 +140,8 @@ int ProtoSendMessage(WPARAM wParam, LPARAM lParam) { 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; + mir_forkthread(sttFakeAckMessageSuccess, ccs->hContact); + return 1; } int ProtoSendMessageW(WPARAM wParam, LPARAM lParam) { @@ -325,71 +280,30 @@ int AddToList(WPARAM wParam, LPARAM lParam) { return (int)hContact; } -static DWORD CALLBACK sttRecvAway( LPVOID param ) -{ - TFakeAckParams *tParam = ( TFakeAckParams* )param; - WaitForSingleObject( tParam->hEvent, INFINITE ); - - Sleep( 100 ); +void __cdecl sttRecvAway(void *param) { + HANDLE hContact = (HANDLE)param; DBVARIANT dbv; char buff[512]; buff[0] = 0; - if(!DBGetContactSettingStringUtf(tParam->hContact, MODULE, "StatusMsg", &dbv) && strlen(dbv.pszVal)) { - strncpy(buff, dbv.pszVal, 512); - buff[511] = 0; + if(!DBGetContactSettingStringUtf(hContact, MODULE, "StatusMsg", &dbv) && strlen(dbv.pszVal)) { + mir_snprintf(buff, 512, "%s", dbv.pszVal); DBFreeVariant(&dbv); } - - CCSDATA ccs = {0}; - PROTORECVEVENT pre = {0}; - - ccs.hContact = tParam->hContact; - ccs.szProtoService = PSR_AWAYMSG; - ccs.wParam = 0; - ccs.lParam = (LPARAM)⪯ - - pre.timestamp = (DWORD)time(0); - if(strlen(buff)) - pre.szMessage = buff; - else - pre.szMessage = 0; - - CallService(MS_PROTO_CHAINRECV, 0, (LPARAM)&ccs); - - CloseHandle( tParam->hEvent ); - delete tParam; - return 0; + ProtoBroadcastAck(MODULE, hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)buff); } int GetAwayMsg(WPARAM wParam, LPARAM lParam) { CCSDATA* ccs = (CCSDATA*)lParam; + if ( ccs == NULL ) + return 0; - HANDLE hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); - - TFakeAckParams *tfap = new TFakeAckParams; - tfap->hContact = ccs->hContact; - tfap->hEvent = hEvent; - tfap->lParam = 0; - - CloseHandle( CreateThread( NULL, 0, sttRecvAway, tfap, 0, 0 )); - SetEvent( hEvent ); + mir_forkthread(sttRecvAway, ccs->hContact); return 1; } -int RecvAwayMsg(WPARAM wParam, LPARAM lParam) { - CCSDATA* ccs = (CCSDATA*)lParam; - PROTORECVEVENT* pre = (PROTORECVEVENT*)ccs->lParam; - - ProtoBroadcastAck(MODULE, ccs->hContact, ACKTYPE_AWAYMSG, ACKRESULT_SUCCESS, (HANDLE)1, (LPARAM)pre->szMessage); - - return 0; -} - - - int SetAwayMsg(WPARAM wParam, LPARAM lParam) { int status = (int)wParam; char *msg = (char *)lParam; @@ -418,6 +332,26 @@ int SendTyping(WPARAM wParam, LPARAM lParam) { return 0; } +int GetAvatarInfo(WPARAM wParam,LPARAM lParam) { + if (DBGetContactSettingByte(0, MODULE, "EnableAvatars", 1) == 0) + return GAIR_NOAVATAR; + + PROTO_AVATAR_INFORMATION* AI = ( PROTO_AVATAR_INFORMATION* )lParam; + + DBVARIANT dbv; + if(!DBGetContactSetting(AI->hContact, MODULE, "AvatarFilename", &dbv)) { + strncpy(AI->filename, dbv.pszVal, sizeof(AI->filename)); + DBFreeVariant(&dbv); + return GAIR_SUCCESS; + } else if((wParam && GAIF_FORCE) != 0 && status > ID_STATUS_OFFLINE && !DBGetContactSetting(AI->hContact, MODULE, "ImageURL", &dbv)) { + DownloadAvatar(AI->hContact, dbv.pszVal); + DBFreeVariant(&dbv); + return GAIR_WAITFOR; + } else + return GAIR_NOAVATAR; +} + + int ContactDeleted(WPARAM wParam, LPARAM lParam) { HANDLE hContact = (HANDLE)wParam; int uid = DBGetContactSettingDword(hContact, MODULE, "UID", 0); @@ -444,11 +378,9 @@ int ContactDeleted(WPARAM wParam, LPARAM lParam) { 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; @@ -486,15 +418,14 @@ void CreateProtoServices() { hServices[i++] = CreateProtoServiceFunction(MODULE, PS_ADDTOLIST, AddToList); hServices[i++] = CreateProtoServiceFunction(MODULE, PSS_GETAWAYMSG, GetAwayMsg); - hServices[i++] = CreateProtoServiceFunction(MODULE, PSR_AWAYMSG, RecvAwayMsg); hServices[i++] = CreateProtoServiceFunction(MODULE, PS_SETAWAYMSG, SetAwayMsg); hServices[i++] = CreateProtoServiceFunction(MODULE, PSS_USERISTYPING, SendTyping); + + hServices[i++] = CreateProtoServiceFunction(MODULE, PS_GETAVATARINFO, GetAvatarInfo); // 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() { diff --git a/MySpace/server_con.cpp b/MySpace/server_con.cpp index baf506f..5131655 100644 --- a/MySpace/server_con.cpp +++ b/MySpace/server_con.cpp @@ -8,6 +8,7 @@ #include #include +#include #define SERVER_READ_BUFFER_SIZE (1024 * 32) @@ -33,6 +34,19 @@ int sesskey = 0, req_id = 1, my_uid = 0; int signon_status = ID_STATUS_ONLINE; char signon_status_msg[512] = {0}; +bool WriteData(char *fn, int fn_size, char *data, int data_size) { + // prepend dir to filename & create dir? + HANDLE hSaveFile = CreateFileA(fn, GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + if(hSaveFile == INVALID_HANDLE_VALUE) return false; + + unsigned long bytes_written = 0; + bool ret = false; + if(WriteFile(hSaveFile, data, data_size, &bytes_written, NULL) == TRUE) ret = true; + + CloseHandle(hSaveFile); + return ret; +} + int stat_mir_to_myspace(int mir_status) { switch(mir_status) { case ID_STATUS_INVISIBLE: return 0; @@ -384,6 +398,8 @@ void __cdecl ServerThreadFunc(void*) { msg_status.add_string("locstring", ""); SendMessage(msg_status); + LookupUID(my_uid); + /* // set login time? Dictionary ld; @@ -515,10 +531,17 @@ void __cdecl ServerThreadFunc(void*) { mpsr.psr.email = email; mpsr.uid = uid; - HANDLE hContact = FindContact(uid); - if(hContact) { - if(mpsr.psr.nick) DBWriteContactSettingStringUtf(hContact, MODULE, "Nick", mpsr.psr.nick); - if(mpsr.psr.email) DBWriteContactSettingStringUtf(hContact, MODULE, "email", mpsr.psr.email); + HANDLE hContact = 0; + hContact = FindContact(uid); + if(hContact || uid == my_uid) { + if(mpsr.psr.nick) { + DBWriteContactSettingStringUtf(hContact, MODULE, "Nick", mpsr.psr.nick); + if(uid == my_uid) DBWriteContactSettingStringUtf(0, MODULE, "Nick", mpsr.psr.nick); + } + if(mpsr.psr.email) { + DBWriteContactSettingStringUtf(hContact, MODULE, "email", mpsr.psr.email); + if(uid == my_uid) DBWriteContactSettingStringUtf(0, MODULE, "email", mpsr.psr.email); + } char band[256], song[256]; band[0] = song[0] = 0; @@ -526,8 +549,25 @@ void __cdecl ServerThreadFunc(void*) { KeyValue &kv = i.val(); if(strcmp(kv.first.text, "Gender") == 0) { DBWriteContactSettingByte(hContact, MODULE, "Gender", kv.second.text[0]); + if(uid == my_uid) DBWriteContactSettingByte(0, MODULE, "Gender", kv.second.text[0]); + } else if(strcmp(kv.first.text, "ImageURL") == 0) { + DBVARIANT dbv; + if(!DBGetContactSettingStringUtf(hContact, MODULE, "ImageURL", &dbv)) { + if(strcmp(kv.first.text, dbv.pszVal) != 0) { + // avatar changed + DBDeleteContactSetting(hContact, MODULE, "AvatarFilename"); + if(uid == my_uid) DBDeleteContactSetting(0, MODULE, "AvatarFilename"); + DBWriteContactSettingStringUtf(hContact, MODULE, kv.first.text, kv.second.text); + if(uid == my_uid) DBWriteContactSettingStringUtf(0, MODULE, kv.first.text, kv.second.text); + } + DBFreeVariant(&dbv); + }else { + DBWriteContactSettingStringUtf(hContact, MODULE, kv.first.text, kv.second.text); + if(uid == my_uid) DBWriteContactSettingStringUtf(0, MODULE, kv.first.text, kv.second.text); + } } else { DBWriteContactSettingStringUtf(hContact, MODULE, kv.first.text, kv.second.text); + if(uid == my_uid) DBWriteContactSettingStringUtf(0, MODULE, kv.first.text, kv.second.text); if(strcmp(kv.first.text, "BandName") == 0) strncpy(band, kv.second.text, 256); if(strcmp(kv.first.text, "SongName") == 0) strncpy(song, kv.second.text, 256); } @@ -536,13 +576,13 @@ void __cdecl ServerThreadFunc(void*) { char listenTo[512]; mir_snprintf(listenTo, 512, "%s/%s", band, song); DBWriteContactSettingStringUtf(hContact, MODULE, "ListeningTo", listenTo); + if(uid == my_uid) DBWriteContactSettingStringUtf(0, MODULE, "ListeningTo", listenTo); } ProtoBroadcastAck(MODULE, hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE)1, 0); } ProtoBroadcastAck(MODULE, 0, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)req, (LPARAM)&mpsr); - } ProtoBroadcastAck(MODULE, 0, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)req, 0); } @@ -663,3 +703,223 @@ void SetServerStatusMessage(char *msg) { QueueUserAPC(sttMainThreadStatusMessageCallback, mainThread, (ULONG_PTR)(msg ? strdup(msg): 0)); } +int NetlibHttpRecvChunkHeader(HANDLE hConnection, BOOL first) +{ + char data[32], *peol1; + + int recvResult = Netlib_Recv(hConnection, data, 31, MSG_PEEK); + data[recvResult] = 0; + + peol1 = strstr(data, "\r\n"); + if (peol1 != NULL) + { + char *peol2 = first ? peol1 : strstr(peol1 + 2, "\r\n"); + if (peol2 != NULL) + { + Netlib_Recv(hConnection, data, peol2 - data + 2, 0); + return atoi(first ? data : peol1+2); + } + } + + return SOCKET_ERROR; +} + +NETLIBHTTPREQUEST* NetlibHttpRecv(HANDLE hConnection, DWORD hflags, DWORD dflags) +{ + int dataLen = -1, i, chunkhdr; + int chunked = FALSE; + + NETLIBHTTPREQUEST *nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_RECVHTTPHEADERS, (WPARAM)hConnection, hflags); + if (nlhrReply==NULL) + return NULL; + + for(i=0;iheadersCount;i++) + { + if(!lstrcmpiA(nlhrReply->headers[i].szName, "Content-Length")) + dataLen = atoi(nlhrReply->headers[i].szValue); + + if(!lstrcmpiA(nlhrReply->headers[i].szName, "Transfer-Encoding") && + !lstrcmpiA(nlhrReply->headers[i].szValue, "chunked")) + { + chunked = TRUE; + chunkhdr = i; + break; + } + } + + if (nlhrReply->resultCode >= 200 && dataLen != 0) + { + int recvResult, chunksz = 0; + int dataBufferAlloced = dataLen + 1; + + if (chunked) + { + chunksz = NetlibHttpRecvChunkHeader(hConnection, TRUE); + if (chunksz == SOCKET_ERROR) + { + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply); + return NULL; + } + dataLen = dataBufferAlloced = chunksz; + } + + nlhrReply->pData = (char *)mir_realloc(nlhrReply->pData, dataBufferAlloced); + + do { + for(;;) { + if(dataBufferAlloced-nlhrReply->dataLength<1024 && dataLen == -1) { + dataBufferAlloced+=2048; + nlhrReply->pData=(char *)mir_realloc(nlhrReply->pData,dataBufferAlloced); + if(nlhrReply->pData==NULL) { + SetLastError(ERROR_OUTOFMEMORY); + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0,(LPARAM)nlhrReply); + return NULL; + } + } + recvResult=Netlib_Recv(hConnection,nlhrReply->pData+nlhrReply->dataLength, + dataBufferAlloced-nlhrReply->dataLength-1, dflags); + + if(recvResult==0) break; + if(recvResult==SOCKET_ERROR) { + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0,(LPARAM)nlhrReply); + return NULL; + } + nlhrReply->dataLength += recvResult; + + if (dataLen > -1 && nlhrReply->dataLength >= dataLen) + break; + } + + if (chunked) + { + chunksz = NetlibHttpRecvChunkHeader(hConnection, FALSE); + if (chunksz == SOCKET_ERROR) + { + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply); + return NULL; + } + dataLen += chunksz; + dataBufferAlloced += chunksz; + + nlhrReply->pData = (char *)mir_realloc(nlhrReply->pData, dataBufferAlloced); + } + } while (chunksz != 0); + + nlhrReply->pData[nlhrReply->dataLength]='\0'; + } + + if (chunked) + { + nlhrReply->headers[chunkhdr].szName = (char *)mir_realloc(nlhrReply->headers[chunkhdr].szName, 16); + lstrcpyA(nlhrReply->headers[chunkhdr].szName, "Content-Length"); + + nlhrReply->headers[chunkhdr].szValue = (char *)mir_realloc(nlhrReply->headers[chunkhdr].szValue, 16); + mir_snprintf(nlhrReply->headers[chunkhdr].szValue, 16, "%u", nlhrReply->dataLength); + } + + return nlhrReply; +} + +typedef struct { + HANDLE hContact; + char *url; +} av_dl_info; + +void __cdecl sttDownloadAvatar(void *param) { + av_dl_info *info = (av_dl_info *)param; + + NETLIBHTTPREQUEST req = {0}; + req.cbSize = sizeof(req); + req.requestType = REQUEST_GET; + req.szUrl = info->url; + req.flags = 0; + NETLIBHTTPREQUEST *nlhrReply = 0; + + ProtoBroadcastAck(MODULE,info->hContact, ACKTYPE_AVATAR, ACKRESULT_CONNECTING, 0, 0); + + HANDLE hConnection = 0; + { + NETLIBOPENCONNECTION nloc={0}; + char szHost[128]; + char *ppath,*phost,*pcolon; + + phost=strstr(info->url,"://"); + if(phost==NULL) phost=info->url; + else phost+=3; + lstrcpynA(szHost,phost,sizeof(szHost)); + ppath=strchr(szHost,'/'); + if(ppath) *ppath='\0'; + nloc.cbSize=sizeof(nloc); + nloc.szHost=szHost; + pcolon=strrchr(szHost,':'); + if(pcolon) { + *pcolon='\0'; + nloc.wPort=(WORD)atoi(pcolon+1); + } + else nloc.wPort=80; + nloc.flags=NLOCF_HTTP; + hConnection=(HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)hNetlibUser,(LPARAM)&nloc); + if(hConnection==NULL) { + ProtoBroadcastAck(MODULE,info->hContact,ACKTYPE_AVATAR,ACKRESULT_FAILED,0, 0); + goto free_and_exit; + } + } + ProtoBroadcastAck(MODULE,info->hContact,ACKTYPE_AVATAR,ACKRESULT_CONNECTED, 0, 0); + + if(!CallService(MS_NETLIB_SENDHTTPREQUEST, (WPARAM)hConnection, (LPARAM)&req)) { + ProtoBroadcastAck(MODULE,info->hContact,ACKTYPE_AVATAR,ACKRESULT_FAILED,0, 0); + goto free_and_exit; + } + + ProtoBroadcastAck(MODULE,info->hContact,ACKTYPE_AVATAR,ACKRESULT_SENTREQUEST, 0, 0); + + int dflags = (req.flags&NLHRF_DUMPASTEXT?MSG_DUMPASTEXT:0) | + (req.flags&NLHRF_NODUMP?MSG_NODUMP:(req.flags&NLHRF_DUMPPROXY?MSG_DUMPPROXY:0)); + + nlhrReply = NetlibHttpRecv(hConnection, 0, dflags); + + Netlib_CloseHandle(hConnection); + + if(nlhrReply) { + ProtoBroadcastAck(MODULE,info->hContact,ACKTYPE_AVATAR,ACKRESULT_DATA, 0, 0); + + char *ext = strrchr(info->url, '.'); + + // write file + int uid = DBGetContactSettingDword(info->hContact, MODULE, "UID", 0); + + char fn[MAX_PATH]; + char buff[128]; + mir_snprintf(fn, MAX_PATH, "%s_%s.%s", _itoa(uid, buff, 10), _itoa((int)time(0), buff, 10), ext); + + WriteData(fn, MAX_PATH, nlhrReply->pData, nlhrReply->dataLength); + + PROTO_AVATAR_INFORMATION AI = {0}; + AI.cbSize = sizeof(PROTO_AVATAR_INFORMATION); + AI.hContact = info->hContact; + strncpy(AI.filename, fn, MAX_PATH); + AI.format = + (stricmp(ext, ".png") ? PA_FORMAT_PNG : + (stricmp(ext, ".jpg") ? PA_FORMAT_JPEG : + (stricmp(ext, ".jpeg") ? PA_FORMAT_JPEG : + (stricmp(ext, ".gif") ? PA_FORMAT_GIF : + (stricmp(ext, ".swf") ? PA_FORMAT_SWF : PA_FORMAT_UNKNOWN))))); + + + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply); + ProtoBroadcastAck(MODULE,info->hContact,ACKTYPE_AVATAR,ACKRESULT_SUCCESS,(HANDLE) &AI, 0); + } else + ProtoBroadcastAck(MODULE,info->hContact,ACKTYPE_AVATAR,ACKRESULT_FAILED,0, 0); + +free_and_exit: + free(info->url); + delete info; +} + +void DownloadAvatar(HANDLE hContact, char *url) { + av_dl_info *info = new av_dl_info; + info->hContact = hContact; + info->url = strdup(url); + + mir_forkthread(sttDownloadAvatar, info); +} \ No newline at end of file diff --git a/MySpace/server_con.h b/MySpace/server_con.h index b247e00..c81ce07 100644 --- a/MySpace/server_con.h +++ b/MySpace/server_con.h @@ -18,6 +18,7 @@ HANDLE CreateContact(int uid, char *nick, char *email, bool add_buddy); int LookupUID(int uid); void SendMessage(ClientNetMessage &msg); +void DownloadAvatar(HANDLE hContact, char *url); typedef struct { PROTOSEARCHRESULT psr; diff --git a/MySpace/version.h b/MySpace/version.h index 7c4d27b..c2ef289 100644 --- a/MySpace/version.h +++ b/MySpace/version.h @@ -5,7 +5,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 0 #define __RELEASE_NUM 1 -#define __BUILD_NUM 17 +#define __BUILD_NUM 18 #define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM #define __FILEVERSION_STRING_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM -- cgit v1.2.3