├── 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 |
--------------------------------------------------------------------------------