/* Miranda SmileyAdd Plugin Copyright (C) 2007 - 2011 Boris Krasnovskiy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "stdafx.h" HNETLIBUSER hNetlibUser; static HANDLE hFolderCache = 0, hFolderPacks = 0; struct QueueElem { CMStringW url; CMStringW fname; bool needext; QueueElem(const CMStringW &purl, const CMStringW &pfname, bool ne) : url(purl), fname(pfname), needext(ne) { } }; static mir_cs csQueue; static LIST dlQueue(10); static wchar_t g_wszCachePath[MAX_PATH]; static bool threadRunning; static bool InternetDownloadFile(const char *szUrl, const wchar_t *szDest, HNETLIBCONN &hHttpDwnl) { int result = 0xBADBAD; // initialize the netlib request MHttpRequest nlhr(REQUEST_GET); nlhr.flags = NLHRF_NODUMP | NLHRF_HTTP11 | NLHRF_PERSISTENT | NLHRF_REDIRECT; nlhr.m_szUrl = szUrl; nlhr.nlc = hHttpDwnl; // change the header so the plugin is pretended to be IE 6 + WinXP nlhr.AddHeader("User-Agent", NETLIB_USER_AGENT); nlhr.AddHeader("Connection", "close"); CreatePathToFileW(szDest); while (result == 0xBADBAD) { // download the page NLHR_PTR nlhrReply(Netlib_DownloadFile(hNetlibUser, &nlhr, szDest)); if (nlhrReply) { hHttpDwnl = nlhrReply->nlc; // if the recieved code is 200 OK if (nlhrReply->resultCode == 200) result = 0; else result = 1; } else { // retry hHttpDwnl = nullptr; } } return result == 0; } void __cdecl SmileyDownloadThread(void*) { Thread_SetName("SmileyAdd: SmileyDownloadThread"); bool needext = false; HNETLIBCONN hHttpDwnl = nullptr; while (!Miranda_IsTerminated()) { QueueElem *pItem = nullptr; { mir_cslock lck(csQueue); if (dlQueue.getCount()) { pItem = dlQueue[0]; dlQueue.remove(int(0)); } } if (pItem == nullptr) { SleepEx(3000, TRUE); continue; } if (_waccess(pItem->fname.c_str(), 0) != 0) { InternetDownloadFile(_T2A(pItem->url.c_str()), pItem->fname, hHttpDwnl); CMStringW fname(pItem->fname); if (pItem->needext) { fname += ProtoGetAvatarExtension(ProtoGetAvatarFileFormat(fname)); needext = true; } _wrename(pItem->fname.c_str(), fname.c_str()); } delete pItem; } for (auto &it : dlQueue) delete it; dlQueue.destroy(); Netlib_CloseHandle(hHttpDwnl); threadRunning = false; if (!Miranda_IsTerminated()) { if (needext) CallServiceSync(MS_SMILEYADD_RELOAD, 0, 0); else NotifyEventHooks(g_hevOptionsChanged, 0, 0); } } bool GetSmileyFile(CMStringW &url, const CMStringW &packstr) { uint8_t hash[MIR_SHA1_HASH_SIZE]; mir_sha1_hash((uint8_t*)url.c_str(), url.GetLength() * sizeof(wchar_t), hash); wchar_t wszHash[MIR_SHA1_HASH_SIZE * 2 + 1]; bin2hexW(hash, sizeof(hash), wszHash); CMStringW filename; filename.AppendFormat(L"%s\\%s\\", g_wszCachePath, packstr.c_str()); int pathpos = filename.GetLength(); MRegexp16 urlsplit(L".*/(.*)"); urlsplit.match(url); CMStringW urlFileName = urlsplit.getGroup(1); int iExtIdx = urlFileName.ReverseFind('.'); if (iExtIdx != -1) { CMStringW wszExt = urlFileName.Mid(iExtIdx); if (ProtoGetAvatarFormat(wszExt) == PA_FORMAT_UNKNOWN) iExtIdx = -1; else filename += urlFileName; } if (iExtIdx == -1) { filename += wszHash; filename += L".*"; } _wfinddata_t c_file; INT_PTR hFile = _wfindfirst(filename, &c_file); if (hFile > -1) { _findclose(hFile); filename.Truncate(pathpos); filename += c_file.name; url = filename; return false; } if (iExtIdx == -1) { filename.Truncate(pathpos); filename += wszHash; filename += L"."; } { mir_cslock lck(csQueue); dlQueue.insert(new QueueElem(url, filename, iExtIdx == -1)); } if (!threadRunning) { threadRunning = true; mir_forkthread(SmileyDownloadThread); } url = filename; return false; } int FolderChanged(WPARAM, LPARAM) { FoldersGetCustomPathW(hFolderCache, g_wszCachePath, MAX_PATH, L""); FoldersGetCustomPathW(hFolderPacks, g_plugin.wszDefaultPath, MAX_PATH, L"%miranda_path%"); size_t len = mir_wstrlen(g_plugin.wszDefaultPath); if (len && g_plugin.wszDefaultPath[len - 1] != '\\') mir_wstrcpy(g_plugin.wszDefaultPath + len, L"\\"); return 0; } void DownloadInit(void) { NETLIBUSER nlu = {}; nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS | NUF_NOHTTPSOPTION; nlu.szSettingsModule = MODULENAME; nlu.szDescriptiveName.a = MODULENAME; hNetlibUser = Netlib_RegisterUser(&nlu); hFolderPacks = FoldersRegisterCustomPathW(LPGEN("SmileyAdd"), LPGEN("Smiley packs' folder"), L"%miranda_path%"); if (hFolderPacks) { hFolderCache = FoldersRegisterCustomPathW(LPGEN("SmileyAdd"), LPGEN("Smiley cache"), MIRANDA_USERDATAW L"\\SmileyCache"); FolderChanged(0, 0); HookEvent(ME_FOLDERS_PATH_CHANGED, FolderChanged); } else { wcsncpy_s(g_wszCachePath, VARSW(L"%miranda_userdata%\\SmileyCache"), _TRUNCATE); wcsncpy_s(g_plugin.wszDefaultPath, VARSW(L"%miranda_path%\\"), _TRUNCATE); } } void DownloadClose(void) { Netlib_CloseHandle(hNetlibUser); }