From 41d503cfb535eca95068b0265418ab2f580264d6 Mon Sep 17 00:00:00 2001 From: Mike Nolan Date: Mon, 1 Jun 2026 06:37:14 -0500 Subject: [PATCH] Fix win32 printing, fix my stupid json vulnerability --- Packaging/Linux/PKGBUILD | 4 +- Packaging/edit-formula.sh | 2 +- changelog.md | 3 + cmake/examples.cmake | 3 + cmake/version.cmake | 2 +- examples/start-my-website.cpp | 8 + include/TessesFramework/Console.hpp | 103 +++---- include/TessesFramework/Platform/Process.hpp | 2 + src/Console.cpp | 297 ++++++++++++------- src/Platform/Process.cpp | 34 +++ src/Serialization/Json.cpp | 6 +- 11 files changed, 306 insertions(+), 158 deletions(-) create mode 100644 examples/start-my-website.cpp diff --git a/Packaging/Linux/PKGBUILD b/Packaging/Linux/PKGBUILD index 7792918..d90a4c7 100644 --- a/Packaging/Linux/PKGBUILD +++ b/Packaging/Linux/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: Mike Nolan pkgname=tessesframework # '-bzr', '-git', '-hg' or '-svn' -pkgver=0.0.4 +pkgver=0.0.5 pkgrel=1 pkgdesc="" arch=('x86_64' 'powerpc') @@ -10,7 +10,7 @@ groups=() depends=('mbedtls') makedepends=('git' 'cmake' 'make' 'base-devel' 'wget') # 'bzr', 'git', 'mercurial' or 'subversion' install= -source=('tessesframework::git+https://git.tesses.org/tesses50/tessesframework') +source=('tessesframework::git+https://git.tesses.org/tesses50/tessesframework#tag=v0.0.5') noextract=() sha256sums=('SKIP') if [[ -z "$CMAKE_TOOLCHAIN" ]]; then diff --git a/Packaging/edit-formula.sh b/Packaging/edit-formula.sh index f142e2c..9f95f51 100644 --- a/Packaging/edit-formula.sh +++ b/Packaging/edit-formula.sh @@ -5,7 +5,7 @@ echo " desc \"\"" >> "Formula/tessesframework.rb" echo " homepage \"\"" >> "Formula/tessesframework.rb" echo " url \"https://git.tesses.org/tesses50/tessesframework/archive/$VERSION.tar.gz\"" >> "Formula/tessesframework.rb" echo " sha256 \"$HASH\"" >> "Formula/tessesframework.rb" -echo " license \"MIT\"" >> "Formula/tessesframework.rb" +echo " license \"GPLv3\"" >> "Formula/tessesframework.rb" echo " depends_on \"cmake\" => :build" >> "Formula/tessesframework.rb" echo " depends_on \"mbedtls@3\"" >> "Formula/tessesframework.rb" echo " def install" >> "Formula/tessesframework.rb" diff --git a/changelog.md b/changelog.md index 4215de1..5c84e8b 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,8 @@ # Changelog +## 0.0.5 +Fix win32 printing, fix my stupid json vulnerability + ## 0.0.4 Overhaul cmake configuration, add console api, fix http code that caused issues with cgi-bin diff --git a/cmake/examples.cmake b/cmake/examples.cmake index 0d7886c..9609aea 100644 --- a/cmake/examples.cmake +++ b/cmake/examples.cmake @@ -1,4 +1,7 @@ if(TESSESFRAMEWORK_ENABLE_EXAMPLES) + add_executable(start-my-website examples/start-my-website.cpp) + target_link_libraries(start-my-website PUBLIC tessesframework) + add_executable(echo-my-name examples/echo-my-name.cpp) target_link_libraries(echo-my-name PUBLIC tessesframework) diff --git a/cmake/version.cmake b/cmake/version.cmake index 478244a..c5abe5a 100644 --- a/cmake/version.cmake +++ b/cmake/version.cmake @@ -1,3 +1,3 @@ set(TESSESFRAMEWORK_MAJOR_VERSION 0) set(TESSESFRAMEWORK_MINOR_VERSION 0) -set(TESSESFRAMEWORK_PATCH_VERSION 4) \ No newline at end of file +set(TESSESFRAMEWORK_PATCH_VERSION 5) \ No newline at end of file diff --git a/examples/start-my-website.cpp b/examples/start-my-website.cpp new file mode 100644 index 0000000..ef0014a --- /dev/null +++ b/examples/start-my-website.cpp @@ -0,0 +1,8 @@ +#include "TessesFramework/TessesFramework.hpp" + +int main(int argc, char **argv) { + Tesses::Framework::TF_Init(); + + Tesses::Framework::Platform::ShellFileOrUrl("https://tesses.net/"); + return 0; +} \ No newline at end of file diff --git a/include/TessesFramework/Console.hpp b/include/TessesFramework/Console.hpp index 60cdb35..48e1a79 100644 --- a/include/TessesFramework/Console.hpp +++ b/include/TessesFramework/Console.hpp @@ -20,60 +20,61 @@ #include namespace Tesses::Framework { - enum class ConsoleColor { - CC_BLACK, - CC_RED, - CC_GREEN, - CC_YELLOW, - CC_BLUE, - CC_MAGENTA, - CC_CYAN, - CC_WHITE - }; - enum class ClearBehaviour { - CB_CURSORANDBELOW, - CB_CURSORANDABOVE, - CB_ENTIRESCREEN - }; - struct Console { - static bool IsTTY(); - static std::pair GetSize(); - static void ProgressBar(double); - static void ProgressBar(int); - static void Write(std::string text); - static void WriteLine(std::string text); - static void WriteView(std::string_view text); - static void WriteLineView(std::string_view text); - static void Error(std::string text); - static void ErrorLine(std::string text); - static void ErrorView(std::string_view text); - static void ErrorLineView(std::string_view text); - static int Read(); - static std::string ReadLine(); +enum class ConsoleColor { + CC_BLACK, + CC_RED, + CC_GREEN, + CC_YELLOW, + CC_BLUE, + CC_MAGENTA, + CC_CYAN, + CC_WHITE +}; +enum class ClearBehaviour { + CB_CURSORANDBELOW, + CB_CURSORANDABOVE, + CB_ENTIRESCREEN +}; +struct Console { + static bool IsTTY(); + static std::pair GetSize(); + static void ProgressBar(double); + static void ProgressBar(int); + static void Write(std::string text); + static void WriteLine(std::string text); + static void WriteView(std::string_view text); + static void WriteLineView(std::string_view text); + static void Error(std::string text); + static void ErrorLine(std::string text); + static void ErrorView(std::string_view text); + static void ErrorLineView(std::string_view text); + static int Read(); + static std::string ReadLine(); - static bool GetEcho(); - static bool SetEcho(bool echo); - static bool GetCanonical(); - static bool SetCanonical(bool can); - static bool GetSignals(); - static bool SetSignals(bool sig); + static bool GetEcho(); + static bool SetEcho(bool echo); + static bool GetCanonical(); + static bool SetCanonical(bool can); + static bool GetSignals(); + static bool SetSignals(bool sig); - static void SetPosition(int x, int y); + static void SetPosition(int x, int y); - static void SetBackgroundColor(ConsoleColor c, bool alt); - static void SetForegroundColor(ConsoleColor c, bool alt); - static void Clear(); - static void MoveToHome(); - static void ClearRetainPosition(ClearBehaviour clearBehaviour); - static void Flush(); + static void SetBackgroundColor(ConsoleColor c, bool alt); + static void SetForegroundColor(ConsoleColor c, bool alt); + static void Clear(); + static void MoveToHome(); + static void ClearRetainPosition(ClearBehaviour clearBehaviour); + static void Reset(); + static void SetInvertedColors(bool inverted); + static void Flush(); - //returns std::string::npos if no tty - static size_t List(std::vector& strs); + // returns std::string::npos if no tty + static size_t List(std::vector &strs); + static std::string ReadPassword(); - static std::string ReadPassword(); - - private: - static void WriteToStream(std::string_view text, bool isStderr); - }; -} \ No newline at end of file + private: + static void WriteToStream(std::string_view text, bool isStderr); +}; +} // namespace Tesses::Framework \ No newline at end of file diff --git a/include/TessesFramework/Platform/Process.hpp b/include/TessesFramework/Platform/Process.hpp index a352f57..853cf10 100644 --- a/include/TessesFramework/Platform/Process.hpp +++ b/include/TessesFramework/Platform/Process.hpp @@ -68,4 +68,6 @@ class Process { ~Process(); }; + +void ShellFileOrUrl(std::string fileOrUrl); } // namespace Tesses::Framework::Platform \ No newline at end of file diff --git a/src/Console.cpp b/src/Console.cpp index 61f392f..fa9d071 100644 --- a/src/Console.cpp +++ b/src/Console.cpp @@ -1,19 +1,19 @@ /* - TessesFramework a library to make C++ easier for me, used in CrossLang: + TessesFramework a library to make C++ easier for me, used in CrossLang: https://git.tesses.org/tesses50/crosslang Copyright (C) 2026 Mike Nolan - 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, either version 3 of the License, or - (at your option) any later version. + 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, either version 3 of the License, or + (at your option) any later version. - 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. + 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 . + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #include "TessesFramework/Console.hpp" @@ -34,6 +34,58 @@ namespace Tesses::Framework { +class ConsoleHelpers { + + bool canon; + bool echo; + bool signals; + +#if defined(_WIN32) + WORD colorFlags; + +#endif + + public: + ConsoleHelpers() { + canon = Console::GetCanonical(); + echo = Console::GetEcho(); + signals = Console::GetSignals(); +#if defined(_WIN32) + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + if (hConsole == INVALID_HANDLE_VALUE) + return; + CONSOLE_SCREEN_BUFFER_INFO bi; + + GetConsoleScreenBufferInfo(hConsole, &bi); + + colorFlags = bi.wAttributes; + +#endif + } + + void reset() { +#if defined(_WIN32) + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + if (hConsole == INVALID_HANDLE_VALUE) + return; + SetConsoleTextAttribute(hConsole, colorFlags); +#else + if (Console::IsTTY()) { + printf("\x1b[0m"); + fflush(stdout); + } +#endif + } + + ~ConsoleHelpers() { + Console::SetCanonical(canon); + Console::SetEcho(echo); + Console::SetSignals(signals); + reset(); + } +}; +ConsoleHelpers consoleHelpers; + size_t Console::List(std::vector &strs) { if (!IsTTY()) return std::string::npos; @@ -54,11 +106,9 @@ size_t Console::List(std::vector &strs) { for (int item = 0; item < size.second; ++item) { if (item == offsetInPage) { - Console::SetBackgroundColor(ConsoleColor::CC_WHITE, true); - Console::SetForegroundColor(ConsoleColor::CC_BLACK, false); + Console::SetInvertedColors(true); } else { - Console::SetBackgroundColor(ConsoleColor::CC_BLACK, false); - Console::SetForegroundColor(ConsoleColor::CC_WHITE, true); + Console::SetInvertedColors(false); } size_t myOffset = (size_t)item + page * (size.second); @@ -72,8 +122,7 @@ size_t Console::List(std::vector &strs) { } } - Console::SetBackgroundColor(ConsoleColor::CC_BLACK, false); - Console::SetForegroundColor(ConsoleColor::CC_WHITE, true); + Console::SetInvertedColors(false); int code = Console::Read(); @@ -102,49 +151,82 @@ size_t Console::List(std::vector &strs) { } Console::SetEcho(echo); Console::SetCanonical(canonical); - Console::SetBackgroundColor(ConsoleColor::CC_BLACK, false); - Console::SetForegroundColor(ConsoleColor::CC_WHITE, true); + Console::SetInvertedColors(false); return i; } +void Console::Reset() { consoleHelpers.reset(); } + +#if defined(_WIN32) +static bool vt100_inverted = false; +static void _setcol(ConsoleColor col, bool alt, bool bg) { + if (bg) { + + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + if (hConsole == INVALID_HANDLE_VALUE) + return; + CONSOLE_SCREEN_BUFFER_INFO bi; + + GetConsoleScreenBufferInfo(hConsole, &bi); + + bi.wAttributes &= ~(BACKGROUND_RED | BACKGROUND_GREEN | + BACKGROUND_BLUE | BACKGROUND_INTENSITY); + + if (col == ConsoleColor::CC_RED || col == ConsoleColor::CC_YELLOW || + col == ConsoleColor::CC_MAGENTA || col == ConsoleColor::CC_WHITE) + bi.wAttributes |= BACKGROUND_RED; + + if (col == ConsoleColor::CC_GREEN || col == ConsoleColor::CC_YELLOW || + col == ConsoleColor::CC_CYAN || col == ConsoleColor::CC_WHITE) + bi.wAttributes |= BACKGROUND_GREEN; + + if (col == ConsoleColor::CC_BLUE || col == ConsoleColor::CC_CYAN || + col == ConsoleColor::CC_MAGENTA || col == ConsoleColor::CC_WHITE) + bi.wAttributes |= BACKGROUND_BLUE; + + if (alt) + bi.wAttributes |= BACKGROUND_INTENSITY; + + SetConsoleTextAttribute(hConsole, bi.wAttributes); + } else { + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + if (hConsole == INVALID_HANDLE_VALUE) + return; + CONSOLE_SCREEN_BUFFER_INFO bi; + + GetConsoleScreenBufferInfo(hConsole, &bi); + + bi.wAttributes &= ~(FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_BLUE | FOREGROUND_INTENSITY); + + if (col == ConsoleColor::CC_RED || col == ConsoleColor::CC_YELLOW || + col == ConsoleColor::CC_MAGENTA || col == ConsoleColor::CC_WHITE) + bi.wAttributes |= FOREGROUND_RED; + + if (col == ConsoleColor::CC_GREEN || col == ConsoleColor::CC_YELLOW || + col == ConsoleColor::CC_CYAN || col == ConsoleColor::CC_WHITE) + bi.wAttributes |= FOREGROUND_GREEN; + + if (col == ConsoleColor::CC_BLUE || col == ConsoleColor::CC_CYAN || + col == ConsoleColor::CC_MAGENTA || col == ConsoleColor::CC_WHITE) + bi.wAttributes |= FOREGROUND_BLUE; + + if (alt) + bi.wAttributes |= FOREGROUND_INTENSITY; + + SetConsoleTextAttribute(hConsole, bi.wAttributes); + } +} +#endif + void Console::SetForegroundColor(ConsoleColor col, bool alt) { if (!IsTTY()) return; -#if __has_include() - if (alt) { - printf("\x1b[%im", ((int)col) + 90); // this should be Write - } else { - printf("\x1b[%im", ((int)col) + 30); // this too - } -#elif defined(_WIN32) - HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - if (hConsole == INVALID_HANDLE_VALUE) - return; - CONSOLE_SCREEN_BUFFER_INFO bi; +#if defined(_WIN32) - GetConsoleScreenBufferInfo(hConsole, &bi); - - bi.wAttributes &= ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | - FOREGROUND_INTENSITY); - - if (col == ConsoleColor::CC_RED || col == ConsoleColor::CC_YELLOW || - col == ConsoleColor::CC_MAGENTA || col == ConsoleColor::CC_WHITE) - bi.wAttributes |= FOREGROUND_RED; - - if (col == ConsoleColor::CC_GREEN || col == ConsoleColor::CC_YELLOW || - col == ConsoleColor::CC_CYAN || col == ConsoleColor::CC_WHITE) - bi.wAttributes |= FOREGROUND_GREEN; - - if (col == ConsoleColor::CC_BLUE || col == ConsoleColor::CC_CYAN || - col == ConsoleColor::CC_MAGENTA || col == ConsoleColor::CC_WHITE) - bi.wAttributes |= FOREGROUND_BLUE; - - if (alt) - bi.wAttributes |= FOREGROUND_INTENSITY; - - SetConsoleTextAttribute(hConsole, bi.wAttributes); + _setcol(col, alt, vt100_inverted); #else if (alt) { @@ -158,40 +240,9 @@ void Console::SetForegroundColor(ConsoleColor col, bool alt) { void Console::SetBackgroundColor(ConsoleColor col, bool alt) { if (!IsTTY()) return; -#if __has_include() - if (alt) { - printf("\x1b[%im", ((int)col) + 100); // this should be Write - } else { - printf("\x1b[%im", ((int)col) + 40); // this too - } -#elif defined(_WIN32) - HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); - if (hConsole == INVALID_HANDLE_VALUE) - return; - CONSOLE_SCREEN_BUFFER_INFO bi; - - GetConsoleScreenBufferInfo(hConsole, &bi); - - bi.wAttributes &= ~(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | - BACKGROUND_INTENSITY); - - if (col == ConsoleColor::CC_RED || col == ConsoleColor::CC_YELLOW || - col == ConsoleColor::CC_MAGENTA || col == ConsoleColor::CC_WHITE) - bi.wAttributes |= BACKGROUND_RED; - - if (col == ConsoleColor::CC_GREEN || col == ConsoleColor::CC_YELLOW || - col == ConsoleColor::CC_CYAN || col == ConsoleColor::CC_WHITE) - bi.wAttributes |= BACKGROUND_GREEN; - - if (col == ConsoleColor::CC_BLUE || col == ConsoleColor::CC_CYAN || - col == ConsoleColor::CC_MAGENTA || col == ConsoleColor::CC_WHITE) - bi.wAttributes |= BACKGROUND_BLUE; - - if (alt) - bi.wAttributes |= BACKGROUND_INTENSITY; - - SetConsoleTextAttribute(hConsole, bi.wAttributes); +#if defined(_WIN32) + _setcol(col, alt, !vt100_inverted); #else if (alt) { printf("\x1b[%im", ((int)col) + 100); // this should be Write @@ -201,6 +252,41 @@ void Console::SetBackgroundColor(ConsoleColor col, bool alt) { #endif } +void Console::SetInvertedColors(bool inverted) { + if (!IsTTY()) + return; +#if defined(_WIN32) + if (inverted != vt100_inverted) { + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + if (hConsole == INVALID_HANDLE_VALUE) + return; + CONSOLE_SCREEN_BUFFER_INFO bi; + + GetConsoleScreenBufferInfo(hConsole, &bi); + + bi.wAttributes = + (bi.wAttributes & 0xFF00) | + ((bi.wAttributes & (FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_BLUE | FOREGROUND_INTENSITY)) + << 4) | + ((bi.wAttributes & (BACKGROUND_RED | BACKGROUND_GREEN | + BACKGROUND_BLUE | BACKGROUND_INTENSITY)) >> + 4); + + SetConsoleTextAttribute(hConsole, bi.wAttributes); + } + + vt100_inverted = inverted; +#else + if (inverted) + Write("\x1b[7m"); + else + Write("\x1b[27m"); + + Flush(); +#endif +} + bool Console::SetEcho(bool echo) { if (!IsTTY()) return false; @@ -607,24 +693,33 @@ void Console::WriteToStream(std::string_view view, bool isStderr) { } if (text.size() > 0 && text.back() == 'm') { - - try { - auto num = - std::stol(text.substr(0, text.size() - 1)); - if (num >= 30 && num <= 37) { - SetForegroundColor((ConsoleColor)(num - 30), - false); - } else if (num >= 40 && num <= 47) { - SetBackgroundColor((ConsoleColor)(num - 40), - false); - } else if (num >= 90 && num <= 97) { - SetForegroundColor((ConsoleColor)(num - 90), - true); - } else if (num >= 100 && num <= 107) { - SetBackgroundColor((ConsoleColor)(num - 100), - true); + if (text.size() == 1) { + consoleHelpers.reset(); + } else { + try { + auto num = + std::stol(text.substr(0, text.size() - 1)); + if (num == 0) + consoleHelpers.reset(); + if (num == 7) + Console::SetInvertedColors(true); + if (num == 27) + Console::SetInvertedColors(false); + if (num >= 30 && num <= 37) { + SetForegroundColor((ConsoleColor)(num - 30), + false); + } else if (num >= 40 && num <= 47) { + SetBackgroundColor((ConsoleColor)(num - 40), + false); + } else if (num >= 90 && num <= 97) { + SetForegroundColor((ConsoleColor)(num - 90), + true); + } else if (num >= 100 && num <= 107) { + SetBackgroundColor( + (ConsoleColor)(num - 100), true); + } + } catch (...) { } - } catch (...) { } } diff --git a/src/Platform/Process.cpp b/src/Platform/Process.cpp index b4686da..f8c0e9e 100644 --- a/src/Platform/Process.cpp +++ b/src/Platform/Process.cpp @@ -691,4 +691,38 @@ std::shared_ptr Process::GetStderrStream() { #endif } +void ShellFileOrUrl(std::string fileOrUrl) { +#if defined(GEKKO) || defined(__PS2__) || defined(__SWITCH__) + throw std::runtime_error("Platform not supported"); +#elif !defined(TESSESFRAMEWORK_ENABLE_PROCESS) + throw std::runtime_error("Process not enabled"); +#elif defined(_WIN32) + auto exec = Tesses::Framework::Platform::Environment::GetRealExecutablePath( + (std::string) "cmd"); + Process p(exec.ToString(), {"cmd", "/c", "start", fileOrUrl}); + if (p.Start()) + if (p.WaitForExit() != 0) + throw std::runtime_error("Exit code did not indicate success"); +#elif defined(__APPLE__) + auto exec = Tesses::Framework::Platform::Environment::GetRealExecutablePath( + (std::string) "open"); + Process p(exec.ToString(), {"open", fileOrUrl}); + if (p.Start()) + if (p.WaitForExit() != 0) + throw std::runtime_error("Exit code did not indicate success"); +#else + if (fileOrUrl == "--help" || fileOrUrl == "--version" || + fileOrUrl == "--manual") + throw std::invalid_argument( + "Invalid argument \"" + fileOrUrl + + "\", this function expects a file or url not xdg-open flags"); + auto exec = Tesses::Framework::Platform::Environment::GetRealExecutablePath( + (std::string) "xdg-open"); + Process p(exec.ToString(), {"xdg-open", fileOrUrl}); + if (p.Start()) + if (p.WaitForExit() != 0) + throw std::runtime_error("Exit code did not indicate success"); +#endif +} + } // namespace Tesses::Framework::Platform diff --git a/src/Serialization/Json.cpp b/src/Serialization/Json.cpp index 9020aa6..9832087 100644 --- a/src/Serialization/Json.cpp +++ b/src/Serialization/Json.cpp @@ -15,9 +15,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ - #include "TessesFramework/Serialization/Json.hpp" #include "TessesFramework/Http/HttpUtils.hpp" +#include "TessesFramework/TessesFramework.hpp" #include #include "TessesFramework/Common.hpp" @@ -129,6 +129,7 @@ JToken Json::Decode(std::string str) { v |= HttpUtils::HexToNibble(str[i]) << ((3 - i2) * 4); } + i--; uint32_t v2 = v; @@ -274,7 +275,8 @@ JToken Json::Decode(std::string str) { break; } else { - throw std::runtime_error("Invalid JSON object."); + throw std::runtime_error("Invalid JSON object. " + + std::to_string(tokenIndex)); } } return obj;