summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--protocols/Steam/Steam.vcxproj1
-rw-r--r--protocols/Steam/Steam.vcxproj.filters3
-rw-r--r--protocols/Steam/src/steam_bbcodes.cpp139
-rw-r--r--protocols/Steam/src/steam_utils.cpp85
4 files changed, 143 insertions, 85 deletions
diff --git a/protocols/Steam/Steam.vcxproj b/protocols/Steam/Steam.vcxproj
index 445cb17cd3..160884db1b 100644
--- a/protocols/Steam/Steam.vcxproj
+++ b/protocols/Steam/Steam.vcxproj
@@ -79,6 +79,7 @@
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="src\steam_avatars.cpp" />
+ <ClCompile Include="src\steam_bbcodes.cpp" />
<ClCompile Include="src\steam_chats.cpp" />
<ClCompile Include="src\steam_contacts.cpp" />
<ClCompile Include="src\steam_crypt.cpp" />
diff --git a/protocols/Steam/Steam.vcxproj.filters b/protocols/Steam/Steam.vcxproj.filters
index 73efa626bb..576ca61aa2 100644
--- a/protocols/Steam/Steam.vcxproj.filters
+++ b/protocols/Steam/Steam.vcxproj.filters
@@ -114,6 +114,9 @@
<ClCompile Include="src\steam_chats.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="src\steam_bbcodes.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\resource.h">
diff --git a/protocols/Steam/src/steam_bbcodes.cpp b/protocols/Steam/src/steam_bbcodes.cpp
new file mode 100644
index 0000000000..662ef58b6c
--- /dev/null
+++ b/protocols/Steam/src/steam_bbcodes.cpp
@@ -0,0 +1,139 @@
+/*
+Copyright (C) 2012-25 Miranda NG team (https://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"
+
+void EncodeBbcodes(SESSION_INFO *si, CMStringW &wszText)
+{
+ int idx = wszText.Find(':');
+ if (idx != -1) {
+ CMStringW wszNick(wszText.Left(idx));
+ for (auto &it : si->getUserList()) {
+ if (wszNick == it->pszNick) {
+ wszText.Delete(0, idx + 1);
+
+ CMStringW wszReplace(FORMAT, L"[mention=%lld]@%s[/mention]", SteamIdToAccountId(_wtoi64(it->pszUID)), it->pszNick);
+ wszText = wszReplace + wszText;
+ break;
+ }
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+struct BBCode
+{
+ CMStringA szTag, szValue, szBody;
+ std::map<CMStringA, CMStringA> attrs;
+};
+
+int parseBbcode(const char *p, BBCode &ret)
+{
+ auto *pSave = p;
+
+ while (isalpha(*p))
+ ret.szTag.AppendChar(*p++);
+
+ // [tag=value][/tag]
+ if (*p == '=') {
+ while (*p && *p != ']')
+ ret.szValue.AppendChar(*p++);
+ if (*p != ']')
+ return -1;
+ }
+ // [tag attr=value][/tag]
+ else if (*p == ' ') {
+ p++;
+ while (*p != ']') {
+ CMStringA szName, szValue;
+ while (*p && *p != '=')
+ szName.AppendChar(*p++);
+ if (*p++ != '=')
+ return -1;
+ if (*p == '\"') {
+ auto *p1 = strchr(++p, '\"');
+ if (p1 == nullptr)
+ return -1;
+
+ p++;
+ szValue.Append(p, p1 - p);
+ p = p1 + 1;
+ }
+ else {
+ while (*p && *p != ' ' && *p != ']')
+ szValue.AppendChar(*p++);
+ if (*p == 0)
+ return -1;
+ }
+
+ if (*p == ' ')
+ p++;
+ }
+ }
+ // [tag][/tag]
+ else if (*p != ']')
+ return -1;
+
+ p++; // skip first ]
+
+ CMStringA szClose = "[/" + ret.szTag + "]";
+ auto *pEnd = strstr(p, szClose);
+ if (pEnd == nullptr)
+ return -1;
+
+ if (pEnd != p)
+ ret.szValue.Append(p, pEnd - p);
+
+ return pEnd + szClose.GetLength() - pSave;
+}
+
+void DecodeBbcodes(SESSION_INFO *si, CMStringA &szText)
+{
+ for (int idx = szText.Find('['); idx != -1; idx = szText.Find('[', idx + 1)) {
+ BBCode code;
+ int iLength = parseBbcode(szText.c_str() + idx + 1, code) + 1;
+ if (iLength == 0)
+ continue;
+
+ bool bPlaceFirst = false;
+ CMStringA szReplace;
+ if (code.szTag == "emoticon")
+ szReplace.Format(":%s:", code.szValue.c_str());
+ else if (code.szTag == "sticker")
+ szReplace.Format(":%s:", code.attrs["type"].c_str());
+ else if (code.szTag == "mention") {
+ CMStringW wszId(FORMAT, L"%lld", AccountIdToSteamId(_atoi64(code.szValue)));
+ if (auto *pUser = g_chatApi.UM_FindUser(si, wszId)) {
+ szReplace.Format("%s:", T2Utf(pUser->pszNick).get());
+ bPlaceFirst = true;
+ }
+ }
+ else if (code.szTag == "lobbyinvite") {
+ szReplace = TranslateU("You were invited to play a game");
+ }
+ else continue;
+
+ szText.Delete(idx, iLength);
+ if (!szReplace.IsEmpty()) {
+ if (bPlaceFirst)
+ szText = szReplace + szText;
+ else
+ szText.Insert(idx, szReplace);
+ }
+ }
+}
diff --git a/protocols/Steam/src/steam_utils.cpp b/protocols/Steam/src/steam_utils.cpp
index 7f1275add3..2b8c3263db 100644
--- a/protocols/Steam/src/steam_utils.cpp
+++ b/protocols/Steam/src/steam_utils.cpp
@@ -20,91 +20,6 @@ bool IsNull(const ProtobufCBinaryData &buf)
/////////////////////////////////////////////////////////////////////////////////////////
-void EncodeBbcodes(SESSION_INFO *si, CMStringW &wszText)
-{
- int idx = wszText.Find(':');
- if (idx != -1) {
- CMStringW wszNick(wszText.Left(idx));
- for (auto &it : si->getUserList()) {
- if (wszNick == it->pszNick) {
- wszText.Delete(0, idx+1);
-
- CMStringW wszReplace(FORMAT, L"[mention=%lld]@%s[/mention]", SteamIdToAccountId(_wtoi64(it->pszUID)), it->pszNick);
- wszText = wszReplace + wszText;
- break;
- }
- }
- }
-}
-
-void DecodeBbcodes(SESSION_INFO *si, CMStringA &szText)
-{
- for (int idx = 0; idx != -1; idx = szText.Find('[', idx+1)) {
- bool isClosing = false;
- idx++;
- if (szText[idx] == '/') {
- isClosing = true;
- idx++;
- }
-
- int iEnd = szText.Find(']', idx + 1);
- if (iEnd == -1)
- return;
-
- bool bPlaceFirst = false;
- CMStringA szReplace;
-
- auto *p = szText.c_str() + idx;
- if (!strncmp(p, "emoticon", 8) || !strncmp(p, "sticker", 7))
- szReplace = ":";
-
- if (!isClosing) {
- if (!strncmp(p, "mention=", 8)) {
- CMStringW wszId(FORMAT, L"%lld", AccountIdToSteamId(_atoi64(p + 8)));
- if (auto *pUser = g_chatApi.UM_FindUser(si, wszId)) {
- int iEnd2 = szText.Find("[/mention]", iEnd);
- if (iEnd2 == -1)
- return;
-
- iEnd = iEnd2 + 10;
- szReplace.Format("%s:", T2Utf(pUser->pszNick).get());
- bPlaceFirst = true;
- }
- }
- else if (!strncmp(p, "lobbyinvite ", 12)) {
- szReplace = TranslateU("You were invited to play a game");
- }
- else if (!strncmp(p, "sticker ", 8)) {
- std::regex regex("type=\"(.+?)\"");
- std::smatch match;
- std::string content(p + 8);
- if (std::regex_search(content, match, regex)) {
- std::string szType = match[1];
- szReplace += szType.c_str();
- szReplace.Replace(" ", "_");
- }
- iEnd++;
- }
- else iEnd++;
- }
- else iEnd++, idx--;
-
- idx--;
- szText.Delete(idx, iEnd - idx);
-
- if (!szReplace.IsEmpty()) {
- if (bPlaceFirst)
- szText = szReplace + szText;
- else
- szText.Insert(idx, szReplace);
- }
- iEnd -= iEnd - idx;
- idx = iEnd;
- }
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
MBinBuffer createMachineID(const char *accName)
{
uint8_t hashOut[MIR_SHA1_HASH_SIZE];