diff options
Diffstat (limited to 'plugins/Svc_crshdmp/upload.cpp')
-rw-r--r-- | plugins/Svc_crshdmp/upload.cpp | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/plugins/Svc_crshdmp/upload.cpp b/plugins/Svc_crshdmp/upload.cpp new file mode 100644 index 0000000000..498b5cb2f6 --- /dev/null +++ b/plugins/Svc_crshdmp/upload.cpp @@ -0,0 +1,292 @@ +/*
+Miranda Crash Dumper Plugin
+Copyright (C) 2008 - 2012 Boris Krasnovskiy All Rights Reserved
+
+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 "utils.h"
+#include <m_netlib.h>
+
+HANDLE hNetlibUser;
+
+static void arrayToHex(BYTE* data, size_t datasz, char* res)
+{
+ char* resptr = res;
+ for (unsigned i=0; i<datasz ; i++)
+ {
+ const BYTE ch = data[i];
+
+ const char ch0 = (char)(ch >> 4);
+ *resptr++ = (char)((ch0 <= 9) ? ('0' + ch0) : (('a' - 10) + ch0));
+
+ const char ch1 = (char)(ch & 0xF);
+ *resptr++ = (char)((ch1 <= 9) ? ('0' + ch1) : (('a' - 10) + ch1));
+ }
+ *resptr = '\0';
+}
+
+void GetLoginStr(char* user, size_t szuser, char* pass)
+{
+ DBVARIANT dbv;
+
+ if (DBGetContactSettingString(NULL, PluginName, "Username", &dbv) == 0)
+ {
+ mir_snprintf(user, szuser, "%s", dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ else
+ user[0] = 0;
+
+ if (DBGetContactSettingString(NULL, PluginName, "Password", &dbv) == 0)
+ {
+ CallService(MS_DB_CRYPT_DECODESTRING, strlen(dbv.pszVal)+1, (LPARAM)dbv.pszVal);
+
+ mir_md5_byte_t hash[16];
+ mir_md5_state_t context;
+
+ mir_md5_init(&context);
+ mir_md5_append(&context, (BYTE*)dbv.pszVal, (int)strlen(dbv.pszVal));
+ mir_md5_finish(&context, hash);
+
+ arrayToHex(hash, sizeof(hash), pass);
+
+ DBFreeVariant(&dbv);
+ }
+ else
+ pass[0] = 0;
+}
+
+void OpenAuthUrl(const char* url)
+{
+ char user[64], pass[40];
+ GetLoginStr(user, sizeof(user), pass);
+
+ if (user[0] && pass[0])
+ {
+ char str[256];
+
+ mir_snprintf(str, sizeof(str), url, user);
+ char* eurl = (char*)CallService(MS_NETLIB_URLENCODE, 0, (LPARAM)str);
+
+ mir_snprintf(str, sizeof(str), "http://www.miranda-vi.org/cdlogin?name=%s&pass=%s&redir=%s", user, pass, eurl);
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM)str);
+ HeapFree(GetProcessHeap(), 0, eurl);
+ }
+ else
+ CallService(MS_UTILS_OPENURL, 1, (LPARAM)"http://www.miranda-vi.org/");
+}
+
+void CreateAuthString(char* auth)
+{
+ char user[64], pass[40];
+ GetLoginStr(user, sizeof(user), pass);
+
+ char str[110];
+ int len = mir_snprintf(str, sizeof(str), "%s:%s", user, pass);
+
+ strcpy(auth, "Basic ");
+ NETLIBBASE64 nlb = { auth+6, 250, (PBYTE)str, len };
+ CallService(MS_NETLIB_BASE64ENCODE, 0, LPARAM(&nlb));
+}
+
+
+bool InternetDownloadFile(const char *szUrl, VerTrnsfr* szReq)
+{
+ int result = 0xBADBAD;
+ char* szRedirUrl = NULL;
+ NETLIBHTTPREQUEST nlhr = {0};
+
+ // initialize the netlib request
+ nlhr.cbSize = sizeof(nlhr);
+ nlhr.requestType = REQUEST_POST;
+ nlhr.flags = NLHRF_HTTP11 | NLHRF_NODUMP;
+ nlhr.szUrl = (char*)szUrl;
+
+ nlhr.headersCount = 6;
+ nlhr.headers=(NETLIBHTTPHEADER*)mir_alloc(sizeof(NETLIBHTTPHEADER)*nlhr.headersCount);
+ nlhr.headers[0].szName = "Connection";
+ nlhr.headers[0].szValue = "close";
+ nlhr.headers[1].szName = "Cache-Control";
+ nlhr.headers[1].szValue = "no-cache";
+ nlhr.headers[2].szName = "Pragma";
+ nlhr.headers[2].szValue = "no-cache";
+ nlhr.headers[3].szName = "Content-Type";
+ nlhr.headers[3].szValue = "text/plain; charset=utf-8";
+ nlhr.headers[4].szName = "AutoUpload";
+ nlhr.headers[4].szValue = (char*)(szReq->autot ? "1" : "0");
+ nlhr.headers[5].szName = "Authorization";
+
+ char auth[256];
+ CreateAuthString(auth);
+ nlhr.headers[5].szValue = auth;
+
+ nlhr.pData = szReq->buf;
+ nlhr.dataLength = (int)strlen(szReq->buf);
+
+ while (result == 0xBADBAD)
+ {
+ // download the page
+ NETLIBHTTPREQUEST *nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION,
+ (WPARAM)hNetlibUser,(LPARAM)&nlhr);
+
+ if (nlhrReply)
+ {
+ int i;
+
+ // if the recieved code is 200 OK
+ switch(nlhrReply->resultCode)
+ {
+ case 200:
+ if (DBGetContactSettingByte(NULL, PluginName, "UploadChanged", 0))
+ ProcessVIHash(true);
+
+ for (i=nlhrReply->headersCount; i--; )
+ {
+ if (_stricmp(nlhrReply->headers[i].szName, "OldPlugins") == 0)
+ {
+ i = atoi(nlhrReply->headers[i].szValue);
+ break;
+ }
+ }
+
+ ShowMessage(1, TranslateT("VersionInfo upload successful,\n %d old plugins"), i);
+ result = 0;
+ break;
+
+ case 401:
+ ShowMessage(0, TranslateT("Cannot upload VersionInfo. Incorrect username or password"));
+ result = 1;
+ break;
+
+ case 510:
+ ShowMessage(0, TranslateT("Cannot upload VersionInfo. User is banned"));
+ result = 1;
+ break;
+
+ case 511:
+ ShowMessage(0, TranslateT("Cannot upload VersionInfo. Daily upload limit exceeded"));
+ result = 1;
+ break;
+
+ case 301:
+ case 302:
+ case 307:
+ // get the url for the new location and save it to szInfo
+ // look for the reply header "Location"
+ for (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;
+ }
+ }
+ break;
+
+ default:
+ result = 1;
+ ShowMessage(0, TranslateT("Cannot upload VersionInfo. Unknown error"));
+ }
+ }
+ else
+ {
+ result = 1;
+ ShowMessage(0, TranslateT("Cannot upload VersionInfo. Host unreachable."));
+ }
+
+ CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT,0,(LPARAM)nlhrReply);
+ }
+
+ mir_free(szRedirUrl);
+ mir_free(nlhr.headers);
+
+ return result == 0;
+}
+
+void __cdecl VersionInfoUploadThread(void* arg)
+{
+ VerTrnsfr* trn = (VerTrnsfr*)arg;
+ InternetDownloadFile("http://www.miranda-vi.org/uploadpost", trn);
+ mir_free(trn->buf);
+ mir_free(trn);
+}
+
+
+void UploadInit(void)
+{
+ NETLIBUSER nlu = {0};
+ nlu.cbSize = sizeof(nlu);
+ nlu.flags = NUF_OUTGOING | NUF_HTTPCONNS | NUF_NOHTTPSOPTION | NUF_TCHAR;
+ nlu.szSettingsModule = (char*)PluginName;
+ nlu.ptszDescriptiveName = TranslateT("Crash Dumper HTTP connections");
+ hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
+}
+
+void UploadClose(void)
+{
+ Netlib_CloseHandle(hNetlibUser);
+}
+
+bool ProcessVIHash(bool store)
+{
+ bkstring buffer;
+ buffer.reserve(0x1800);
+ PrintVersionInfo(buffer, 0);
+
+ mir_md5_byte_t hash[16];
+ mir_md5_state_t context;
+
+ mir_md5_init(&context);
+ mir_md5_append(&context, (PBYTE)buffer.c_str(), (int)buffer.sizebytes());
+ mir_md5_finish(&context, hash);
+
+ char hashstr[40];
+ arrayToHex(hash, sizeof(hash), hashstr);
+
+ bool result;
+ if (store)
+ {
+ DBWriteContactSettingString(NULL, PluginName, "VIHash", hashstr);
+ result = true;
+ }
+ else
+ {
+ DBVARIANT dbv;
+ if (DBGetContactSettingString(NULL, PluginName, "VIHash", &dbv) == 0)
+ {
+ result = strcmp(hashstr, dbv.pszVal) == 0;
+ DBFreeVariant(&dbv);
+ }
+ else
+ result = false;
+ }
+ return result;
+}
|