From 1db3c48ee480eceb092da877cdf861b1200a0291 Mon Sep 17 00:00:00 2001 From: Michael Theall Date: Mon, 3 Oct 2022 21:52:19 -0500 Subject: [PATCH] Add log upload to hastebin --- 3ds/romfs/sni.cloudflaressl.com.ca | 74 ++++++++++ Makefile.3ds | 9 +- Makefile.linux | 7 +- Makefile.nds | 4 +- Makefile.switch | 9 +- include/ftpConfig.h | 4 +- include/ftpServer.h | 20 ++- include/log.h | 7 +- source/3ds/platform.cpp | 2 +- source/ftpConfig.cpp | 6 +- source/ftpServer.cpp | 209 +++++++++++++++++++++++++++-- source/ftpSession.cpp | 10 +- source/log.cpp | 42 +++++- source/main.cpp | 8 +- 14 files changed, 369 insertions(+), 42 deletions(-) create mode 100644 3ds/romfs/sni.cloudflaressl.com.ca diff --git a/3ds/romfs/sni.cloudflaressl.com.ca b/3ds/romfs/sni.cloudflaressl.com.ca new file mode 100644 index 0000000..540e0c5 --- /dev/null +++ b/3ds/romfs/sni.cloudflaressl.com.ca @@ -0,0 +1,74 @@ +-----BEGIN CERTIFICATE----- +MIIFNzCCBN6gAwIBAgIQDY30H+7eX+UAL96D4Q4pCTAKBggqhkjOPQQDAjBKMQsw +CQYDVQQGEwJVUzEZMBcGA1UEChMQQ2xvdWRmbGFyZSwgSW5jLjEgMB4GA1UEAxMX +Q2xvdWRmbGFyZSBJbmMgRUNDIENBLTMwHhcNMjIwNzA2MDAwMDAwWhcNMjMwNzA2 +MjM1OTU5WjB1MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQG +A1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQQ2xvdWRmbGFyZSwgSW5jLjEe +MBwGA1UEAxMVc25pLmNsb3VkZmxhcmVzc2wuY29tMFkwEwYHKoZIzj0CAQYIKoZI +zj0DAQcDQgAEYORbsKsnHR3Fgl5NnfC69t+zjW+thQ8/EsuWWyfJ/BceQF8t1h26 +EN6BRaMb1c5UTpX1tI5JMgaXxXpFtESRI6OCA3kwggN1MB8GA1UdIwQYMBaAFKXO +N+rrsHUOlGeItEX62SQQh5YfMB0GA1UdDgQWBBQQcujrZ4f9+4Oh6nEzkQZ52Dku +zzA+BgNVHREENzA1gg4qLmhhc3RlYmluLmNvbYIVc25pLmNsb3VkZmxhcmVzc2wu +Y29tggxoYXN0ZWJpbi5jb20wDgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQWMBQGCCsG +AQUFBwMBBggrBgEFBQcDAjB7BgNVHR8EdDByMDegNaAzhjFodHRwOi8vY3JsMy5k +aWdpY2VydC5jb20vQ2xvdWRmbGFyZUluY0VDQ0NBLTMuY3JsMDegNaAzhjFodHRw +Oi8vY3JsNC5kaWdpY2VydC5jb20vQ2xvdWRmbGFyZUluY0VDQ0NBLTMuY3JsMD4G +A1UdIAQ3MDUwMwYGZ4EMAQICMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cuZGln +aWNlcnQuY29tL0NQUzB2BggrBgEFBQcBAQRqMGgwJAYIKwYBBQUHMAGGGGh0dHA6 +Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBABggrBgEFBQcwAoY0aHR0cDovL2NhY2VydHMu +ZGlnaWNlcnQuY29tL0Nsb3VkZmxhcmVJbmNFQ0NDQS0zLmNydDAMBgNVHRMBAf8E +AjAAMIIBfwYKKwYBBAHWeQIEAgSCAW8EggFrAWkAdgDoPtDaPvUGNTLnVyi8iWvJ +A9PL0RFr7Otp4Xd9bQa9bgAAAYHRAkxAAAAEAwBHMEUCIAhr5wFeEo8D3dOu+FYr +8vljOnpEIvMuNJjB6iBOcuXWAiEA6pI8/KK1U9Ig+xlAsKsol7+btAokI6OzNxfN +VOVM3KQAdgA1zxkbv7FsV78PrUxtQsu7ticgJlHqP+Eq76gDwzvWTAAAAYHRAkxs +AAAEAwBHMEUCIDIOIZDfw+ITXL6KvYGCJJx8yxDk2uiMy9ixN3XIG6AKAiEArbT1 +OhUlElPkGlwHWvcDXRnT24tKxP9WteDcCUD9W8QAdwC3Pvsk35xNunXyOcW6WPRs +XfxCz3qfNcSeHQmBJe20mQAAAYHRAkx3AAAEAwBIMEYCIQCptt9MYfIgiomqP9Xb +nXD2h3RK/11gtOTCzv+/qGKF9QIhANApIgtpOEeTIbXPXFJQBScB0NksARcRcBby +uoI1A2Y/MAoGCCqGSM49BAMCA0cAMEQCIFwUBWYQxZT+B0ItToj+mkoVTO1mDQox +ruuJ/G4Jmh4dAiA4ar4ImAlk4uptLNoZzxbc1m8CyHB2siaCDv3Lf7QktA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDzTCCArWgAwIBAgIQCjeHZF5ftIwiTv0b7RQMPDANBgkqhkiG9w0BAQsFADBa +MQswCQYDVQQGEwJJRTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJl +clRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTIw +MDEyNzEyNDgwOFoXDTI0MTIzMTIzNTk1OVowSjELMAkGA1UEBhMCVVMxGTAXBgNV +BAoTEENsb3VkZmxhcmUsIEluYy4xIDAeBgNVBAMTF0Nsb3VkZmxhcmUgSW5jIEVD +QyBDQS0zMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEua1NZpkUC0bsH4HRKlAe +nQMVLzQSfS2WuIg4m4Vfj7+7Te9hRsTJc9QkT+DuHM5ss1FxL2ruTAUJd9NyYqSb +16OCAWgwggFkMB0GA1UdDgQWBBSlzjfq67B1DpRniLRF+tkkEIeWHzAfBgNVHSME +GDAWgBTlnVkwgkdYzKz6CFQ2hns6tQRN8DAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0l +BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8CAQAwNAYI +KwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5j +b20wOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL09t +bmlyb290MjAyNS5jcmwwbQYDVR0gBGYwZDA3BglghkgBhv1sAQEwKjAoBggrBgEF +BQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzALBglghkgBhv1sAQIw +CAYGZ4EMAQIBMAgGBmeBDAECAjAIBgZngQwBAgMwDQYJKoZIhvcNAQELBQADggEB +AAUkHd0bsCrrmNaF4zlNXmtXnYJX/OvoMaJXkGUFvhZEOFp3ArnPEELG4ZKk40Un ++ABHLGioVplTVI+tnkDB0A+21w0LOEhsUCxJkAZbZB2LzEgwLt4I4ptJIsCSDBFe +lpKU1fwg3FZs5ZKTv3ocwDfjhUkV+ivhdDkYD7fa86JXWGBPzI6UAPxGezQxPk1H +goE6y/SJXQ7vTQ1unBuCJN0yJV0ReFEQPaA1IwQvZW+cwdFD19Ae8zFnWSfda9J1 +CZMRJCQUzym+5iPDuI9yP+kHyCREU3qzuWFloUwOxkgAyXVjBYdwRVKD05WdRerw +6DEdfgkfCv4+3ao8XnTSrLE= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- diff --git a/Makefile.3ds b/Makefile.3ds index 5fc2f56..5c72c06 100644 --- a/Makefile.3ds +++ b/Makefile.3ds @@ -52,7 +52,7 @@ RSF_FILE := meta/ftpd-classic-cia.rsf endif APP_DESCRIPTION := v$(VERSION) -APP_AUTHOR := (c) 2021 Michael Theall, Dave Murphy, TuxSH +APP_AUTHOR := (c) 2022 Michael Theall, Dave Murphy, TuxSH ICON := meta/icon.png BNR_IMAGE := meta/banner.png @@ -72,9 +72,10 @@ CFLAGS += $(INCLUDE) -DARM11 -D__3DS__ \ -DSTATUS_STRING="\"ftpd v$(VERSION)\"" \ -DIMGUI_DISABLE_INCLUDE_IMCONFIG_H=1 \ -DNO_IPV6 -DFTPDCONFIG="\"/config/ftpd/ftpd.cfg\"" \ - -DANTI_ALIAS=1 + -DANTI_ALIAS=1 \ + `curl-config --cflags` -CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17 +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++2a ASFLAGS := -g $(ARCH) LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) $(OPTIMIZE) @@ -82,7 +83,7 @@ LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) $(OPTIMIZE) CC := `which ccache 2>/dev/null` $(CC) CXX := `which ccache 2>/dev/null` $(CXX) -LIBS := -lcitro3d -lctru -lm +LIBS := `curl-config --libs` -lcitro3d -lctru -lm #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing diff --git a/Makefile.linux b/Makefile.linux index cb41a61..7af1532 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -12,10 +12,11 @@ CPPFLAGS := -g -Wall -pthread -Iinclude -Isource/linux \ -DSTATUS_STRING="\"ftpd v$(VERSION)\"" \ -DIMGUI_DISABLE_INCLUDE_IMCONFIG_H=1 \ -DIMGUI_IMPL_OPENGL_LOADER_GLAD=1 \ - -DFTPDCONFIG="\"ftpd.cfg\"" + -DFTPDCONFIG="\"ftpd.cfg\"" \ + `curl-config --cflags` CFLAGS := $(CPPFLAGS) -CXXFLAGS := $(CPPFLAGS) -std=gnu++17 -LDFLAGS := -pthread `pkg-config --libs gl glfw3` -ldl +CXXFLAGS := $(CPPFLAGS) -std=gnu++2a +LDFLAGS := -pthread `curl-config --libs` `pkg-config --libs gl glfw3` -ldl .PHONY: all clean diff --git a/Makefile.nds b/Makefile.nds index 283da3d..05e0ef1 100644 --- a/Makefile.nds +++ b/Makefile.nds @@ -35,7 +35,7 @@ NITRO := # These set the information text in the nds file GAME_TITLE := ftpd classic GAME_SUBTITLE1 := v$(VERSION) -GAME_SUBTITLE2 := (c) 2021 mtheall +GAME_SUBTITLE2 := (c) 2022 mtheall #--------------------------------------------------------------------------------- # options for code generation @@ -48,7 +48,7 @@ CFLAGS := -g -Wall $(OPTIMIZE) \ -DSTATUS_STRING="\"ftpd v$(VERSION)\"" \ -DIMGUI_DISABLE_INCLUDE_IMCONFIG_H=1 \ -DNO_IPV6 -DCLASSIC -DFTPDCONFIG="\"/config/ftpd/ftpd.cfg\"" -CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17 +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++2a ASFLAGS := -g $(ARCH) LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) $(OPTIMIZE) diff --git a/Makefile.switch b/Makefile.switch index 2141f46..e592647 100644 --- a/Makefile.switch +++ b/Makefile.switch @@ -37,7 +37,7 @@ include $(DEVKITPRO)/libnx/switch_rules # of a homebrew executable (.nro). This is intended to be used for sysmodules. # NACP building is skipped as well. #--------------------------------------------------------------------------------- -APP_AUTHOR := (c) 2021 Michael Theall, Dave Murphy, TuxSH +APP_AUTHOR := (c) 2022 Michael Theall, Dave Murphy, TuxSH ICON := meta/ftpd.jpg APP_VERSION := $(VERSION) @@ -75,9 +75,10 @@ CFLAGS += $(INCLUDE) -D__SWITCH__ \ -DSTATUS_STRING="\"ftpd v$(VERSION)\"" \ -DIMGUI_DISABLE_INCLUDE_IMCONFIG_H=1 \ -DFTPDCONFIG="\"/config/ftpd/ftpd.cfg\"" \ - `$(PREFIX)pkg-config --cflags libzstd` + `$(PREFIX)pkg-config --cflags libzstd` \ + `curl-config --cflags` -CXXFLAGS := $(CFLAGS) -std=gnu++17 -fno-exceptions -fno-rtti +CXXFLAGS := $(CFLAGS) -std=gnu++2a -fno-exceptions -fno-rtti ASFLAGS := -g $(ARCH) LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) \ @@ -86,7 +87,7 @@ LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) \ CC := `which ccache 2>/dev/null` $(CC) CXX := `which ccache 2>/dev/null` $(CXX) -LIBS := `$(PREFIX)pkg-config --libs libzstd` -ldeko3d -lnx +LIBS := `curl-config --libs` `$(PREFIX)pkg-config --libs libzstd` -ldeko3d -lnx #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing diff --git a/include/ftpConfig.h b/include/ftpConfig.h index 64c3959..d3c021d 100644 --- a/include/ftpConfig.h +++ b/include/ftpConfig.h @@ -3,7 +3,7 @@ // - RFC 3659 (https://tools.ietf.org/html/rfc3659) // - suggested implementation details from https://cr.yp.to/ftp/filesystem.html // -// Copyright (C) 2020 Michael Theall +// Copyright (C) 2022 Michael Theall // // 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 @@ -44,7 +44,7 @@ public: static UniqueFtpConfig load (char const *path_); #ifndef NDS - std::lock_guard lockGuard (); + std::scoped_lock lockGuard (); #endif /// \brief Save config diff --git a/include/ftpServer.h b/include/ftpServer.h index a0a21f0..2822309 100644 --- a/include/ftpServer.h +++ b/include/ftpServer.h @@ -3,7 +3,7 @@ // - RFC 3659 (https://tools.ietf.org/html/rfc3659) // - suggested implementation details from https://cr.yp.to/ftp/filesystem.html // -// Copyright (C) 2020 Michael Theall +// Copyright (C) 2022 Michael Theall // // 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 @@ -25,6 +25,10 @@ #include "platform.h" #include "socket.h" +#ifndef CLASSIC +#include +#endif + #include #include #include @@ -107,6 +111,20 @@ private: /// \brief Whether thread should quit std::atomic m_quit; +#ifndef CLASSIC + /// \brief Log upload cURL context + CURLM *m_uploadLogCurlM = nullptr; + /// \brief Log upload mime context + curl_mime *m_uploadLogMime = nullptr; + /// \brief Log upload cURL context + std::atomic m_uploadLogCurl = nullptr; + + /// \brief Log upload data + std::string m_uploadLogData; + /// \brief Log upload result + std::string m_uploadLogResult; +#endif + #ifndef CLASSIC /// \brief Whether to show settings menu bool m_showSettings = false; diff --git a/include/log.h b/include/log.h index a4e0ef7..a0a8659 100644 --- a/include/log.h +++ b/include/log.h @@ -3,7 +3,7 @@ // - RFC 3659 (https://tools.ietf.org/html/rfc3659) // - suggested implementation details from https://cr.yp.to/ftp/filesystem.html // -// Copyright (C) 2020 Michael Theall +// Copyright (C) 2022 Michael Theall // // 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 @@ -37,6 +37,11 @@ enum LogLevel /// \brief Draw log void drawLog (); +#ifndef CLASSIC +/// \brief Get log +std::string getLog (); +#endif + /// \brief Add debug message to bound log /// \param fmt_ Message format __attribute__ ((format (printf, 1, 2))) void debug (char const *fmt_, ...); diff --git a/source/3ds/platform.cpp b/source/3ds/platform.cpp index 278c5d0..fa34d4f 100644 --- a/source/3ds/platform.cpp +++ b/source/3ds/platform.cpp @@ -168,7 +168,7 @@ void handleAPTHook (APT_HookType const type_, void *const param_) bool getNetworkVisibility () { // serialize ac:u access from multiple threads - auto lock = std::lock_guard (s_acuFence); + auto const lock = std::scoped_lock (s_acuFence); // get wifi status std::uint32_t wifi = 0; diff --git a/source/ftpConfig.cpp b/source/ftpConfig.cpp index 52cc687..461d11f 100644 --- a/source/ftpConfig.cpp +++ b/source/ftpConfig.cpp @@ -3,7 +3,7 @@ // - RFC 3659 (https://tools.ietf.org/html/rfc3659) // - suggested implementation details from https://cr.yp.to/ftp/filesystem.html // -// Copyright (C) 2021 Michael Theall +// Copyright (C) 2022 Michael Theall // // 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 @@ -187,9 +187,9 @@ UniqueFtpConfig FtpConfig::load (char const *const path_) } #ifndef NDS -std::lock_guard FtpConfig::lockGuard () +std::scoped_lock FtpConfig::lockGuard () { - return std::lock_guard (m_lock); + return std::scoped_lock (m_lock); } #endif diff --git a/source/ftpServer.cpp b/source/ftpServer.cpp index fcd21ac..fb6f9b8 100644 --- a/source/ftpServer.cpp +++ b/source/ftpServer.cpp @@ -3,7 +3,7 @@ // - RFC 3659 (https://tools.ietf.org/html/rfc3659) // - suggested implementation details from https://cr.yp.to/ftp/filesystem.html // -// Copyright (C) 2021 Michael Theall +// Copyright (C) 2022 Michael Theall // // 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 @@ -52,7 +52,7 @@ using namespace std::chrono_literals; #define LOCKED(x) \ do \ { \ - auto const lock = std::lock_guard (m_lock); \ + auto const lock = std::scoped_lock (m_lock); \ x; \ } while (0) #endif @@ -69,6 +69,86 @@ platform::Mutex s_lock; /// \brief Free space string std::string s_freeSpace; + +#ifndef CLASSIC +#ifndef NDEBUG +std::string printable (char *const data_, std::size_t const size_) +{ + std::string result; + result.reserve (size_); + + for (std::size_t i = 0; i < size_; ++i) + { + if (std::isprint (data_[i]) || std::isspace (data_[i])) + result.push_back (data_[i]); + else + { + char buffer[5]; + std::snprintf (buffer, sizeof (buffer), "%%%02u", static_cast (data_[i])); + result += buffer; + } + } + + return result; +} + +int curlDebug (CURL *const handle_, curl_infotype const type_, char *const data_, std::size_t const size_, void *const user_) +{ + (void)user_; + + auto const text = printable (data_, size_); + + switch (type_) + { + case CURLINFO_TEXT: + info ("== Info: %s", text.c_str ()); + break; + + case CURLINFO_HEADER_OUT: + info ("=> Send header: %s", text.c_str ()); + break; + + case CURLINFO_DATA_OUT: + info ("=> Send data: %s", text.c_str ()); + break; + + case CURLINFO_SSL_DATA_OUT: + info ("=> Send SSL data: %s", text.c_str ()); + break; + + case CURLINFO_HEADER_IN: + info ("<= Receive header: %s", text.c_str ()); + break; + + case CURLINFO_DATA_IN: + info ("<= Receive data: %s", text.c_str ()); + break; + + case CURLINFO_SSL_DATA_IN: + info ("<= Receive SSL data: %s", text.c_str ()); + break; + + default: + break; + } + + return 0; +} +#endif + +std::size_t curlCallback (void *const contents_, std::size_t const size_, std::size_t const count_, void *const user_) +{ + + auto const total = size_ * count_; + auto const start = static_cast (contents_); + auto const end = start + total; + + auto &result = *static_cast (user_); + result.insert (std::end (result), start, end); + + return total; +} +#endif } /////////////////////////////////////////////////////////////////////////// @@ -79,6 +159,18 @@ FtpServer::~FtpServer () #ifndef NDS m_thread.join (); #endif + +#ifndef CLASSIC + if (m_uploadLogCurl) + { + curl_multi_remove_handle (m_uploadLogCurlM, m_uploadLogCurl); + curl_easy_cleanup (m_uploadLogCurl); + curl_mime_free (m_uploadLogMime); + } + + if (m_uploadLogCurlM) + curl_multi_cleanup (m_uploadLogCurlM); +#endif } FtpServer::FtpServer (UniqueFtpConfig config_) : m_config (std::move (config_)), m_quit (false) @@ -98,7 +190,7 @@ void FtpServer::draw () { char port[7]; #ifndef NDS - auto const lock = std::lock_guard (m_lock); + auto const lock = std::scoped_lock (m_lock); #endif if (m_socket) std::sprintf (port, ":%u", m_socket->sockName ().port ()); @@ -123,7 +215,7 @@ void FtpServer::draw () { #ifndef NDS - auto const lock = std::lock_guard (s_lock); + auto const lock = std::scoped_lock (s_lock); #endif if (!s_freeSpace.empty ()) { @@ -137,7 +229,7 @@ void FtpServer::draw () { #ifndef NDS - auto const lock = std::lock_guard (m_lock); + auto const lock = std::scoped_lock (m_lock); #endif consoleSelect (&g_sessionConsole); std::fputs ("\x1b[2J", stdout); @@ -167,7 +259,7 @@ void FtpServer::draw () char title[64]; { - auto const serverLock = std::lock_guard (m_lock); + auto const serverLock = std::scoped_lock (m_lock); std::snprintf (title, sizeof (title), STATUS_STRING " %s###ftpd", @@ -213,7 +305,7 @@ void FtpServer::draw () #endif { - auto const lock = std::lock_guard (m_lock); + auto const lock = std::scoped_lock (m_lock); for (auto &session : m_sessions) session->draw (); } @@ -234,7 +326,7 @@ UniqueFtpServer FtpServer::create () std::string FtpServer::getFreeSpace () { #ifndef NDS - auto const lock = std::lock_guard (s_lock); + auto const lock = std::scoped_lock (s_lock); #endif return s_freeSpace; } @@ -252,7 +344,7 @@ void FtpServer::updateFreeSpace () auto freeSpace = fs::printSize (static_cast (st.f_bsize) * st.f_bfree); #ifndef NDS - auto const lock = std::lock_guard (s_lock); + auto const lock = std::scoped_lock (s_lock); #endif if (freeSpace != s_freeSpace) s_freeSpace = std::move (freeSpace); @@ -330,7 +422,7 @@ void FtpServer::showMenu () if (ImGui::BeginMenuBar ()) { #if defined(__3DS__) || defined(__SWITCH__) - if (ImGui::BeginMenu (u8"Menu \xee\x80\x83")) // Y Button + if (ImGui::BeginMenu ("Menu \xee\x80\x83")) // Y Button #else if (ImGui::BeginMenu ("Menu")) #endif @@ -338,6 +430,58 @@ void FtpServer::showMenu () if (ImGui::MenuItem ("Settings")) m_showSettings = true; + if (ImGui::MenuItem ("Upload Log")) + { +#ifndef NDS + auto const lock = std::scoped_lock (m_lock); +#endif + if (!m_uploadLogCurlM) + m_uploadLogCurlM = curl_multi_init (); + + if (m_uploadLogCurlM && !m_uploadLogCurl.load (std::memory_order_relaxed)) + { + m_uploadLogData = getLog (); + + auto const handle = curl_easy_init (); + +#ifdef __3DS__ + // 3DS CA fails peer verification, so add CA here + curl_easy_setopt (handle, CURLOPT_CAINFO, "romfs:/sni.cloudflaressl.com.ca"); +#endif + +#ifndef NDEBUG + curl_easy_setopt (handle, CURLOPT_DEBUGFUNCTION, &curlDebug); + curl_easy_setopt (handle, CURLOPT_DEBUGDATA, nullptr); + curl_easy_setopt (handle, CURLOPT_VERBOSE, 1L); +#endif + + // write result into string + m_uploadLogResult.clear (); + curl_easy_setopt (handle, CURLOPT_WRITEFUNCTION, &curlCallback); + curl_easy_setopt (handle, CURLOPT_WRITEDATA, &m_uploadLogResult); + + // set headers + static char contentType[] = "Content-Type: multipart/form-data"; + static curl_slist const headers = { contentType, nullptr }; + curl_easy_setopt (handle, CURLOPT_URL, "https://hastebin.com/documents"); + curl_easy_setopt (handle, CURLOPT_HTTPHEADER, &headers); + + // set form data + auto const mime = curl_mime_init (handle); + auto const part = curl_mime_addpart (mime); + curl_mime_name (part, "data"); + curl_mime_data (part, m_uploadLogData.data (), m_uploadLogData.size ()); + curl_easy_setopt (handle, CURLOPT_MIMEPOST, mime); + + // add to multi handle + curl_multi_add_handle (m_uploadLogCurlM, handle); + + // signal network thread to process + m_uploadLogMime = mime; + m_uploadLogCurl.store (handle, std::memory_order_relaxed); + } + } + if (ImGui::MenuItem ("About")) m_showAbout = true; @@ -666,6 +810,49 @@ void FtpServer::loop () handleNetworkFound (); } +#ifndef CLASSIC + { + auto const lock = std::scoped_lock (m_lock); + if (m_uploadLogCurl.load (std::memory_order_relaxed)) + { + int busy = 0; + auto const mc = curl_multi_perform (m_uploadLogCurlM, &busy); + if (mc != CURLM_OK) + { + error ("curl_multi_perform: %d %s\n", mc, curl_multi_strerror (mc)); + + curl_multi_remove_handle (m_uploadLogCurlM, m_uploadLogCurl); + curl_easy_cleanup (m_uploadLogCurl); + curl_mime_free (m_uploadLogMime); + m_uploadLogMime = nullptr; + m_uploadLogCurl.store (nullptr, std::memory_order_relaxed); + } + else + { + int count = 0; + auto const msg = curl_multi_info_read (m_uploadLogCurlM, &count); + if (msg && msg->msg == CURLMSG_DONE && msg->easy_handle == m_uploadLogCurl) + { + if (msg->data.result != CURLE_OK) + info ("cURL finished with status %d\n", msg->data.result); + + if (m_uploadLogResult.starts_with ("{\"key\":\"")) + { + auto const key = m_uploadLogResult.substr (8, 10); + info ("https://hastebin.com/%s\n", key.c_str ()); + } + + curl_multi_remove_handle (m_uploadLogCurlM, m_uploadLogCurl); + curl_easy_cleanup (m_uploadLogCurl); + curl_mime_free (m_uploadLogMime); + m_uploadLogMime = nullptr; + m_uploadLogCurl.store (nullptr, std::memory_order_relaxed); + } + } + } + } +#endif + // poll listen socket if (m_socket) { @@ -698,7 +885,7 @@ void FtpServer::loop () { // remove dead sessions #ifndef NDS - auto const lock = std::lock_guard (m_lock); + auto const lock = std::scoped_lock (m_lock); #endif auto it = std::begin (m_sessions); while (it != std::end (m_sessions)) diff --git a/source/ftpSession.cpp b/source/ftpSession.cpp index 8922345..a902640 100644 --- a/source/ftpSession.cpp +++ b/source/ftpSession.cpp @@ -3,7 +3,7 @@ // - RFC 3659 (https://tools.ietf.org/html/rfc3659) // - suggested implementation details from https://cr.yp.to/ftp/filesystem.html // -// Copyright (C) 2020 Michael Theall +// Copyright (C) 2022 Michael Theall // // 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 @@ -50,7 +50,7 @@ using namespace std::chrono_literals; #define LOCKED(x) \ do \ { \ - auto const lock = std::lock_guard (m_lock); \ + auto const lock = std::scoped_lock (m_lock); \ x; \ } while (0) #endif @@ -318,7 +318,7 @@ FtpSession::FtpSession (FtpConfig &config_, UniqueSocket commandSocket_) bool FtpSession::dead () { #ifndef NDS - auto const lock = std::lock_guard (m_lock); + auto const lock = std::scoped_lock (m_lock); #endif if (m_commandSocket || m_pasvSocket || m_dataSocket) return false; @@ -329,7 +329,7 @@ bool FtpSession::dead () void FtpSession::draw () { #ifndef NDS - auto const lock = std::lock_guard (m_lock); + auto const lock = std::scoped_lock (m_lock); #endif #ifdef CLASSIC @@ -615,7 +615,7 @@ void FtpSession::setState (State const state_, bool const closePasv_, bool const { { #ifndef NDS - auto lock = std::lock_guard (m_lock); + auto const lock = std::scoped_lock (m_lock); #endif m_restartPosition = 0; diff --git a/source/log.cpp b/source/log.cpp index 6ec4594..3b82ada 100644 --- a/source/log.cpp +++ b/source/log.cpp @@ -3,7 +3,7 @@ // - RFC 3659 (https://tools.ietf.org/html/rfc3659) // - suggested implementation details from https://cr.yp.to/ftp/filesystem.html // -// Copyright (C) 2020 Michael Theall +// Copyright (C) 2022 Michael Theall // // 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 @@ -25,6 +25,7 @@ #include "imgui.h" #include +#include #include namespace @@ -79,7 +80,7 @@ platform::Mutex s_lock; void drawLog () { #ifndef NDS - auto const lock = std::lock_guard (s_lock); + auto const lock = std::scoped_lock (s_lock); #endif #ifdef CLASSIC @@ -149,6 +150,39 @@ void drawLog () #endif } +#ifndef CLASSIC +std::string getLog () +{ +#ifndef NDS + auto const lock = std::scoped_lock (s_lock); +#endif + + if (s_messages.empty ()) + return {}; + + std::vector stack; + stack.reserve (s_messages.size ()); + + std::size_t size = 0; + for (auto const &msg : s_messages | std::views::reverse) + { + if (size + msg.message.size () > 1024 * 1024) + break; + + size += msg.message.size (); + stack.emplace_back (&msg); + } + + std::string log; + log.reserve (size); + + for (auto const &msg : stack | std::views::reverse) + log += msg->message; + + return log; +} +#endif + void debug (char const *const fmt_, ...) { #ifndef NDEBUG @@ -211,7 +245,7 @@ void addLog (LogLevel const level_, char const *const fmt_, va_list ap_) std::vsnprintf (buffer, sizeof (buffer), fmt_, ap_); #ifndef NDS - auto const lock = std::lock_guard (s_lock); + auto const lock = std::scoped_lock (s_lock); #endif #ifndef NDEBUG // std::fprintf (stderr, "%s", s_prefix[level_]); @@ -239,7 +273,7 @@ void addLog (LogLevel const level_, std::string_view const message_) } #ifndef NDS - auto const lock = std::lock_guard (s_lock); + auto const lock = std::scoped_lock (s_lock); #endif #ifndef NDEBUG // std::fprintf (stderr, "%s", s_prefix[level_]); diff --git a/source/main.cpp b/source/main.cpp index def262b..f7f098c 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -3,7 +3,7 @@ // - RFC 3659 (https://tools.ietf.org/html/rfc3659) // - suggested implementation details from https://cr.yp.to/ftp/filesystem.html // -// Copyright (C) 2020 Michael Theall +// Copyright (C) 2022 Michael Theall // // 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 @@ -24,12 +24,17 @@ #include "imgui.h" +#ifndef CLASSIC +#include +#endif + #include #include int main (int argc_, char *argv_[]) { #ifndef CLASSIC + curl_global_init (CURL_GLOBAL_ALL); IMGUI_CHECKVERSION (); ImGui::CreateContext (); #endif @@ -65,5 +70,6 @@ int main (int argc_, char *argv_[]) #ifndef CLASSIC ImGui::DestroyContext (); + curl_global_cleanup (); #endif }