From a5d5de36daa8a810784f0e14a40ccb72bf6c8faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20P=C3=B6sel?= Date: Sat, 3 Dec 2016 10:11:26 +0100 Subject: SkypeWeb: Decode numeric html entities (fixes #639) Code taken from 'utils\std_string_utils.cpp'. We should combine both codes and move the better / more effective code to the mentioned file so more plugins can share it. --- protocols/SkypeWeb/src/skype_utils.cpp | 1194 +++++++++++++++++--------------- 1 file changed, 621 insertions(+), 573 deletions(-) (limited to 'protocols/SkypeWeb/src/skype_utils.cpp') diff --git a/protocols/SkypeWeb/src/skype_utils.cpp b/protocols/SkypeWeb/src/skype_utils.cpp index 41d01665b8..5bdc3eab4a 100644 --- a/protocols/SkypeWeb/src/skype_utils.cpp +++ b/protocols/SkypeWeb/src/skype_utils.cpp @@ -1,574 +1,622 @@ -/* -Copyright (c) 2015-16 Miranda NG project (http://miranda-ng.org) - -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" - -#pragma warning(disable:4566) - -time_t CSkypeProto::IsoToUnixTime(const char *stamp) -{ - char date[9]; - int i, y; - - if (stamp == NULL) - return 0; - - char *p = NEWSTR_ALLOCA(stamp); - - // skip '-' chars - int si = 0, sj = 0; - while (true) { - if (p[si] == '-') - si++; - else if (!(p[sj++] = p[si++])) - break; - } - - // Get the date part - for (i = 0; *p != '\0' && i < 8 && isdigit(*p); p++, i++) - date[i] = *p; - - // Parse year - if (i == 6) { - // 2-digit year (1970-2069) - y = (date[0] - '0') * 10 + (date[1] - '0'); - if (y < 70) y += 100; - } - else if (i == 8) { - // 4-digit year - y = (date[0] - '0') * 1000 + (date[1] - '0') * 100 + (date[2] - '0') * 10 + date[3] - '0'; - y -= 1900; - } - else return 0; - - struct tm timestamp; - timestamp.tm_year = y; - - // Parse month - timestamp.tm_mon = (date[i - 4] - '0') * 10 + date[i - 3] - '0' - 1; - - // Parse date - timestamp.tm_mday = (date[i - 2] - '0') * 10 + date[i - 1] - '0'; - - // Skip any date/time delimiter - for (; *p != '\0' && !isdigit(*p); p++); - - // Parse time - if (sscanf(p, "%d:%d:%d", ×tamp.tm_hour, ×tamp.tm_min, ×tamp.tm_sec) != 3) - return (time_t)0; - - timestamp.tm_isdst = 0; // DST is already present in _timezone below - time_t t = mktime(×tamp); - - _tzset(); - t -= _timezone; - return (t >= 0) ? t : 0; -} - -struct HtmlEntity -{ - const char *entity; - const char *symbol; -}; - -const HtmlEntity htmlEntities[] = -{ - { "AElig", "\u00C6" }, - { "Aacute", "\u00C1" }, - { "Acirc", "\u00C2" }, - { "Agrave", "\u00C0" }, - { "Alpha", "\u0391" }, - { "Aring", "\u00C5" }, - { "Atilde", "\u00C3" }, - { "Auml", "\u00C4" }, - { "Beta", "\u0392" }, - { "Ccedil", "\u00C7" }, - { "Chi", "\u03A7" }, - { "Dagger", "‡" }, - { "Delta", "\u0394" }, - { "ETH", "\u00D0" }, - { "Eacute", "\u00C9" }, - { "Ecirc", "\u00CA" }, - { "Egrave", "\u00C8" }, - { "Epsilon", "\u0395" }, - { "Eta", "\u0397" }, - { "Euml", "\u00CB" }, - { "Gamma", "\u0393" }, - { "Iacute", "\u00CD" }, - { "Icirc", "\u00CE" }, - { "Igrave", "\u00CC" }, - { "Iota", "\u0399" }, - { "Iuml", "\u00CF" }, - { "Kappa", "\u039A" }, - { "Lambda", "\u039B" }, - { "Mu", "\u039C" }, - { "Ntilde", "\u00D1" }, - { "Nu", "\u039D" }, - { "OElig", "\u0152" }, - { "Oacute", "\u00D3" }, - { "Ocirc", "\u00D4" }, - { "Ograve", "\u00D2" }, - { "Omega", "\u03A9" }, - { "Omicron", "\u039F" }, - { "Oslash", "\u00D8" }, - { "Otilde", "\u00D5" }, - { "Ouml", "\u00D6" }, - { "Phi", "\u03A6" }, - { "Pi", "\u03A0" }, - { "Prime", "\u2033" }, - { "Psi", "\u03A8" }, - { "Rho", "\u03A1" }, - { "Scaron", "Š" }, - { "Sigma", "Σ" }, - { "THORN", "Þ" }, - { "Tau", "Τ" }, - { "Theta", "Θ" }, - { "Uacute", "Ú" }, - { "Ucirc", "Û" }, - { "Ugrave", "Ù" }, - { "Upsilon", "Υ" }, - { "Uuml", "Ü" }, - { "Xi", "Ξ" }, - { "Yacute", "Ý" }, - { "Yuml", "Ÿ" }, - { "Zeta", "Ζ" }, - { "aacute", "á" }, - { "acirc", "â" }, - { "acute", "´" }, - { "aelig", "æ" }, - { "agrave", "à" }, - { "alefsym", "ℵ" }, - { "alpha", "α" }, - { "amp", "&" }, - { "and", "∧" }, - { "ang", "∠" }, - { "apos", "'" }, - { "aring", "å" }, - { "asymp", "≈" }, - { "atilde", "ã" }, - { "auml", "ä" }, - { "bdquo", "„" }, - { "beta", "β" }, - { "brvbar", "¦" }, - { "bull", "•" }, - { "cap", "∩" }, - { "ccedil", "ç" }, - { "cedil", "¸" }, - { "cent", "¢" }, - { "chi", "χ" }, - { "circ", "ˆ" }, - { "clubs", "♣" }, - { "cong", "≅" }, - { "copy", "©" }, - { "crarr", "↵" }, - { "cup", "∪" }, - { "curren", "¤" }, - { "dArr", "⇓" }, - { "dagger", "†" }, - { "darr", "↓" }, - { "deg", "°" }, - { "delta", "δ" }, - { "diams", "♦" }, - { "divide", "÷" }, - { "eacute", "é" }, - { "ecirc", "ê" }, - { "egrave", "è" }, - { "empty", "∅" }, - { "emsp", " " }, - { "ensp", " " }, - { "epsilon", "ε" }, - { "equiv", "≡" }, - { "eta", "η" }, - { "eth", "ð" }, - { "euml", "ë" }, - { "euro", "€" }, - { "exist", "∃" }, - { "fnof", "ƒ" }, - { "forall", "∀" }, - { "frac12", "½" }, - { "frac14", "¼" }, - { "frac34", "¾" }, - { "frasl", "⁄" }, - { "gamma", "γ" }, - { "ge", "≥" }, - { "gt", ">" }, - { "hArr", "⇔" }, - { "harr", "↔" }, - { "hearts", "♥" }, - { "hellip", "…" }, - { "iacute", "í" }, - { "icirc", "î" }, - { "iexcl", "¡" }, - { "igrave", "ì" }, - { "image", "ℑ" }, - { "infin", "∞" }, - { "int", "∫" }, - { "iota", "ι" }, - { "iquest", "¿" }, - { "isin", "∈" }, - { "iuml", "ï" }, - { "kappa", "κ" }, - { "lArr", "⇐" }, - { "lambda", "λ" }, - { "lang", "〈" }, - { "laquo", "«" }, - { "larr", "←" }, - { "lceil", "⌈" }, - { "ldquo", "“" }, - { "le", "≤" }, - { "lfloor", "⌊" }, - { "lowast", "∗" }, - { "loz", "◊" }, - { "lrm", "\xE2\x80\x8E" }, - { "lsaquo", "‹" }, - { "lsquo", "‘" }, - { "lt", "<" }, - { "macr", "¯" }, - { "mdash", "—" }, - { "micro", "µ" }, - { "middot", "·" }, - { "minus", "−" }, - { "mu", "μ" }, - { "nabla", "∇" }, - { "nbsp", " " }, - { "ndash", "–" }, - { "ne", "≠" }, - { "ni", "∋" }, - { "not", "¬" }, - { "notin", "∉" }, - { "nsub", "⊄" }, - { "ntilde", "ñ" }, - { "nu", "ν" }, - { "oacute", "ó" }, - { "ocirc", "ô" }, - { "oelig", "œ" }, - { "ograve", "ò" }, - { "oline", "‾" }, - { "omega", "ω" }, - { "omicron", "ο" }, - { "oplus", "⊕" }, - { "or", "∨" }, - { "ordf", "ª" }, - { "ordm", "º" }, - { "oslash", "ø" }, - { "otilde", "õ" }, - { "otimes", "⊗" }, - { "ouml", "ö" }, - { "para", "¶" }, - { "part", "∂" }, - { "permil", "‰" }, - { "perp", "⊥" }, - { "phi", "φ" }, - { "pi", "π" }, - { "piv", "ϖ" }, - { "plusmn", "±" }, - { "pound", "£" }, - { "prime", "′" }, - { "prod", "∏" }, - { "prop", "∝" }, - { "psi", "ψ" }, - { "quot", "\"" }, - { "rArr", "⇒" }, - { "radic", "√" }, - { "rang", "〉" }, - { "raquo", "»" }, - { "rarr", "→" }, - { "rceil", "⌉" }, - { "rdquo", "”" }, - { "real", "ℜ" }, - { "reg", "®" }, - { "rfloor", "⌋" }, - { "rho", "ρ" }, - { "rlm", "\xE2\x80\x8F" }, - { "rsaquo", "›" }, - { "rsquo", "’" }, - { "sbquo", "‚" }, - { "scaron", "š" }, - { "sdot", "⋅" }, - { "sect", "§" }, - { "shy", "\xC2\xAD" }, - { "sigma", "σ" }, - { "sigmaf", "ς" }, - { "sim", "∼" }, - { "spades", "♠" }, - { "sub", "⊂" }, - { "sube", "⊆" }, - { "sum", "∑" }, - { "sup", "⊃" }, - { "sup1", "¹" }, - { "sup2", "²" }, - { "sup3", "³" }, - { "supe", "⊇" }, - { "szlig", "ß" }, - { "tau", "τ" }, - { "there4", "∴" }, - { "theta", "θ" }, - { "thetasym", "ϑ" }, - { "thinsp", " " }, - { "thorn", "þ" }, - { "tilde", "˜" }, - { "times", "×" }, - { "trade", "™" }, - { "uArr", "⇑" }, - { "uacute", "ú" }, - { "uarr", "↑" }, - { "ucirc", "û" }, - { "ugrave", "ù" }, - { "uml", "¨" }, - { "upsih", "ϒ" }, - { "upsilon", "υ" }, - { "uuml", "ü" }, - { "weierp", "℘" }, - { "xi", "ξ" }, - { "yacute", "ý" }, - { "yen", "¥" }, - { "yuml", "ÿ" }, - { "zeta", "ζ" }, - { "zwj", "\xE2\x80\x8D" }, - { "zwnj", "\xE2\x80\x8C" } -}; - -char *CSkypeProto::RemoveHtml(const char *text) -{ - std::string new_string = ""; - std::string data = text; - - for (std::string::size_type i = 0; i < data.length(); i++) - { - if (data.at(i) == '<') - { - i = data.find(">", i); - if (i == std::string::npos) - break; - - continue; - } - - if (data.at(i) == '&') { - std::string::size_type begin = i; - i = data.find(";", i); - if (i == std::string::npos) { - i = begin; - } - else { - std::string entity = data.substr(begin + 1, i - begin - 1); - - bool found = false; - for (int j = 0; j < _countof(htmlEntities); j++) - { - if (!mir_strcmpi(entity.c_str(), htmlEntities[j].entity)) - { - new_string += htmlEntities[j].symbol; - found = true; - break; - } - } - - if (found) - continue; - else - i = begin; - } - } - - new_string += data.at(i); - } - - return mir_strdup(new_string.c_str()); -} - -const char *CSkypeProto::MirandaToSkypeStatus(int status) -{ - switch (status) - { - case ID_STATUS_AWAY: - return "Away"; - - case ID_STATUS_DND: - return "Busy"; - - case ID_STATUS_IDLE: - return "Idle"; - - case ID_STATUS_INVISIBLE: - return "Hidden"; - } - return "Online"; -} - -int CSkypeProto::SkypeToMirandaStatus(const char *status) -{ - if (!mir_strcmpi(status, "Online")) - return ID_STATUS_ONLINE; - else if (!mir_strcmpi(status, "Hidden")) - return ID_STATUS_INVISIBLE; - else if (!mir_strcmpi(status, "Away")) - return ID_STATUS_AWAY; - else if (!mir_strcmpi(status, "Idle")) - return /*ID_STATUS_IDLE*/ID_STATUS_AWAY; - else if (!mir_strcmpi(status, "Busy")) - return ID_STATUS_DND; - else - return ID_STATUS_OFFLINE; -} - -bool CSkypeProto::IsFileExists(std::wstring path) -{ - return _waccess(path.c_str(), 0) == 0; -} - -// url parsing - -CMStringA CSkypeProto::ParseUrl(const char *url, const char *token) -{ - const char *start = strstr(url, token); - if (start == NULL) - return CMStringA(); - - start = start + mir_strlen(token); - const char *end = strchr(start, '/'); - if (end == NULL) - return CMStringA(start); - return CMStringA(start, end - start); -} - -CMStringA CSkypeProto::GetStringChunk(const char *haystack, const char *start, const char *end) -{ - const char *sstart = strstr(haystack, start); - if (sstart == NULL) - return CMStringA(); - - sstart = sstart + mir_strlen(start); - const char *send = strstr(sstart, end); - if (send == NULL) - return CMStringA(sstart); - return CMStringA(sstart, send - sstart); -} - -CMStringA CSkypeProto::UrlToSkypename(const char *url) -{ - CMStringA szResult; - - if (strstr(url, "/1:")) - szResult = ParseUrl(url, "/1:"); - else if (strstr(url, "/8:")) - szResult = ParseUrl(url, "/8:"); - else if (strstr(url, "/19:")) - szResult = ParseUrl(url, "/19:"); - - return szResult; -} - -CMStringA CSkypeProto::GetServerFromUrl(const char *url) -{ - return ParseUrl(url, "://"); -} - -INT_PTR CSkypeProto::ParseSkypeUriService(WPARAM, LPARAM lParam) -{ - wchar_t *arg = (wchar_t *)lParam; - if (arg == NULL) - return 1; - - // skip leading prefix - wchar_t szUri[1024]; - wcsncpy_s(szUri, arg, _TRUNCATE); - wchar_t *szJid = wcschr(szUri, ':'); - if (szJid == NULL) - return 1; - - // empty jid? - if (!*szJid) - return 1; - - // command code - wchar_t *szCommand = szJid; - szCommand = wcschr(szCommand, '?'); - if (szCommand) - *(szCommand++) = 0; - - // parameters - wchar_t *szSecondParam = szCommand ? wcschr(szCommand, '&') : NULL; - if (szSecondParam) - *(szSecondParam++) = 0; - - // no command or message command - if (!szCommand || (szCommand && !mir_wstrcmpi(szCommand, L"chat"))) - { - if (szSecondParam) - { - wchar_t *szChatId = wcsstr(szSecondParam, L"id="); - if (szChatId) - { - szChatId += 5; - StartChatRoom(szChatId, szChatId); - return 0; - } - } - MCONTACT hContact = AddContact(_T2A(szJid), true); - CallService(MS_MSG_SENDMESSAGE, (WPARAM)hContact, NULL); - return 0; - } - else if (!mir_wstrcmpi(szCommand, L"call")) - { - MCONTACT hContact = AddContact(_T2A(szJid), true); - NotifyEventHooks(g_hCallEvent, (WPARAM)hContact, (LPARAM)0); - return 0; - } - else if (!mir_wstrcmpi(szCommand, L"userinfo")){ return 0; } - else if (!mir_wstrcmpi(szCommand, L"add")) - { - MCONTACT hContact = FindContact(_T2A(szJid)); - if (hContact == NULL) - { - PROTOSEARCHRESULT psr = { 0 }; - psr.cbSize = sizeof(psr); - psr.id.w = mir_wstrdup(szJid); - psr.nick.w = mir_wstrdup(szJid); - psr.flags = PSR_UNICODE; - - ADDCONTACTSTRUCT acs = { 0 }; - acs.handleType = HANDLE_SEARCHRESULT; - acs.szProto = m_szModuleName; - acs.psr = &psr; - - CallService(MS_ADDCONTACT_SHOW, 0, (LPARAM)&acs); - } - return 0; - } - if (!mir_wstrcmpi(szCommand, L"sendfile")) - { - MCONTACT hContact = AddContact(_T2A(szJid), true); - CallService(MS_FILE_SENDFILE, hContact, NULL); - return 1; - } - if (!mir_wstrcmpi(szCommand, L"voicemail")) - { - return 1; - } - return 1; -} - -INT_PTR CSkypeProto::GlobalParseSkypeUriService(WPARAM wParam, LPARAM lParam) -{ - mir_cslock lck(accountsLock); - for (int i = 0; i < Accounts.getCount(); i++) - if (Accounts[i]->IsOnline()) - return Accounts[i]->ParseSkypeUriService(wParam, lParam); - - return 1; +/* +Copyright (c) 2015-16 Miranda NG project (http://miranda-ng.org) + +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" + +#pragma warning(disable:4566) + +time_t CSkypeProto::IsoToUnixTime(const char *stamp) +{ + char date[9]; + int i, y; + + if (stamp == NULL) + return 0; + + char *p = NEWSTR_ALLOCA(stamp); + + // skip '-' chars + int si = 0, sj = 0; + while (true) { + if (p[si] == '-') + si++; + else if (!(p[sj++] = p[si++])) + break; + } + + // Get the date part + for (i = 0; *p != '\0' && i < 8 && isdigit(*p); p++, i++) + date[i] = *p; + + // Parse year + if (i == 6) { + // 2-digit year (1970-2069) + y = (date[0] - '0') * 10 + (date[1] - '0'); + if (y < 70) y += 100; + } + else if (i == 8) { + // 4-digit year + y = (date[0] - '0') * 1000 + (date[1] - '0') * 100 + (date[2] - '0') * 10 + date[3] - '0'; + y -= 1900; + } + else return 0; + + struct tm timestamp; + timestamp.tm_year = y; + + // Parse month + timestamp.tm_mon = (date[i - 4] - '0') * 10 + date[i - 3] - '0' - 1; + + // Parse date + timestamp.tm_mday = (date[i - 2] - '0') * 10 + date[i - 1] - '0'; + + // Skip any date/time delimiter + for (; *p != '\0' && !isdigit(*p); p++); + + // Parse time + if (sscanf(p, "%d:%d:%d", ×tamp.tm_hour, ×tamp.tm_min, ×tamp.tm_sec) != 3) + return (time_t)0; + + timestamp.tm_isdst = 0; // DST is already present in _timezone below + time_t t = mktime(×tamp); + + _tzset(); + t -= _timezone; + return (t >= 0) ? t : 0; +} + +struct HtmlEntity +{ + const char *entity; + const char *symbol; +}; + +const HtmlEntity htmlEntities[] = +{ + { "AElig", "\u00C6" }, + { "Aacute", "\u00C1" }, + { "Acirc", "\u00C2" }, + { "Agrave", "\u00C0" }, + { "Alpha", "\u0391" }, + { "Aring", "\u00C5" }, + { "Atilde", "\u00C3" }, + { "Auml", "\u00C4" }, + { "Beta", "\u0392" }, + { "Ccedil", "\u00C7" }, + { "Chi", "\u03A7" }, + { "Dagger", "‡" }, + { "Delta", "\u0394" }, + { "ETH", "\u00D0" }, + { "Eacute", "\u00C9" }, + { "Ecirc", "\u00CA" }, + { "Egrave", "\u00C8" }, + { "Epsilon", "\u0395" }, + { "Eta", "\u0397" }, + { "Euml", "\u00CB" }, + { "Gamma", "\u0393" }, + { "Iacute", "\u00CD" }, + { "Icirc", "\u00CE" }, + { "Igrave", "\u00CC" }, + { "Iota", "\u0399" }, + { "Iuml", "\u00CF" }, + { "Kappa", "\u039A" }, + { "Lambda", "\u039B" }, + { "Mu", "\u039C" }, + { "Ntilde", "\u00D1" }, + { "Nu", "\u039D" }, + { "OElig", "\u0152" }, + { "Oacute", "\u00D3" }, + { "Ocirc", "\u00D4" }, + { "Ograve", "\u00D2" }, + { "Omega", "\u03A9" }, + { "Omicron", "\u039F" }, + { "Oslash", "\u00D8" }, + { "Otilde", "\u00D5" }, + { "Ouml", "\u00D6" }, + { "Phi", "\u03A6" }, + { "Pi", "\u03A0" }, + { "Prime", "\u2033" }, + { "Psi", "\u03A8" }, + { "Rho", "\u03A1" }, + { "Scaron", "Š" }, + { "Sigma", "Σ" }, + { "THORN", "Þ" }, + { "Tau", "Τ" }, + { "Theta", "Θ" }, + { "Uacute", "Ú" }, + { "Ucirc", "Û" }, + { "Ugrave", "Ù" }, + { "Upsilon", "Υ" }, + { "Uuml", "Ü" }, + { "Xi", "Ξ" }, + { "Yacute", "Ý" }, + { "Yuml", "Ÿ" }, + { "Zeta", "Ζ" }, + { "aacute", "á" }, + { "acirc", "â" }, + { "acute", "´" }, + { "aelig", "æ" }, + { "agrave", "à" }, + { "alefsym", "ℵ" }, + { "alpha", "α" }, + { "amp", "&" }, + { "and", "∧" }, + { "ang", "∠" }, + { "apos", "'" }, + { "aring", "å" }, + { "asymp", "≈" }, + { "atilde", "ã" }, + { "auml", "ä" }, + { "bdquo", "„" }, + { "beta", "β" }, + { "brvbar", "¦" }, + { "bull", "•" }, + { "cap", "∩" }, + { "ccedil", "ç" }, + { "cedil", "¸" }, + { "cent", "¢" }, + { "chi", "χ" }, + { "circ", "ˆ" }, + { "clubs", "♣" }, + { "cong", "≅" }, + { "copy", "©" }, + { "crarr", "↵" }, + { "cup", "∪" }, + { "curren", "¤" }, + { "dArr", "⇓" }, + { "dagger", "†" }, + { "darr", "↓" }, + { "deg", "°" }, + { "delta", "δ" }, + { "diams", "♦" }, + { "divide", "÷" }, + { "eacute", "é" }, + { "ecirc", "ê" }, + { "egrave", "è" }, + { "empty", "∅" }, + { "emsp", " " }, + { "ensp", " " }, + { "epsilon", "ε" }, + { "equiv", "≡" }, + { "eta", "η" }, + { "eth", "ð" }, + { "euml", "ë" }, + { "euro", "€" }, + { "exist", "∃" }, + { "fnof", "ƒ" }, + { "forall", "∀" }, + { "frac12", "½" }, + { "frac14", "¼" }, + { "frac34", "¾" }, + { "frasl", "⁄" }, + { "gamma", "γ" }, + { "ge", "≥" }, + { "gt", ">" }, + { "hArr", "⇔" }, + { "harr", "↔" }, + { "hearts", "♥" }, + { "hellip", "…" }, + { "iacute", "í" }, + { "icirc", "î" }, + { "iexcl", "¡" }, + { "igrave", "ì" }, + { "image", "ℑ" }, + { "infin", "∞" }, + { "int", "∫" }, + { "iota", "ι" }, + { "iquest", "¿" }, + { "isin", "∈" }, + { "iuml", "ï" }, + { "kappa", "κ" }, + { "lArr", "⇐" }, + { "lambda", "λ" }, + { "lang", "〈" }, + { "laquo", "«" }, + { "larr", "←" }, + { "lceil", "⌈" }, + { "ldquo", "“" }, + { "le", "≤" }, + { "lfloor", "⌊" }, + { "lowast", "∗" }, + { "loz", "◊" }, + { "lrm", "\xE2\x80\x8E" }, + { "lsaquo", "‹" }, + { "lsquo", "‘" }, + { "lt", "<" }, + { "macr", "¯" }, + { "mdash", "—" }, + { "micro", "µ" }, + { "middot", "·" }, + { "minus", "−" }, + { "mu", "μ" }, + { "nabla", "∇" }, + { "nbsp", " " }, + { "ndash", "–" }, + { "ne", "≠" }, + { "ni", "∋" }, + { "not", "¬" }, + { "notin", "∉" }, + { "nsub", "⊄" }, + { "ntilde", "ñ" }, + { "nu", "ν" }, + { "oacute", "ó" }, + { "ocirc", "ô" }, + { "oelig", "œ" }, + { "ograve", "ò" }, + { "oline", "‾" }, + { "omega", "ω" }, + { "omicron", "ο" }, + { "oplus", "⊕" }, + { "or", "∨" }, + { "ordf", "ª" }, + { "ordm", "º" }, + { "oslash", "ø" }, + { "otilde", "õ" }, + { "otimes", "⊗" }, + { "ouml", "ö" }, + { "para", "¶" }, + { "part", "∂" }, + { "permil", "‰" }, + { "perp", "⊥" }, + { "phi", "φ" }, + { "pi", "π" }, + { "piv", "ϖ" }, + { "plusmn", "±" }, + { "pound", "£" }, + { "prime", "′" }, + { "prod", "∏" }, + { "prop", "∝" }, + { "psi", "ψ" }, + { "quot", "\"" }, + { "rArr", "⇒" }, + { "radic", "√" }, + { "rang", "〉" }, + { "raquo", "»" }, + { "rarr", "→" }, + { "rceil", "⌉" }, + { "rdquo", "”" }, + { "real", "ℜ" }, + { "reg", "®" }, + { "rfloor", "⌋" }, + { "rho", "ρ" }, + { "rlm", "\xE2\x80\x8F" }, + { "rsaquo", "›" }, + { "rsquo", "’" }, + { "sbquo", "‚" }, + { "scaron", "š" }, + { "sdot", "⋅" }, + { "sect", "§" }, + { "shy", "\xC2\xAD" }, + { "sigma", "σ" }, + { "sigmaf", "ς" }, + { "sim", "∼" }, + { "spades", "♠" }, + { "sub", "⊂" }, + { "sube", "⊆" }, + { "sum", "∑" }, + { "sup", "⊃" }, + { "sup1", "¹" }, + { "sup2", "²" }, + { "sup3", "³" }, + { "supe", "⊇" }, + { "szlig", "ß" }, + { "tau", "τ" }, + { "there4", "∴" }, + { "theta", "θ" }, + { "thetasym", "ϑ" }, + { "thinsp", " " }, + { "thorn", "þ" }, + { "tilde", "˜" }, + { "times", "×" }, + { "trade", "™" }, + { "uArr", "⇑" }, + { "uacute", "ú" }, + { "uarr", "↑" }, + { "ucirc", "û" }, + { "ugrave", "ù" }, + { "uml", "¨" }, + { "upsih", "ϒ" }, + { "upsilon", "υ" }, + { "uuml", "ü" }, + { "weierp", "℘" }, + { "xi", "ξ" }, + { "yacute", "ý" }, + { "yen", "¥" }, + { "yuml", "ÿ" }, + { "zeta", "ζ" }, + { "zwj", "\xE2\x80\x8D" }, + { "zwnj", "\xE2\x80\x8C" } +}; + +char *CSkypeProto::RemoveHtml(const char *text) +{ + std::string new_string = ""; + std::string data = text; + + for (std::string::size_type i = 0; i < data.length(); i++) + { + if (data.at(i) == '<') + { + i = data.find(">", i); + if (i == std::string::npos) + break; + + continue; + } + + if (data.at(i) == '&') + { + std::string::size_type begin = i; + i = data.find(";", i); + if (i == std::string::npos) + { + i = begin; + } + else { + std::string entity = data.substr(begin + 1, i - begin - 1); + + bool found = false; + if (entity.length() > 1 && entity.at(0) == '#') + { + // Numeric replacement + bool hex = false; + if (data.at(1) == 'x') + { + hex = true; + entity = entity.substr(2); + } + else + { + entity = entity.substr(1); + } + if (!entity.empty()) + { + unsigned long value = strtoul(entity.c_str(), NULL, hex ? 16 : 10); + + if (value <= 127) + { // U+0000 .. U+007F + new_string += (char)value; + } + else if (value >= 128 && value <= 2047) + { // U+0080 .. U+07FF + new_string += (char)(192 + (value / 64)); + new_string += (char)(128 + (value % 64)); + } + else if (value >= 2048 && value <= 65535) + { // U+0800 .. U+FFFF + new_string += (char)(224 + (value / 4096)); + new_string += (char)(128 + ((value / 64) % 64)); + new_string += (char)(128 + (value % 64)); + } + else + { + new_string += (char)((value >> 24) & 0xFF); + new_string += (char)((value >> 16) & 0xFF); + new_string += (char)((value >> 8) & 0xFF); + new_string += (char)((value)& 0xFF); + } + found = true; + } + } + else + { + // Keyword replacement + for (int j = 0; j < _countof(htmlEntities); j++) + { + if (!mir_strcmpi(entity.c_str(), htmlEntities[j].entity)) + { + new_string += htmlEntities[j].symbol; + found = true; + break; + } + } + } + + if (found) + continue; + else + i = begin; + } + } + + new_string += data.at(i); + } + + return mir_strdup(new_string.c_str()); +} + +const char *CSkypeProto::MirandaToSkypeStatus(int status) +{ + switch (status) + { + case ID_STATUS_AWAY: + return "Away"; + + case ID_STATUS_DND: + return "Busy"; + + case ID_STATUS_IDLE: + return "Idle"; + + case ID_STATUS_INVISIBLE: + return "Hidden"; + } + return "Online"; +} + +int CSkypeProto::SkypeToMirandaStatus(const char *status) +{ + if (!mir_strcmpi(status, "Online")) + return ID_STATUS_ONLINE; + else if (!mir_strcmpi(status, "Hidden")) + return ID_STATUS_INVISIBLE; + else if (!mir_strcmpi(status, "Away")) + return ID_STATUS_AWAY; + else if (!mir_strcmpi(status, "Idle")) + return /*ID_STATUS_IDLE*/ID_STATUS_AWAY; + else if (!mir_strcmpi(status, "Busy")) + return ID_STATUS_DND; + else + return ID_STATUS_OFFLINE; +} + +bool CSkypeProto::IsFileExists(std::wstring path) +{ + return _waccess(path.c_str(), 0) == 0; +} + +// url parsing + +CMStringA CSkypeProto::ParseUrl(const char *url, const char *token) +{ + const char *start = strstr(url, token); + if (start == NULL) + return CMStringA(); + + start = start + mir_strlen(token); + const char *end = strchr(start, '/'); + if (end == NULL) + return CMStringA(start); + return CMStringA(start, end - start); +} + +CMStringA CSkypeProto::GetStringChunk(const char *haystack, const char *start, const char *end) +{ + const char *sstart = strstr(haystack, start); + if (sstart == NULL) + return CMStringA(); + + sstart = sstart + mir_strlen(start); + const char *send = strstr(sstart, end); + if (send == NULL) + return CMStringA(sstart); + return CMStringA(sstart, send - sstart); +} + +CMStringA CSkypeProto::UrlToSkypename(const char *url) +{ + CMStringA szResult; + + if (strstr(url, "/1:")) + szResult = ParseUrl(url, "/1:"); + else if (strstr(url, "/8:")) + szResult = ParseUrl(url, "/8:"); + else if (strstr(url, "/19:")) + szResult = ParseUrl(url, "/19:"); + + return szResult; +} + +CMStringA CSkypeProto::GetServerFromUrl(const char *url) +{ + return ParseUrl(url, "://"); +} + +INT_PTR CSkypeProto::ParseSkypeUriService(WPARAM, LPARAM lParam) +{ + wchar_t *arg = (wchar_t *)lParam; + if (arg == NULL) + return 1; + + // skip leading prefix + wchar_t szUri[1024]; + wcsncpy_s(szUri, arg, _TRUNCATE); + wchar_t *szJid = wcschr(szUri, ':'); + if (szJid == NULL) + return 1; + + // empty jid? + if (!*szJid) + return 1; + + // command code + wchar_t *szCommand = szJid; + szCommand = wcschr(szCommand, '?'); + if (szCommand) + *(szCommand++) = 0; + + // parameters + wchar_t *szSecondParam = szCommand ? wcschr(szCommand, '&') : NULL; + if (szSecondParam) + *(szSecondParam++) = 0; + + // no command or message command + if (!szCommand || (szCommand && !mir_wstrcmpi(szCommand, L"chat"))) + { + if (szSecondParam) + { + wchar_t *szChatId = wcsstr(szSecondParam, L"id="); + if (szChatId) + { + szChatId += 5; + StartChatRoom(szChatId, szChatId); + return 0; + } + } + MCONTACT hContact = AddContact(_T2A(szJid), true); + CallService(MS_MSG_SENDMESSAGE, (WPARAM)hContact, NULL); + return 0; + } + else if (!mir_wstrcmpi(szCommand, L"call")) + { + MCONTACT hContact = AddContact(_T2A(szJid), true); + NotifyEventHooks(g_hCallEvent, (WPARAM)hContact, (LPARAM)0); + return 0; + } + else if (!mir_wstrcmpi(szCommand, L"userinfo")){ return 0; } + else if (!mir_wstrcmpi(szCommand, L"add")) + { + MCONTACT hContact = FindContact(_T2A(szJid)); + if (hContact == NULL) + { + PROTOSEARCHRESULT psr = { 0 }; + psr.cbSize = sizeof(psr); + psr.id.w = mir_wstrdup(szJid); + psr.nick.w = mir_wstrdup(szJid); + psr.flags = PSR_UNICODE; + + ADDCONTACTSTRUCT acs = { 0 }; + acs.handleType = HANDLE_SEARCHRESULT; + acs.szProto = m_szModuleName; + acs.psr = &psr; + + CallService(MS_ADDCONTACT_SHOW, 0, (LPARAM)&acs); + } + return 0; + } + if (!mir_wstrcmpi(szCommand, L"sendfile")) + { + MCONTACT hContact = AddContact(_T2A(szJid), true); + CallService(MS_FILE_SENDFILE, hContact, NULL); + return 1; + } + if (!mir_wstrcmpi(szCommand, L"voicemail")) + { + return 1; + } + return 1; +} + +INT_PTR CSkypeProto::GlobalParseSkypeUriService(WPARAM wParam, LPARAM lParam) +{ + mir_cslock lck(accountsLock); + for (int i = 0; i < Accounts.getCount(); i++) + if (Accounts[i]->IsOnline()) + return Accounts[i]->ParseSkypeUriService(wParam, lParam); + + return 1; } \ No newline at end of file -- cgit v1.2.3