summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
authorRobert Pösel <robyer@seznam.cz>2016-12-03 10:11:26 +0100
committerRobert Pösel <robyer@seznam.cz>2016-12-03 10:11:26 +0100
commita5d5de36daa8a810784f0e14a40ccb72bf6c8faf (patch)
tree58bfee182fb1dd55f6b1582a63148b5cbd34f889 /protocols
parent563ccc952ef6cd57642b958ef8753e1cc8bba1a0 (diff)
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.
Diffstat (limited to 'protocols')
-rw-r--r--protocols/SkypeWeb/src/skype_utils.cpp1194
1 files changed, 621 insertions, 573 deletions
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 <http://www.gnu.org/licenses/>.
-*/
-
-#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", &timestamp.tm_hour, &timestamp.tm_min, &timestamp.tm_sec) != 3)
- return (time_t)0;
-
- timestamp.tm_isdst = 0; // DST is already present in _timezone below
- time_t t = mktime(&timestamp);
-
- _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 <http://www.gnu.org/licenses/>.
+*/
+
+#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", &timestamp.tm_hour, &timestamp.tm_min, &timestamp.tm_sec) != 3)
+ return (time_t)0;
+
+ timestamp.tm_isdst = 0; // DST is already present in _timezone below
+ time_t t = mktime(&timestamp);
+
+ _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