summaryrefslogtreecommitdiff
path: root/plugins/SmileyAdd/download.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/SmileyAdd/download.cpp')
-rw-r--r--plugins/SmileyAdd/download.cpp292
1 files changed, 292 insertions, 0 deletions
diff --git a/plugins/SmileyAdd/download.cpp b/plugins/SmileyAdd/download.cpp
new file mode 100644
index 0000000000..39de234634
--- /dev/null
+++ b/plugins/SmileyAdd/download.cpp
@@ -0,0 +1,292 @@
+/*
+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 <http://www.gnu.org/licenses/>.
+*/
+
+#include "general.h"
+#include "m_smileyadd.h"
+#include "m_folders.h"
+
+extern HANDLE hEvent1;
+HANDLE hNetlibUser;
+static HANDLE hFolder, hFolderHook;
+
+struct QueueElem
+{
+ bkstring url;
+ bkstring fname;
+ bool needext;
+
+ QueueElem(bkstring& purl, bkstring& pfname, bool ne)
+ : url(purl), fname(pfname), needext(ne) {}
+};
+
+static HANDLE g_hDlMutex;
+static OBJLIST<QueueElem> dlQueue(10);
+
+static TCHAR cachepath[MAX_PATH];
+static bool threadRunning;
+
+bool InternetDownloadFile(const char *szUrl, char* szDest, HANDLE &hHttpDwnl)
+{
+ int result = 0xBADBAD;
+ char* szRedirUrl = NULL;
+ NETLIBHTTPREQUEST nlhr = {0};
+
+ // initialize the netlib request
+ nlhr.cbSize = sizeof(nlhr);
+ nlhr.requestType = REQUEST_GET;
+ nlhr.flags = NLHRF_NODUMP;
+ nlhr.szUrl = (char*)szUrl;
+ nlhr.nlc = hHttpDwnl;
+
+ if (CallService(MS_SYSTEM_GETVERSION, 0, 0) >= PLUGIN_MAKE_VERSION(0,9,0,5))
+ nlhr.flags |= NLHRF_HTTP11 | NLHRF_PERSISTENT | NLHRF_REDIRECT;
+
+ // change the header so the plugin is pretended to be IE 6 + WinXP
+ nlhr.headersCount = 2;
+ nlhr.headers=(NETLIBHTTPHEADER*)alloca(sizeof(NETLIBHTTPHEADER)*nlhr.headersCount);
+ nlhr.headers[0].szName = "User-Agent";
+ nlhr.headers[0].szValue = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
+ nlhr.headers[1].szName = "Connection";
+ nlhr.headers[1].szValue = "close";
+
+ while (result == 0xBADBAD)
+ {
+ // download the page
+ NETLIBHTTPREQUEST *nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION,
+ (WPARAM)hNetlibUser,(LPARAM)&nlhr);
+
+ if (nlhrReply)
+ {
+ hHttpDwnl = nlhrReply->nlc;
+ // if the recieved code is 200 OK
+ if(nlhrReply->resultCode == 200)
+ {
+ char* delim = strrchr(szDest, '\\');
+ if (delim) *delim = '\0';
+ CallService(MS_UTILS_CREATEDIRTREE, 0, (LPARAM)szDest);
+ if (delim) *delim = '\\';
+ int res = -1;
+ int fh = _open(szDest, _O_BINARY | _O_WRONLY | _O_CREAT, _S_IREAD | _S_IWRITE);
+ if (fh != -1)
+ {
+ res = _write(fh, nlhrReply->pData, nlhrReply->dataLength);
+ _close(fh);
+ }
+ if (res < 0)
+ remove(szDest);
+ else
+ result = 0;
+ }
+ // if the recieved code is 302 Moved, Found, etc
+ // workaround for url forwarding
+ else if(nlhrReply->resultCode == 302 || nlhrReply->resultCode == 301 || nlhrReply->resultCode == 307) // page moved
+ {
+ // get the url for the new location and save it to szInfo
+ // look for the reply header "Location"
+ for (int i=0; i<nlhrReply->headersCount; i++)
+ {
+ if (!strcmp(nlhrReply->headers[i].szName, "Location"))
+ {
+ size_t rlen = 0;
+ if (nlhrReply->headers[i].szValue[0] == '/')
+ {
+ const char* szPath;
+ const char* szPref = strstr(szUrl, "://");
+ szPref = szPref ? szPref + 3 : szUrl;
+ szPath = strchr(szPref, '/');
+ rlen = szPath != NULL ? szPath - szUrl : strlen(szUrl);
+ }
+
+ szRedirUrl = (char*)mir_realloc(szRedirUrl,
+ rlen + strlen(nlhrReply->headers[i].szValue)*3 + 1);
+
+ strncpy(szRedirUrl, szUrl, rlen);
+ strcpy(szRedirUrl+rlen, nlhrReply->headers[i].szValue);
+
+ nlhr.szUrl = szRedirUrl;
+ break;
+ }
+ }
+ }
+ else
+ result = 1;
+ }
+ else
+ {
+ hHttpDwnl = NULL;
+ result = 1;
+ }
+
+ CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT,0,(LPARAM)nlhrReply);
+ }
+
+ mir_free(szRedirUrl);
+
+ return result == 0;
+}
+
+
+void __cdecl SmileyDownloadThread(void*)
+{
+ bool needext = false;
+ HANDLE hHttpDwnl = NULL;
+ WaitForSingleObject(g_hDlMutex, 3000);
+ while (!Miranda_Terminated() && dlQueue.getCount())
+ {
+ ReleaseMutex(g_hDlMutex);
+ if (_taccess(dlQueue[0].fname.c_str(), 0) != 0)
+ {
+ InternetDownloadFile(T2A_SM(dlQueue[0].url.c_str()), T2A_SM(dlQueue[0].fname.c_str()), hHttpDwnl);
+ WaitForSingleObject(g_hDlMutex, 3000);
+
+ bkstring fname(dlQueue[0].fname);
+ if (dlQueue[0].needext) { fname += GetImageExt(fname); needext = true; }
+ _trename(dlQueue[0].fname.c_str(), fname.c_str());
+ }
+ else
+ WaitForSingleObject(g_hDlMutex, 3000);
+
+ dlQueue.remove(0);
+ }
+ dlQueue.destroy();
+ if (hHttpDwnl) Netlib_CloseHandle(hHttpDwnl);
+ threadRunning = false;
+ ReleaseMutex(g_hDlMutex);
+
+ if (!Miranda_Terminated())
+ {
+ if (needext)
+ CallServiceSync(MS_SMILEYADD_RELOAD, 0, 0);
+ else
+ NotifyEventHooks(hEvent1, 0, 0);
+ }
+}
+
+
+bool GetSmileyFile(bkstring& url, const bkstring& packstr)
+{
+ _TPattern * urlsplit = _TPattern::compile(_T(".*/(.*)"));
+ _TMatcher * m0 = urlsplit->createTMatcher(url);
+
+ m0->findFirstMatch();
+
+ bkstring filename;
+ filename.appendfmt(_T("%s\\%s\\"), cachepath, packstr.c_str());
+ size_t pathpos = filename.size();
+ filename += m0->getGroup(1);
+
+ delete m0;
+ delete urlsplit;
+
+ bool needext = filename.find('.') == filename.npos;
+ if (needext) filename += _T(".*");
+
+ _tfinddata_t c_file;
+ INT_PTR hFile = _tfindfirst((TCHAR*)filename.c_str(), &c_file);
+ if (hFile > -1)
+ {
+ _findclose(hFile);
+ filename.erase(pathpos);
+ filename += c_file.name;
+ url = filename;
+ return false;
+ }
+ if (needext) filename.erase(filename.size()-1);
+
+ WaitForSingleObject(g_hDlMutex, 3000);
+ dlQueue.insert(new QueueElem(url, filename, needext));
+ ReleaseMutex(g_hDlMutex);
+
+ if (!threadRunning)
+ {
+ threadRunning = true;
+ mir_forkthread(SmileyDownloadThread, NULL);
+ }
+
+ url = filename;
+ return false;
+}
+
+void GetDefaultSmileyCacheFolder(TCHAR* szPath, size_t cbLen)
+{
+ TCHAR *tmpPath = Utils_ReplaceVarsT(_T("%miranda_userdata%\\SmileyCache"));
+ if ((INT_PTR)tmpPath != CALLSERVICE_NOTFOUND)
+ {
+ mir_sntprintf(szPath, cbLen, _T("%s"), tmpPath);
+ mir_free(tmpPath);
+ }
+ else
+ {
+ char dbPath[MAX_PATH];
+ CallService(MS_DB_GETPROFILEPATH, SIZEOF(dbPath), (LPARAM)dbPath);
+ mir_sntprintf(szPath, cbLen, _T("%s\\SmileyCache"), A2T_SM(dbPath));
+ }
+}
+
+int FolderChanged(WPARAM, LPARAM)
+{
+ FOLDERSGETDATA fgd = {0};
+ fgd.cbSize = sizeof(FOLDERSGETDATA);
+ fgd.nMaxPathSize = SIZEOF(cachepath);
+ fgd.szPathT = cachepath;
+ if (CallService(MS_FOLDERS_GET_PATH, (WPARAM) hFolder, (LPARAM) &fgd))
+ {
+ GetDefaultSmileyCacheFolder(cachepath, SIZEOF(cachepath));
+ }
+
+ return 0;
+}
+
+void GetSmileyCacheFolder(void)
+{
+ TCHAR defaultPath[MAX_PATH];
+
+ GetDefaultSmileyCacheFolder(defaultPath, SIZEOF(defaultPath));
+
+ FOLDERSDATA fd = {0};
+ fd.cbSize = sizeof(FOLDERSDATA);
+ strcpy(fd.szSection, "SmileyAdd");
+ strcpy(fd.szName,"Smiley Cache");
+ fd.szFormatT = defaultPath;
+ fd.flags = FF_TCHAR;
+ hFolder = (HANDLE)CallService(MS_FOLDERS_REGISTER_PATH, 0, (LPARAM) &fd);
+
+ FolderChanged(0, 0);
+
+ hFolderHook = HookEvent(ME_FOLDERS_PATH_CHANGED, FolderChanged);
+}
+
+void DownloadInit(void)
+{
+ NETLIBUSER nlu = {0};
+ nlu.cbSize = sizeof(nlu);
+ nlu.flags = NUF_OUTGOING|NUF_HTTPCONNS|NUF_NOHTTPSOPTION;
+ nlu.szSettingsModule = "SmileyAdd";
+ nlu.szDescriptiveName = Translate("SmileyAdd HTTP connections");
+ hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
+
+ GetSmileyCacheFolder();
+ g_hDlMutex = CreateMutex(NULL, FALSE, NULL);
+}
+
+void DownloadClose(void)
+{
+ UnhookEvent(hFolderHook);
+ CloseHandle(g_hDlMutex);
+ Netlib_CloseHandle(hNetlibUser);
+}