diff options
-rw-r--r-- | MySpace/MySpace.cpp | 3 | ||||
-rw-r--r-- | MySpace/common.h | 3 | ||||
-rw-r--r-- | MySpace/formatting.cpp | 13 | ||||
-rw-r--r-- | MySpace/net.cpp | 2 | ||||
-rw-r--r-- | MySpace/proto.cpp | 153 | ||||
-rw-r--r-- | MySpace/server_con.cpp | 270 | ||||
-rw-r--r-- | MySpace/server_con.h | 1 | ||||
-rw-r--r-- | 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 <m_options.h>
#include <m_protomod.h>
#include <m_protosvc.h>
+#include <m_protocols.h>
#include <stdio.h> // for m_utils
#include <winsock2.h> // for FD_SETSIZE
#include <m_netlib.h>
@@ -49,6 +50,8 @@ #include <m_popup.h>
#include <m_updater.h>
+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 <a></a> 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 <malloc.h>
#include <ctime>
+#include <cstdlib>
#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;i<nlhrReply->headersCount;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
|