├── src ├── Slunk.h ├── Types.cpp ├── Sink_Abstract.cpp ├── Timer.h ├── Average.h ├── Sink_Abstract.h ├── Sink_Null.h ├── Sink_StdOut.h ├── Types.h ├── Compat.h ├── Sink_File.h ├── Client_FTP.h ├── Thread.h ├── Sink_Null.cpp ├── URL.h ├── Utils.h ├── Average.cpp ├── Timer.cpp ├── Sink_StdOut.cpp ├── Sync.h ├── Client_HTTP.h ├── Client_Abstract.h ├── Sink_File.cpp ├── Params.h ├── Sync.cpp ├── Client_FTP.cpp ├── URL.cpp ├── Version.h ├── Zero.cpp ├── Thread.cpp ├── Client_Abstract.cpp ├── Params.cpp └── Client_HTTP.cpp ├── etc ├── bin │ ├── date.exe │ └── zip.exe ├── lib │ └── EncodePointer.lib ├── examples │ ├── multi_download_example.bat │ └── multi_download_example.py └── doc │ └── Style.inc ├── res ├── inetget.ico └── compat.manifest ├── img └── inetget │ └── inetget.png ├── .gitignore ├── z_paths.bat.template ├── z_mkdocs.bat ├── INetGet_VC100.sln ├── INetGet_VC120.sln ├── INetGet.rcc ├── INetGet_VC100.vcxproj.filters ├── INetGet_VC120.vcxproj.filters ├── z_build.bat ├── INetGet_VC120.vcxproj ├── INetGet_VC100.vcxproj └── LICENSE.md /src/Slunk.h: -------------------------------------------------------------------------------- 1 | bool slunk_handler(void); 2 | -------------------------------------------------------------------------------- /src/Types.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lordmulder/INetGet/HEAD/src/Types.cpp -------------------------------------------------------------------------------- /etc/bin/date.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lordmulder/INetGet/HEAD/etc/bin/date.exe -------------------------------------------------------------------------------- /etc/bin/zip.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lordmulder/INetGet/HEAD/etc/bin/zip.exe -------------------------------------------------------------------------------- /res/inetget.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lordmulder/INetGet/HEAD/res/inetget.ico -------------------------------------------------------------------------------- /img/inetget/inetget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lordmulder/INetGet/HEAD/img/inetget/inetget.png -------------------------------------------------------------------------------- /etc/lib/EncodePointer.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lordmulder/INetGet/HEAD/etc/lib/EncodePointer.lib -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /obj 3 | /out 4 | z_paths.bat 5 | *.sdf 6 | *.suo 7 | *.opensdf 8 | *.user 9 | *.local.* 10 | /ipch 11 | /src/*.ori 12 | -------------------------------------------------------------------------------- /etc/examples/multi_download_example.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set "PYTHON_DIR=C:\Program Files\Python36" 3 | set "PATH=%PYTHON_DIR%,%PATH%" 4 | cd /d "%~dp0" 5 | "%PYTHON_DIR%\python.exe" "%~dpn0.py" %1 %2 %3 %4 %5 %6 %7 %8 %9 6 | set RESULT=%ERRORLEVEL% 7 | exit /b %RESULT% 8 | -------------------------------------------------------------------------------- /z_paths.bat.template: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set "INETGET_MSVC_PATH=C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC" 4 | set "INETGET_UPX3_PATH=C:\Program Files (x86)\UPX" 5 | set "INETGET_PDOC_PATH=C:\Program Files (x86)\Pandoc" 6 | set "INETGET_HTMC_PATH=C:\Program Files (x86)\HTMLCompressor\bin" 7 | set "INETGET_TOOL_VERS=100" 8 | -------------------------------------------------------------------------------- /res/compat.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /etc/doc/Style.inc: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /z_mkdocs.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | REM /////////////////////////////////////////////////////////////////////////// 4 | REM // INetGet - Lightweight command-line front-end to WinINet API 5 | REM // Copyright (C) 2018 LoRd_MuldeR 6 | REM /////////////////////////////////////////////////////////////////////////// 7 | 8 | call "%~dp0\z_paths.bat" 9 | cd /d "%~dp0" 10 | set "PATH=%INETGET_HTMC_PATH%;%PATH%" 11 | 12 | echo --------------------------------------------------------------------- 13 | echo GENERATING DOCS 14 | echo --------------------------------------------------------------------- 15 | echo. 16 | 17 | for %%i in (*.md) do ( 18 | echo %%~ni --^> %%~ni.local.html 19 | "%INETGET_PDOC_PATH%\pandoc.exe" --from markdown_github+pandoc_title_block+header_attributes+implicit_figures --to html5 -H "%~dp0\etc\doc\Style.inc" --standalone "%%~i" | "%JAVA_HOME%\bin\java.exe" -jar "%INETGET_HTMC_PATH%\htmlcompressor-1.5.3.jar" --compress-css --compress-js -o "%~dp0\%%~ni.local.html" 20 | echo. 21 | ) 22 | -------------------------------------------------------------------------------- /src/Sink_Abstract.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #include "Sink_Abstract.h" 23 | 24 | AbstractSink::AbstractSink() 25 | { 26 | } 27 | 28 | AbstractSink::~AbstractSink() 29 | { 30 | } 31 | -------------------------------------------------------------------------------- /INetGet_VC100.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "INetGet_VC100", "INetGet_VC100.vcxproj", "{157E1DB2-A934-4AB6-99CF-626AADB42F79}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Debug|x64 = Debug|x64 10 | Release|Win32 = Release|Win32 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {157E1DB2-A934-4AB6-99CF-626AADB42F79}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {157E1DB2-A934-4AB6-99CF-626AADB42F79}.Debug|Win32.Build.0 = Debug|Win32 16 | {157E1DB2-A934-4AB6-99CF-626AADB42F79}.Debug|x64.ActiveCfg = Debug|x64 17 | {157E1DB2-A934-4AB6-99CF-626AADB42F79}.Debug|x64.Build.0 = Debug|x64 18 | {157E1DB2-A934-4AB6-99CF-626AADB42F79}.Release|Win32.ActiveCfg = Release|Win32 19 | {157E1DB2-A934-4AB6-99CF-626AADB42F79}.Release|Win32.Build.0 = Release|Win32 20 | {157E1DB2-A934-4AB6-99CF-626AADB42F79}.Release|x64.ActiveCfg = Release|x64 21 | {157E1DB2-A934-4AB6-99CF-626AADB42F79}.Release|x64.Build.0 = Release|x64 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /INetGet_VC120.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.40629.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "INetGet_VC120", "INetGet_VC120.vcxproj", "{157E1DB2-A934-4AB6-99CF-626AADB42F79}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Release|Win32 = Release|Win32 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {157E1DB2-A934-4AB6-99CF-626AADB42F79}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {157E1DB2-A934-4AB6-99CF-626AADB42F79}.Debug|Win32.Build.0 = Debug|Win32 18 | {157E1DB2-A934-4AB6-99CF-626AADB42F79}.Debug|x64.ActiveCfg = Debug|x64 19 | {157E1DB2-A934-4AB6-99CF-626AADB42F79}.Debug|x64.Build.0 = Debug|x64 20 | {157E1DB2-A934-4AB6-99CF-626AADB42F79}.Release|Win32.ActiveCfg = Release|Win32 21 | {157E1DB2-A934-4AB6-99CF-626AADB42F79}.Release|Win32.Build.0 = Release|Win32 22 | {157E1DB2-A934-4AB6-99CF-626AADB42F79}.Release|x64.ActiveCfg = Release|x64 23 | {157E1DB2-A934-4AB6-99CF-626AADB42F79}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /src/Timer.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | class Timer 27 | { 28 | public: 29 | Timer(void); 30 | ~Timer(void); 31 | 32 | void reset(void); 33 | double query(void); 34 | 35 | private: 36 | uint64_t m_reference; 37 | const uint64_t m_frequency; 38 | }; 39 | 40 | -------------------------------------------------------------------------------- /src/Average.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | class Average 29 | { 30 | public: 31 | Average(const uint32_t &queue_len); 32 | ~Average(); 33 | 34 | double update(const double &value); 35 | 36 | private: 37 | const uint32_t m_queue_len; 38 | std::deque m_values; 39 | double m_current; 40 | }; 41 | -------------------------------------------------------------------------------- /src/Sink_Abstract.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | #include "Sync.h" 27 | 28 | class AbstractSink 29 | { 30 | public: 31 | AbstractSink(void); 32 | virtual ~AbstractSink(void); 33 | 34 | virtual bool open(void) = 0; 35 | virtual bool close(const bool &success) = 0; 36 | 37 | virtual bool write(uint8_t *const buffer, const size_t &count) = 0; 38 | 39 | //Thread-safety 40 | Sync::Mutex m_mutex; 41 | }; 42 | -------------------------------------------------------------------------------- /src/Sink_Null.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #pragma once 23 | 24 | #include "Sink_Abstract.h" 25 | 26 | #include 27 | #include 28 | 29 | class NullSink : public AbstractSink 30 | { 31 | public: 32 | NullSink(void); 33 | virtual ~NullSink(void); 34 | 35 | virtual bool open(void); 36 | virtual bool close(const bool &success); 37 | 38 | virtual bool write(uint8_t *const buffer, const size_t &count); 39 | 40 | private: 41 | bool m_isOpen; 42 | }; 43 | 44 | -------------------------------------------------------------------------------- /src/Sink_StdOut.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #pragma once 23 | 24 | #include "Sink_Abstract.h" 25 | 26 | #include 27 | #include 28 | 29 | class StdOutSink : public AbstractSink 30 | { 31 | public: 32 | StdOutSink(void); 33 | virtual ~StdOutSink(void); 34 | 35 | virtual bool open(void); 36 | virtual bool close(const bool &success); 37 | 38 | virtual bool write(uint8_t *const buffer, const size_t &count); 39 | 40 | private: 41 | bool m_isOpen; 42 | }; 43 | 44 | -------------------------------------------------------------------------------- /src/Types.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | //HTTP status codes 27 | typedef struct 28 | { 29 | const uint32_t code; 30 | const wchar_t *const info; 31 | } 32 | http_status_t; 33 | 34 | //List of status codes 35 | extern const http_status_t STATUS_CODES[]; 36 | 37 | //HTTP methods (verbs) 38 | typedef enum 39 | { 40 | HTTP_GET = 0x0, 41 | HTTP_POST = 0x1, 42 | HTTP_PUT = 0x2, 43 | HTTP_DELETE = 0x3, 44 | HTTP_HEAD = 0x4, 45 | HTTP_UNDEF = 0xF, 46 | } 47 | http_verb_t; 48 | -------------------------------------------------------------------------------- /src/Compat.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #if _MSC_VER >= 1800 23 | #define ISNAN(X) std::isnan((X)) 24 | #define ROUND(X) std::round((X)) 25 | #else 26 | #define ISNAN(X) _isnan((X)) 27 | #include 28 | static inline double ROUND(const double &d) 29 | { 30 | return (d >= 0.0) ? floor(d + 0.5) : ceil(d - 0.5); 31 | } 32 | #endif 33 | 34 | #define DBL_TO_UINT32(X) (((X) < UINT32_MAX) ? uint32_t((X)) : UINT32_MAX) 35 | 36 | #define DBL_VALID_GTR(X,Y) ((!ISNAN((X))) && ((X) > (Y))) 37 | #define DBL_VALID_LSS(X,Y) ((!ISNAN((X))) && ((X) < (Y))) 38 | #define DBL_VALID_GEQ(X,Y) ((!ISNAN((X))) && ((X) >= (Y))) 39 | #define DBL_VALID_LEQ(X,Y) ((!ISNAN((X))) && ((X) <= (Y))) 40 | -------------------------------------------------------------------------------- /src/Sink_File.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #pragma once 23 | 24 | #include "Sink_Abstract.h" 25 | 26 | #include 27 | #include 28 | 29 | class FileSink : public AbstractSink 30 | { 31 | public: 32 | FileSink(const std::wstring &fileName, const uint64_t ×tamp = 0, const bool &keepFailed = false); 33 | virtual ~FileSink(void); 34 | 35 | virtual bool open(void); 36 | virtual bool close(const bool &success); 37 | 38 | virtual bool write(uint8_t *const buffer, const size_t &count); 39 | 40 | private: 41 | const uint64_t m_timestamp; 42 | const std::wstring m_fileName; 43 | const bool m_keepFailed; 44 | 45 | uintptr_t m_handle; 46 | }; 47 | 48 | -------------------------------------------------------------------------------- /src/Client_FTP.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #pragma once 23 | 24 | #include "Client_Abstract.h" 25 | 26 | class FtpClient : public AbstractClient 27 | { 28 | public: 29 | //Constructor & destructor 30 | FtpClient(const Sync::Signal &user_aborted, const bool &disable_proxy = false, const std::wstring &userAgentStr = std::wstring(), const bool &no_redir = false, const bool &insecure = false, const double &timeout_con = -1.0, const double &timeout_rcv = -1.0, const uint32_t &connect_retry = 3, const bool &verbose = false); 31 | virtual ~FtpClient(void); 32 | 33 | //Connection handling 34 | virtual bool open(const http_verb_t &verb, const URL &url, const std::string &post_data, const std::wstring &referrer, const uint64_t ×tamp); 35 | virtual bool close(void); 36 | 37 | //Fetch result 38 | virtual bool result(bool &success, uint32_t &status_code, uint64_t &file_size, uint64_t &time_stamp, std::wstring &content_type, std::wstring &content_encd); 39 | 40 | //Read payload 41 | virtual bool read_data(uint8_t *out_buff, const uint32_t &buff_size, size_t &bytes_read, bool &eof_flag); 42 | }; 43 | -------------------------------------------------------------------------------- /src/Thread.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | 27 | #include "Sync.h" 28 | 29 | class Thread 30 | { 31 | public: 32 | Thread(); 33 | ~Thread(); 34 | 35 | //Start 36 | bool start(void); 37 | 38 | //Stop 39 | bool join(const uint32_t &timeout = 0U); 40 | bool join(const Sync::Signal &interrupt, const uint32_t &timeout = 0U); 41 | bool stop(const uint32_t &timeout = 0U, const bool &force = false); 42 | 43 | //Info 44 | bool is_running(void) const; 45 | uint32_t get_result(void) const; 46 | 47 | //Error text 48 | std::wstring get_error_text(void) const 49 | { 50 | return m_error_text.get(); 51 | } 52 | 53 | private: 54 | void close_handle(void); 55 | static uint32_t __stdcall thread_start(void *const data); 56 | 57 | Sync::Event m_event_stop; 58 | Sync::Signal m_signal_stop; 59 | 60 | Sync::Interlocked m_error_text; 61 | 62 | uintptr_t m_thread; 63 | 64 | protected: 65 | virtual uint32_t main(void) = 0; 66 | void set_error_text(const std::wstring &text = std::wstring()); 67 | bool is_stopped(void); 68 | Sync::Interlocked m_priority; 69 | }; 70 | 71 | -------------------------------------------------------------------------------- /src/Sink_Null.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #include "Sink_Null.h" 23 | 24 | //Internal 25 | #include "Utils.h" 26 | 27 | //CRT 28 | #include 29 | #include 30 | 31 | //============================================================================= 32 | // CONSTRUCTOR / DESTRUCTOR 33 | //============================================================================= 34 | 35 | NullSink::NullSink(void) 36 | : 37 | m_isOpen(false) 38 | { 39 | } 40 | 41 | NullSink::~NullSink(void) 42 | { 43 | close(false); 44 | } 45 | 46 | //============================================================================= 47 | // OPEN / CLOSE 48 | //============================================================================= 49 | 50 | bool NullSink::open(void) 51 | { 52 | Sync::Locker locker(m_mutex); 53 | m_isOpen = true; 54 | return true; 55 | } 56 | 57 | bool NullSink::close(const bool& /*success*/) 58 | { 59 | Sync::Locker locker(m_mutex); 60 | m_isOpen = false; 61 | return true; 62 | } 63 | 64 | //============================================================================= 65 | // WRITE 66 | //============================================================================= 67 | 68 | bool NullSink::write(uint8_t *const, const size_t&) 69 | { 70 | Sync::Locker locker(m_mutex); 71 | if(m_isOpen) 72 | { 73 | return true; 74 | } 75 | return false; 76 | } 77 | -------------------------------------------------------------------------------- /src/URL.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | 27 | class URL 28 | { 29 | public: 30 | URL(const URL &url); 31 | URL(const std::wstring &url); 32 | ~URL(void); 33 | 34 | //Getter 35 | inline const int16_t &getScheme (void) const { return m_iSchemeId; } 36 | inline const std::wstring &getHostName (void) const { return m_strHostName; } 37 | inline const std::wstring &getUserName (void) const { return m_strUserName; } 38 | inline const std::wstring &getPassword (void) const { return m_strPassword; } 39 | inline const std::wstring &getUrlPath (void) const { return m_strUrlPath; } 40 | inline const std::wstring &getExtraInfo(void) const { return m_strExtraInfo; } 41 | inline const uint16_t &getPortNo (void) const { return m_uiPortNumber; } 42 | 43 | //Public Functions 44 | bool isComplete(void) const; 45 | std::wstring toString(void) const; 46 | 47 | //Static Functions 48 | static std::wstring urlEncode(const std::wstring &url); 49 | static std::string urlEncode(const std::string &url); 50 | 51 | private: 52 | std::wstring m_strScheme; 53 | std::wstring m_strHostName; 54 | std::wstring m_strUserName; 55 | std::wstring m_strPassword; 56 | std::wstring m_strUrlPath; 57 | std::wstring m_strExtraInfo; 58 | 59 | int16_t m_iSchemeId; 60 | uint16_t m_uiPortNumber; 61 | }; 62 | 63 | -------------------------------------------------------------------------------- /src/Utils.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #pragma once 23 | 24 | //CRT 25 | #include 26 | #include 27 | 28 | //Internal 29 | #include "Types.h" 30 | #include "Sync.h" 31 | 32 | namespace Utils 33 | { 34 | static const uint64_t TICKS_PER_SECCOND = 10000000ui64; 35 | 36 | std::wstring &trim(std::wstring &str); 37 | bool next_token(const std::wstring &str, const wchar_t *sep, std::wstring &token, size_t &offset); 38 | 39 | std::wstring exe_path(const std::wstring &suffix = std::wstring()); 40 | bool file_exists(const std::wstring &path); 41 | 42 | void set_console_title(const std::wstring &title); 43 | 44 | std::wstring win_error_string(const uint32_t &error_code); 45 | std::wstring crt_error_string(const int &error_code); 46 | std::wstring status_to_string(const uint32_t &rspns_code); 47 | 48 | std::wstring nbytes_to_string(const double &count); 49 | std::wstring second_to_string(const double &count); 50 | 51 | std::string wide_str_to_utf8(const std::wstring &str); 52 | std::wstring utf8_to_wide_str(const std::string &str); 53 | 54 | void trigger_system_sound(const bool &success); 55 | 56 | uint64_t parse_timestamp(const std::wstring &str); 57 | std::wstring timestamp_to_str(const uint64_t ×tamp); 58 | time_t decode_date_str(const char *const date_str); 59 | 60 | uint64_t get_file_time(const std::wstring &path); 61 | bool set_file_time(const int &file_no, const uint64_t ×tamp); 62 | } 63 | -------------------------------------------------------------------------------- /src/Average.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #include "Average.h" 23 | #include "Compat.h" 24 | 25 | //CRT 26 | #include 27 | #include 28 | #include 29 | 30 | //Const 31 | static const uint32_t MIN_LEN = 3; 32 | static const double PI = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679; 33 | static const double ALPHA = 0.25; 34 | 35 | Average::Average(const uint32_t &queue_len) 36 | : 37 | m_queue_len(queue_len), 38 | m_current(std::numeric_limits::quiet_NaN()) 39 | { 40 | } 41 | 42 | Average::~Average() 43 | { 44 | } 45 | 46 | double Average::update(const double &value) 47 | { 48 | m_values.push_back(value); 49 | while(m_values.size() > m_queue_len) 50 | { 51 | m_values.pop_front(); 52 | } 53 | 54 | if(m_values.size() >= MIN_LEN) 55 | { 56 | std::vector sorted(m_values.cbegin(), m_values.cend()); 57 | std::sort(sorted.begin(), sorted.end()); 58 | 59 | const size_t skip_count = sorted.size() / 10U; 60 | const size_t limit = sorted.size() - skip_count; 61 | 62 | double mean_value = 0.0; 63 | for(size_t i = skip_count; i < limit; i++) 64 | { 65 | mean_value += (sorted[i] / double(sorted.size())); 66 | } 67 | 68 | if(ISNAN(m_current)) 69 | { 70 | m_current = mean_value; 71 | } 72 | 73 | return m_current = (mean_value * ALPHA) + (m_current * (1.0 - ALPHA)); 74 | } 75 | 76 | return std::numeric_limits::quiet_NaN(); 77 | } 78 | -------------------------------------------------------------------------------- /src/Timer.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #include "Timer.h" 23 | 24 | //Win32 25 | #define WIN32_LEAN_AND_MEAN 1 26 | #include 27 | 28 | //CRT 29 | #include 30 | 31 | static inline uint64_t query_frequency(void) 32 | { 33 | LARGE_INTEGER frequency; 34 | if(!QueryPerformanceFrequency(&frequency)) 35 | { 36 | throw std::runtime_error("QueryPerformanceFrequency() has failed!"); 37 | } 38 | return (uint64_t) max(frequency.QuadPart, 0i64); 39 | } 40 | 41 | static inline uint64_t query_timer(void) 42 | { 43 | LARGE_INTEGER timer; 44 | if(!QueryPerformanceCounter(&timer)) 45 | { 46 | throw std::runtime_error("QueryPerformanceCounter() has failed!"); 47 | } 48 | return (uint64_t) max(timer.QuadPart, 0i64); 49 | } 50 | 51 | //============================================================================= 52 | // CONSTRUCTOR / DESTRUCTOR 53 | //============================================================================= 54 | 55 | Timer::Timer() 56 | : 57 | m_frequency(query_frequency()) 58 | { 59 | reset(); 60 | } 61 | 62 | Timer::~Timer() 63 | { 64 | } 65 | 66 | //============================================================================= 67 | // TIMER FUNCTIONS 68 | //============================================================================= 69 | 70 | void Timer::reset(void) 71 | { 72 | m_reference = query_timer(); 73 | } 74 | 75 | double Timer::query(void) 76 | { 77 | return double(query_timer() - m_reference) / double(m_frequency); 78 | } 79 | -------------------------------------------------------------------------------- /src/Sink_StdOut.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #include "Sink_StdOut.h" 23 | 24 | //Internal 25 | #include "Utils.h" 26 | 27 | //CRT 28 | #include 29 | #include 30 | 31 | //============================================================================= 32 | // CONSTRUCTOR / DESTRUCTOR 33 | //============================================================================= 34 | 35 | StdOutSink::StdOutSink(void) 36 | : 37 | m_isOpen(false) 38 | { 39 | } 40 | 41 | StdOutSink::~StdOutSink(void) 42 | { 43 | close(false); 44 | } 45 | 46 | //============================================================================= 47 | // OPEN / CLOSE 48 | //============================================================================= 49 | 50 | bool StdOutSink::open(void) 51 | { 52 | Sync::Locker locker(m_mutex); 53 | if(!ferror(stdout)) 54 | { 55 | m_isOpen = true; 56 | return true; 57 | } 58 | return false; 59 | } 60 | 61 | bool StdOutSink::close(const bool& /*success*/) 62 | { 63 | Sync::Locker locker(m_mutex); 64 | fflush(stdout); 65 | m_isOpen = false; 66 | return true; 67 | } 68 | 69 | //============================================================================= 70 | // WRITE 71 | //============================================================================= 72 | 73 | bool StdOutSink::write(uint8_t *const buffer, const size_t &count) 74 | { 75 | Sync::Locker locker(m_mutex); 76 | if(m_isOpen) 77 | { 78 | if(count > 0) 79 | { 80 | const size_t bytesWritten = fwrite(buffer, sizeof(uint8_t), count, stdout); 81 | if(bytesWritten < count) 82 | { 83 | const int error_code = errno; 84 | std::wcerr << L"An I/O error occurred while trying to write to STDOUT:\n" << Utils::crt_error_string(error_code) << L'\n' << std::endl; 85 | return false; 86 | } 87 | } 88 | return true; 89 | } 90 | return false; 91 | } 92 | -------------------------------------------------------------------------------- /src/Sync.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | namespace Sync 27 | { 28 | class Mutex 29 | { 30 | friend class Locker; 31 | 32 | public: 33 | Mutex(void); 34 | ~Mutex(void); 35 | 36 | protected: 37 | void enter(void); 38 | void leave(void); 39 | 40 | private: 41 | const uintptr_t m_handle; 42 | }; 43 | 44 | class Locker 45 | { 46 | public: 47 | Locker(Mutex &mutex); 48 | ~Locker(void); 49 | 50 | private: 51 | Mutex &m_mutex; 52 | }; 53 | 54 | class Event 55 | { 56 | friend class Signal; 57 | 58 | public: 59 | Event(void); 60 | ~Event(void); 61 | 62 | void set(const bool &flag); 63 | 64 | protected: 65 | bool get(void) const; 66 | bool await(const uint32_t &timeout) const; 67 | 68 | private: 69 | const uintptr_t m_handle; 70 | }; 71 | 72 | class Signal 73 | { 74 | public: 75 | Signal(const Event &_event); 76 | ~Signal(); 77 | 78 | bool get(void) const; 79 | bool await(const uint32_t &timeout) const; 80 | uintptr_t handle() const; 81 | 82 | private: 83 | const Event &m_event; 84 | }; 85 | 86 | template 87 | class Interlocked 88 | { 89 | public: 90 | Interlocked(const T &initial_value) 91 | { 92 | m_value = initial_value; 93 | } 94 | 95 | T get(void) const 96 | { 97 | T current; 98 | { 99 | Locker locker(m_mutex); 100 | current = m_value; 101 | } 102 | return current; 103 | } 104 | 105 | void set(const T &new_value) 106 | { 107 | Locker locker(m_mutex); 108 | m_value = new_value; 109 | } 110 | 111 | template 112 | void add(const K &new_value) 113 | { 114 | Locker locker(m_mutex); 115 | m_value += new_value; 116 | } 117 | 118 | template 119 | void insert(const K &new_value) 120 | { 121 | Locker locker(m_mutex); 122 | m_value.insert(new_value); 123 | } 124 | 125 | private: 126 | mutable Mutex m_mutex; 127 | T m_value; 128 | }; 129 | } 130 | -------------------------------------------------------------------------------- /INetGet.rcc: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #define INETGET_RCC 1 23 | #include "src/Version.h" 24 | 25 | #define APSTUDIO_READONLY_SYMBOLS 26 | #include "WinResrc.h" //"afxres.h" 27 | LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL 28 | #pragma code_page(1252) 29 | 30 | ///////////////////////////////////////////////////////////////////////////// 31 | // Version 32 | ///////////////////////////////////////////////////////////////////////////// 33 | 34 | VS_VERSION_INFO VERSIONINFO 35 | FILEVERSION VER_INETGET_MAJOR,VER_INETGET_MIN_H,VER_INETGET_MIN_L,0 36 | PRODUCTVERSION VER_INETGET_MAJOR,VER_INETGET_MIN_H,VER_INETGET_MIN_L,0 37 | FILEFLAGSMASK 0x17L 38 | #ifdef _DEBUG 39 | FILEFLAGS 0x3L 40 | #else 41 | FILEFLAGS 0x2L 42 | #endif 43 | FILEOS 0x40004L 44 | FILETYPE 0x1L 45 | FILESUBTYPE 0x0L 46 | BEGIN 47 | BLOCK "StringFileInfo" 48 | BEGIN 49 | BLOCK "000004b0" 50 | BEGIN 51 | VALUE "ProductVersion", VER_INETGET_STR 52 | VALUE "FileVersion", VER_INETGET_STR 53 | VALUE "ProductName", "INetGet - Lightweight command-line front-end to WinINet API" 54 | VALUE "FileDescription", "INetGet - Lightweight command-line front-end to WinINet API" 55 | VALUE "CompanyName", "Muldersoft.com" 56 | VALUE "LegalCopyright", "Copyright (C) 2015-2018 LoRd_MuldeR " 57 | VALUE "LegalTrademarks", "This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License " 58 | VALUE "InternalName", "INetGet" 59 | VALUE "OriginalFilename", "INetGet.exe" 60 | VALUE "Comments", "This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY" 61 | END 62 | END 63 | BLOCK "VarFileInfo" 64 | BEGIN 65 | VALUE "Translation", 0x0, 1200 66 | END 67 | END 68 | 69 | ///////////////////////////////////////////////////////////////////////////// 70 | // Icon 71 | ///////////////////////////////////////////////////////////////////////////// 72 | 73 | INETGET ICON "res\\inetget.ico" 74 | -------------------------------------------------------------------------------- /src/Client_HTTP.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #pragma once 23 | 24 | #include "Client_Abstract.h" 25 | 26 | class HttpClient : public AbstractClient 27 | { 28 | public: 29 | //Constructor & destructor 30 | HttpClient(const Sync::Signal &user_aborted, const bool &disable_proxy = false, const std::wstring &userAgentStr = std::wstring(), const bool &no_redir = false, uint64_t range_start = 0U, uint64_t range_end = UINT64_MAX, const bool &insecure = false, const bool &force_crl = false, const double &timeout_con = -1.0, const double &timeout_rcv = -1.0, const uint32_t &connect_retry = 3, const bool &verbose = false); 31 | virtual ~HttpClient(void); 32 | 33 | //Connection handling 34 | virtual bool open(const http_verb_t &verb, const URL &url, const std::string &post_data, const std::wstring &referrer, const uint64_t ×tamp); 35 | virtual bool close(void); 36 | 37 | //Fetch result 38 | virtual bool result(bool &success, uint32_t &status_code, uint64_t &file_size, uint64_t &time_stamp, std::wstring &content_type, std::wstring &content_encd); 39 | 40 | //Read payload 41 | virtual bool read_data(uint8_t *out_buff, const uint32_t &buff_size, size_t &bytes_read, bool &eof_flag); 42 | 43 | private: 44 | //Create connection/request 45 | bool connect(const std::wstring &hostName, const uint16_t &portNo, const std::wstring &userName, const std::wstring &password); 46 | bool create_request(const bool &use_tls, const http_verb_t &verb, const std::wstring &path, const std::wstring &query, const std::string &post_data, const std::wstring &referrer, const uint64_t ×tamp); 47 | 48 | //Status handler 49 | virtual void update_status(const uint32_t &status, const uintptr_t &information); 50 | 51 | //Utilities 52 | const wchar_t *http_verb_str(const http_verb_t &verb); 53 | bool update_security_opts(void *const request, const uint32_t &new_flags, const bool &enable); 54 | bool get_header_int(void *const request, const uint32_t type, uint32_t &value); 55 | bool get_header_str(void *const request, const uint32_t type, std::wstring &value); 56 | uint64_t parse_file_size(const std::wstring &str); 57 | 58 | //Handles 59 | void *m_hConnection; 60 | void *m_hRequest; 61 | 62 | //Const 63 | const bool m_insecure_tls; 64 | const bool m_force_crl; 65 | const bool m_disable_redir; 66 | const uint64_t m_range_start; 67 | const uint64_t m_range_end; 68 | 69 | //Current status 70 | uint32_t m_current_status; 71 | }; 72 | 73 | -------------------------------------------------------------------------------- /src/Client_Abstract.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #pragma once 23 | 24 | #include "Types.h" 25 | #include "Sync.h" 26 | 27 | class URL; 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | class AbstractListener 34 | { 35 | friend class AbstractClient; 36 | protected: 37 | virtual void onMessage(const std::wstring message) = 0; 38 | }; 39 | 40 | class AbstractClient 41 | { 42 | public: 43 | static const uint64_t SIZE_UNKNOWN = UINT64_MAX; 44 | static const uint64_t TIME_UNKNOWN = 0; 45 | 46 | AbstractClient(const Sync::Signal &user_aborted, const bool &disable_proxy = false, const std::wstring &agent_str = std::wstring(), const double &timeout_con = -1.0, const double &timeout_rcv = -1.0, const uint32_t &connect_retry = 3, const bool &verbose = false); 47 | virtual ~AbstractClient(void); 48 | 49 | //Add listener 50 | void add_listener(AbstractListener &callback); 51 | 52 | //Connection handling 53 | virtual bool open(const http_verb_t &verb, const URL &url, const std::string &post_data, const std::wstring &referrer, const uint64_t ×tamp) = 0; 54 | virtual bool close(void) = 0; 55 | 56 | //Fetch result 57 | virtual bool result(bool &success, uint32_t &status_code, uint64_t &file_size, uint64_t &time_stamp, std::wstring &content_type, std::wstring &content_encd) = 0; 58 | 59 | //Read payload 60 | virtual bool read_data(uint8_t *out_buff, const uint32_t &buff_size, size_t &bytes_read, bool &eof_flag) = 0; 61 | 62 | //Error message 63 | std::wstring get_error_text() const 64 | { 65 | return m_error_text.get(); 66 | } 67 | 68 | protected: 69 | //WinINet initialization 70 | bool wininet_init(void); 71 | bool wininet_exit(void); 72 | 73 | //Status callback 74 | static void __stdcall status_callback(void *hInternet, uintptr_t dwContext, uint32_t dwInternetStatus, void *lpvStatusInformation, uint32_t dwStatusInformationLength); 75 | virtual void update_status(const uint32_t &status, const uintptr_t &information); 76 | 77 | //Status messages 78 | void set_error_text(const std::wstring &text = std::wstring()); 79 | void emit_message(const std::wstring message); 80 | 81 | //Utilities 82 | bool close_handle(void *&handle); 83 | bool set_inet_options(void *const request, const uint32_t &option, const uint32_t &value); 84 | bool get_inet_options(void *const request, const uint32_t &option, uint32_t &value); 85 | std::wstring status_str(const uintptr_t &info); 86 | 87 | //Const 88 | const Sync::Signal &m_user_aborted; 89 | const bool m_disable_proxy; 90 | const bool m_verbose; 91 | const std::wstring m_agent_str; 92 | const double m_timeout_con; 93 | const double m_timeout_rcv; 94 | const uint32_t m_connect_retry; 95 | 96 | //Thread-safety 97 | Sync::Mutex m_mutex; 98 | 99 | //Handle 100 | void *m_hInternet; 101 | 102 | private: 103 | //Listener support 104 | Sync::Interlocked> m_listeners; 105 | Sync::Interlocked m_error_text; 106 | }; 107 | -------------------------------------------------------------------------------- /src/Sink_File.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #include "Sink_File.h" 23 | 24 | //Internal 25 | #include "Utils.h" 26 | 27 | //Win32 28 | #define WIN32_LEAN_AND_MEAN 1 29 | #include 30 | 31 | //CRT 32 | #include 33 | #include 34 | 35 | //============================================================================= 36 | // CONSTRUCTOR / DESTRUCTOR 37 | //============================================================================= 38 | 39 | FileSink::FileSink(const std::wstring &fileName, const uint64_t ×tamp, const bool &keepFailed) 40 | : 41 | m_handle(NULL), 42 | m_timestamp(timestamp), 43 | m_fileName(fileName), 44 | m_keepFailed(keepFailed) 45 | { 46 | } 47 | 48 | FileSink::~FileSink(void) 49 | { 50 | close(false); 51 | } 52 | 53 | //============================================================================= 54 | // OPEN / CLOSE 55 | //============================================================================= 56 | 57 | bool FileSink::open(void) 58 | { 59 | Sync::Locker locker(m_mutex); 60 | 61 | //Close existign file, just to be sure 62 | close(false); 63 | 64 | //Try to open the file now 65 | FILE *hFile = NULL; 66 | if(_wfopen_s(&hFile, m_fileName.c_str(), L"wb") != 0) 67 | { 68 | const int error_code = errno; 69 | std::wcerr << L"The specified output file could not be opened for writing:\n" << Utils::crt_error_string(error_code) << L'\n' << std::endl; 70 | return false; 71 | } 72 | 73 | m_handle = uintptr_t(hFile); 74 | return true; 75 | } 76 | 77 | bool FileSink::close(const bool &success) 78 | { 79 | bool okay = true; 80 | Sync::Locker locker(m_mutex); 81 | 82 | if(FILE *const hFile = (FILE*)m_handle) 83 | { 84 | if(success && (m_timestamp > 0)) 85 | { 86 | fflush(hFile); 87 | Utils::set_file_time(_fileno(hFile), m_timestamp); 88 | } 89 | 90 | okay = (fclose(hFile) == 0); 91 | 92 | if((!success) && (!m_keepFailed)) 93 | { 94 | _wremove(m_fileName.c_str()); 95 | } 96 | } 97 | 98 | m_handle = NULL; 99 | return okay; 100 | } 101 | 102 | //============================================================================= 103 | // WRITE 104 | //============================================================================= 105 | 106 | bool FileSink::write(uint8_t *const buffer, const size_t &count) 107 | { 108 | Sync::Locker locker(m_mutex); 109 | 110 | if(FILE *const hFile = (FILE*)m_handle) 111 | { 112 | if(count > 0) 113 | { 114 | if(!ferror(hFile)) 115 | { 116 | const size_t bytesWritten = fwrite(buffer, sizeof(uint8_t), count, hFile); 117 | if(bytesWritten != count) 118 | { 119 | const int error_code = errno; 120 | std::wcerr << L"\b\b\bfailed!\n\nAn I/O error occurred while trying to write to output file:\n" << Utils::crt_error_string(error_code) << L'\n' << std::endl; 121 | return false; 122 | } 123 | return true; 124 | } 125 | return false; 126 | } 127 | return true; 128 | } 129 | return false; 130 | } -------------------------------------------------------------------------------- /src/Params.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #pragma once 23 | 24 | #include 25 | #include "Types.h" 26 | 27 | class Params 28 | { 29 | public: 30 | Params(void); 31 | ~Params(void); 32 | 33 | bool parse_cli_args(const int argc, const wchar_t *const argv[]); 34 | bool load_conf_file(const std::wstring &config_file); 35 | 36 | //Getter 37 | inline const std::wstring &getSource (void) const { return m_strSource; } 38 | inline const std::wstring &getOutput (void) const { return m_strOutput; } 39 | inline const http_verb_t &getHttpVerb (void) const { return m_iHttpVerb; } 40 | inline const std::wstring &getPostData (void) const { return m_strPostData; } 41 | inline const bool &getShowHelp (void) const { return m_bShowHelp; } 42 | inline const bool &getDisableProxy (void) const { return m_bDisableProxy; } 43 | inline const std::wstring &getUserAgent (void) const { return m_strUserAgent; } 44 | inline const bool &getDisableRedir (void) const { return m_bDisableRedir; } 45 | inline const uint64_t &getRangeStart (void) const { return m_uRangeStart; } 46 | inline const uint64_t &getRangeEnd (void) const { return m_uRangeEnd; } 47 | inline const bool &getInsecure (void) const { return m_bInsecure; } 48 | inline const std::wstring &getReferrer (void) const { return m_strReferrer; } 49 | inline const bool &getEnableAlert (void) const { return m_bEnableAlert; } 50 | inline const double &getTimeoutCon (void) const { return m_dTimeoutCon; } 51 | inline const double &getTimeoutRcv (void) const { return m_dTimeoutRcv; } 52 | inline const uint32_t &getRetryCount (void) const { return m_uRetryCount; } 53 | inline const bool &getForceCrl (void) const { return m_bForceCrl; } 54 | inline const bool &getSetTimestamp (void) const { return m_bSetTimestamp; } 55 | inline const bool &getUpdateMode (void) const { return m_bUpdateMode; } 56 | inline const bool &getKeepFailed (void) const { return m_bKeepFailed; } 57 | inline const bool &getVerboseMode (void) const { return m_bVerboseMode; } 58 | 59 | private: 60 | bool validate(const bool &is_final); 61 | bool load_conf_file(const std::wstring &config_file, const bool &recursive); 62 | 63 | bool processParamN(const size_t n, const std::wstring ¶m); 64 | bool processOption(const std::wstring &option); 65 | bool processOption(const std::wstring &option_key, const std::wstring &option_val); 66 | 67 | static http_verb_t parseHttpVerb(const std::wstring &value); 68 | 69 | std::wstring m_strSource; 70 | std::wstring m_strOutput; 71 | http_verb_t m_iHttpVerb; 72 | std::wstring m_strPostData; 73 | bool m_bShowHelp; 74 | bool m_bDisableProxy; 75 | std::wstring m_strUserAgent; 76 | bool m_bDisableRedir; 77 | uint64_t m_uRangeStart; 78 | uint64_t m_uRangeEnd; 79 | bool m_bInsecure; 80 | std::wstring m_strReferrer; 81 | bool m_bEnableAlert; 82 | double m_dTimeoutCon; 83 | double m_dTimeoutRcv; 84 | uint32_t m_uRetryCount; 85 | bool m_bForceCrl; 86 | bool m_bSetTimestamp; 87 | bool m_bUpdateMode; 88 | bool m_bKeepFailed; 89 | bool m_bVerboseMode; 90 | }; 91 | 92 | -------------------------------------------------------------------------------- /src/Sync.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #include "Sync.h" 23 | 24 | //Win32 25 | #define NOMINMAX 1 26 | #define WIN32_LEAN_AND_MEAN 1 27 | #include 28 | 29 | //CRT 30 | #include 31 | #include 32 | 33 | //============================================================================= 34 | // MUTEX 35 | //============================================================================= 36 | 37 | Sync::Mutex::Mutex(void) 38 | : 39 | m_handle((uintptr_t) LocalAlloc(LPTR, sizeof(RTL_CRITICAL_SECTION))) 40 | { 41 | if(m_handle == NULL) 42 | { 43 | throw std::runtime_error("Failed to allocate CriticalSection object!"); 44 | } 45 | InitializeCriticalSection((LPCRITICAL_SECTION) m_handle); 46 | } 47 | 48 | Sync::Mutex::~Mutex(void) 49 | { 50 | if(m_handle) 51 | { 52 | DeleteCriticalSection((LPCRITICAL_SECTION) m_handle); 53 | LocalFree((HLOCAL) m_handle); 54 | } 55 | } 56 | 57 | void Sync::Mutex::enter(void) 58 | { 59 | if(m_handle) 60 | { 61 | EnterCriticalSection((LPCRITICAL_SECTION) m_handle); 62 | } 63 | } 64 | 65 | void Sync::Mutex::leave(void) 66 | { 67 | if(m_handle) 68 | { 69 | LeaveCriticalSection((LPCRITICAL_SECTION) m_handle); 70 | } 71 | } 72 | 73 | //============================================================================= 74 | // MUTEX RAII-STYLE LOCKER 75 | //============================================================================= 76 | 77 | Sync::Locker::Locker(Mutex &mutex) 78 | : 79 | m_mutex(mutex) 80 | { 81 | m_mutex.enter(); 82 | } 83 | 84 | Sync::Locker::~Locker() 85 | { 86 | m_mutex.leave(); 87 | } 88 | 89 | //============================================================================= 90 | // EVENT 91 | //============================================================================= 92 | 93 | Sync::Event::Event(void) 94 | : 95 | m_handle((uintptr_t) CreateEvent(NULL, TRUE, FALSE, NULL)) 96 | { 97 | if(m_handle == NULL) 98 | { 99 | throw std::runtime_error("Failed to allocate Event object!"); 100 | } 101 | } 102 | 103 | Sync::Event::~Event(void) 104 | { 105 | if(m_handle) 106 | { 107 | CloseHandle((HANDLE) m_handle); 108 | } 109 | } 110 | 111 | void Sync::Event::set(const bool &flag) 112 | { 113 | if(m_handle) 114 | { 115 | if(!(flag ? SetEvent((HANDLE) m_handle) : ResetEvent((HANDLE) m_handle))) 116 | { 117 | throw std::runtime_error("Failed to set or reset Event object!"); 118 | } 119 | } 120 | } 121 | 122 | bool Sync::Event::get(void) const 123 | { 124 | if(m_handle) 125 | { 126 | return (WaitForSingleObject((HANDLE) m_handle, 0) == WAIT_OBJECT_0); 127 | } 128 | return false; 129 | } 130 | 131 | bool Sync::Event::await(const uint32_t &timeout) const 132 | { 133 | if(m_handle) 134 | { 135 | return (WaitForSingleObject((HANDLE) m_handle, std::max(timeout, 1U)) == WAIT_OBJECT_0); 136 | } 137 | return false; 138 | } 139 | 140 | //============================================================================= 141 | // SIGNAL 142 | //============================================================================= 143 | 144 | Sync::Signal::Signal(const Event &_event) 145 | : 146 | m_event(_event) 147 | { 148 | } 149 | 150 | Sync::Signal::~Signal() 151 | { 152 | } 153 | 154 | bool Sync::Signal::get(void) const 155 | { 156 | return m_event.get(); 157 | } 158 | 159 | bool Sync::Signal::await(const uint32_t &timeout) const 160 | { 161 | return m_event.await(timeout); 162 | } 163 | 164 | uintptr_t Sync::Signal::handle(void) const 165 | { 166 | HANDLE retval = NULL; 167 | if(DuplicateHandle(GetCurrentProcess(), (HANDLE) m_event.m_handle, GetCurrentProcess(), &retval, SYNCHRONIZE, FALSE, 0)) 168 | { 169 | return (uintptr_t) retval; 170 | } 171 | return NULL; 172 | } -------------------------------------------------------------------------------- /src/Client_FTP.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #include "Client_FTP.h" 23 | 24 | //Internal 25 | #include "URL.h" 26 | #include "Utils.h" 27 | 28 | //Win32 29 | #define WIN32_LEAN_AND_MEAN 1 30 | #include 31 | #include 32 | 33 | //CRT 34 | #include 35 | #include 36 | #include 37 | 38 | //Helper functions 39 | //static const wchar_t *CSTR(const std::wstring &str) { return str.empty() ? NULL : str.c_str(); } 40 | //static const char *CSTR(const std::string &str) { return str.empty() ? NULL : str.c_str(); } 41 | 42 | //Const 43 | static const wchar_t *const HTTP_VER_11 = L"HTTP/1.1"; 44 | static const wchar_t *const ACCEPTED_TYPES[] = { L"*/*", NULL }; 45 | static const wchar_t *const TYPE_FORM_DATA = L"Content-Type: application/x-www-form-urlencoded"; 46 | 47 | //Macros 48 | #define OPTIONAL_FLAG(X,Y,Z) do \ 49 | { \ 50 | if((Y)) { (X) |= (Z); } \ 51 | } \ 52 | while(0) 53 | 54 | //============================================================================= 55 | // CONSTRUCTOR / DESTRUCTOR 56 | //============================================================================= 57 | 58 | FtpClient::FtpClient(const Sync::Signal &user_aborted, const bool &disableProxy, const std::wstring &userAgentStr, const bool& /*no_redir*/, const bool& /*insecure*/, const double &timeout_con, const double &timeout_rcv, const uint32_t &connect_retry, const bool &verbose) 59 | : 60 | AbstractClient(user_aborted, disableProxy, userAgentStr, timeout_con, timeout_rcv, connect_retry, verbose) 61 | { 62 | } 63 | 64 | FtpClient::~FtpClient(void) 65 | { 66 | } 67 | 68 | //============================================================================= 69 | // CONNECTION HANDLING 70 | //============================================================================= 71 | 72 | bool FtpClient::open(const http_verb_t& /*verb*/, const URL& /*url*/, const std::string& /*post_data*/, const std::wstring& /*referrer*/, const uint64_t& /*timestamp*/) 73 | { 74 | if(!wininet_init()) 75 | { 76 | return false; /*WinINet failed to initialize*/ 77 | } 78 | 79 | //Close the existing connection, just to be sure 80 | if(!close()) 81 | { 82 | set_error_text(std::wstring(L"ERROR: Failed to close the existing connection!")); 83 | return false; 84 | } 85 | 86 | throw std::runtime_error("FTP support *not* implemented in this version :-("); 87 | } 88 | 89 | bool FtpClient::close(void) 90 | { 91 | bool success = true; 92 | 93 | //Close the request, if it currently exists 94 | /*if(!close_handle(m_hRequest)) 95 | { 96 | success = false; 97 | }*/ 98 | 99 | //Close connection, if it is currently open 100 | /*if(!close_handle(m_hConnection)) 101 | { 102 | success = false; 103 | }*/ 104 | 105 | return success; 106 | } 107 | 108 | //============================================================================= 109 | // QUERY RESULT 110 | //============================================================================= 111 | 112 | bool FtpClient::result(bool& /*success*/, uint32_t& /*status_code*/, uint64_t& /*file_size*/, uint64_t& /*time_stamp*/, std::wstring& /*content_type*/, std::wstring& /*content_encd*/) 113 | { 114 | throw std::runtime_error("FTP support *not* implemented in this version :-("); 115 | //return false; 116 | } 117 | 118 | //============================================================================= 119 | // READ PAYLOAD 120 | //============================================================================= 121 | 122 | bool FtpClient::read_data(uint8_t* /*out_buff*/, const uint32_t& /*buff_size*/, size_t& /*bytes_read*/, bool& /*eof_flag*/) 123 | { 124 | throw std::runtime_error("FTP support *not* implemented in this version :-("); 125 | //return false; 126 | } 127 | -------------------------------------------------------------------------------- /src/URL.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #include "URL.h" 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "Utils.h" 32 | 33 | //============================================================================= 34 | // HELPER MACROS 35 | //============================================================================= 36 | 37 | #define INIT_URL_STRING(X,Y) do \ 38 | { \ 39 | m_str##Y.clear(); \ 40 | if(components.lpsz##Y && (components.dw##Y##Length > 0U)) \ 41 | { \ 42 | std::wstring temp(components.lpsz##Y, components.dw##Y##Length); \ 43 | m_str##Y = (X) ? Utils::trim(temp) : urlEncode(Utils::trim(temp)); \ 44 | } \ 45 | } \ 46 | while(0) 47 | 48 | //============================================================================= 49 | // CONSTRUCTOR 50 | //============================================================================= 51 | 52 | URL::URL(const URL &other) 53 | : 54 | m_iSchemeId(other.m_iSchemeId), 55 | m_uiPortNumber(other.m_uiPortNumber) 56 | { 57 | m_strScheme = other.m_strScheme; 58 | m_strHostName = other.m_strHostName; 59 | m_strUserName = other.m_strUserName; 60 | m_strPassword = other.m_strPassword; 61 | m_strUrlPath = other.m_strUrlPath; 62 | m_strExtraInfo = other.m_strExtraInfo; 63 | } 64 | 65 | URL::URL(const std::wstring &url) 66 | : 67 | m_iSchemeId(INTERNET_SCHEME_UNKNOWN), 68 | m_uiPortNumber(INTERNET_INVALID_PORT_NUMBER) 69 | { 70 | URL_COMPONENTS components; 71 | SecureZeroMemory(&components, sizeof(URL_COMPONENTS)); 72 | 73 | components.dwStructSize = sizeof(URL_COMPONENTS); 74 | 75 | components.dwSchemeLength = DWORD(-1); 76 | components.dwHostNameLength = DWORD(-1); 77 | components.dwUserNameLength = DWORD(-1); 78 | components.dwPasswordLength = DWORD(-1); 79 | components.dwUrlPathLength = DWORD(-1); 80 | components.dwExtraInfoLength = DWORD(-1); 81 | 82 | if(InternetCrackUrl(url.c_str(), 0, 0, &components)) 83 | { 84 | INIT_URL_STRING(0, Scheme); 85 | INIT_URL_STRING(0, HostName); 86 | INIT_URL_STRING(0, UserName); 87 | INIT_URL_STRING(0, Password); 88 | INIT_URL_STRING(1, UrlPath); 89 | INIT_URL_STRING(1, ExtraInfo); 90 | m_iSchemeId = int16_t(components.nScheme); 91 | m_uiPortNumber = components.nPort; 92 | } 93 | } 94 | 95 | URL::~URL() 96 | { 97 | } 98 | 99 | //============================================================================= 100 | // PUBLIC FUNCTIONS 101 | //============================================================================= 102 | 103 | std::wstring URL::toString(void) const 104 | { 105 | std::wostringstream result; 106 | result << m_strScheme; 107 | result << L"://"; 108 | result << m_strHostName; 109 | result << m_strUrlPath; 110 | result << m_strExtraInfo; 111 | return result.str(); 112 | } 113 | 114 | bool URL::isComplete(void) const 115 | { 116 | if(m_strHostName.empty() || m_strUrlPath .empty()) 117 | { 118 | return false; 119 | } 120 | return (m_iSchemeId > 0); 121 | } 122 | 123 | //============================================================================= 124 | // STATIC FUNCTIONS 125 | //============================================================================= 126 | 127 | std::wstring URL::urlEncode(const std::wstring &url) 128 | { 129 | return Utils::utf8_to_wide_str(urlEncode(Utils::wide_str_to_utf8(url))); 130 | } 131 | 132 | std::string URL::urlEncode(const std::string &url) 133 | { 134 | static const char *const ALLOWED_URL_CHARS = "!#$%&'()*+,-./:;=?@[\\]^_{|}"; 135 | std::ostringstream result; 136 | for(std::string::const_iterator iter = url.cbegin(); iter != url.cend(); iter++) 137 | { 138 | if(isalnum(*iter) || strchr(ALLOWED_URL_CHARS, (*iter))) 139 | { 140 | result << (*iter); 141 | continue; 142 | } 143 | const std::ios::fmtflags backup(result.flags()); 144 | result << '%' << std::setw(2) << std::setfill('0') << std::hex << std::uppercase << static_cast(static_cast(*iter)); 145 | result.flags(backup); 146 | } 147 | 148 | return result.str(); 149 | } 150 | -------------------------------------------------------------------------------- /src/Version.h: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #pragma once 23 | 24 | //============================================================================= 25 | // PROGRAM VERSION 26 | //============================================================================= 27 | 28 | #define VER_INETGET_MAJOR 1 29 | #define VER_INETGET_MIN_H 0 30 | #define VER_INETGET_MIN_L 2 31 | #define VER_INETGET_PATCH 0 32 | 33 | //============================================================================= 34 | // Helper macros (aka: having fun with the C pre-processor) 35 | //============================================================================= 36 | 37 | #ifdef INETGET_RCC 38 | 39 | #define VER_INETGET_STR_HLP1(X) #X 40 | #define VER_INETGET_STR_HLP2(W,X,Y,Z) VER_INETGET_STR_HLP1(v##W.X##Y-Z) 41 | #define VER_INETGET_STR_HLP3(W,X,Y,Z) VER_INETGET_STR_HLP2(W,X,Y,Z) 42 | #define VER_INETGET_STR VER_INETGET_STR_HLP3(VER_INETGET_MAJOR,VER_INETGET_MIN_H,VER_INETGET_MIN_L,VER_INETGET_PATCH) 43 | 44 | #define VER_INETGET_MINOR_HLP1(X,Y) X##Y 45 | #define VER_INETGET_MINOR_HLP2(X,Y) VER_INETGET_MINOR_HLP1(X,Y) 46 | #define VER_INETGET_MINOR VER_INETGET_MINOR_HLP2(VER_INETGET_MIN_H,VER_INETGET_MIN_L) 47 | 48 | #endif //INETGET_RCC 49 | 50 | //============================================================================= 51 | // BUILD INFORMATION 52 | //============================================================================= 53 | 54 | #ifndef INETGET_RCC 55 | #include 56 | 57 | #if (defined(NDEBUG) && defined(_DEBUG)) || ((!defined(NDEBUG)) && (!defined(_DEBUG))) 58 | #error Inconsistent DEBUG flags! 59 | #endif 60 | 61 | static const char *BUILD_DATE = __DATE__; 62 | static const char *BUILD_TIME = __TIME__; 63 | 64 | #ifdef NDEBUG 65 | static const char *BUILD_CONF = "Release"; 66 | #else 67 | static const char *BUILD_CONF = "DEBUG"; 68 | #endif 69 | 70 | static const uint32_t VERSION_MAJOR = VER_INETGET_MAJOR; 71 | static const uint32_t VERSION_MINOR = VER_INETGET_MIN_L + (VER_INETGET_MIN_H * 10); 72 | static const uint32_t VERSION_PATCH = VER_INETGET_PATCH; 73 | 74 | #if defined(_MSC_VER) 75 | #if(_MSC_VER == 1900) 76 | static const char *const BUILD_COMP = "MSVC 14.0"; 77 | #elif(_MSC_VER == 1800) 78 | #if (_MSC_FULL_VER == 180021005) 79 | static const char *const BUILD_COMP = "MSVC 12.0"; 80 | #elif (_MSC_FULL_VER == 180030501) 81 | static const char *const BUILD_COMP = "MSVC 12.2"; 82 | #elif (_MSC_FULL_VER == 180030723) 83 | static const char *const BUILD_COMP = "MSVC 12.3"; 84 | #elif (_MSC_FULL_VER == 180031101) 85 | static const char *const BUILD_COMP = "MSVC 12.4"; 86 | #elif (_MSC_FULL_VER == 180040629) 87 | static const char *const BUILD_COMP = "MSVC 12.5"; 88 | #else 89 | #error Compiler version is not supported yet! 90 | #endif 91 | #elif(_MSC_VER == 1700) 92 | #if (_MSC_FULL_VER == 170050727) 93 | static const char *const BUILD_COMP = "MSVC 11.0"; 94 | #elif (_MSC_FULL_VER == 170051106) 95 | static const char *const BUILD_COMP = "MSVC 11.1"; 96 | #elif (_MSC_FULL_VER == 170060315) 97 | static const char *const BUILD_COMP = "MSVC 11.2"; 98 | #elif (_MSC_FULL_VER == 170060610) 99 | static const char *const BUILD_COMP = "MSVC 11.3"; 100 | #elif (_MSC_FULL_VER == 170061030) 101 | static const char *const BUILD_COMP = "MSVC 11.4"; 102 | #else 103 | #error Compiler version is not supported yet! 104 | #endif 105 | #elif(_MSC_VER == 1600) 106 | #if (_MSC_FULL_VER >= 160040219) 107 | static const char *const BUILD_COMP = "MSVC 10.1"; 108 | #else 109 | static const char *const BUILD_COMP = "MSVC 10.0"; 110 | #endif 111 | #else 112 | #error Unsupported compiler version! 113 | #endif 114 | 115 | #ifdef _M_X64 116 | static const char *const BUILD_ARCH = "x64"; 117 | #else 118 | static const char *const BUILD_ARCH = "x86"; 119 | #endif 120 | #else 121 | #error Unsupported compiler detected! 122 | #endif 123 | 124 | #undef VER_INETGET_MAJOR 125 | #undef VER_INETGET_MIN_H 126 | #undef VER_INETGET_MIN_L 127 | #undef VER_INETGET_PATCH 128 | 129 | #endif //INETGET_RCC 130 | -------------------------------------------------------------------------------- /src/Zero.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | //Win32 23 | #define NOMINMAX 1 24 | #define WIN32_LEAN_AND_MEAN 1 25 | #include 26 | #include 27 | 28 | //CRT 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | //Internal 35 | #include "Sync.h" 36 | 37 | //Validation 38 | #if (defined(NDEBUG) && defined(_DEBUG)) || ((!defined(NDEBUG)) && (!defined(_DEBUG))) 39 | #error Inconsistent DEBUG flags! 40 | #endif 41 | 42 | //Events 43 | static Sync::Event g_eventUserAbort; 44 | namespace Zero 45 | { 46 | Sync::Signal g_sigUserAbort(g_eventUserAbort); 47 | } 48 | 49 | //============================================================================= 50 | // ERROR HANDLING 51 | //============================================================================= 52 | 53 | static BOOL WINAPI my_sigint_handler(DWORD dwCtrlType) 54 | { 55 | switch(dwCtrlType) 56 | { 57 | case CTRL_C_EVENT: 58 | case CTRL_BREAK_EVENT: 59 | case CTRL_CLOSE_EVENT: 60 | g_eventUserAbort.set(true); 61 | return TRUE; 62 | } 63 | return FALSE; 64 | } 65 | 66 | #ifdef NDEBUG 67 | 68 | static void my_invalid_param_handler(const wchar_t*, const wchar_t*, const wchar_t*, unsigned int, uintptr_t) 69 | { 70 | std::wcerr << L"\n\nGURU MEDITATION: Invalid parameter handler invoked, application will exit!\n" << std::endl; 71 | _exit(EXIT_FAILURE); 72 | } 73 | 74 | static LONG WINAPI my_exception_handler(struct _EXCEPTION_POINTERS* /*ExceptionInfo*/) 75 | { 76 | std::wcerr << L"\n\nGURU MEDITATION: Unhandeled exception handler invoked, application will exit!\n" << std::endl; 77 | _exit(EXIT_FAILURE); 78 | return EXCEPTION_EXECUTE_HANDLER; 79 | } 80 | 81 | static void setup_error_handlers(void) 82 | { 83 | SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); 84 | SetUnhandledExceptionFilter(my_exception_handler); 85 | _set_invalid_parameter_handler(my_invalid_param_handler); 86 | 87 | if(const HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll")) 88 | { 89 | typedef BOOL (WINAPI *SetDefaultDllDirectoriesT)(DWORD flags); 90 | if(const SetDefaultDllDirectoriesT set_default_dll_directories = (SetDefaultDllDirectoriesT) GetProcAddress(hKernel32, "SetDefaultDllDirectories")) 91 | { 92 | set_default_dll_directories(0x0800); /*LOAD_LIBRARY_SEARCH_SYSTEM32*/ 93 | } 94 | typedef BOOL (WINAPI *SetDllDirectoryT)(LPCWSTR lpPathName); 95 | if(const SetDllDirectoryT set_dll_directory = (SetDllDirectoryT) GetProcAddress(hKernel32, "SetDllDirectoryW")) 96 | { 97 | set_dll_directory(L""); /*remove current directory from search path*/ 98 | } 99 | } 100 | } 101 | 102 | #endif //NDEBUG 103 | 104 | //============================================================================= 105 | // STARTUP 106 | //============================================================================= 107 | 108 | int inetget_main(const int argc, const wchar_t *const argv[]); 109 | 110 | static int inetget_startup(const int argc, const wchar_t *const argv[]) 111 | { 112 | _setmode(_fileno(stdout), _O_BINARY); 113 | _setmode(_fileno(stderr), _O_U8TEXT); 114 | _setmode(_fileno(stdin ), _O_BINARY); 115 | 116 | timeBeginPeriod(1); 117 | SetConsoleCtrlHandler(my_sigint_handler, TRUE); 118 | 119 | return inetget_main(argc, argv); 120 | } 121 | 122 | //============================================================================= 123 | // ENTRY POINT 124 | //============================================================================= 125 | 126 | #ifdef NDEBUG 127 | static int wmain_ex(const int argc, const wchar_t *const argv[]) 128 | { 129 | int ret = -1; 130 | try 131 | { 132 | ret = inetget_startup(argc, argv); 133 | } 134 | catch(std::exception &err) 135 | { 136 | std::wcerr << L"\n\nUNHANDELED EXCEPTION: " << err.what() << '\n' << std::endl; 137 | _exit(EXIT_FAILURE); 138 | } 139 | catch(...) 140 | { 141 | std::wcerr << L"\n\nUNHANDELED EXCEPTION: Unknown C++ exception error!\n" << std::endl; 142 | _exit(EXIT_FAILURE); 143 | } 144 | return ret; 145 | } 146 | #endif //NDEBUG 147 | 148 | int wmain(int argc, wchar_t* argv[]) 149 | { 150 | int ret = -1; 151 | #ifdef NDEBUG 152 | __try 153 | { 154 | setup_error_handlers(); 155 | ret = wmain_ex(argc, argv); 156 | } 157 | __except(EXCEPTION_EXECUTE_HANDLER) 158 | { 159 | std::wcerr << L"\n\nGURU MEDITATION: Unhandeled exception error, application will exit!\n" << std::endl; 160 | } 161 | #else 162 | ret = inetget_startup(argc, argv); 163 | #endif 164 | return ret; 165 | } 166 | -------------------------------------------------------------------------------- /src/Thread.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #include "Thread.h" 23 | 24 | //Win32 25 | #define NOMINMAX 1 26 | #define WIN32_LEAN_AND_MEAN 1 27 | #include 28 | 29 | //CRT 30 | #include 31 | #include 32 | #include 33 | 34 | //Internal 35 | #include "Utils.h" 36 | 37 | //============================================================================= 38 | // THREAD ENTRY POINT 39 | //============================================================================= 40 | 41 | static int map_priority(const int8_t &priority) 42 | { 43 | switch(std::max(int8_t(-3), std::min(int8_t(3), priority))) 44 | { 45 | case 3: return THREAD_PRIORITY_TIME_CRITICAL; 46 | case 2: return THREAD_PRIORITY_HIGHEST; 47 | case 1: return THREAD_PRIORITY_ABOVE_NORMAL; 48 | case 0: return THREAD_PRIORITY_NORMAL; 49 | case -1: return THREAD_PRIORITY_BELOW_NORMAL; 50 | case -2: return THREAD_PRIORITY_LOWEST; 51 | case -3: return THREAD_PRIORITY_IDLE; 52 | } 53 | throw std::runtime_error("Bad priority value!"); 54 | } 55 | 56 | uint32_t __stdcall Thread::thread_start(void *const data) 57 | { 58 | if(Thread *const thread = ((Thread*)data)) 59 | { 60 | if(SetThreadPriority(GetCurrentThread(), map_priority(thread->m_priority.get()))) 61 | { 62 | const DWORD ret = thread->main(); 63 | return (ret == STILL_ACTIVE) ? (ret + 1) : ret; 64 | } 65 | } 66 | return DWORD(-1L); 67 | } 68 | 69 | //============================================================================= 70 | // CONSTRUCTOR & DESTRUCTOR 71 | //============================================================================= 72 | 73 | Thread::Thread() 74 | : 75 | m_signal_stop(m_event_stop), 76 | m_error_text(std::wstring()), 77 | m_priority(0) 78 | { 79 | m_thread = NULL; 80 | } 81 | 82 | Thread::~Thread() 83 | { 84 | if(is_running()) 85 | { 86 | stop(1000, true); 87 | } 88 | close_handle(); 89 | } 90 | 91 | //============================================================================= 92 | // PUBLIC FUNCTIONS 93 | //============================================================================= 94 | 95 | bool Thread::start(void) 96 | { 97 | if(is_running()) 98 | { 99 | return false; /*thread already running*/ 100 | } 101 | 102 | close_handle(); 103 | m_event_stop.set(false); 104 | set_error_text(); 105 | 106 | if(m_thread = _beginthreadex(NULL, 0, thread_start, this, 0, NULL)) 107 | { 108 | return true; 109 | } 110 | 111 | return false; /*failed to create*/ 112 | } 113 | 114 | bool Thread::join(const uint32_t &timeout) 115 | { 116 | if(m_thread) 117 | { 118 | return (WaitForSingleObject((HANDLE) m_thread, ((timeout > 0) ? timeout : INFINITE)) == WAIT_OBJECT_0); 119 | } 120 | return false; 121 | } 122 | 123 | bool Thread::join(const Sync::Signal &interrupt, const uint32_t &timeout) 124 | { 125 | if(m_thread) 126 | { 127 | if(HANDLE hInterrupt = (HANDLE) interrupt.handle()) 128 | { 129 | HANDLE handles[] = { (HANDLE) m_thread, hInterrupt, NULL }; 130 | const DWORD retval = WaitForMultipleObjects(2U, handles, FALSE, ((timeout > 0) ? timeout : INFINITE)); 131 | CloseHandle(hInterrupt); 132 | return (retval == WAIT_OBJECT_0); 133 | } 134 | else 135 | { 136 | return join(timeout); 137 | } 138 | } 139 | return false; 140 | } 141 | 142 | bool Thread::stop(const uint32_t &timeout, const bool &force) 143 | { 144 | if(m_thread) 145 | { 146 | m_event_stop.set(true); 147 | if(join(std::max(1U, timeout))) 148 | { 149 | return true; 150 | } 151 | else if(force) 152 | { 153 | if(TerminateThread((HANDLE) m_thread, DWORD(-1L))) 154 | { 155 | return join(); 156 | } 157 | } 158 | } 159 | return false; 160 | } 161 | 162 | bool Thread::is_running(void) const 163 | { 164 | if(m_thread) 165 | { 166 | return (WaitForSingleObject((HANDLE) m_thread, 0) == WAIT_TIMEOUT); 167 | } 168 | return false; 169 | } 170 | 171 | uint32_t Thread::get_result(void) const 172 | { 173 | if(m_thread) 174 | { 175 | DWORD exit_code = DWORD(-1); 176 | if(GetExitCodeThread((HANDLE) m_thread, &exit_code)) 177 | { 178 | if(exit_code != STILL_ACTIVE) 179 | { 180 | return exit_code; 181 | } 182 | } 183 | } 184 | return DWORD(-1); 185 | } 186 | 187 | //============================================================================= 188 | // PROTECTED FUNCTIONS 189 | //============================================================================= 190 | 191 | bool Thread::is_stopped(void) 192 | { 193 | return m_signal_stop.get(); 194 | } 195 | 196 | void Thread::set_error_text(const std::wstring &text) 197 | { 198 | std::wstring error_text(text); 199 | Utils::trim(error_text); 200 | m_error_text.set(error_text.empty() ? std::wstring() : error_text); 201 | } 202 | 203 | //============================================================================= 204 | // INTERNAL FUNCTIONS 205 | //============================================================================= 206 | 207 | void Thread::close_handle(void) 208 | { 209 | if(m_thread) 210 | { 211 | CloseHandle((HANDLE) m_thread); 212 | m_thread = NULL; 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /INetGet_VC100.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {824fad5a-8688-4c8d-b241-21524a311030} 18 | 19 | 20 | {eaeadb5a-06bc-4f59-9825-914e4eeb64c0} 21 | 22 | 23 | {2f50a9cf-3fae-418f-a6a3-a5c72119daaf} 24 | 25 | 26 | {91702e3d-4c5a-4f3a-9098-a7219744efaa} 27 | 28 | 29 | {10bbf51a-54e9-4e51-89f2-f9b8f7a4dc50} 30 | 31 | 32 | {6e637c83-d194-45f8-b3a6-142d6ba965db} 33 | 34 | 35 | {96891b88-f5a4-4128-a055-3a695a88b04e} 36 | 37 | 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files\Utilities 50 | 51 | 52 | Source Files\Utilities 53 | 54 | 55 | Source Files\Utilities 56 | 57 | 58 | Source Files\Utilities 59 | 60 | 61 | Source Files\Utilities 62 | 63 | 64 | Source Files\IO 65 | 66 | 67 | Source Files\IO 68 | 69 | 70 | Source Files\IO 71 | 72 | 73 | Source Files\IO 74 | 75 | 76 | Source Files\Client 77 | 78 | 79 | Source Files\Client 80 | 81 | 82 | Source Files\Client 83 | 84 | 85 | Source Files\Utilities 86 | 87 | 88 | Source Files\Utilities 89 | 90 | 91 | Source Files\Utilities 92 | 93 | 94 | 95 | 96 | Header Files 97 | 98 | 99 | Header Files 100 | 101 | 102 | Header Files\IO 103 | 104 | 105 | Header Files\IO 106 | 107 | 108 | Header Files\IO 109 | 110 | 111 | Header Files\IO 112 | 113 | 114 | Header Files\Utilties 115 | 116 | 117 | Header Files\Utilties 118 | 119 | 120 | Header Files\Utilties 121 | 122 | 123 | Header Files\Utilties 124 | 125 | 126 | Header Files\Utilties 127 | 128 | 129 | Header Files\Client 130 | 131 | 132 | Header Files\Client 133 | 134 | 135 | Header Files\Client 136 | 137 | 138 | Header Files\Utilties 139 | 140 | 141 | Header Files\Utilties 142 | 143 | 144 | Header Files\Utilties 145 | 146 | 147 | Header Files\Utilties 148 | 149 | 150 | 151 | 152 | Resource Files\data 153 | 154 | 155 | 156 | 157 | Resource Files\data 158 | 159 | 160 | 161 | 162 | Resource Files 163 | 164 | 165 | -------------------------------------------------------------------------------- /INetGet_VC120.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {824fad5a-8688-4c8d-b241-21524a311030} 18 | 19 | 20 | {eaeadb5a-06bc-4f59-9825-914e4eeb64c0} 21 | 22 | 23 | {2f50a9cf-3fae-418f-a6a3-a5c72119daaf} 24 | 25 | 26 | {91702e3d-4c5a-4f3a-9098-a7219744efaa} 27 | 28 | 29 | {10bbf51a-54e9-4e51-89f2-f9b8f7a4dc50} 30 | 31 | 32 | {6e637c83-d194-45f8-b3a6-142d6ba965db} 33 | 34 | 35 | {96891b88-f5a4-4128-a055-3a695a88b04e} 36 | 37 | 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files\Utilities 50 | 51 | 52 | Source Files\Utilities 53 | 54 | 55 | Source Files\Utilities 56 | 57 | 58 | Source Files\Utilities 59 | 60 | 61 | Source Files\Utilities 62 | 63 | 64 | Source Files\IO 65 | 66 | 67 | Source Files\IO 68 | 69 | 70 | Source Files\IO 71 | 72 | 73 | Source Files\IO 74 | 75 | 76 | Source Files\Client 77 | 78 | 79 | Source Files\Client 80 | 81 | 82 | Source Files\Client 83 | 84 | 85 | Source Files\Utilities 86 | 87 | 88 | Source Files\Utilities 89 | 90 | 91 | Source Files\Utilities 92 | 93 | 94 | 95 | 96 | Header Files 97 | 98 | 99 | Header Files 100 | 101 | 102 | Header Files\IO 103 | 104 | 105 | Header Files\IO 106 | 107 | 108 | Header Files\IO 109 | 110 | 111 | Header Files\IO 112 | 113 | 114 | Header Files\Utilties 115 | 116 | 117 | Header Files\Utilties 118 | 119 | 120 | Header Files\Utilties 121 | 122 | 123 | Header Files\Utilties 124 | 125 | 126 | Header Files\Utilties 127 | 128 | 129 | Header Files\Client 130 | 131 | 132 | Header Files\Client 133 | 134 | 135 | Header Files\Client 136 | 137 | 138 | Header Files\Utilties 139 | 140 | 141 | Header Files\Utilties 142 | 143 | 144 | Header Files\Utilties 145 | 146 | 147 | Header Files\Utilties 148 | 149 | 150 | 151 | 152 | Resource Files\data 153 | 154 | 155 | 156 | 157 | Resource Files\data 158 | 159 | 160 | 161 | 162 | Resource Files 163 | 164 | 165 | -------------------------------------------------------------------------------- /etc/examples/multi_download_example.py: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # INetGet - Lightweight command-line front-end to WinINet API 3 | # Copyright (C) 2018 LoRd_MuldeR 4 | # 5 | # This program is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU General Public License 7 | # as published by the Free Software Foundation; either version 2 8 | # of the License, or (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along 16 | # with this program; if not, write to the Free Software Foundation, Inc., 17 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | # 19 | # See https:#www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | ############################################################################## 21 | 22 | import sys 23 | import re 24 | import math 25 | 26 | from os import devnull, remove 27 | from subprocess import Popen, PIPE, DEVNULL, CREATE_NEW_CONSOLE 28 | from shutil import copyfileobj 29 | from time import sleep 30 | 31 | sys.stdout.write('INetGet multi-download *example* script\n\n') 32 | 33 | if (len(sys.argv) < 4) or (sys.argv[1].lower() == '--help') or (sys.argv[1] == '/?'): 34 | sys.stdout.write('Usage:\n') 35 | sys.stdout.write(' multi_download_example.py [options] \n\n') 36 | sys.stdout.write('Options:\n') 37 | sys.stdout.write(' --no-progress Do not display progress output of sub-processes\n\n') 38 | sys.stdout.write('Example:\n') 39 | sys.stdout.write(' multi_download_example.py 5 \\\n') 40 | sys.stdout.write(' http://releases.ubuntu.com/16.04.4/ubuntu-16.04.4-desktop-amd64.iso \\\n') 41 | sys.stdout.write(' ubuntu-16.04.4-desktop-amd64.iso\n\n') 42 | sys.stdout.write('Note: Additional options will be passed through to INetGet.\n\n') 43 | sys.exit(-1) 44 | 45 | arg_offset, hidden_mode, extra_args = 1, False, [] 46 | while sys.argv[arg_offset].startswith('--'): 47 | switch_name = sys.argv[arg_offset][2:].lower().split("=")[0] 48 | if not switch_name: 49 | break 50 | if switch_name == "no-progress": 51 | hidden_mode = True 52 | elif (switch_name == "range-end") or (switch_name == "range-off") or (switch_name == "verb"): 53 | sys.stdout.write('WARNING: Switch "%s" is ignored!\n\n' % sys.argv[arg_offset]) 54 | else: 55 | extra_args.append(sys.argv[arg_offset]) 56 | arg_offset = arg_offset + 1 57 | 58 | if arg_offset+2 >= len(sys.argv): 59 | sys.stdout.write('ERROR: At least one required argument is missing! Use "--help" for details.\n\n') 60 | sys.exit(-1) 61 | 62 | NCHUNKS = int(sys.argv[arg_offset]) if sys.argv[arg_offset].isdigit() else 0 63 | ADDRESS = sys.argv[arg_offset+1].strip() 64 | OUTNAME = sys.argv[arg_offset+2].strip() 65 | 66 | if (not ADDRESS) or (not OUTNAME): 67 | sys.stdout.write('ERROR: The download URL ("%s") or the output file name ("%s") is empty!\n\n' % (sys.argv[arg_offset+1], sys.argv[arg_offset+2])) 68 | sys.exit(-1) 69 | 70 | if (NCHUNKS < 1) or (NCHUNKS > 9): 71 | sys.stdout.write('ERROR: The number of chunks ("%s") must be within the 1 to 9 range!\n\n' % sys.argv[arg_offset]) 72 | sys.exit(-1) 73 | 74 | 75 | ############################################################################## 76 | # STEP #1: Determine the total file size 77 | ############################################################################## 78 | 79 | sys.stdout.write('Determining file size, please wait...\n') 80 | 81 | try: 82 | process = Popen(['INetGet.exe', '--verb=HEAD', *extra_args, ADDRESS, devnull], stderr=PIPE) 83 | stdout, stderr = process.communicate() 84 | except: 85 | sys.stdout.write('\nERROR: Failed to launch INetGet process! Is INetGet.exe in the path?\n\n') 86 | raise 87 | 88 | if not process.returncode == 0: 89 | sys.stdout.write('\nERROR: Failed to determine file size! Please see INetGet log below for details.\n\n') 90 | sys.stdout.write(stderr.decode("utf-8")) 91 | sys.exit(-1) 92 | 93 | match = re.search(r"Content\s+length\s*:\s*(\d+)\s*Byte", stderr.decode("utf-8"), re.IGNORECASE) 94 | 95 | if not match: 96 | sys.stdout.write('\nERROR: Failed to determine file size! Does the server offer "resume" support?\n\n') 97 | sys.stdout.write(stderr.decode("utf-8")) 98 | sys.exit(-1) 99 | 100 | sys.stdout.write('Done.\n\n') 101 | 102 | size_total = int(match.group(1)) 103 | sys.stdout.write('Total file size is: %d Byte\n\n' % size_total) 104 | 105 | if size_total < 1: 106 | sys.stdout.write('\nERROR: The requested file appears to be empty!\n\n') 107 | sys.exit(-1) 108 | 109 | if size_total < (NCHUNKS * 1024): 110 | sys.stdout.write('\nERROR: The requested file is too small for chunk\'ed download!\n\n') 111 | sys.exit(-1) 112 | 113 | 114 | ############################################################################## 115 | # STEP #2: Start the download processes 116 | ############################################################################## 117 | 118 | size_chunk = size_total // NCHUNKS 119 | size_rmndr = math.fmod(size_total, size_chunk) 120 | 121 | while size_rmndr >= NCHUNKS: 122 | size_chunk = size_chunk + (size_rmndr // NCHUNKS) 123 | size_rmndr = math.fmod(size_total, size_chunk) 124 | 125 | sys.stdout.write('Chunksize: %d\n' % size_chunk) 126 | sys.stdout.write('Remainder: %d\n\n' % size_rmndr) 127 | 128 | proc_list = [] 129 | offset, file_no = 0, 0 130 | 131 | digits = len(str(size_total - 1)) 132 | format = 'Chunk #%%d range: %%0%dd - %%0%dd\n' % (digits, digits) 133 | 134 | if size_chunk > 0: 135 | for i in range(0, NCHUNKS): 136 | range_end = offset + size_chunk - 1 + (0 if (i < NCHUNKS-1) else size_rmndr) #add remainder to *last* chunk! 137 | sys.stdout.write(format % (file_no, offset, range_end)) 138 | proc_list.append(Popen(['INetGet.exe', \ 139 | '--range-off=%d' % offset, '--range-end=%d' % range_end, *extra_args, 140 | ADDRESS, OUTNAME+"~chunk%d" % file_no], \ 141 | stderr = (DEVNULL if hidden_mode else None), creationflags = (0 if hidden_mode else CREATE_NEW_CONSOLE))) 142 | offset, file_no = offset + size_chunk, file_no + 1 143 | sleep(.25) 144 | 145 | sys.stdout.write('\nDownloads are running in the background, please be patient...\n') 146 | 147 | 148 | ############################################################################## 149 | # STEP #3: Wait for completion... 150 | ############################################################################## 151 | 152 | success = True 153 | procs_completed = [] 154 | 155 | while len(procs_completed) < len(proc_list): 156 | for i in range(0, len(proc_list)): 157 | subproc = proc_list[i] 158 | if subproc in procs_completed: 159 | continue 160 | retval = subproc.poll() 161 | if retval == None: 162 | continue; 163 | procs_completed.append(subproc) 164 | if retval != 0: 165 | sys.stdout.write('Chunk #%d failed !!!\n' % i) 166 | success = False 167 | break 168 | sys.stdout.write('Chunk #%d succeeded.\n' % i) 169 | sleep(.015625) 170 | 171 | if success: 172 | sys.stdout.write('Completed.\n\n') 173 | else: 174 | sys.stdout.write('\nERROR: At least one chunk failed to download!\n\n') 175 | sys.exit(-1) 176 | 177 | 178 | ############################################################################## 179 | # STEP #4: Concatenate chunk files 180 | ############################################################################## 181 | 182 | sys.stdout.write('Concatenating chunks, please wait...\n') 183 | 184 | try: 185 | with open(OUTNAME, 'wb') as wfd: 186 | for i in range(0, NCHUNKS): 187 | with open(OUTNAME+"~chunk%d" % i, 'rb') as fd: 188 | copyfileobj(fd, wfd) 189 | except: 190 | sys.stdout.write('\nERROR: Failed to concatenate chunk files. Out of space?\n\n') 191 | raise 192 | 193 | sys.stdout.write('Done.\n\n') 194 | 195 | try: 196 | for i in range(0, NCHUNKS): 197 | remove(OUTNAME+"~chunk%d" % i) 198 | except: 199 | sys.stdout.write('\nWARNING: Failed to remove temporary files!\n\n') 200 | -------------------------------------------------------------------------------- /z_build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal enabledelayedexpansion 3 | 4 | REM /////////////////////////////////////////////////////////////////////////// 5 | REM // INetGet - Lightweight command-line front-end to WinINet API 6 | REM // Copyright (C) 2018 LoRd_MuldeR 7 | REM /////////////////////////////////////////////////////////////////////////// 8 | 9 | echo Preparing to build INetGet, please wait... 10 | echo. 11 | 12 | REM /////////////////////////////////////////////////////////////////////////// 13 | REM // Check paths 14 | REM /////////////////////////////////////////////////////////////////////////// 15 | 16 | cd /d "%~dp0" 17 | call "%~dp0\z_paths.bat" 18 | 19 | if not exist "%INETGET_MSVC_PATH%\vcvarsall.bat" ( 20 | echo Visual C++ compiler not found. Please check your INETGET_MSVC_PATH var^^! 21 | goto BuildError 22 | ) 23 | 24 | if not exist "%INETGET_UPX3_PATH%\upx.exe" ( 25 | echo UPX binary could not be found. Please check your INETGET_UPX3_PATH var^^! 26 | goto BuildError 27 | ) 28 | 29 | if not exist "%INETGET_PDOC_PATH%\pandoc.exe" ( 30 | echo Pandoc app could not be found. Please check your INETGET_PDOC_PATH var^^! 31 | goto BuildError 32 | ) 33 | 34 | if not exist "%INETGET_HTMC_PATH%\htmlcompressor-1.5.3.jar" ( 35 | echo Html Compressor was not found. Please check your INETGET_HTMC_PATH var^^! 36 | goto BuildError 37 | ) 38 | 39 | if not exist "%JAVA_HOME%\bin\java.exe" ( 40 | echo Java runtime executable was not found. Please check your JAVA_HOME var^^! 41 | goto BuildError 42 | ) 43 | 44 | REM /////////////////////////////////////////////////////////////////////////// 45 | REM // Setup environment 46 | REM /////////////////////////////////////////////////////////////////////////// 47 | 48 | set "PATH=%INETGET_HTMC_PATH%;%PATH%" 49 | call "%INETGET_MSVC_PATH%\vcvarsall.bat" x86 50 | 51 | REM /////////////////////////////////////////////////////////////////////////// 52 | REM // Get current date and time (in ISO format) 53 | REM /////////////////////////////////////////////////////////////////////////// 54 | 55 | set "ISO_DATE=" 56 | set "ISO_TIME=" 57 | 58 | for /F "tokens=1,2 delims=:" %%a in ('"%~dp0\etc\bin\date.exe" +ISODATE:%%Y-%%m-%%d') do ( 59 | if "%%a"=="ISODATE" set "ISO_DATE=%%b" 60 | ) 61 | 62 | for /F "tokens=1,2,3,4 delims=:" %%a in ('"%~dp0\etc\bin\date.exe" +ISOTIME:%%T') do ( 63 | if "%%a"=="ISOTIME" set "ISO_TIME=%%b:%%c:%%d" 64 | ) 65 | 66 | if "%ISO_DATE%"=="" goto BuildError 67 | if "%ISO_TIME%"=="" goto BuildError 68 | 69 | REM /////////////////////////////////////////////////////////////////////////// 70 | REM // Detect version number 71 | REM /////////////////////////////////////////////////////////////////////////// 72 | 73 | set "VER_MAJOR=" 74 | set "VER_MINOR=" 75 | set "VER_PATCH=" 76 | 77 | for /F "tokens=1,2,3" %%a in (%~dp0\src\Version.h) do ( 78 | if "%%a"=="#define" ( 79 | if "%%b"=="VER_INETGET_MAJOR" set "VER_MAJOR=%%c" 80 | if "%%b"=="VER_INETGET_MIN_H" set "VER_MINOR=%%c!VER_MINOR!" 81 | if "%%b"=="VER_INETGET_MIN_L" set "VER_MINOR=!VER_MINOR!%%c" 82 | if "%%b"=="VER_INETGET_PATCH" set "VER_PATCH=%%c" 83 | ) 84 | ) 85 | 86 | if "%VER_MAJOR%"=="" goto BuildError 87 | if "%VER_MINOR%"=="" goto BuildError 88 | if "%VER_PATCH%"=="" goto BuildError 89 | 90 | echo Version: %VER_MAJOR%.%VER_MINOR%-%VER_PATCH% 91 | echo ISODate: %ISO_DATE%, %ISO_TIME% 92 | echo. 93 | 94 | REM /////////////////////////////////////////////////////////////////////////// 95 | REM // Clean Binaries 96 | REM /////////////////////////////////////////////////////////////////////////// 97 | 98 | for /d %%d in (%~dp0\bin\*) do (rmdir /S /Q "%%~d") 99 | for /d %%d in (%~dp0\obj\*) do (rmdir /S /Q "%%~d") 100 | 101 | REM /////////////////////////////////////////////////////////////////////////// 102 | REM // Build the binaries 103 | REM /////////////////////////////////////////////////////////////////////////// 104 | 105 | for %%p in (Win32,x64) do ( 106 | echo --------------------------------------------------------------------- 107 | echo BEGIN BUILD [%%p/Release] 108 | echo --------------------------------------------------------------------- 109 | echo. 110 | MSBuild.exe /property:Platform=%%p /property:Configuration=Release /target:clean "%~dp0\INetGet_VC%INETGET_TOOL_VERS%.sln" 111 | if not "!ERRORLEVEL!"=="0" goto BuildError 112 | MSBuild.exe /property:Platform=%%p /property:Configuration=Release /target:rebuild "%~dp0\INetGet_VC%INETGET_TOOL_VERS%.sln" 113 | if not "!ERRORLEVEL!"=="0" goto BuildError 114 | MSBuild.exe /property:Platform=%%p /property:Configuration=Release /target:build "%~dp0\INetGet_VC%INETGET_TOOL_VERS%.sln" 115 | if not "!ERRORLEVEL!"=="0" goto BuildError 116 | echo. 117 | ) 118 | 119 | REM /////////////////////////////////////////////////////////////////////////// 120 | REM // Copy program files 121 | REM /////////////////////////////////////////////////////////////////////////// 122 | 123 | echo --------------------------------------------------------------------- 124 | echo BEGIN PACKAGING 125 | echo --------------------------------------------------------------------- 126 | echo. 127 | 128 | set "PACK_PATH=%TMP%\~%RANDOM%%RANDOM%.tmp" 129 | 130 | mkdir "%PACK_PATH%" 131 | mkdir "%PACK_PATH%\img" 132 | mkdir "%PACK_PATH%\img\inetget" 133 | mkdir "%PACK_PATH%\examples" 134 | 135 | copy "%~dp0\bin\v%INETGET_TOOL_VERS%\Win32\Release\INetGet.exe" "%PACK_PATH%\INetGet.exe" 136 | if not "!ERRORLEVEL!"=="0" goto BuildError 137 | 138 | copy "%~dp0\bin\v%INETGET_TOOL_VERS%\.\x64\Release\INetGet.exe" "%PACK_PATH%\INetGet.x64.exe" 139 | if not "!ERRORLEVEL!"=="0" goto BuildError 140 | 141 | copy "%~dp0\img\inetget\*.png" "%PACK_PATH%\img\inetget" 142 | if not "!ERRORLEVEL!"=="0" goto BuildError 143 | 144 | copy "%~dp0\etc\examples\*example*" "%PACK_PATH%\examples" 145 | if not "!ERRORLEVEL!"=="0" goto BuildError 146 | 147 | echo. 148 | 149 | REM /////////////////////////////////////////////////////////////////////////// 150 | REM // Final Processing 151 | REM /////////////////////////////////////////////////////////////////////////// 152 | 153 | for %%i in (*.md) do ( 154 | echo %%~ni --^> "%PACK_PATH%\%%~ni.html" 155 | "%INETGET_PDOC_PATH%\pandoc.exe" --from markdown_github+pandoc_title_block+header_attributes+implicit_figures --to html5 -H "%~dp0\etc\doc\Style.inc" --standalone "%%~i" | "%JAVA_HOME%\bin\java.exe" -jar "%INETGET_HTMC_PATH%\htmlcompressor-1.5.3.jar" --compress-css --compress-js -o "%PACK_PATH%\%%~ni.html" 156 | if not "!ERRORLEVEL!"=="0" goto BuildError 157 | ) 158 | 159 | "%INETGET_UPX3_PATH%\upx.exe" --brute "%PACK_PATH%\*.exe" 160 | if not "!ERRORLEVEL!"=="0" goto BuildError 161 | 162 | echo. 163 | 164 | REM /////////////////////////////////////////////////////////////////////////// 165 | REM // Create version tag 166 | REM /////////////////////////////////////////////////////////////////////////// 167 | 168 | echo INetGet - Lightweight command-line front-end to WinINet API> "%PACK_PATH%\BUILD_TAG" 169 | echo Copyright (C) 2018 LoRd_MuldeR ^>> "%PACK_PATH%\BUILD_TAG" 170 | echo.>> "%PACK_PATH%\BUILD_TAG" 171 | echo Version %VER_MAJOR%.%VER_MINOR%-%VER_PATCH%. Built on %ISO_DATE%, at %ISO_TIME%>> "%PACK_PATH%\BUILD_TAG" 172 | echo.>> "%PACK_PATH%\BUILD_TAG" 173 | echo This program is free software; you can redistribute it and/or modify>> "%PACK_PATH%\BUILD_TAG" 174 | echo it under the terms of the GNU General Public License as published by>> "%PACK_PATH%\BUILD_TAG" 175 | echo the Free Software Foundation; either version 2 of the License, or>> "%PACK_PATH%\BUILD_TAG" 176 | echo (at your option) any later version.>> "%PACK_PATH%\BUILD_TAG" 177 | echo.>> "%PACK_PATH%\BUILD_TAG" 178 | echo This program is distributed in the hope that it will be useful,>> "%PACK_PATH%\BUILD_TAG" 179 | echo but WITHOUT ANY WARRANTY; without even the implied warranty of>> "%PACK_PATH%\BUILD_TAG" 180 | echo MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the>> "%PACK_PATH%\BUILD_TAG" 181 | echo GNU General Public License for more details.>> "%PACK_PATH%\BUILD_TAG" 182 | 183 | REM /////////////////////////////////////////////////////////////////////////// 184 | REM // Attributes 185 | REM /////////////////////////////////////////////////////////////////////////// 186 | 187 | attrib +R "%PACK_PATH%\*" 188 | attrib +R "%PACK_PATH%\img\inetget\*" 189 | 190 | REM /////////////////////////////////////////////////////////////////////////// 191 | REM // Generate outfile name 192 | REM /////////////////////////////////////////////////////////////////////////// 193 | 194 | mkdir "%~dp0\out" 2> NUL 195 | set "OUT_NAME=WinINetGet.%ISO_DATE%" 196 | 197 | :CheckOutName 198 | if exist "%~dp0\out\%OUT_NAME%.zip" ( 199 | set "OUT_NAME=%OUT_NAME%.new" 200 | goto CheckOutName 201 | ) 202 | 203 | REM /////////////////////////////////////////////////////////////////////////// 204 | REM // Build the package 205 | REM /////////////////////////////////////////////////////////////////////////// 206 | 207 | pushd "%PACK_PATH%\" 208 | "%~dp0\etc\bin\zip.exe" -9 -r -z "%~dp0\out\%OUT_NAME%.zip" "*.*" < "%PACK_PATH%\BUILD_TAG" 209 | popd 210 | attrib +R "%~dp0\out\%OUT_NAME%.zip" 211 | 212 | REM Clean up! 213 | rmdir /Q /S "%PACK_PATH%" 214 | 215 | REM /////////////////////////////////////////////////////////////////////////// 216 | REM // COMPLETE 217 | REM /////////////////////////////////////////////////////////////////////////// 218 | 219 | echo. 220 | echo Build completed. 221 | echo. 222 | 223 | pause 224 | goto:eof 225 | 226 | REM /////////////////////////////////////////////////////////////////////////// 227 | REM // FAILED 228 | REM /////////////////////////////////////////////////////////////////////////// 229 | 230 | :BuildError 231 | 232 | echo. 233 | echo Build has failed ^^!^^!^^! 234 | echo. 235 | 236 | pause 237 | goto:eof 238 | -------------------------------------------------------------------------------- /src/Client_Abstract.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #include "Client_Abstract.h" 23 | 24 | //Internal 25 | #include "Compat.h" 26 | #include "Utils.h" 27 | 28 | //Win32 29 | #define WIN32_LEAN_AND_MEAN 1 30 | #include 31 | #include 32 | 33 | //CRT 34 | #include 35 | #include 36 | #include 37 | 38 | //Default User Agent string 39 | static const wchar_t *const USER_AGENT = L"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9) Gecko/2008062901 IceWeasel/3.0"; /*use something unobtrusive*/ 40 | 41 | //============================================================================= 42 | // CONSTRUCTOR / DESTRUCTOR 43 | //============================================================================= 44 | 45 | AbstractClient::AbstractClient(const Sync::Signal &user_aborted, const bool &disable_proxy, const std::wstring &agent_str, const double &timeout_con, const double &timeout_rcv, const uint32_t &connect_retry, const bool &verbose) 46 | : 47 | m_user_aborted(user_aborted), 48 | m_disable_proxy(disable_proxy), 49 | m_timeout_con(timeout_con), 50 | m_timeout_rcv(timeout_rcv), 51 | m_agent_str(agent_str), 52 | m_connect_retry(connect_retry), 53 | m_verbose(verbose), 54 | m_error_text(std::wstring()), 55 | m_listeners(std::set()), 56 | m_hInternet(NULL) 57 | { 58 | } 59 | 60 | AbstractClient::~AbstractClient() 61 | { 62 | wininet_exit(); 63 | } 64 | 65 | //============================================================================= 66 | // INITIALIZE OR EXIT CLIENT 67 | //============================================================================= 68 | 69 | bool AbstractClient::wininet_init() 70 | { 71 | if(m_hInternet == NULL) 72 | { 73 | m_hInternet = InternetOpen(m_agent_str.empty() ? USER_AGENT : m_agent_str.c_str(), m_disable_proxy ? INTERNET_OPEN_TYPE_DIRECT : INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); 74 | if(m_hInternet == NULL) 75 | { 76 | const DWORD error_code = GetLastError(); 77 | set_error_text(std::wstring(L"InternetOpen() has failed:\n").append(Utils::win_error_string(error_code))); 78 | return false; 79 | } 80 | 81 | //Query version info 82 | DWORD versionInfoSize = sizeof(INTERNET_VERSION_INFO); 83 | INTERNET_VERSION_INFO versionInfo; 84 | if(m_verbose && InternetQueryOption(m_hInternet, INTERNET_OPTION_VERSION, &versionInfo, &versionInfoSize)) 85 | { 86 | std::wostringstream version; version << versionInfo.dwMajorVersion << L'.' << versionInfo.dwMinorVersion; 87 | emit_message(std::wstring(L"Using WinINet API library version ").append(version.str())); 88 | } 89 | 90 | //Setup the connection and receive timeouts 91 | if(DBL_VALID_GTR(m_timeout_con, 0.0)) 92 | { 93 | const double con_timeout = (m_timeout_con < DBL_MAX) ? ROUND(1000.0 * m_timeout_con) : double(UINT32_MAX); 94 | if(!set_inet_options(m_hInternet, INTERNET_OPTION_CONNECT_TIMEOUT, DBL_TO_UINT32(con_timeout))) 95 | { 96 | return false; /*failed to setup timeout!*/ 97 | } 98 | } 99 | if(DBL_VALID_GTR(m_timeout_rcv, 0.0)) 100 | { 101 | const double rcv_timeout = (m_timeout_rcv < DBL_MAX) ? ROUND(1000.0 * m_timeout_rcv) : double(UINT32_MAX); 102 | static const uint32_t OPTS[] = 103 | { 104 | INTERNET_OPTION_RECEIVE_TIMEOUT, INTERNET_OPTION_DATA_RECEIVE_TIMEOUT, 105 | INTERNET_OPTION_SEND_TIMEOUT, INTERNET_OPTION_DATA_SEND_TIMEOUT, NULL 106 | }; 107 | for(size_t i = 0; OPTS[i]; i++) 108 | { 109 | if(!set_inet_options(m_hInternet, OPTS[i], DBL_TO_UINT32(rcv_timeout))) 110 | { 111 | return false; /*failed to setup timeout!*/ 112 | } 113 | } 114 | } 115 | } 116 | 117 | return (m_hInternet != NULL); 118 | } 119 | 120 | bool AbstractClient::wininet_exit(void) 121 | { 122 | return close_handle(m_hInternet); 123 | } 124 | 125 | //============================================================================= 126 | // ERROR MESSAGE 127 | //============================================================================= 128 | 129 | void AbstractClient::set_error_text(const std::wstring &text) 130 | { 131 | std::wstring error_text(text); 132 | Utils::trim(error_text); 133 | m_error_text.set(error_text.empty() ? std::wstring() : error_text); 134 | } 135 | 136 | //============================================================================= 137 | // LISTENER SUPPORT 138 | //============================================================================= 139 | 140 | void AbstractClient::add_listener(AbstractListener &callback) 141 | { 142 | m_listeners.insert(&callback); 143 | } 144 | 145 | void AbstractClient::emit_message(const std::wstring message) 146 | { 147 | const std::set listeners = m_listeners.get(); 148 | for(std::set::const_iterator iter = listeners.cbegin(); iter != listeners.cend(); iter++) 149 | { 150 | (*iter)->onMessage(message); 151 | } 152 | } 153 | 154 | //============================================================================= 155 | // STATUS CALLBACK 156 | //============================================================================= 157 | 158 | #define CHECK_STATUS(X) do \ 159 | { \ 160 | if(status == (X)) \ 161 | { \ 162 | static const wchar_t *name = L#X; \ 163 | emit_message(std::wstring(&name[16])); \ 164 | return; \ 165 | } \ 166 | } \ 167 | while(0) 168 | 169 | void __stdcall AbstractClient::status_callback(void* /*hInternet*/, uintptr_t dwContext, uint32_t dwInternetStatus, void *lpvStatusInformation, uint32_t /*dwStatusInformationLength*/) 170 | { 171 | if(AbstractClient *const instance = reinterpret_cast(dwContext)) 172 | { 173 | instance->update_status(dwInternetStatus, uintptr_t(lpvStatusInformation)); 174 | } 175 | } 176 | 177 | void AbstractClient::update_status(const uint32_t &status, const uintptr_t& /*information*/) 178 | { 179 | if(m_verbose) 180 | { 181 | CHECK_STATUS(INTERNET_STATUS_RESOLVING_NAME); 182 | CHECK_STATUS(INTERNET_STATUS_NAME_RESOLVED); 183 | CHECK_STATUS(INTERNET_STATUS_CONNECTING_TO_SERVER); 184 | CHECK_STATUS(INTERNET_STATUS_CONNECTED_TO_SERVER); 185 | CHECK_STATUS(INTERNET_STATUS_SENDING_REQUEST); 186 | CHECK_STATUS(INTERNET_STATUS_REQUEST_SENT); 187 | CHECK_STATUS(INTERNET_STATUS_RECEIVING_RESPONSE); 188 | CHECK_STATUS(INTERNET_STATUS_RESPONSE_RECEIVED); 189 | CHECK_STATUS(INTERNET_STATUS_CTL_RESPONSE_RECEIVED); 190 | CHECK_STATUS(INTERNET_STATUS_PREFETCH); 191 | CHECK_STATUS(INTERNET_STATUS_CLOSING_CONNECTION); 192 | CHECK_STATUS(INTERNET_STATUS_CONNECTION_CLOSED); 193 | CHECK_STATUS(INTERNET_STATUS_HANDLE_CREATED); 194 | CHECK_STATUS(INTERNET_STATUS_HANDLE_CLOSING); 195 | CHECK_STATUS(INTERNET_STATUS_DETECTING_PROXY); 196 | CHECK_STATUS(INTERNET_STATUS_REQUEST_COMPLETE); 197 | CHECK_STATUS(INTERNET_STATUS_REDIRECT); 198 | CHECK_STATUS(INTERNET_STATUS_INTERMEDIATE_RESPONSE); 199 | CHECK_STATUS(INTERNET_STATUS_USER_INPUT_REQUIRED); 200 | CHECK_STATUS(INTERNET_STATUS_STATE_CHANGE); 201 | CHECK_STATUS(INTERNET_STATUS_COOKIE_SENT); 202 | CHECK_STATUS(INTERNET_STATUS_COOKIE_RECEIVED); 203 | CHECK_STATUS(INTERNET_STATUS_PRIVACY_IMPACTED); 204 | CHECK_STATUS(INTERNET_STATUS_P3P_HEADER); 205 | CHECK_STATUS(INTERNET_STATUS_P3P_POLICYREF); 206 | CHECK_STATUS(INTERNET_STATUS_COOKIE_HISTORY); 207 | CHECK_STATUS(INTERNET_STATE_CONNECTED); 208 | CHECK_STATUS(INTERNET_STATE_DISCONNECTED); 209 | CHECK_STATUS(INTERNET_STATE_DISCONNECTED_BY_USER); 210 | CHECK_STATUS(INTERNET_STATE_IDLE); 211 | CHECK_STATUS(INTERNET_STATE_BUSY); 212 | } 213 | } 214 | 215 | //============================================================================= 216 | // UTILITIES 217 | //============================================================================= 218 | 219 | bool AbstractClient::close_handle(void *&handle) 220 | { 221 | bool success = true; 222 | 223 | if(handle != NULL) 224 | { 225 | if(InternetCloseHandle(handle) != TRUE) 226 | { 227 | success = false; 228 | } 229 | handle = NULL; 230 | } 231 | 232 | return success; 233 | } 234 | 235 | bool AbstractClient::set_inet_options(void *const request, const uint32_t &option, const uint32_t &value) 236 | { 237 | if(!InternetSetOption(request, option, (LPVOID)&value, sizeof(uint32_t))) 238 | { 239 | const DWORD error_code = GetLastError(); 240 | set_error_text(std::wstring(L"InternetSetOption() function has failed:\n").append(Utils::win_error_string(error_code))); 241 | return false; 242 | } 243 | return true; 244 | } 245 | 246 | bool AbstractClient::get_inet_options(void *const request, const uint32_t &option, uint32_t &value) 247 | { 248 | DWORD buff_len = sizeof(uint32_t); 249 | if(!InternetQueryOption(request, option, (LPVOID)&value, &buff_len)) 250 | { 251 | const DWORD error_code = GetLastError(); 252 | set_error_text(std::wstring(L"InternetQueryOption() function has failed:\n").append(Utils::win_error_string(error_code))); 253 | return false; 254 | } 255 | return (buff_len >= sizeof(uint32_t)); 256 | } 257 | 258 | std::wstring AbstractClient::status_str(const uintptr_t &info) 259 | { 260 | if(const char *const chr_data = (const char*) info) 261 | { 262 | if(isprint(chr_data[0]) && isprint(chr_data[1])) 263 | { 264 | std::wstring temp(Utils::utf8_to_wide_str(std::string(chr_data))); 265 | if(Utils::trim(temp).length() > 0) 266 | { 267 | return temp; 268 | } 269 | } 270 | } 271 | 272 | if(const wchar_t *const wcs_data = (const wchar_t*) info) 273 | { 274 | if(iswprint(wcs_data[0]) && iswprint(wcs_data[1])) 275 | { 276 | std::wstring temp(wcs_data); 277 | if(Utils::trim(temp).length() > 0) 278 | { 279 | return temp; 280 | } 281 | } 282 | } 283 | 284 | return std::wstring(L""); 285 | } 286 | -------------------------------------------------------------------------------- /INetGet_VC120.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | Document 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | {157E1DB2-A934-4AB6-99CF-626AADB42F79} 74 | Win32Proj 75 | INetGet 76 | 77 | 78 | 79 | Application 80 | true 81 | v120_xp 82 | Unicode 83 | 84 | 85 | Application 86 | true 87 | v120_xp 88 | Unicode 89 | 90 | 91 | Application 92 | false 93 | v120_xp 94 | true 95 | Unicode 96 | 97 | 98 | Application 99 | false 100 | v120_xp 101 | true 102 | Unicode 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | true 122 | $(SolutionDir)\bin\v$(PlatformToolsetVersion)\$(Platform)\$(Configuration)\ 123 | $(SolutionDir)\obj\v$(PlatformToolsetVersion)\$(Platform)\$(Configuration)\ 124 | INetGet 125 | 126 | 127 | true 128 | $(SolutionDir)\bin\v$(PlatformToolsetVersion)\$(Platform)\$(Configuration)\ 129 | $(SolutionDir)\obj\v$(PlatformToolsetVersion)\$(Platform)\$(Configuration)\ 130 | INetGet 131 | 132 | 133 | false 134 | $(SolutionDir)\bin\v$(PlatformToolsetVersion)\$(Platform)\$(Configuration)\ 135 | $(SolutionDir)\obj\v$(PlatformToolsetVersion)\$(Platform)\$(Configuration)\ 136 | INetGet 137 | 138 | 139 | false 140 | $(SolutionDir)\bin\v$(PlatformToolsetVersion)\$(Platform)\$(Configuration)\ 141 | $(SolutionDir)\obj\v$(PlatformToolsetVersion)\$(Platform)\$(Configuration)\ 142 | INetGet 143 | 144 | 145 | 146 | 147 | 148 | Level4 149 | Disabled 150 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 151 | NoExtensions 152 | true 153 | 4127;4510;4512;4610;4706;4996 154 | 155 | 156 | Console 157 | true 158 | WinInet.lib;Winmm.lib;%(AdditionalDependencies) 159 | 160 | 161 | 162 | 163 | 164 | 165 | Level4 166 | Disabled 167 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 168 | StreamingSIMDExtensions2 169 | 4127;4510;4512;4610;4706;4996 170 | 171 | 172 | Console 173 | true 174 | WinInet.lib;Winmm.lib;%(AdditionalDependencies) 175 | 176 | 177 | 178 | 179 | Level4 180 | 181 | 182 | MinSpace 183 | true 184 | true 185 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 186 | NoExtensions 187 | MultiThreaded 188 | false 189 | false 190 | true 191 | 4127;4510;4512;4610;4706;4996 192 | 193 | 194 | Console 195 | false 196 | true 197 | true 198 | EncodePointer.lib;WinInet.lib;Winmm.lib;%(AdditionalDependencies) 199 | $(SolutionDir)\etc\lib;%(AdditionalLibraryDirectories) 200 | true 201 | true 202 | false 203 | 204 | 205 | 206 | 207 | Level4 208 | 209 | 210 | MinSpace 211 | true 212 | true 213 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 214 | NotSet 215 | MultiThreaded 216 | false 217 | false 218 | 4127;4510;4512;4610;4706;4996 219 | 220 | 221 | Console 222 | false 223 | true 224 | true 225 | WinInet.lib;Winmm.lib;%(AdditionalDependencies) 226 | $(SolutionDir)\etc\lib;%(AdditionalLibraryDirectories) 227 | true 228 | true 229 | false 230 | 231 | 232 | 233 | 234 | 235 | -------------------------------------------------------------------------------- /INetGet_VC100.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | Document 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | {157E1DB2-A934-4AB6-99CF-626AADB42F79} 74 | Win32Proj 75 | INetGet 76 | 77 | 78 | 79 | Application 80 | true 81 | v100 82 | Unicode 83 | 84 | 85 | Application 86 | true 87 | v100 88 | Unicode 89 | 90 | 91 | Application 92 | false 93 | v100 94 | true 95 | Unicode 96 | 97 | 98 | Application 99 | false 100 | v100 101 | true 102 | Unicode 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | true 122 | $(SolutionDir)\bin\v$(PlatformToolsetVersion)\$(Platform)\$(Configuration)\ 123 | $(SolutionDir)\obj\v$(PlatformToolsetVersion)\$(Platform)\$(Configuration)\ 124 | INetGet 125 | 126 | 127 | true 128 | $(SolutionDir)\bin\v$(PlatformToolsetVersion)\$(Platform)\$(Configuration)\ 129 | $(SolutionDir)\obj\v$(PlatformToolsetVersion)\$(Platform)\$(Configuration)\ 130 | INetGet 131 | 132 | 133 | false 134 | $(SolutionDir)\bin\v$(PlatformToolsetVersion)\$(Platform)\$(Configuration)\ 135 | $(SolutionDir)\obj\v$(PlatformToolsetVersion)\$(Platform)\$(Configuration)\ 136 | INetGet 137 | 138 | 139 | false 140 | $(SolutionDir)\bin\v$(PlatformToolsetVersion)\$(Platform)\$(Configuration)\ 141 | $(SolutionDir)\obj\v$(PlatformToolsetVersion)\$(Platform)\$(Configuration)\ 142 | INetGet 143 | 144 | 145 | 146 | 147 | 148 | Level4 149 | Disabled 150 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 151 | NotSet 152 | true 153 | 4127;4510;4512;4610;4706;4996 154 | 155 | 156 | Console 157 | true 158 | WinInet.lib;Winmm.lib;%(AdditionalDependencies) 159 | 160 | 161 | 162 | 163 | 164 | 165 | Level4 166 | Disabled 167 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 168 | StreamingSIMDExtensions2 169 | 4127;4510;4512;4610;4706;4996 170 | 171 | 172 | Console 173 | true 174 | WinInet.lib;Winmm.lib;%(AdditionalDependencies) 175 | 176 | 177 | 178 | 179 | Level4 180 | 181 | 182 | MinSpace 183 | true 184 | true 185 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 186 | NotSet 187 | MultiThreaded 188 | false 189 | false 190 | true 191 | 4127;4510;4512;4610;4706;4996 192 | Size 193 | true 194 | 195 | 196 | Console 197 | false 198 | true 199 | true 200 | EncodePointer.lib;WinInet.lib;Winmm.lib;%(AdditionalDependencies) 201 | $(SolutionDir)\etc\lib;%(AdditionalLibraryDirectories) 202 | true 203 | true 204 | false 205 | 206 | 207 | 208 | 209 | Level4 210 | 211 | 212 | MinSpace 213 | true 214 | true 215 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 216 | StreamingSIMDExtensions2 217 | MultiThreaded 218 | false 219 | false 220 | 4127;4510;4512;4610;4706;4996 221 | Size 222 | true 223 | 224 | 225 | Console 226 | false 227 | true 228 | true 229 | WinInet.lib;Winmm.lib;%(AdditionalDependencies) 230 | $(SolutionDir)\etc\lib;%(AdditionalLibraryDirectories) 231 | true 232 | true 233 | false 234 | 235 | 236 | 237 | 238 | 239 | -------------------------------------------------------------------------------- /src/Params.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #include "Params.h" 23 | 24 | //Internal 25 | #include "URL.h" 26 | #include "Slunk.h" 27 | #include "Utils.h" 28 | 29 | //CRT 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | //============================================================================= 37 | // UTILITIES 38 | //============================================================================= 39 | 40 | static inline std::wstring argv_i(const wchar_t *const argv[], const int i) 41 | { 42 | std::wstring temp(argv[i]); 43 | return Utils::trim(temp); 44 | } 45 | 46 | #define IS_OPTION(X) (option_key.compare(L##X) == 0) 47 | 48 | #define ENSURE_VALUE() do \ 49 | { \ 50 | if(option_val.empty()) \ 51 | { \ 52 | std::wcerr << L"ERROR: Required argument for option \"--" << option_key << "\" is missing!\n" << std::endl; \ 53 | return false; \ 54 | } \ 55 | } \ 56 | while(0) 57 | 58 | #define ENSURE_NOVAL() do \ 59 | { \ 60 | if(!option_val.empty()) \ 61 | { \ 62 | std::wcerr << L"ERROR: Excess argument \"" << option_val << "\" for option \"--" << option_key << "\" encountered!\n" << std::endl; \ 63 | return false; \ 64 | } \ 65 | } \ 66 | while(0) 67 | 68 | #define PARSE_ENUM(X,Y) do \ 69 | { \ 70 | static const wchar_t *const name = L#Y; \ 71 | if(_wcsicmp(value.c_str(), &name[(X)]) == 0) \ 72 | { \ 73 | return (Y); \ 74 | } \ 75 | } \ 76 | while(0) 77 | 78 | #define PARSE_UINT32(X) do \ 79 | { \ 80 | try \ 81 | { \ 82 | (X) = (_wcsicmp(option_val.c_str(), L"infinite") == 0) ? UINT32_MAX : std::stoul(option_val); \ 83 | } \ 84 | catch(std::exception&) \ 85 | { \ 86 | std::wcerr << L"ERROR: Numeric value \"" << option_val << "\" could not be parsed!\n" << std::endl; \ 87 | return false; \ 88 | } \ 89 | } \ 90 | while(0) 91 | 92 | #define PARSE_UINT64(X) do \ 93 | { \ 94 | try \ 95 | { \ 96 | (X) = (_wcsicmp(option_val.c_str(), L"infinite") == 0) ? UINT64_MAX : std::stoull(option_val); \ 97 | } \ 98 | catch(std::exception&) \ 99 | { \ 100 | std::wcerr << L"ERROR: Numeric value \"" << option_val << "\" could not be parsed!\n" << std::endl; \ 101 | return false; \ 102 | } \ 103 | } \ 104 | while(0) 105 | 106 | #define PARSE_DOUBLE(X) do \ 107 | { \ 108 | try \ 109 | { \ 110 | (X) = (_wcsicmp(option_val.c_str(), L"infinite") == 0) ? DBL_MAX : std::stod(option_val); \ 111 | } \ 112 | catch(std::exception&) \ 113 | { \ 114 | std::wcerr << L"ERROR: Numeric value \"" << option_val << "\" could not be parsed!\n" << std::endl; \ 115 | return false; \ 116 | } \ 117 | } \ 118 | while(0) 119 | 120 | //============================================================================= 121 | // CONSTRUCTOR / DESTRUCTOR 122 | //============================================================================= 123 | 124 | Params::Params(void) 125 | : 126 | m_iHttpVerb(HTTP_GET), 127 | m_bShowHelp(false), 128 | m_bDisableProxy(false), 129 | m_bDisableRedir(false), 130 | m_uRangeStart(0), 131 | m_uRangeEnd(UINT64_MAX), 132 | m_bInsecure(false), 133 | m_bEnableAlert(false), 134 | m_bForceCrl(false), 135 | m_bSetTimestamp(false), 136 | m_bUpdateMode(false), 137 | m_bVerboseMode(false), 138 | m_bKeepFailed(false), 139 | m_dTimeoutCon(std::numeric_limits::quiet_NaN()), 140 | m_dTimeoutRcv(std::numeric_limits::quiet_NaN()), 141 | m_uRetryCount(2U) 142 | { 143 | } 144 | 145 | Params::~Params() 146 | { 147 | } 148 | 149 | //============================================================================= 150 | // PARSE PARAMETERS 151 | //============================================================================= 152 | 153 | bool Params::parse_cli_args(const int argc, const wchar_t *const argv[]) 154 | { 155 | const std::wstring marker(L"--"); 156 | 157 | bool stopFlag = false; 158 | size_t argCounter = 0; 159 | 160 | for(int i = 1; i < argc; i++) 161 | { 162 | const std::wstring current = argv_i(argv, i); 163 | if(!current.empty()) 164 | { 165 | if((!stopFlag) && (current.find(marker) == 0)) 166 | { 167 | if(current.length() > marker.length()) 168 | { 169 | std::wstring option(current.substr(2, std::wstring::npos)); 170 | if(!processOption(Utils::trim(option))) 171 | { 172 | return false; 173 | } 174 | } 175 | else 176 | { 177 | stopFlag = true; 178 | } 179 | } 180 | else 181 | { 182 | if(!(stopFlag = processParamN(argCounter++, current))) 183 | { 184 | return false; 185 | } 186 | } 187 | } 188 | } 189 | 190 | if((argCounter < 2) && (argc >= 2)) 191 | { 192 | if((!_wcsicmp(argv[1], L"-h")) || (!_wcsicmp(argv[1], L"-?")) || (!_wcsicmp(argv[1], L"/?"))) 193 | { 194 | m_bShowHelp = true; 195 | } 196 | } 197 | 198 | return validate(true); 199 | } 200 | 201 | bool Params::load_conf_file(const std::wstring &config_file) 202 | { 203 | return load_conf_file(config_file, false); 204 | } 205 | 206 | //============================================================================= 207 | // INTERNAL FUNCTIONS 208 | //============================================================================= 209 | 210 | bool Params::validate(const bool &is_final) 211 | { 212 | if(is_final && (m_strSource.empty() || m_strOutput.empty()) && (!m_bShowHelp)) 213 | { 214 | std::wcerr << L"ERROR: Required parameter is missing!\n" << std::endl; 215 | return false; 216 | } 217 | 218 | if(m_bInsecure && m_bForceCrl) 219 | { 220 | std::wcerr << L"ERROR: Options '--insecure' and '--force-crl' are mutually exclusive!\n" << std::endl; 221 | return false; 222 | } 223 | 224 | if((!m_strReferrer.empty()) && (!URL(m_strReferrer).isComplete())) 225 | { 226 | std::wcerr << L"ERROR: The specified referrer address is invalid!\n" << std::endl; 227 | return false; 228 | } 229 | 230 | if(m_uRangeEnd < m_uRangeStart) 231 | { 232 | std::wcerr << L"ERROR: The specified byte range is invalid!\n" << std::endl; 233 | return false; 234 | } 235 | 236 | if(is_final && m_bInsecure) 237 | { 238 | std::wcerr << L"WARNING: Using insecure HTTPS mode, certificates will *not* be checked!\n" << std::endl; 239 | } 240 | 241 | if(is_final && (!m_strPostData.empty()) && (m_iHttpVerb != HTTP_POST) && (m_iHttpVerb != HTTP_PUT)) 242 | { 243 | std::wcerr << L"WARNING: Sending 'x-www-form-urlencoded' data, but HTTP verb is not POST/PUT!\n"; 244 | std::wcerr << L" You probably want to add the \"--verb=post\" or \"--verb=put\" argument.\n" << std::endl; 245 | } 246 | 247 | if(is_final && m_bUpdateMode && (!m_bSetTimestamp)) 248 | { 249 | std::wcerr << L"WARNING: Update mode enabled, but \"--set-ftime\" option *not* currently set!\n" << std::endl; 250 | } 251 | 252 | return true; 253 | } 254 | 255 | bool Params::load_conf_file(const std::wstring &config_file, const bool &recursive) 256 | { 257 | static const size_t BUFF_SIZE = 16384; 258 | std::unique_ptr buffer(new wchar_t[BUFF_SIZE]); 259 | 260 | std::wstring current_file; 261 | size_t offset = 0; 262 | while(Utils::next_token(config_file, L"|", current_file, offset)) 263 | { 264 | std::wcerr << L"Reading file \"" << current_file << L"\"\n" << std::endl; 265 | 266 | std::wifstream stream; 267 | stream.open(current_file); 268 | if(!stream.good()) 269 | { 270 | const errno_t error = errno; 271 | std::wcerr << L"Failed to open configuration file for reading:\n" << current_file << L"\n\nERROR: " << Utils::crt_error_string(error) << L'\n' << std::endl; 272 | return false; 273 | } 274 | 275 | while(stream.good()) 276 | { 277 | stream.getline(buffer.get(), BUFF_SIZE); 278 | if(stream.bad() || (stream.fail() && (!stream.eof()))) 279 | { 280 | std::wcerr << L"Failed to read next line from configuration file:\n" << current_file << L'\n' << std::endl; 281 | stream.close(); 282 | return false; /*file read error*/ 283 | } 284 | 285 | std::wstring temp(buffer.get()); 286 | if(!Utils::trim(temp).empty()) 287 | { 288 | if((temp.front() == L'#') || (temp.front() == L';')) 289 | { 290 | continue; /*comment line detected*/ 291 | } 292 | if(!processOption(temp)) 293 | { 294 | stream.close(); 295 | return false; 296 | } 297 | } 298 | } 299 | 300 | stream.close(); 301 | } 302 | 303 | return recursive ? true : validate(false); 304 | } 305 | 306 | bool Params::processParamN(const size_t n, const std::wstring ¶m) 307 | { 308 | switch(n) 309 | { 310 | case 0: 311 | m_strSource = param; 312 | return true; 313 | case 1: 314 | m_strOutput = param; 315 | return true; 316 | default: 317 | std::wcerr << L"ERROR: Excess argument \"" << param << L"\" encountered!\n" << std::endl; 318 | return false; 319 | } 320 | } 321 | 322 | bool Params::processOption(const std::wstring &option) 323 | { 324 | std::wstring option_key, option_val; 325 | 326 | const size_t delim_pos = option.find_first_of(L'='); 327 | if(delim_pos != std::wstring::npos) 328 | { 329 | if((delim_pos == 0) || (delim_pos >= option.length() - 1)) 330 | { 331 | std::wcerr << L"ERROR: Format of option \"--" << option << "\" is invalid!\n" << std::endl; 332 | return false; 333 | } 334 | option_key = option.substr(0, delim_pos); 335 | option_val = option.substr(delim_pos + 1, std::wstring::npos); 336 | } 337 | else 338 | { 339 | option_key = option; 340 | } 341 | 342 | return processOption(option_key, option_val); 343 | } 344 | 345 | bool Params::processOption(const std::wstring &option_key, const std::wstring &option_val) 346 | { 347 | if(IS_OPTION("help")) 348 | { 349 | ENSURE_NOVAL(); 350 | return (m_bShowHelp = true); 351 | } 352 | else if(IS_OPTION("verb")) 353 | { 354 | ENSURE_VALUE(); 355 | return (HTTP_UNDEF != (m_iHttpVerb = parseHttpVerb(option_val))); 356 | } 357 | else if(IS_OPTION("data")) 358 | { 359 | ENSURE_VALUE(); 360 | m_strPostData = option_val; 361 | return true; 362 | } 363 | else if(IS_OPTION("no-proxy")) 364 | { 365 | ENSURE_NOVAL(); 366 | return (m_bDisableProxy = true); 367 | } 368 | else if(IS_OPTION("agent")) 369 | { 370 | ENSURE_VALUE(); 371 | m_strUserAgent = option_val; 372 | return true; 373 | } 374 | else if(IS_OPTION("no-redir")) 375 | { 376 | ENSURE_NOVAL(); 377 | return (m_bDisableRedir = true); 378 | } 379 | else if(IS_OPTION("insecure")) 380 | { 381 | ENSURE_NOVAL(); 382 | return (m_bInsecure = true); 383 | } 384 | else if(IS_OPTION("range-off")) 385 | { 386 | ENSURE_VALUE(); 387 | PARSE_UINT64(m_uRangeStart); 388 | return true; 389 | } 390 | else if(IS_OPTION("range-end")) 391 | { 392 | ENSURE_VALUE(); 393 | PARSE_UINT64(m_uRangeEnd); 394 | return true; 395 | } 396 | else if(IS_OPTION("refer")) 397 | { 398 | ENSURE_VALUE(); 399 | m_strReferrer = option_val; 400 | return true; 401 | } 402 | else if(IS_OPTION("notify")) 403 | { 404 | ENSURE_NOVAL(); 405 | return (m_bEnableAlert = true); 406 | } 407 | else if(IS_OPTION("time-cn")) 408 | { 409 | ENSURE_VALUE(); 410 | PARSE_DOUBLE(m_dTimeoutCon); 411 | return true; 412 | } 413 | else if(IS_OPTION("time-rc")) 414 | { 415 | ENSURE_VALUE(); 416 | PARSE_DOUBLE(m_dTimeoutRcv); 417 | return true; 418 | } 419 | else if(IS_OPTION("timeout")) 420 | { 421 | ENSURE_VALUE(); 422 | PARSE_DOUBLE(m_dTimeoutCon); 423 | PARSE_DOUBLE(m_dTimeoutRcv); 424 | return true; 425 | } 426 | else if(IS_OPTION("retry")) 427 | { 428 | ENSURE_VALUE(); 429 | PARSE_UINT32(m_uRetryCount); 430 | return true; 431 | } 432 | else if(IS_OPTION("no-retry")) 433 | { 434 | ENSURE_NOVAL(); 435 | m_uRetryCount = 0; 436 | return true; 437 | } 438 | else if(IS_OPTION("force-crl")) 439 | { 440 | ENSURE_NOVAL(); 441 | return (m_bForceCrl = true); 442 | } 443 | else if(IS_OPTION("set-ftime")) 444 | { 445 | ENSURE_NOVAL(); 446 | return (m_bSetTimestamp = true); 447 | } 448 | else if(IS_OPTION("update")) 449 | { 450 | ENSURE_NOVAL(); 451 | return (m_bUpdateMode = true); 452 | } 453 | else if(IS_OPTION("keep-failed")) 454 | { 455 | ENSURE_NOVAL(); 456 | return (m_bKeepFailed = true); 457 | } 458 | else if(IS_OPTION("verbose")) 459 | { 460 | ENSURE_NOVAL(); 461 | return (m_bVerboseMode = true); 462 | } 463 | else if(IS_OPTION("slunk")) 464 | { 465 | ENSURE_NOVAL(); 466 | return (m_bVerboseMode = slunk_handler()); 467 | } 468 | else if(IS_OPTION("config")) 469 | { 470 | ENSURE_VALUE(); 471 | return load_conf_file(option_val, true); 472 | } 473 | 474 | std::wcerr << L"ERROR: Unknown option \"--" << option_key << "\" encountered!\n" << std::endl; 475 | return false; 476 | } 477 | 478 | http_verb_t Params::parseHttpVerb(const std::wstring &value) 479 | { 480 | PARSE_ENUM(5, HTTP_GET); 481 | PARSE_ENUM(5, HTTP_POST); 482 | PARSE_ENUM(5, HTTP_PUT); 483 | PARSE_ENUM(5, HTTP_DELETE); 484 | PARSE_ENUM(5, HTTP_HEAD); 485 | 486 | std::wcerr << L"ERROR: Unknown HTTP method \"" << value << "\" encountered!\n" << std::endl; 487 | return HTTP_UNDEF; 488 | } 489 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The GNU General Public License, Version 2, June 1991 (GPLv2) 2 | ============================================================ 3 | 4 | > Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | > 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 6 | 7 | Everyone is permitted to copy and distribute verbatim copies of this license 8 | document, but changing it is not allowed. 9 | 10 | 11 | Preamble 12 | -------- 13 | 14 | The licenses for most software are designed to take away your freedom to share 15 | and change it. By contrast, the GNU General Public License is intended to 16 | guarantee your freedom to share and change free software--to make sure the 17 | software is free for all its users. This General Public License applies to most 18 | of the Free Software Foundation's software and to any other program whose 19 | authors commit to using it. (Some other Free Software Foundation software is 20 | covered by the GNU Library General Public License instead.) You can apply it to 21 | your programs, too. 22 | 23 | When we speak of free software, we are referring to freedom, not price. Our 24 | General Public Licenses are designed to make sure that you have the freedom to 25 | distribute copies of free software (and charge for this service if you wish), 26 | that you receive source code or can get it if you want it, that you can change 27 | the software or use pieces of it in new free programs; and that you know you can 28 | do these things. 29 | 30 | To protect your rights, we need to make restrictions that forbid anyone to deny 31 | you these rights or to ask you to surrender the rights. These restrictions 32 | translate to certain responsibilities for you if you distribute copies of the 33 | software, or if you modify it. 34 | 35 | For example, if you distribute copies of such a program, whether gratis or for a 36 | fee, you must give the recipients all the rights that you have. You must make 37 | sure that they, too, receive or can get the source code. And you must show them 38 | these terms so they know their rights. 39 | 40 | We protect your rights with two steps: (1) copyright the software, and (2) offer 41 | you this license which gives you legal permission to copy, distribute and/or 42 | modify the software. 43 | 44 | Also, for each author's protection and ours, we want to make certain that 45 | everyone understands that there is no warranty for this free software. If the 46 | software is modified by someone else and passed on, we want its recipients to 47 | know that what they have is not the original, so that any problems introduced by 48 | others will not reflect on the original authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software patents. We wish 51 | to avoid the danger that redistributors of a free program will individually 52 | obtain patent licenses, in effect making the program proprietary. To prevent 53 | this, we have made it clear that any patent must be licensed for everyone's free 54 | use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and modification 57 | follow. 58 | 59 | 60 | Terms And Conditions For Copying, Distribution And Modification 61 | --------------------------------------------------------------- 62 | 63 | **0.** This License applies to any program or other work which contains a notice 64 | placed by the copyright holder saying it may be distributed under the terms of 65 | this General Public License. The "Program", below, refers to any such program or 66 | work, and a "work based on the Program" means either the Program or any 67 | derivative work under copyright law: that is to say, a work containing the 68 | Program or a portion of it, either verbatim or with modifications and/or 69 | translated into another language. (Hereinafter, translation is included without 70 | limitation in the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not covered by 73 | this License; they are outside its scope. The act of running the Program is not 74 | restricted, and the output from the Program is covered only if its contents 75 | constitute a work based on the Program (independent of having been made by 76 | running the Program). Whether that is true depends on what the Program does. 77 | 78 | **1.** You may copy and distribute verbatim copies of the Program's source code 79 | as you receive it, in any medium, provided that you conspicuously and 80 | appropriately publish on each copy an appropriate copyright notice and 81 | disclaimer of warranty; keep intact all the notices that refer to this License 82 | and to the absence of any warranty; and give any other recipients of the Program 83 | a copy of this License along with the Program. 84 | 85 | You may charge a fee for the physical act of transferring a copy, and you may at 86 | your option offer warranty protection in exchange for a fee. 87 | 88 | **2.** You may modify your copy or copies of the Program or any portion of it, 89 | thus forming a work based on the Program, and copy and distribute such 90 | modifications or work under the terms of Section 1 above, provided that you also 91 | meet all of these conditions: 92 | 93 | * **a)** You must cause the modified files to carry prominent notices stating 94 | that you changed the files and the date of any change. 95 | 96 | * **b)** You must cause any work that you distribute or publish, that in whole 97 | or in part contains or is derived from the Program or any part thereof, to 98 | be licensed as a whole at no charge to all third parties under the terms of 99 | this License. 100 | 101 | * **c)** If the modified program normally reads commands interactively when 102 | run, you must cause it, when started running for such interactive use in the 103 | most ordinary way, to print or display an announcement including an 104 | appropriate copyright notice and a notice that there is no warranty (or 105 | else, saying that you provide a warranty) and that users may redistribute 106 | the program under these conditions, and telling the user how to view a copy 107 | of this License. (Exception: if the Program itself is interactive but does 108 | not normally print such an announcement, your work based on the Program is 109 | not required to print an announcement.) 110 | 111 | These requirements apply to the modified work as a whole. If identifiable 112 | sections of that work are not derived from the Program, and can be reasonably 113 | considered independent and separate works in themselves, then this License, and 114 | its terms, do not apply to those sections when you distribute them as separate 115 | works. But when you distribute the same sections as part of a whole which is a 116 | work based on the Program, the distribution of the whole must be on the terms of 117 | this License, whose permissions for other licensees extend to the entire whole, 118 | and thus to each and every part regardless of who wrote it. 119 | 120 | Thus, it is not the intent of this section to claim rights or contest your 121 | rights to work written entirely by you; rather, the intent is to exercise the 122 | right to control the distribution of derivative or collective works based on the 123 | Program. 124 | 125 | In addition, mere aggregation of another work not based on the Program with the 126 | Program (or with a work based on the Program) on a volume of a storage or 127 | distribution medium does not bring the other work under the scope of this 128 | License. 129 | 130 | **3.** You may copy and distribute the Program (or a work based on it, under 131 | Section 2) in object code or executable form under the terms of Sections 1 and 2 132 | above provided that you also do one of the following: 133 | 134 | * **a)** Accompany it with the complete corresponding machine-readable source 135 | code, which must be distributed under the terms of Sections 1 and 2 above on 136 | a medium customarily used for software interchange; or, 137 | 138 | * **b)** Accompany it with a written offer, valid for at least three years, to 139 | give any third party, for a charge no more than your cost of physically 140 | performing source distribution, a complete machine-readable copy of the 141 | corresponding source code, to be distributed under the terms of Sections 1 142 | and 2 above on a medium customarily used for software interchange; or, 143 | 144 | * **c)** Accompany it with the information you received as to the offer to 145 | distribute corresponding source code. (This alternative is allowed only for 146 | noncommercial distribution and only if you received the program in object 147 | code or executable form with such an offer, in accord with Subsection b 148 | above.) 149 | 150 | The source code for a work means the preferred form of the work for making 151 | modifications to it. For an executable work, complete source code means all the 152 | source code for all modules it contains, plus any associated interface 153 | definition files, plus the scripts used to control compilation and installation 154 | of the executable. However, as a special exception, the source code distributed 155 | need not include anything that is normally distributed (in either source or 156 | binary form) with the major components (compiler, kernel, and so on) of the 157 | operating system on which the executable runs, unless that component itself 158 | accompanies the executable. 159 | 160 | If distribution of executable or object code is made by offering access to copy 161 | from a designated place, then offering equivalent access to copy the source code 162 | from the same place counts as distribution of the source code, even though third 163 | parties are not compelled to copy the source along with the object code. 164 | 165 | **4.** You may not copy, modify, sublicense, or distribute the Program except as 166 | expressly provided under this License. Any attempt otherwise to copy, modify, 167 | sublicense or distribute the Program is void, and will automatically terminate 168 | your rights under this License. However, parties who have received copies, or 169 | rights, from you under this License will not have their licenses terminated so 170 | long as such parties remain in full compliance. 171 | 172 | **5.** You are not required to accept this License, since you have not signed 173 | it. However, nothing else grants you permission to modify or distribute the 174 | Program or its derivative works. These actions are prohibited by law if you do 175 | not accept this License. Therefore, by modifying or distributing the Program (or 176 | any work based on the Program), you indicate your acceptance of this License to 177 | do so, and all its terms and conditions for copying, distributing or modifying 178 | the Program or works based on it. 179 | 180 | **6.** Each time you redistribute the Program (or any work based on the 181 | Program), the recipient automatically receives a license from the original 182 | licensor to copy, distribute or modify the Program subject to these terms and 183 | conditions. You may not impose any further restrictions on the recipients' 184 | exercise of the rights granted herein. You are not responsible for enforcing 185 | compliance by third parties to this License. 186 | 187 | **7.** If, as a consequence of a court judgment or allegation of patent 188 | infringement or for any other reason (not limited to patent issues), conditions 189 | are imposed on you (whether by court order, agreement or otherwise) that 190 | contradict the conditions of this License, they do not excuse you from the 191 | conditions of this License. If you cannot distribute so as to satisfy 192 | simultaneously your obligations under this License and any other pertinent 193 | obligations, then as a consequence you may not distribute the Program at all. 194 | For example, if a patent license would not permit royalty-free redistribution of 195 | the Program by all those who receive copies directly or indirectly through you, 196 | then the only way you could satisfy both it and this License would be to refrain 197 | entirely from distribution of the Program. 198 | 199 | If any portion of this section is held invalid or unenforceable under any 200 | particular circumstance, the balance of the section is intended to apply and the 201 | section as a whole is intended to apply in other circumstances. 202 | 203 | It is not the purpose of this section to induce you to infringe any patents or 204 | other property right claims or to contest validity of any such claims; this 205 | section has the sole purpose of protecting the integrity of the free software 206 | distribution system, which is implemented by public license practices. Many 207 | people have made generous contributions to the wide range of software 208 | distributed through that system in reliance on consistent application of that 209 | system; it is up to the author/donor to decide if he or she is willing to 210 | distribute software through any other system and a licensee cannot impose that 211 | choice. 212 | 213 | This section is intended to make thoroughly clear what is believed to be a 214 | consequence of the rest of this License. 215 | 216 | **8.** If the distribution and/or use of the Program is restricted in certain 217 | countries either by patents or by copyrighted interfaces, the original copyright 218 | holder who places the Program under this License may add an explicit 219 | geographical distribution limitation excluding those countries, so that 220 | distribution is permitted only in or among countries not thus excluded. In such 221 | case, this License incorporates the limitation as if written in the body of this 222 | License. 223 | 224 | **9.** The Free Software Foundation may publish revised and/or new versions of 225 | the General Public License from time to time. Such new versions will be similar 226 | in spirit to the present version, but may differ in detail to address new 227 | problems or concerns. 228 | 229 | Each version is given a distinguishing version number. If the Program specifies 230 | a version number of this License which applies to it and "any later version", 231 | you have the option of following the terms and conditions either of that version 232 | or of any later version published by the Free Software Foundation. If the 233 | Program does not specify a version number of this License, you may choose any 234 | version ever published by the Free Software Foundation. 235 | 236 | **10.** If you wish to incorporate parts of the Program into other free programs 237 | whose distribution conditions are different, write to the author to ask for 238 | permission. For software which is copyrighted by the Free Software Foundation, 239 | write to the Free Software Foundation; we sometimes make exceptions for this. 240 | Our decision will be guided by the two goals of preserving the free status of 241 | all derivatives of our free software and of promoting the sharing and reuse of 242 | software generally. 243 | 244 | 245 | No Warranty 246 | ----------- 247 | 248 | **11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR 249 | THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE 250 | STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM 251 | "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, 252 | BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 253 | PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 254 | PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 255 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 256 | 257 | **12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 258 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE 259 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 260 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR 261 | INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA 262 | BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 263 | FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER 264 | OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 265 | -------------------------------------------------------------------------------- /src/Client_HTTP.cpp: -------------------------------------------------------------------------------- 1 | /////////////////////////////////////////////////////////////////////////////// 2 | // INetGet - Lightweight command-line front-end to WinINet API 3 | // Copyright (C) 2015-2018 LoRd_MuldeR 4 | // 5 | // This program is free software; you can redistribute it and/or 6 | // modify it under the terms of the GNU General Public License 7 | // as published by the Free Software Foundation; either version 2 8 | // of the License, or (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along 16 | // with this program; if not, write to the Free Software Foundation, Inc., 17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | // 19 | // See https://www.gnu.org/licenses/gpl-2.0-standalone.html for details! 20 | /////////////////////////////////////////////////////////////////////////////// 21 | 22 | #include "Client_HTTP.h" 23 | 24 | //Internal 25 | #include "URL.h" 26 | #include "Utils.h" 27 | 28 | //Win32 29 | #define WIN32_LEAN_AND_MEAN 1 30 | #include 31 | #include 32 | 33 | //CRT 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | //Helper functions 40 | static const wchar_t *CSTR(const std::wstring &str) { return str.empty() ? NULL : str.c_str(); } 41 | static const char *CSTR(const std::string &str) { return str.empty() ? NULL : str.c_str(); } 42 | 43 | //Const 44 | static const wchar_t *const HTTP_VER_11 = L"HTTP/1.1"; 45 | static const wchar_t *const ACCEPTED_TYPES[] = { L"*/*", NULL }; 46 | static const wchar_t *const TYPE_FORM_DATA = L"Content-Type: application/x-www-form-urlencoded"; 47 | static const wchar_t *const MODIFIED_SINCE = L"If-Modified-Since: "; 48 | static const wchar_t *const RANGE_BYTES = L"Range: bytes="; 49 | //Macros 50 | #define OPTIONAL_FLAG(X,Y,Z) do \ 51 | { \ 52 | if((Y)) { (X) |= (Z); } \ 53 | } \ 54 | while(0) 55 | 56 | //============================================================================= 57 | // CONSTRUCTOR / DESTRUCTOR 58 | //============================================================================= 59 | 60 | HttpClient::HttpClient(const Sync::Signal &user_aborted, const bool &disableProxy, const std::wstring &userAgentStr, const bool &no_redir, uint64_t range_start, uint64_t range_end, const bool &insecure, const bool &force_crl, const double &timeout_con, const double &timeout_rcv, const uint32_t &connect_retry, const bool &verbose) 61 | : 62 | AbstractClient(user_aborted, disableProxy, userAgentStr, timeout_con, timeout_rcv, connect_retry, verbose), 63 | m_disable_redir(no_redir), 64 | m_range_start(range_start), 65 | m_range_end(range_end), 66 | m_insecure_tls(insecure), 67 | m_force_crl(force_crl), 68 | m_hConnection(NULL), 69 | m_hRequest(NULL), 70 | m_current_status(UINT32_MAX) 71 | { 72 | if(m_insecure_tls && m_force_crl) 73 | { 74 | throw std::runtime_error("Flags 'insecure' and 'force_crl' are mutually exclusive!"); 75 | } 76 | } 77 | 78 | HttpClient::~HttpClient(void) 79 | { 80 | } 81 | 82 | //============================================================================= 83 | // CONNECTION HANDLING 84 | //============================================================================= 85 | 86 | bool HttpClient::open(const http_verb_t &verb, const URL &url, const std::string &post_data, const std::wstring &referrer, const uint64_t ×tamp) 87 | { 88 | Sync::Locker locker(m_mutex); 89 | if(!wininet_init()) 90 | { 91 | return false; /*WinINet failed to initialize*/ 92 | } 93 | 94 | //Close the existing connection, just to be sure 95 | if(!close()) 96 | { 97 | set_error_text(std::wstring(L"ERROR: Failed to close the existing connection!")); 98 | return false; 99 | } 100 | 101 | //Print URL details 102 | const bool use_tls = (url.getScheme() == INTERNET_SCHEME_HTTPS); 103 | if(m_verbose) 104 | { 105 | std::wostringstream url_str; 106 | url_str << (use_tls ? L"HTTPS" : L"HTTP") << L'|' << url.getHostName() << L'|' << url.getUserName() << L'|' << url.getPassword() << L'|' << url.getPortNo() << L'|' << url.getUrlPath() << url.getExtraInfo(); 107 | emit_message(std::wstring(L"RQST_URL: \"") + url_str.str() + L'"'); 108 | emit_message(std::wstring(L"REFERRER: \"") + referrer + L'"'); 109 | emit_message(std::wstring(L"POST_DAT: \"") + Utils::utf8_to_wide_str(post_data.c_str()) + L'"'); 110 | } 111 | 112 | //Reset status 113 | m_current_status = UINT32_MAX; 114 | 115 | //Create connection 116 | if(!connect(url.getHostName(), url.getPortNo(), url.getUserName(), url.getPassword())) 117 | { 118 | return false; /*the connection could not be created*/ 119 | } 120 | 121 | //Create HTTP request and send! 122 | if(!create_request(use_tls, verb, url.getUrlPath(), url.getExtraInfo(), post_data, referrer, timestamp)) 123 | { 124 | return false; /*the request could not be created or sent*/ 125 | } 126 | 127 | //Sucess 128 | set_error_text(); 129 | emit_message(std::wstring(L"Response received.")); 130 | return true; 131 | } 132 | 133 | bool HttpClient::close(void) 134 | { 135 | Sync::Locker locker(m_mutex); 136 | bool success = true; 137 | 138 | //Close the request, if it currently exists 139 | if(!close_handle(m_hRequest)) 140 | { 141 | success = false; 142 | } 143 | 144 | //Close connection, if it is currently open 145 | if(!close_handle(m_hConnection)) 146 | { 147 | success = false; 148 | } 149 | 150 | set_error_text(); 151 | return success; 152 | } 153 | 154 | //============================================================================= 155 | // QUERY RESULT 156 | //============================================================================= 157 | 158 | bool HttpClient::result(bool &success, uint32_t &status_code, uint64_t &file_size, uint64_t &time_stamp, std::wstring &content_type, std::wstring &content_encd) 159 | { 160 | success = false; 161 | status_code = 0; 162 | file_size = SIZE_UNKNOWN; 163 | time_stamp = TIME_UNKNOWN; 164 | content_type.clear(); 165 | content_encd.clear(); 166 | 167 | Sync::Locker locker(m_mutex); 168 | 169 | if(m_hRequest == NULL) 170 | { 171 | set_error_text(std::wstring(L"INTERNAL ERROR: There currently is no active request!")); 172 | return false; /*request not created yet*/ 173 | } 174 | 175 | if(!get_header_int(m_hRequest, HTTP_QUERY_STATUS_CODE, status_code)) 176 | { 177 | return false; /*couldn't get status code*/ 178 | } 179 | 180 | get_header_str(m_hRequest, HTTP_QUERY_CONTENT_TYPE, content_type); 181 | get_header_str(m_hRequest, HTTP_QUERY_CONTENT_ENCODING, content_encd); 182 | 183 | std::wstring content_length; 184 | if(get_header_str(m_hRequest, HTTP_QUERY_CONTENT_LENGTH, content_length)) 185 | { 186 | file_size = parse_file_size(content_length); 187 | } 188 | 189 | std::wstring last_modified; 190 | if(get_header_str(m_hRequest, HTTP_QUERY_LAST_MODIFIED, last_modified)) 191 | { 192 | time_stamp = Utils::parse_timestamp(last_modified); 193 | } 194 | 195 | set_error_text(); 196 | success = ((status_code >= 200) && (status_code < 300)); 197 | return true; 198 | } 199 | 200 | //============================================================================= 201 | // READ PAYLOAD 202 | //============================================================================= 203 | 204 | bool HttpClient::read_data(uint8_t *out_buff, const uint32_t &buff_size, size_t &bytes_read, bool &eof_flag) 205 | { 206 | Sync::Locker locker(m_mutex); 207 | 208 | if(m_hRequest == NULL) 209 | { 210 | set_error_text(std::wstring(L"INTERNAL ERROR: There currently is no active request!")); 211 | return false; /*request not created yet*/ 212 | } 213 | 214 | DWORD temp; 215 | if(!InternetReadFile(m_hRequest, out_buff, buff_size, &temp)) 216 | { 217 | const DWORD error_code = GetLastError(); 218 | set_error_text(std::wstring(L"An error occurred while receiving data from the server:\n").append(Utils::win_error_string(error_code))); 219 | return false; 220 | } 221 | 222 | set_error_text(); 223 | eof_flag = ((bytes_read = temp) < 1); 224 | return true; 225 | } 226 | 227 | //============================================================================= 228 | // INTERNAL FUNCTIONS 229 | //============================================================================= 230 | 231 | bool HttpClient::connect(const std::wstring &hostName, const uint16_t &portNo, const std::wstring &userName, const std::wstring &password) 232 | { 233 | //Try to open the new connection 234 | m_hConnection = InternetConnect(m_hInternet, CSTR(hostName), portNo, CSTR(userName), CSTR(password), INTERNET_SERVICE_HTTP, 0, reinterpret_cast(this)); 235 | if(m_hConnection == NULL) 236 | { 237 | const DWORD error_code = GetLastError(); 238 | set_error_text(std::wstring(L"InternetConnect() function has failed:\n").append(Utils::win_error_string(error_code))); 239 | return false; 240 | } 241 | 242 | //Install the callback handler (only in verbose mode) 243 | if(InternetSetStatusCallback(m_hConnection, (INTERNET_STATUS_CALLBACK)(&status_callback)) == INTERNET_INVALID_STATUS_CALLBACK) 244 | { 245 | const DWORD error_code = GetLastError(); 246 | set_error_text(std::wstring(L"InternetSetStatusCallback() function has failed:\n").append(Utils::win_error_string(error_code))); 247 | return false; 248 | } 249 | 250 | return (!m_user_aborted.get()); 251 | } 252 | 253 | bool HttpClient::create_request(const bool &use_tls, const http_verb_t &verb, const std::wstring &path, const std::wstring &query, const std::string &post_data, const std::wstring &referrer, const uint64_t ×tamp) 254 | { 255 | //Setup request flags 256 | DWORD flags = INTERNET_FLAG_RELOAD | INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS; 257 | OPTIONAL_FLAG(flags, use_tls, INTERNET_FLAG_SECURE); 258 | OPTIONAL_FLAG(flags, m_disable_redir, INTERNET_FLAG_NO_AUTO_REDIRECT); 259 | OPTIONAL_FLAG(flags, m_insecure_tls, INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP); 260 | OPTIONAL_FLAG(flags, m_disable_proxy, INTERNET_FLAG_PRAGMA_NOCACHE); 261 | 262 | //Try to create the HTTP request 263 | m_hRequest = HttpOpenRequestW(m_hConnection, http_verb_str(verb), CSTR(path + query), HTTP_VER_11, CSTR(referrer), (LPCWSTR*)ACCEPTED_TYPES, flags, intptr_t(this)); 264 | if(m_hRequest == NULL) 265 | { 266 | const DWORD error_code = GetLastError(); 267 | set_error_text(std::wstring(L"HttpOpenRequest() function has failed:\n").append(Utils::win_error_string(error_code))); 268 | return false; 269 | } 270 | 271 | //Update the security flags, if required 272 | static const DWORD insecure_flags = SECURITY_FLAG_IGNORE_REVOCATION | SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_WRONG_USAGE; 273 | if(!update_security_opts(m_hRequest, insecure_flags, m_insecure_tls)) 274 | { 275 | return false; /*updating the flags failed!*/ 276 | } 277 | 278 | //Prepare headers 279 | std::wostringstream headers; 280 | if(post_data.length() > 0) 281 | { 282 | headers << TYPE_FORM_DATA << std::endl; 283 | } 284 | if(timestamp > TIME_UNKNOWN) 285 | { 286 | headers << MODIFIED_SINCE << Utils::timestamp_to_str(timestamp) << std::endl; 287 | } 288 | if((m_range_start > 0U) || (m_range_end != UINT64_MAX)) 289 | { 290 | if(m_range_end != UINT64_MAX) 291 | { 292 | headers << RANGE_BYTES << m_range_start << '-' << m_range_end << std::endl; 293 | } 294 | else 295 | { 296 | headers << RANGE_BYTES << m_range_start << '-' << std::endl; 297 | } 298 | } 299 | 300 | //Setup retry point 301 | uint32_t retry_counter = 0; 302 | bool retry_flag = m_insecure_tls || m_force_crl; 303 | label_retry_create_request: 304 | 305 | //Try to actually send the HTTP request 306 | BOOL success = HttpSendRequest(m_hRequest, CSTR(headers.str()), DWORD(-1L), ((LPVOID)CSTR(post_data)), DWORD(post_data.length())); 307 | if(success != TRUE) 308 | { 309 | const DWORD error_code = GetLastError(); 310 | if(m_user_aborted.get()) 311 | { 312 | return false; /*aborted by user*/ 313 | } 314 | if((error_code == ERROR_INTERNET_SEC_CERT_REV_FAILED) && (!retry_flag)) 315 | { 316 | if(retry_flag = update_security_opts(m_hRequest, SECURITY_FLAG_IGNORE_REVOCATION, true)) 317 | { 318 | emit_message(std::wstring(L"Failed to check for revocation, retrying with revocation checks disabled!")); 319 | goto label_retry_create_request; 320 | } 321 | } 322 | else if(((error_code == ERROR_INTERNET_CANNOT_CONNECT) || (error_code == ERROR_INTERNET_TIMEOUT)) && (retry_counter++ < m_connect_retry)) 323 | { 324 | std::wostringstream retry_info; 325 | retry_info << L'[' << retry_counter << L'/' << m_connect_retry << L']'; 326 | emit_message(std::wstring(L"Connection has failed. Retrying! ").append(retry_info.str())); 327 | goto label_retry_create_request; 328 | } 329 | set_error_text(std::wstring(L"Failed to connect to the server:\n").append(Utils::win_error_string(error_code))); 330 | return false; 331 | } 332 | 333 | return (!m_user_aborted.get()); 334 | } 335 | 336 | //============================================================================= 337 | // STATUS HANDLER 338 | //============================================================================= 339 | 340 | void HttpClient::update_status(const uint32_t &status, const uintptr_t &info) 341 | { 342 | if(m_user_aborted.get()) 343 | { 344 | return; /*aborted by user*/ 345 | } 346 | 347 | AbstractClient::update_status(status, info); 348 | if(m_current_status != status) 349 | { 350 | std::wostringstream status_info; 351 | switch(status) 352 | { 353 | case INTERNET_STATUS_DETECTING_PROXY: status_info << "Detecting proxy server..." ; break; 354 | case INTERNET_STATUS_RESOLVING_NAME: status_info << "Resolving host name..." ; break; 355 | case INTERNET_STATUS_NAME_RESOLVED: status_info << "Server address resolved to: " << status_str(info); break; 356 | case INTERNET_STATUS_CONNECTING_TO_SERVER: status_info << "Connecting to server..." ; break; 357 | case INTERNET_STATUS_SENDING_REQUEST: status_info << "Sending request to server..." ; break; 358 | case INTERNET_STATUS_REDIRECT: status_info << "Redirecting: " << status_str(info) ; break; 359 | case INTERNET_STATUS_RECEIVING_RESPONSE: status_info << "Request sent, awaiting response..." ; break; 360 | default: return; /*unknown code*/ 361 | } 362 | emit_message(status_info.str()); 363 | m_current_status = status; 364 | } 365 | } 366 | 367 | //============================================================================= 368 | // UTILITIES 369 | //============================================================================= 370 | 371 | #define CHECK_HTTP_VERB(X) do \ 372 | { \ 373 | if((X) == verb) \ 374 | { \ 375 | static const wchar_t *const name = L#X; \ 376 | return &name[5]; \ 377 | } \ 378 | } \ 379 | while(0) 380 | 381 | const wchar_t *HttpClient::http_verb_str(const http_verb_t &verb) 382 | { 383 | CHECK_HTTP_VERB(HTTP_GET); 384 | CHECK_HTTP_VERB(HTTP_POST); 385 | CHECK_HTTP_VERB(HTTP_PUT); 386 | CHECK_HTTP_VERB(HTTP_DELETE); 387 | CHECK_HTTP_VERB(HTTP_HEAD); 388 | 389 | throw new std::runtime_error("Invalid verb specified!"); 390 | } 391 | 392 | bool HttpClient::update_security_opts(void *const request, const uint32_t &new_flags, const bool &enable) 393 | { 394 | uint32_t security_flags = 0; 395 | if(get_inet_options(request, INTERNET_OPTION_SECURITY_FLAGS, security_flags)) 396 | { 397 | security_flags = enable ? (security_flags | new_flags) : (security_flags & (~new_flags)); 398 | return set_inet_options(request, INTERNET_OPTION_SECURITY_FLAGS, security_flags); 399 | } 400 | return false; 401 | } 402 | 403 | bool HttpClient::get_header_int(void *const request, const uint32_t type, uint32_t &value) 404 | { 405 | DWORD result; 406 | DWORD resultSize = sizeof(DWORD); 407 | 408 | if(HttpQueryInfo(request, type | HTTP_QUERY_FLAG_NUMBER, &result, &resultSize, 0) == TRUE) 409 | { 410 | value = result; 411 | return true; 412 | } 413 | 414 | const DWORD error_code = GetLastError(); 415 | if(error_code != ERROR_HTTP_HEADER_NOT_FOUND) 416 | { 417 | set_error_text(std::wstring(L"HttpQueryInfo() has failed:\n").append(Utils::win_error_string(error_code))); 418 | } 419 | 420 | return false; 421 | } 422 | 423 | bool HttpClient::get_header_str(void *const request, const uint32_t type, std::wstring &value) 424 | { 425 | static const size_t BUFF_SIZE = 2048; 426 | wchar_t result[BUFF_SIZE]; 427 | DWORD resultSize = BUFF_SIZE * sizeof(wchar_t); 428 | 429 | if(HttpQueryInfo(request, type, &result, &resultSize, 0) == TRUE) 430 | { 431 | std::wstring temp(result); 432 | value = Utils::trim(temp); 433 | return (!value.empty()); 434 | } 435 | 436 | const DWORD error_code = GetLastError(); 437 | if(error_code != ERROR_HTTP_HEADER_NOT_FOUND) 438 | { 439 | set_error_text(std::wstring(L"HttpQueryInfo() has failed:\n").append(Utils::win_error_string(error_code))); 440 | } 441 | 442 | value.clear(); 443 | return false; 444 | } 445 | 446 | uint64_t HttpClient::parse_file_size(const std::wstring &str) 447 | { 448 | if(str.empty()) 449 | { 450 | return SIZE_UNKNOWN; /*string is empty*/ 451 | } 452 | 453 | try 454 | { 455 | const uint64_t result = std::stoull(str); 456 | return (result > 0ui64) ? result : SIZE_UNKNOWN; 457 | } 458 | catch(std::exception&) 459 | { 460 | return SIZE_UNKNOWN; /*parsing error*/ 461 | } 462 | } 463 | 464 | 465 | --------------------------------------------------------------------------------