static void ReportSslError(SECURITY_STATUS scRet, int line, bool = false) { TCHAR szMsgBuf[256]; switch (scRet) { case 0: case ERROR_NOT_READY: return; case SEC_E_INVALID_TOKEN: _tcsncpy_s(szMsgBuf, TranslateT("Client cannot decode host message. Possible causes: host does not support SSL or requires not existing security package"), _TRUNCATE); break; case CERT_E_CN_NO_MATCH: case SEC_E_WRONG_PRINCIPAL: _tcsncpy_s(szMsgBuf, TranslateT("Host we are connecting to is not the one certificate was issued for"), _TRUNCATE); break; default: FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, scRet, LANG_USER_DEFAULT, szMsgBuf, _countof(szMsgBuf), NULL); } TCHAR szMsgBuf2[512]; mir_sntprintf(szMsgBuf2, _T("SSL connection failure (%x %u): %s"), scRet, line, szMsgBuf); char* szMsg = Utf8EncodeT(szMsgBuf2); SslLog(szMsg); mir_free(szMsg); SetLastError(scRet); PUShowMessageT(szMsgBuf2, SM_WARNING); }
int StartServer() { int failure = 1; if (sdCmdLine) { if (sdCmdLine->instances == 0) { HANDLE server = mir_forkthread(ServerWorkerThread); if (server) { wchar_t path[MIMFOLDER_SIZE]; GetModuleFileNameW(GetModuleHandle(nullptr), path, _countof(path)); wchar_t *p = wcsrchr(path, '\\'); if (p) *p = 0; wcsncpy_s(sdCmdLine->mimFolder, path, _TRUNCATE); sdCmdLine->instances++; failure = 0; } else PUShowMessageT(TranslateT("Could not create CommandLine listening server!"), SM_WARNING); } else MessageBox(nullptr, TranslateT("You can only run one instance of CmdLine plugin."), TranslateT("Error"), MB_ICONERROR | MB_OK); } return failure; }
void TlenGetAvatarFileName(TlenProtocol *proto, TLEN_LIST_ITEM *item, TCHAR* ptszDest, int cbLen) { int tPathLen = mir_sntprintf(ptszDest, cbLen, TEXT("%s\\%S"), VARST( TEXT("%miranda_avatarcache%")), proto->m_szModuleName); if (_taccess(ptszDest, 0)) { int ret = CreateDirectoryTreeT(ptszDest); if (ret == 0) proto->debugLog(_T("getAvatarFilename(): Created new directory for avatar cache: %s."), ptszDest); else { proto->debugLog(_T("getAvatarFilename(): Can not create directory for avatar cache: %s. errno=%d: %s"), ptszDest, errno, strerror(errno)); TCHAR buffer[512]; mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("Cannot create avatars cache directory. ERROR: %d: %s\n%s"), errno, _tcserror(errno), ptszDest); PUShowMessageT(buffer, SM_WARNING); } } int format = PA_FORMAT_PNG; ptszDest[ tPathLen++ ] = '\\'; if (item != NULL) format = item->avatarFormat; else if (proto->threadData != NULL) format = proto->threadData->avatarFormat; else format = db_get_dw(NULL, proto->m_szModuleName, "AvatarFormat", PA_FORMAT_UNKNOWN); const TCHAR *tszFileType = ProtoGetAvatarExtension(format); if ( item != NULL ) mir_sntprintf(ptszDest + tPathLen, MAX_PATH - tPathLen, TEXT("%S%s"), ptrA( TlenSha1(item->jid)), tszFileType); else mir_sntprintf(ptszDest + tPathLen, MAX_PATH - tPathLen, TEXT("%S_avatar%s"), proto->m_szModuleName, tszFileType); }
void ShowError(wchar_t *msg) { wchar_t buffer[512]; ErrorDisplay disp = options.err_method; // funny logic :) ... try to avoid message boxes // if want popups but no popups, try baloons if(disp == ED_POP && !options.bHavePopups) disp = ED_BAL; mir_snwprintf(buffer, L"%s Error", _A2W(MODULENAME)); wchar_t *message; switch (disp) { case ED_POP: { int size = int(mir_wstrlen(msg) + 515); message = new wchar_t[size]; // newline and null terminator mir_snwprintf(message, size, L"%s\r\n%s", buffer, msg); PUShowMessageT(message, SM_WARNING); delete[] message; } break; case ED_MB: MessageBox(nullptr, msg, buffer, MB_OK | MB_ICONERROR); break; case ED_BAL: Clist_TrayNotifyW(MODULENAME, buffer, msg, NIIF_ERROR, 10000); break; } }
boolean checkUploadAvatarResponse(TlenProtocol *proto, NETLIBHTTPREQUEST *resp){ if (resp == NULL){ proto->debugLogA("Error while setting avatar on Tlen account (no response)"); PUShowMessageT(TranslateT("Error while setting avatar on Tlen account (no response)"), SM_WARNING); return false; } if (resp->resultCode != 200 || !resp->dataLength || !resp->pData) { proto->debugLogA("Error while setting avatar on Tlen account (invalid response) resultCode=%d, dataLength=%d", resp->resultCode, resp->dataLength); PUShowMessageT(TranslateT("Error while setting avatar on Tlen account (invalid response)"), SM_WARNING); return false; } if (strncmp(resp->pData, "<ok", 3)){ proto->debugLogA("Error while setting avatar on Tlen account: %s", resp->pData); PUShowMessageT(TranslateT("Error while setting avatar on Tlen account"), SM_WARNING); return false; } return true; }
void PopupPreview() { TCHAR *lptzTitle1Eng = TranslateT("The Jabberwocky"); TCHAR *lptzText1Eng = TranslateT("`Twas brillig, and the slithy toves\r\nDid gyre and gimble in the wabe:\r\nAll mimsy were the borogoves,\r\nAnd the mome raths outgrabe.\r\n\t[b][i]Lewis Carroll, 1855[/i][/b]"); TCHAR *lptzTitle2 = TranslateT("Test preview for the popup plugin settings. This is supposed to be long enough not to fit in one line..."); TCHAR *lptzText2 = TranslateTS( LPGENT("This is a special test preview for the popup plugin settings. The text and title are quite long so you can tweak your skin and plugin settings to best fit your needs :)") ); POPUPDATA2 ppd = { 0 }; memset(&ppd, 0, sizeof(ppd)); ppd.cbSize = sizeof(ppd); ppd.flags = PU2_TCHAR; ppd.lptzTitle = lptzTitle1Eng; ppd.lptzText = lptzText1Eng; ppd.lchIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE); CallService(MS_POPUP_ADDPOPUP2, (WPARAM)&ppd, APF_NO_HISTORY); if (PopupOptions.UseAnimations || PopupOptions.UseEffect) Sleep((ANIM_TIME * 2) / 3); // Pause memset(&ppd, 0, sizeof(ppd)); ppd.cbSize = sizeof(ppd); ppd.flags = PU2_TCHAR; ppd.lptzTitle = lptzTitle2; ppd.lptzText = lptzText2; ppd.lchIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); ppd.hbmAvatar = hbmNoAvatar; CallService(MS_POPUP_ADDPOPUP2, (WPARAM)&ppd, APF_NO_HISTORY); if (PopupOptions.UseAnimations || PopupOptions.UseEffect) Sleep((ANIM_TIME * 2) / 3); // Pause PUShowMessageT(TranslateT("This is a notification message"), (DWORD)SM_NOTIFY | 0x80000000); if (PopupOptions.UseAnimations || PopupOptions.UseEffect) Sleep((ANIM_TIME * 2) / 3); // Pause PUShowMessageT(TranslateT("This is a warning message"), (DWORD)SM_WARNING | 0x80000000); if (PopupOptions.UseAnimations || PopupOptions.UseEffect) Sleep((ANIM_TIME * 2) / 3); // Pause PUShowMessageT(TranslateT("This is an error message"), (DWORD)SM_ERROR | 0x80000000); }
int MyPUShowMessage(TCHAR *lpzText, BYTE kind) { if (ServiceExists(MS_POPUP_SHOWMESSAGE)) { return PUShowMessageT(lpzText, kind); } else{ TCHAR *title = (kind == SM_NOTIFY) ? TranslateT("Notify") : TranslateT("Warning"); return MessageBox(NULL, lpzText, title, MB_OK | (kind == SM_NOTIFY) ? MB_ICONINFORMATION : MB_ICONEXCLAMATION); } }
int WeatherError(WPARAM wParam, LPARAM lParam) { if ( !opt.UsePopup) return 0; TCHAR* tszMsg = ( TCHAR* )wParam; if ((DWORD)lParam == SM_WARNING) PUShowMessageT( tszMsg, SM_WARNING ); else if ((DWORD)lParam == SM_NOTIFY) PUShowMessageT( tszMsg, SM_NOTIFY); else if ((DWORD)lParam == SM_WEATHERALERT) { POPUPDATAT ppd = {0}; TCHAR *chop, str1[512], str2[512]; // get the 2 strings _tcscpy(str1, tszMsg); _tcscpy(str2, tszMsg); chop = _tcschr(str1, 255); if (chop != NULL) *chop = '\0'; else str1[0] = 0; chop = _tcschr(str2, 255); if (chop != NULL) _tcscpy(str2, chop+1); else str2[0] = 0; // setup the popup ppd.lchIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(OIC_BANG), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED); _tcscpy(ppd.lptzContactName, str1); _tcscpy(ppd.lptzText, str2); ppd.colorBack = (opt.UseWinColors)?GetSysColor(COLOR_BTNFACE):opt.BGColour; ppd.colorText = (opt.UseWinColors)?GetSysColor(COLOR_WINDOWTEXT):opt.TextColour; ppd.iSeconds = opt.pDelay; PUAddPopupT( &ppd ); } return 0; }
void ShowError(TCHAR *msg) { TCHAR buffer[512]; ErrorDisplay disp = options.err_method; // funny logic :) ... try to avoid message boxes // if want baloons but no balloons, try popups // if want popups but no popups, try baloons // if, after that, you want balloons but no balloons, revert to message boxes if(disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_POP; if(disp == ED_POP && !options.bHavePopups) disp = ED_BAL; if(disp == ED_BAL && !ServiceExists(MS_CLIST_SYSTRAY_NOTIFY)) disp = ED_MB; mir_sntprintf(buffer, SIZEOF(buffer), _T("%s Error"), _T(MODULENAME)); TCHAR *message; switch(disp) { case ED_POP: { int size = int(_tcslen(msg) + 515); message = new TCHAR[size]; // newline and null terminator mir_sntprintf(message, size, _T("%s\r\n%s"), buffer, msg); PUShowMessageT(message, SM_WARNING); delete message; } break; case ED_MB: MessageBox(0, msg, buffer, MB_OK | MB_ICONERROR); break; case ED_BAL: { MIRANDASYSTRAYNOTIFY sn = {0}; sn.cbSize = sizeof(sn); sn.szProto = MODULENAME; sn.tszInfoTitle = buffer; sn.tszInfo = msg; sn.dwInfoFlags = NIIF_ERROR | NIIF_INTERN_UNICODE; sn.uTimeout = 10; CallService(MS_CLIST_SYSTRAY_NOTIFY, 0, (LPARAM)&sn); } break; } }
static void SetAvatar(TlenProtocol *proto, HANDLE hContact, TLEN_LIST_ITEM *item, char *data, int len, DWORD format) { TCHAR filename[MAX_PATH]; char md5[33]; mir_md5_state_t ctx; DWORD digest[4]; if (format == PA_FORMAT_UNKNOWN && len > 4) format = ProtoGetBufferFormat(data); mir_md5_init( &ctx ); mir_md5_append( &ctx, ( BYTE* )data, len); mir_md5_finish( &ctx, ( BYTE* )digest ); sprintf( md5, "%08x%08x%08x%08x", (int)htonl(digest[0]), (int)htonl(digest[1]), (int)htonl(digest[2]), (int)htonl(digest[3])); //!!!!!!!!!!!!!! if (item != NULL) { char *hash = item->avatarHash; item->avatarFormat = format; item->avatarHash = mir_strdup(md5); mir_free(hash); } else { proto->threadData->avatarFormat = format; strcpy(proto->threadData->avatarHash, md5); } TlenGetAvatarFileName(proto, item, filename, sizeof filename ); DeleteFile(filename); FILE *out = _tfopen(filename, TEXT("wb") ); if (out != NULL) { fwrite(data, len, 1, out); fclose(out); db_set_ts(hContact, "ContactPhoto", "File", filename ); db_set_s(hContact, proto->m_szModuleName, "AvatarHash", md5); db_set_dw(hContact, proto->m_szModuleName, "AvatarFormat", format); } else { TCHAR buffer[128]; mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("Can not save new avatar file \"%s\" Error:\n\t%s (Error: %d)"), filename, _tcserror(errno), errno); PUShowMessageT(buffer, SM_WARNING); proto->debugLog(buffer); return; } ProtoBroadcastAck( proto->m_szModuleName, hContact, ACKTYPE_AVATAR, ACKRESULT_STATUS, NULL , 0); }
void MirandaUtils::setStatusOnAccount(ActionThreadArgStruct* args) { logger->log(L"MirandaUtils::setStatusOnAccount: start"); int status = CallProtoService(args->accountSzModuleName, PS_GETSTATUS, 0, 0); logger->log_p(L"SSOA: on account: [%S] targetHandle = [" SCNuPTR L"] at status = [%d]", args->accountSzModuleName, args->targetHandle, status); int result = -1; if (!(CallProtoService(args->accountSzModuleName, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_INDIVMODEMSG)){ result = CallProtoService(args->accountSzModuleName, PS_SETAWAYMSGW, (WPARAM)status, (LPARAM)args->userActionSelection); if (result == CALLSERVICE_NOTFOUND){ char *szMsg = mir_u2a(args->userActionSelection); result = CallProtoService(args->accountSzModuleName, PS_SETAWAYMSG, (WPARAM)status, (LPARAM)szMsg); mir_free(szMsg); } } MirandaAccount* mirandaAccount = args->mirfoxDataPtr->getMirandaAccountPtrBySzModuleName(args->accountSzModuleName); TCHAR* tszAccountName = NULL; if (mirandaAccount){ tszAccountName = mirandaAccount->tszAccountName; } wchar_t* buffer = new wchar_t[1024 * sizeof(wchar_t)]; if(result == 0){ if (tszAccountName != NULL){ logger->log_p(L"SSOA: Status message set on [%s]", tszAccountName); mir_sntprintf(buffer, 1024, TranslateT("Status message set on %s"), tszAccountName); } else { logger->log(L"SSOA: Status message set"); buffer = mir_wstrdup(TranslateT("Status message set")); } if(ServiceExists(MS_POPUP_ADDPOPUPCLASS)) { ShowClassPopupT("MirFox_Notify", TranslateT("MirFox"), buffer); } else { PUShowMessageT(buffer, SM_NOTIFY); } } else { if (tszAccountName != NULL){ logger->log_p(L"SSOA: ERROR - Cannot set status message 2 on [%s] - result = [%d] ", tszAccountName, result); mir_sntprintf(buffer, 1024, TranslateT("Cannot set status message on %s"), tszAccountName); } else { logger->log_p(L"SSOA: ERROR - Cannot set status message 2 - result = [%d] ", result); buffer = mir_wstrdup(TranslateT("Cannot set status message")); } if(ServiceExists(MS_POPUP_ADDPOPUPCLASS)) { ShowClassPopupT("MirFox_Error", TranslateT("MirFox error"), buffer); } else { PUShowMessageT(buffer, SM_WARNING); } } delete buffer; }
void MirandaUtils::sendMessage(ActionThreadArgStruct* args, MFENUM_SEND_MESSAGE_MODE mode) { logger->log_p(L"MirandaUtils::sendMessage: mode = [%d] to = [" SCNuPTR L"] msg = [%s]", mode, args->targetHandle, args->userActionSelection ); if (mode == MFENUM_SMM_ONLY_SEND || mode == MFENUM_SMM_SEND_AND_SHOW_MW){ //TODO - metacontacts support - C:\MIRANDA\SOURCES\PLUGINS\popup_trunk\src\popup_wnd2.cpp : 1083 // //check for MetaContact and get szProto from subcontact // if(strcmp(targetHandleSzProto, gszMetaProto)==0) { // HANDLE hSubContact = (HANDLE)CallService(MS_MC_GETDEFAULTCONTACT, (WPARAM)hContact, 0); // if(!hSubContact) return FALSE; // targetHandleSzProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hSubContact, 0); // } char* targetHandleSzProto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)args->targetHandle, 0); //targetHandleSzProto doesnt need mir_free or delete if (targetHandleSzProto == NULL){ logger->log(L"MirandaUtils::sendMessageToContact: ERROR targetHandleSzProto == NULL"); return; } int mirandaSendModeFlag = getMirandaSendModeFlag(targetHandleSzProto); char* msgBuffer = NULL; std::size_t bufSize = 0; if (mirandaSendModeFlag == PREF_UTF){ msgBuffer = mir_utf8encodeW(args->userActionSelection); bufSize = strlen(msgBuffer) + 1; } else if (mirandaSendModeFlag == PREF_UNICODE){ msgBuffer = mir_t2a(args->userActionSelection); bufSize = strlen(msgBuffer) + 1; size_t bufSizeT = (wcslen(args->userActionSelection) + 1) * sizeof(wchar_t); msgBuffer = (char*)mir_realloc(msgBuffer, bufSizeT + bufSize); memcpy((wchar_t*)&msgBuffer[bufSize], args->userActionSelection, bufSizeT); bufSize += bufSizeT; } logger->log_p(L"SMTC: mirandaSendModeFlag = [%d] bufSize = [%d]", mirandaSendModeFlag, bufSize); HANDLE hProcess = sendMessageMiranda(args->targetHandle, mirandaSendModeFlag, msgBuffer); logger->log_p(L"SMTC: hProcess = [" SCNuPTR L"]", hProcess); MIRFOXACKDATA* myMfAck = NULL; if (hProcess != NULL){ //if hProcess of sending process is null there will not be any ack EnterCriticalSection(&ackMapCs); ackMap[hProcess] = (MIRFOXACKDATA*)NULL; LeaveCriticalSection(&ackMapCs); int counter = 0; const int ACK_WAIT_TIME = 250; //[ms] const int MAX_ACK_WAIT_COUNTER = 40; //40 * 250ms = 10s do { SleepEx(ACK_WAIT_TIME, TRUE); counter++; EnterCriticalSection(&ackMapCs); myMfAck = ackMap[hProcess]; LeaveCriticalSection(&ackMapCs); if(Miranda_Terminated() || args->mirfoxDataPtr->Plugin_Terminated){ logger->log_p(L"SMTC: ACK break by Plugin_Terminated (=%d) or Miranda_Terminated()", args->mirfoxDataPtr->Plugin_Terminated); break; } } while (myMfAck == NULL && counter <= MAX_ACK_WAIT_COUNTER); //TODO or Plugin_Terminated or Miranda_Terminated() logger->log_p(L"SMTC: ACK found counter = [%d] myMfAck = [" SCNuPTR L"]", counter, myMfAck); } MirandaContact* mirandaContact = args->mirfoxDataPtr->getMirandaContactPtrByHandle(args->targetHandle); const wchar_t* contactNameW = NULL; TCHAR* tszAccountName = NULL; if (mirandaContact){ contactNameW = mirandaContact->contactNameW.c_str(); MirandaAccount* mirandaAccount = mirandaContact->mirandaAccountPtr; if (mirandaAccount){ tszAccountName = mirandaAccount->tszAccountName; } } if(myMfAck != NULL && myMfAck->result == ACKRESULT_SUCCESS){ addMessageToDB(args->targetHandle, mirandaSendModeFlag, msgBuffer, bufSize, targetHandleSzProto); if (mode == MFENUM_SMM_ONLY_SEND){ //show notyfication popup (only in SMM_ONLY_SEND mode) wchar_t* buffer = new wchar_t[1024 * sizeof(wchar_t)]; if (contactNameW != NULL && tszAccountName != NULL){ mir_sntprintf(buffer, 1024, TranslateT("Message sent to %s (%s)"), contactNameW, tszAccountName); } else { buffer = mir_wstrdup(TranslateT("Message sent")); } if(ServiceExists(MS_POPUP_ADDPOPUPCLASS)) { ShowClassPopupT("MirFox_Notify", TranslateT("MirFox"), buffer); } else { PUShowMessageT(buffer, SM_NOTIFY); } delete buffer; } else if (mode == MFENUM_SMM_SEND_AND_SHOW_MW){ //notify hook to open window if (args->mirfoxDataPtr != NULL && args->mirfoxDataPtr->hhook_EventOpenMW != NULL){ OnHookOpenMvStruct* onHookOpenMv = new(OnHookOpenMvStruct); onHookOpenMv->targetHandle = args->targetHandle; onHookOpenMv->msgBuffer = NULL; NotifyEventHooks(args->mirfoxDataPtr->hhook_EventOpenMW, (WPARAM)onHookOpenMv, (LPARAM)NULL); } else { logger->log(L"SMTC: ERROR1 args->mirfoxDataPtr == NULL || args->mirfoxDataPtr->hhook_EventOpenMW == NULL"); } } } else { //error - show error popup wchar_t* buffer = new wchar_t[1024 * sizeof(wchar_t)]; if (myMfAck != NULL){ logger->log_p(L"SMTC: ERROR - Cannot send message - result = [%d] ", myMfAck->result); if (myMfAck->errorDesc != NULL){ if (contactNameW != NULL && tszAccountName != NULL){ mir_sntprintf(buffer, 1024, TranslateT("Cannot send message to %s (%s) - %S"), contactNameW, tszAccountName, myMfAck->errorDesc); } else { mir_sntprintf(buffer, 1024, TranslateT("Cannot send message - %S"), myMfAck->errorDesc); } } else { if (contactNameW != NULL && tszAccountName != NULL){ mir_sntprintf(buffer, 1024, TranslateT("Cannot send message to %s (%s)"), contactNameW, tszAccountName); } else { buffer = mir_wstrdup(TranslateT("Cannot send message - %S")); } } } else { logger->log(L"SMTC: ERROR - Cannot send message 2"); if (contactNameW != NULL && tszAccountName != NULL){ mir_sntprintf(buffer, 1024, TranslateT("Cannot send message to %s (%s)"), contactNameW, tszAccountName); } else { buffer = mir_wstrdup(TranslateT("Cannot send message")); } } if(ServiceExists(MS_POPUP_ADDPOPUPCLASS)) { ShowClassPopupT("MirFox_Error", TranslateT("MirFox error"), buffer); } else { PUShowMessageT(buffer, SM_WARNING); } delete buffer; } if (myMfAck != NULL){ //when we found ack, not when we exceed MAX_ACK_WAIT_COUNTER if (myMfAck->errorDesc != NULL) delete myMfAck->errorDesc; delete myMfAck->szModule; delete myMfAck; } EnterCriticalSection(&ackMapCs); ackMap.erase(hProcess); LeaveCriticalSection(&ackMapCs); mir_free(msgBuffer); } else if (mode == MFENUM_SMM_ONLY_SHOW_MW){ //notify hook to open window if (args->mirfoxDataPtr != NULL && args->mirfoxDataPtr->hhook_EventOpenMW != NULL){ OnHookOpenMvStruct* onHookOpenMv = new(OnHookOpenMvStruct); onHookOpenMv->targetHandle = args->targetHandle; //adding newline to message in Message Window, only in this mode std::wstring* msgBuffer = new std::wstring(); //deleted at on_hook_OpenMW msgBuffer->append(args->userActionSelection); msgBuffer->append(L"\r\n"); onHookOpenMv->msgBuffer = msgBuffer; NotifyEventHooks(args->mirfoxDataPtr->hhook_EventOpenMW, (WPARAM)onHookOpenMv, (LPARAM)NULL); } else { logger->log(L"SMTC: ERROR1 args->mirfoxDataPtr == NULL || args->mirfoxDataPtr->hhook_EventOpenMW == NULL"); } } }
bool UpdateXMLData(const Category cat, const char *redirect_url /*= 0*/, int recurse_count /*=0*/) { if(recurse_count > MAX_REDIRECT_RECURSE) { PUShowMessageT(TranslateT("Updater: Error getting data - too many redirects"), SM_WARNING); return false; } NETLIBHTTPREQUEST req = {0}; NETLIBHTTPHEADER etag_hdr = {0}; if(OldXMLDataExists(cat)) { // ensure backend not checked more than once every MIN_XMLDATA_AGE hours long age = OldXMLDataAge(cat); if(age >= 0 && age < MIN_XMLDATA_AGE) { // get it only if our file is at least 8 hours old #ifdef DEBUG_HTTP_POPUPS char buff[512]; sprintf(buff, "XML Data is recent (%d hours old) - not downloading, using local copy", age); PUShowMessage(buff, SM_NOTIFY); #endif return LoadOldXMLData(cat, false); } // add ETag header for conditional get DBCONTACTGETSETTING cgs; DBVARIANT dbv; cgs.szModule = MODULE; char buff[256]; strcpy(buff, "DataETag_"); strcat(buff, category_files[cat]); cgs.szSetting = buff; cgs.pValue = &dbv; if(!CallService(MS_DB_CONTACT_GETSETTING, 0, (LPARAM)&cgs)) { req.headersCount = 1; req.headers = &etag_hdr; etag_hdr.szName = "If-None-Match"; etag_hdr.szValue = _strdup(dbv.pszVal); DBFreeVariant(&dbv); } } req.cbSize = sizeof(req); req.requestType = REQUEST_GET; char URL[MAX_PATH]; if(!redirect_url) { strcpy(URL, MIM_BACKEND_URL_PREFIX); strcat(URL, category_files[cat]); strcat(URL, ".bz2"); } else { strcpy(URL, redirect_url); } req.szUrl = URL; req.flags = NLHRF_HTTP11; req.nlc = hNetlibHttp; if (CallService(MS_SYSTEM_GETVERSION, 0, 0) >= PLUGIN_MAKE_VERSION(0,9,0,5)) req.flags |= NLHRF_PERSISTENT | NLHRF_REDIRECT; NETLIBHTTPREQUEST *resp = (NETLIBHTTPREQUEST *)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUser, (LPARAM)&req); free(etag_hdr.szValue); if (!resp) { hNetlibHttp = NULL; if (!Miranda_Terminated()) { int err = GetLastError(); if (err) { TCHAR buff[512]; int len = mir_sntprintf(buff, SIZEOF(buff), TranslateT("Failed to download XML data: ")); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, err, 0, buff + len, 512 - len, 0); ShowError(buff); //MessageBox(0, buff + len, TranslateT("Updater: Error Downloading XML Data"), MB_OK | MB_ICONWARNING); } else { ShowError(TranslateT("Failed to download XML data - Response is NULL")); //MessageBox(0, TranslateT("Error downloading XML data...\nResponse is NULL"), TranslateT("Updater Error"), MB_OK | MB_ICONWARNING); NLog("Failed to download XML data - Response is NULL"); } } return LoadOldXMLData(cat, false); } else if (resp->resultCode == 304) { // 'Not Modified' response hNetlibHttp = resp->nlc; CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp); resp = 0; #ifdef DEBUG_HTTP_POPUPS PUShowMessage("XML Data unchanged - using local copy", SM_NOTIFY); #endif // mark data as current return LoadOldXMLData(cat, true); } else if(resp->resultCode >= 300 && resp->resultCode < 400) { // redirect response hNetlibHttp = resp->nlc; // get new location bool ret = false; for(int i = 0; i < resp->headersCount; i++) { //MessageBox(0, resp->headers[i].szValue, resp->headers[i].szName, MB_OK); if(strcmp(resp->headers[i].szName, "Location") == 0) { ret = UpdateXMLData(cat, resp->headers[i].szValue, recurse_count + 1); break; } } CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp); resp = 0; if(!ret) return LoadOldXMLData(cat, false); return ret; } else if(resp->resultCode != 200) { hNetlibHttp = resp->nlc; TCHAR buff[512]; mir_sntprintf(buff, SIZEOF(buff), TranslateT("Failed to download XML data - Invalid response, code %d"), resp->resultCode); ShowError(buff); NLog(buff); CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp); resp = 0; return LoadOldXMLData(cat, false); } // resp->resultCode == 200 hNetlibHttp = resp->nlc; if(!bz2_decompress_xml(resp->pData, resp->dataLength, &pData[cat], &dataLength[cat])) { ShowError(TranslateT("Failed to decompress XML data")); CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp); resp = 0; return LoadOldXMLData(cat, false); } // store date header and data for response 'Not Modified' (304) above for(int i = 0; i < resp->headersCount; i++) { //MessageBox(0, resp->headers[i].szValue, resp->headers[i].szName, MB_OK); if(strcmp(resp->headers[i].szName, "ETag") == 0) { //MessageBox(0, resp->headers[i].szValue, "Storing ETag", MB_OK); char buff[256]; strcpy(buff, "DataETag_"); strcat(buff, category_files[cat]); DBWriteContactSettingString(0, MODULE, buff, resp->headers[i].szValue); } } CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)resp); resp = 0; SaveXMLData(cat); doc[cat] = ezxml_parse_str((char*)pData[cat], strlen((char*)pData[cat])); if (!doc[cat]) return false; return true; }