first commit
This commit is contained in:
commit
856373b396
|
@ -0,0 +1,2 @@
|
|||
build
|
||||
.vscode
|
|
@ -0,0 +1,149 @@
|
|||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
project(TessesFramework VERSION 1.0)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
list(APPEND TESSESFRAMEWORK_SOURCE
|
||||
src/Http/FileServer.cpp
|
||||
src/Http/HttpServer.cpp
|
||||
src/Http/HttpUtils.cpp
|
||||
src/Http/HttpClient.cpp
|
||||
src/Http/HttpStream.cpp
|
||||
src/Http/ContentDisposition.cpp
|
||||
src/Streams/FileStream.cpp
|
||||
src/Streams/MemoryStream.cpp
|
||||
src/Streams/NetworkStream.cpp
|
||||
src/Streams/Stream.cpp
|
||||
src/Streams/BufferedStream.cpp
|
||||
src/TextStreams/StreamReader.cpp
|
||||
src/TextStreams/StreamWriter.cpp
|
||||
src/TextStreams/TextReader.cpp
|
||||
src/TextStreams/TextWriter.cpp
|
||||
src/Threading/Thread.cpp
|
||||
src/Threading/Mutex.cpp
|
||||
src/Filesystem/VFS.cpp
|
||||
src/Filesystem/LocalFS.cpp
|
||||
src/Filesystem/SubdirFilesystem.cpp
|
||||
src/Filesystem/NullFilesystem.cpp
|
||||
src/Filesystem/MountableFilesystem.cpp
|
||||
src/Crypto/ClientTLSStream.cpp
|
||||
src/TF_Init.cpp
|
||||
)
|
||||
|
||||
set(TESSESFRAMEWORK_CERT_BUNDLE_FILE "/etc/ssl/certs/ca-certificates.crt")
|
||||
option(TESSESFRAMEWORK_EMBED_CERT_BUNDLE "Embed the certificate chain bundle" ON)
|
||||
option(TESSESFRAMEWORK_ENABLE_MBED "Enable Tesses Framework mbedtls" ON)
|
||||
option(TESSESFRAMEWORK_ENABLE_EXAMPLES "Enable Tesses Framework examples" ON)
|
||||
option(TESSESFRAMEWORK_ENABLE_STATIC "Enable Tesses Framework Static Libraries" ON)
|
||||
option(TESSESFRAMEWORK_ENABLE_SHARED "Enable Tesses Framework Shared Libraries" ON)
|
||||
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include)
|
||||
|
||||
if(TESSESFRAMEWORK_ENABLE_MBED)
|
||||
if(TESSESFRAMEWORK_EMBED_CERT_BUNDLE)
|
||||
include(cmake/bin2h.cmake)
|
||||
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/include/CertificateChain.h "#pragma once\n")
|
||||
#target_compile_definitions(TessesFramework PUBLIC TESSESFRAMEWORK_EMBED_CERT_BUNDLE)
|
||||
bin2h(SOURCE_FILE ${TESSESFRAMEWORK_CERT_BUNDLE_FILE} HEADER_FILE ${CMAKE_CURRENT_BINARY_DIR}/include/CertificateChain.h VARIABLE_NAME CertificateChain APPEND NULL_TERMINATE)
|
||||
file(APPEND ${CMAKE_CURRENT_BINARY_DIR}/include/CertificateChain.h "\n")
|
||||
#else()
|
||||
#target_compile_definitions(TessesFramework PUBLIC TESSESFRAMEWORK_CERT_BUNDLE_FILE=${TESSESFRAMEWORK_CERT_BUNDLE_FILE})
|
||||
|
||||
endif()
|
||||
endif()
|
||||
set(MBEDTLS_DIR "")
|
||||
|
||||
function(link_deps TessesFramework_TARGET)
|
||||
if(TESSESFRAMEWORK_ENABLE_MBED)
|
||||
target_compile_definitions(${TessesFramework_TARGET} PUBLIC TESSESFRAMEWORK_ENABLE_MBED)
|
||||
if(TESSESFRAMEWORK_EMBED_CERT_BUNDLE)
|
||||
target_compile_definitions(${TessesFramework_TARGET} PUBLIC TESSESFRAMEWORK_EMBED_CERT_BUNDLE)
|
||||
else()
|
||||
target_compile_definitions(TessesFramework PUBLIC TESSESFRAMEWORK_CERT_BUNDLE_FILE=${TESSESFRAMEWORK_CERT_BUNDLE_FILE})
|
||||
endif()
|
||||
if(MBEDTLS_DIR STREQUAL "")
|
||||
else()
|
||||
target_include_directories(${TessesFramework_TARGET} PUBLIC ${MBEDTLS_DIR}/include)
|
||||
target_link_directories(${TessesFramework_TARGET} PUBLIC ${MBEDTLS_DIR}/lib)
|
||||
endif()
|
||||
target_link_libraries(${TessesFramework_TARGET} PUBLIC mbedtls mbedx509 mbedcrypto)
|
||||
target_include_directories(${TessesFramework_TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/include)
|
||||
endif()
|
||||
target_include_directories(${TessesFramework_TARGET}
|
||||
PUBLIC
|
||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
||||
)
|
||||
if("${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoWii" OR "${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoGameCube")
|
||||
target_link_libraries(${TessesFramework_TARGET} PUBLIC fat)
|
||||
endif()
|
||||
if("${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoWii")
|
||||
target_link_libraries(${TessesFramework_TARGET} PUBLIC wiisocket)
|
||||
target_compile_definitions(${TessesFramework_TARGET} PUBLIC TESSESFRAMEWORK_USE_WII_SOCKET)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
if(TESSESFRAMEWORK_ENABLE_STATIC)
|
||||
|
||||
add_library(tessesframework STATIC ${TESSESFRAMEWORK_SOURCE})
|
||||
link_deps(tessesframework)
|
||||
list(APPEND TessesFrameworkLibs tessesframework)
|
||||
endif()
|
||||
|
||||
|
||||
if(TESSESFRAMEWORK_ENABLE_SHARED)
|
||||
|
||||
add_library(tessesframework_shared SHARED ${TESSESFRAMEWORK_SOURCE})
|
||||
link_deps(tessesframework_shared)
|
||||
list(APPEND TessesFrameworkLibs tessesframework_shared)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
install(TARGETS ${TessesFrameworkLibs}
|
||||
EXPORT TessesFrameworkTargets
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
)
|
||||
|
||||
install(DIRECTORY include/TessesFramework DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
install(EXPORT TessesFrameworkTargets
|
||||
FILE TessesFrameworkTargets.cmake
|
||||
NAMESPACE TessesFramework::
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/TessesFramework
|
||||
)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/TessesFrameworkConfig.cmake"
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/TessesFramework)
|
||||
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/TessesFrameworkConfig.cmake"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/TessesFramework)
|
||||
|
||||
if(TESSESFRAMEWORK_ENABLE_EXAMPLES)
|
||||
add_executable(copyfile examples/copyfile.cpp)
|
||||
target_link_libraries(copyfile PUBLIC tessesframework)
|
||||
|
||||
|
||||
add_executable(fileserver examples/fileserver.cpp)
|
||||
target_link_libraries(fileserver PUBLIC tessesframework)
|
||||
add_executable(webserverex examples/webserverex.cpp)
|
||||
target_link_libraries(webserverex PUBLIC tessesframework)
|
||||
|
||||
add_executable(safesubpath examples/safesubpath.cpp)
|
||||
target_link_libraries(safesubpath PUBLIC tessesframework)
|
||||
|
||||
add_executable(mountabletest examples/mountabletest.cpp)
|
||||
target_link_libraries(mountabletest PUBLIC tessesframework)
|
||||
|
||||
add_executable(download examples/download.cpp)
|
||||
target_link_libraries(download PUBLIC tessesframework)
|
||||
endif()
|
|
@ -0,0 +1,5 @@
|
|||
@PACKAGE_INIT@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/TessesFrameworkTargets.cmake")
|
||||
|
||||
check_required_components(TessesFramework)
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2024 Mike Nolan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -0,0 +1,6 @@
|
|||
Other peoples code
|
||||
==================
|
||||
|
||||
- cmake/bin2h.cmake, from: https://github.com/sivachandran/cmake-bin2h (MIT)
|
||||
- Cppified the multipart/form-data code from: https://github.com/dajuric/simple-http (MIT)
|
||||
- mbedtls ssl code from mbedtls examples (Apache 2.0)
|
|
@ -0,0 +1,84 @@
|
|||
#Released under MIT from https://github.com/sivachandran/cmake-bin2h
|
||||
include(CMakeParseArguments)
|
||||
|
||||
# Function to wrap a given string into multiple lines at the given column position.
|
||||
# Parameters:
|
||||
# VARIABLE - The name of the CMake variable holding the string.
|
||||
# AT_COLUMN - The column position at which string will be wrapped.
|
||||
function(WRAP_STRING)
|
||||
set(oneValueArgs VARIABLE AT_COLUMN)
|
||||
cmake_parse_arguments(WRAP_STRING "${options}" "${oneValueArgs}" "" ${ARGN})
|
||||
|
||||
string(LENGTH ${${WRAP_STRING_VARIABLE}} stringLength)
|
||||
math(EXPR offset "0")
|
||||
|
||||
while(stringLength GREATER 0)
|
||||
|
||||
if(stringLength GREATER ${WRAP_STRING_AT_COLUMN})
|
||||
math(EXPR length "${WRAP_STRING_AT_COLUMN}")
|
||||
else()
|
||||
math(EXPR length "${stringLength}")
|
||||
endif()
|
||||
|
||||
string(SUBSTRING ${${WRAP_STRING_VARIABLE}} ${offset} ${length} line)
|
||||
set(lines "${lines}\n${line}")
|
||||
|
||||
math(EXPR stringLength "${stringLength} - ${length}")
|
||||
math(EXPR offset "${offset} + ${length}")
|
||||
endwhile()
|
||||
|
||||
set(${WRAP_STRING_VARIABLE} "${lines}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Function to embed contents of a file as byte array in C/C++ header file(.h). The header file
|
||||
# will contain a byte array and integer variable holding the size of the array.
|
||||
# Parameters
|
||||
# SOURCE_FILE - The path of source file whose contents will be embedded in the header file.
|
||||
# VARIABLE_NAME - The name of the variable for the byte array. The string "_SIZE" will be append
|
||||
# to this name and will be used a variable name for size variable.
|
||||
# HEADER_FILE - The path of header file.
|
||||
# APPEND - If specified appends to the header file instead of overwriting it
|
||||
# NULL_TERMINATE - If specified a null byte(zero) will be append to the byte array. This will be
|
||||
# useful if the source file is a text file and we want to use the file contents
|
||||
# as string. But the size variable holds size of the byte array without this
|
||||
# null byte.
|
||||
# Usage:
|
||||
# bin2h(SOURCE_FILE "Logo.png" HEADER_FILE "Logo.h" VARIABLE_NAME "LOGO_PNG")
|
||||
function(BIN2H)
|
||||
set(options APPEND NULL_TERMINATE)
|
||||
set(oneValueArgs SOURCE_FILE VARIABLE_NAME HEADER_FILE)
|
||||
cmake_parse_arguments(BIN2H "${options}" "${oneValueArgs}" "" ${ARGN})
|
||||
|
||||
# reads source file contents as hex string
|
||||
file(READ ${BIN2H_SOURCE_FILE} hexString HEX)
|
||||
string(LENGTH ${hexString} hexStringLength)
|
||||
|
||||
# appends null byte if asked
|
||||
if(BIN2H_NULL_TERMINATE)
|
||||
set(hexString "${hexString}00")
|
||||
endif()
|
||||
|
||||
# wraps the hex string into multiple lines at column 32(i.e. 16 bytes per line)
|
||||
wrap_string(VARIABLE hexString AT_COLUMN 32)
|
||||
math(EXPR arraySize "${hexStringLength} / 2")
|
||||
|
||||
# adds '0x' prefix and comma suffix before and after every byte respectively
|
||||
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1, " arrayValues ${hexString})
|
||||
# removes trailing comma
|
||||
string(REGEX REPLACE ", $" "" arrayValues ${arrayValues})
|
||||
|
||||
# converts the variable name into proper C identifier
|
||||
string(MAKE_C_IDENTIFIER "${BIN2H_VARIABLE_NAME}" BIN2H_VARIABLE_NAME)
|
||||
string(TOUPPER "${BIN2H_VARIABLE_NAME}" BIN2H_VARIABLE_NAME)
|
||||
|
||||
# declares byte array and the length variables
|
||||
set(arrayDefinition "const unsigned char ${BIN2H_VARIABLE_NAME}[] = { ${arrayValues} };")
|
||||
set(arraySizeDefinition "const size_t ${BIN2H_VARIABLE_NAME}_SIZE = ${arraySize};")
|
||||
|
||||
set(declarations "${arrayDefinition}\n\n${arraySizeDefinition}\n\n")
|
||||
if(BIN2H_APPEND)
|
||||
file(APPEND ${BIN2H_HEADER_FILE} "${declarations}")
|
||||
else()
|
||||
file(WRITE ${BIN2H_HEADER_FILE} "${declarations}")
|
||||
endif()
|
||||
endfunction()
|
|
@ -0,0 +1,16 @@
|
|||
#include "TessesFramework/TessesFramework.hpp"
|
||||
|
||||
using namespace Tesses::Framework::Filesystem;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
LocalFilesystem fs;
|
||||
VFSPath src = fs.SystemToVFSPath(argv[1]);
|
||||
VFSPath dest = fs.SystemToVFSPath(argv[2]);
|
||||
auto srcs = fs.OpenFile(src,"rb");
|
||||
auto dests = fs.OpenFile(dest,"wb");
|
||||
srcs->CopyTo(*dests);
|
||||
|
||||
delete srcs;
|
||||
delete dests;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#include "TessesFramework/TessesFramework.hpp"
|
||||
#include <iostream>
|
||||
using namespace Tesses::Framework;
|
||||
using namespace Tesses::Framework::Streams;
|
||||
using namespace Tesses::Framework::Http;
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if(argc < 3)
|
||||
{
|
||||
printf("USAGE: %s <url> <path>\n",argv[0]);
|
||||
return 1;
|
||||
}
|
||||
FileStream strm(argv[2],"wb");
|
||||
|
||||
HttpRequest req;
|
||||
req.url = argv[1];
|
||||
HttpResponse resp(req);
|
||||
resp.CopyToStream(&strm);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#include "TessesFramework/TessesFramework.hpp"
|
||||
#include <iostream>
|
||||
using namespace Tesses::Framework;
|
||||
using namespace Tesses::Framework::Http;
|
||||
using namespace Tesses::Framework::Streams;
|
||||
using namespace Tesses::Framework::TextStreams;
|
||||
using namespace Tesses::Framework::Threading;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
TF_Init();
|
||||
if(argc < 1)
|
||||
{
|
||||
printf("USAGE: %s <dir>\n",argv[0]);
|
||||
return 0;
|
||||
}
|
||||
FileServer fs(argv[1],true,false);
|
||||
HttpServer server(10000U,fs);
|
||||
server.StartAccepting();
|
||||
TF_RunEventLoop();
|
||||
std::cout << "Closing server" << std::endl;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
#include "TessesFramework/TessesFramework.hpp"
|
||||
#include <iostream>
|
||||
|
||||
using namespace Tesses::Framework;
|
||||
using namespace Tesses::Framework::Filesystem;
|
||||
using namespace Tesses::Framework::Streams;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if(argc < 2)
|
||||
{
|
||||
printf("USAGE: %s <command> <args...>\n",argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LocalFilesystem lfs;
|
||||
|
||||
std::string root = "./root";
|
||||
std::string mountDemi = "./demi";
|
||||
std::string mountJoelSlashJim = "./joelslashjim";
|
||||
|
||||
SubdirFilesystem rootdir(&lfs,root,false);
|
||||
|
||||
SubdirFilesystem mountDemidir(&lfs,mountDemi,false);
|
||||
|
||||
|
||||
SubdirFilesystem mountjohnslashjim(&lfs,mountJoelSlashJim,false);
|
||||
|
||||
MountableFilesystem fs(&rootdir,false);
|
||||
fs.Mount(std::string("/demi"), &mountDemidir,false);
|
||||
|
||||
fs.Mount(std::string("/joel/jim"), &mountjohnslashjim,false);
|
||||
|
||||
std::string command = argv[1];
|
||||
|
||||
|
||||
if(command == "ls")
|
||||
{
|
||||
std::string dir = "/";
|
||||
if(argc > 2) dir = argv[2];
|
||||
std::vector<VFSPath> paths;
|
||||
fs.GetPaths(dir, paths);
|
||||
for(auto item : paths)
|
||||
{
|
||||
std::cout << item.GetFileName() << std::endl;
|
||||
}
|
||||
}
|
||||
else if(command == "cat")
|
||||
{
|
||||
FileStream strm(stdout, false,"wb",false);
|
||||
for(int a = 2; a < argc; a++)
|
||||
{
|
||||
std::string path = argv[a];
|
||||
auto f = fs.OpenFile(path,"rb");
|
||||
if(f != nullptr)
|
||||
{
|
||||
f->CopyTo(strm);
|
||||
delete f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#include "TessesFramework/TessesFramework.hpp"
|
||||
#include <iostream>
|
||||
|
||||
using namespace Tesses::Framework::Filesystem;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if(argc < 3)
|
||||
{
|
||||
std::cout << "USAGE: " << argv[0] << " <parent> <subpath>\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
VFSPath parent(argv[1]);
|
||||
VFSPath subpath(argv[2]);
|
||||
VFSPath newPath(parent,subpath.CollapseRelativeParents());
|
||||
|
||||
std::cout << newPath.ToString() << "\n";
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
#include "TessesFramework/TessesFramework.hpp"
|
||||
#include <iostream>
|
||||
using namespace Tesses::Framework;
|
||||
using namespace Tesses::Framework::Http;
|
||||
using namespace Tesses::Framework::Streams;
|
||||
using namespace Tesses::Framework::TextStreams;
|
||||
using namespace Tesses::Framework::Threading;
|
||||
|
||||
class MyWebServer : public IHttpServer {
|
||||
public:
|
||||
bool Handle(ServerContext& ctx)
|
||||
{
|
||||
if(ctx.path == "/")
|
||||
{
|
||||
FileStream fs("index.html","rb");
|
||||
|
||||
ctx
|
||||
.WithMimeType("text/html")
|
||||
.SendStream(fs);
|
||||
return true;
|
||||
}
|
||||
else if(ctx.path == "/streaming.html")
|
||||
{
|
||||
StreamWriter writer(ctx.OpenResponseStream(),true);
|
||||
writer.WriteLine("<html>");
|
||||
writer.WriteLine("<head><title>Streaming</title></head>");
|
||||
writer.WriteLine("<body>");
|
||||
|
||||
writer.WriteLine("<h1>Streaming</h1>");
|
||||
|
||||
writer.WriteLine("<ul>");
|
||||
|
||||
for(size_t i=0;i<10000; i++)
|
||||
{
|
||||
writer.WriteLine("<li>" + std::to_string(i) + "</li>");
|
||||
|
||||
}
|
||||
|
||||
writer.WriteLine("</ul>");
|
||||
|
||||
writer.WriteLine("</body>");
|
||||
writer.WriteLine("</html>");
|
||||
return true;
|
||||
}
|
||||
else if(ctx.path == "/main.js")
|
||||
{
|
||||
|
||||
FileStream fs("main.js","rb");
|
||||
|
||||
ctx
|
||||
.WithMimeType("text/js")
|
||||
.SendStream(fs);
|
||||
return true;
|
||||
}
|
||||
else if(ctx.path == "/upload")
|
||||
{
|
||||
ctx.ParseFormData([](std::string mime, std::string filename, std::string name)->Tesses::Framework::Streams::Stream*{
|
||||
return new FileStream(filename,"wb");
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Handle1(ServerContext& ctx)
|
||||
{
|
||||
std::string name;
|
||||
if(ctx.queryParams.TryGetFirst("name",name))
|
||||
{
|
||||
std::cout << name << std::endl;
|
||||
ctx
|
||||
.WithMimeType("text/plain")
|
||||
.WithContentDisposition(HttpUtils::Sanitise(name) + ".txt",false)
|
||||
.SendText(name + " is cool.");
|
||||
//do something with q
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
TF_Init();
|
||||
TcpServer server(9985U,10);
|
||||
MyWebServer svr;
|
||||
while(true)
|
||||
{
|
||||
std::string ip;
|
||||
uint16_t port;
|
||||
auto res = server.GetStream(ip, port);
|
||||
if(res == nullptr) return 0;
|
||||
std::cout << "Got from " << ip << ":" << port << std::endl;
|
||||
Thread thrd([ip,port,res,&svr]()->void {
|
||||
HttpServer::Process(*res, svr, ip,port, false);
|
||||
delete res;
|
||||
});
|
||||
thrd.Detach();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace Tesses::Framework
|
||||
{
|
||||
void TF_Init();
|
||||
void TF_ConnectToSelf(uint16_t port);
|
||||
void TF_RunEventLoop();
|
||||
void TF_RunEventLoopItteration();
|
||||
bool TF_IsRunning();
|
||||
void TF_Quit();
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
#include "../Streams/Stream.hpp"
|
||||
|
||||
|
||||
namespace Tesses::Framework::Crypto
|
||||
{
|
||||
class ClientTLSStream : public Tesses::Framework::Streams::Stream {
|
||||
void* privateData;
|
||||
static int strm_send(void* ctx,const unsigned char* buf,size_t len);
|
||||
static int strm_recv(void* ctx,unsigned char* buf,size_t len);
|
||||
public:
|
||||
static std::string GetCertChain();
|
||||
|
||||
ClientTLSStream(Tesses::Framework::Streams::Stream* innerStream, bool owns, bool verify, std::string domain);
|
||||
ClientTLSStream(Tesses::Framework::Streams::Stream* innerStream, bool owns, bool verify, std::string domain, std::string cert);
|
||||
size_t Read(uint8_t* buff, size_t sz);
|
||||
size_t Write(const uint8_t* buff, size_t sz);
|
||||
bool CanRead();
|
||||
bool CanWrite();
|
||||
bool EndOfStream();
|
||||
~ClientTLSStream();
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
#include "VFS.hpp"
|
||||
namespace Tesses::Framework::Filesystem
|
||||
{
|
||||
class LocalFilesystem : public VFS
|
||||
{
|
||||
public:
|
||||
Tesses::Framework::Streams::Stream* OpenFile(VFSPath path, std::string mode);
|
||||
void CreateDirectory(VFSPath path);
|
||||
void DeleteDirectory(VFSPath path);
|
||||
bool RegularFileExists(VFSPath path);
|
||||
bool SymlinkExists(VFSPath path);
|
||||
bool CharacterDeviceExists(VFSPath path);
|
||||
bool BlockDeviceExists(VFSPath path);
|
||||
bool SocketFileExists(VFSPath path);
|
||||
bool FIFOFileExists(VFSPath path);
|
||||
bool DirectoryExists(VFSPath path);
|
||||
void DeleteFile(VFSPath path);
|
||||
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
|
||||
void GetPaths(VFSPath path, std::vector<VFSPath>& paths);
|
||||
void CreateHardlink(VFSPath existingFile, VFSPath newName);
|
||||
void MoveFile(VFSPath src, VFSPath dest);
|
||||
void MoveDirectory(VFSPath src, VFSPath dest);
|
||||
VFSPath ReadLink(VFSPath path);
|
||||
std::string VFSPathToSystem(VFSPath path);
|
||||
VFSPath SystemToVFSPath(std::string path);
|
||||
};
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
#pragma once
|
||||
#include "VFS.hpp"
|
||||
namespace Tesses::Framework::Filesystem
|
||||
{
|
||||
class MountableDirectory {
|
||||
public:
|
||||
std::string name;
|
||||
VFS* vfs;
|
||||
bool owns;
|
||||
std::vector<MountableDirectory*> dirs;
|
||||
void GetFS(VFSPath srcPath, VFSPath curDir, VFSPath& destRoot, VFSPath& destPath, VFS*& vfs);
|
||||
~MountableDirectory();
|
||||
};
|
||||
|
||||
class MountableFilesystem : public VFS
|
||||
{
|
||||
bool owns;
|
||||
VFS* root;
|
||||
|
||||
std::vector<MountableDirectory*> directories;
|
||||
|
||||
void GetFS(VFSPath srcPath, VFSPath& destRoot, VFSPath& destPath, VFS*& vfs);
|
||||
|
||||
|
||||
public:
|
||||
MountableFilesystem();
|
||||
MountableFilesystem(VFS* root, bool owns);
|
||||
void Mount(VFSPath path, VFS* fs, bool owns);
|
||||
void Unmount(VFSPath path);
|
||||
Tesses::Framework::Streams::Stream* OpenFile(VFSPath path, std::string mode);
|
||||
void CreateDirectory(VFSPath path);
|
||||
void DeleteDirectory(VFSPath path);
|
||||
bool SpecialFileExists(VFSPath path);
|
||||
bool FileExists(VFSPath path);
|
||||
bool RegularFileExists(VFSPath path);
|
||||
bool SymlinkExists(VFSPath path);
|
||||
bool CharacterDeviceExists(VFSPath path);
|
||||
bool BlockDeviceExists(VFSPath path);
|
||||
bool SocketFileExists(VFSPath path);
|
||||
bool FIFOFileExists(VFSPath path);
|
||||
bool DirectoryExists(VFSPath path);
|
||||
void DeleteFile(VFSPath path);
|
||||
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
|
||||
void GetPaths(VFSPath path, std::vector<VFSPath>& paths);
|
||||
void CreateHardlink(VFSPath existingFile, VFSPath newName);
|
||||
void MoveFile(VFSPath src, VFSPath dest);
|
||||
void MoveDirectory(VFSPath src, VFSPath dest);
|
||||
VFSPath ReadLink(VFSPath path);
|
||||
std::string VFSPathToSystem(VFSPath path);
|
||||
VFSPath SystemToVFSPath(std::string path);
|
||||
~MountableFilesystem();
|
||||
};
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
#include "VFS.hpp"
|
||||
namespace Tesses::Framework::Filesystem
|
||||
{
|
||||
class NullFilesystem : public VFS
|
||||
{
|
||||
public:
|
||||
Tesses::Framework::Streams::Stream* OpenFile(VFSPath path, std::string mode);
|
||||
void CreateDirectory(VFSPath path);
|
||||
void DeleteDirectory(VFSPath path);
|
||||
bool RegularFileExists(VFSPath path);
|
||||
bool DirectoryExists(VFSPath path);
|
||||
void DeleteFile(VFSPath path);
|
||||
void GetPaths(VFSPath path, std::vector<VFSPath>& paths);
|
||||
void MoveFile(VFSPath src, VFSPath dest);
|
||||
std::string VFSPathToSystem(VFSPath path);
|
||||
VFSPath SystemToVFSPath(std::string path);
|
||||
};
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
#pragma once
|
||||
#include "VFS.hpp"
|
||||
namespace Tesses::Framework::Filesystem
|
||||
{
|
||||
class SubdirFilesystem : public VFS
|
||||
{
|
||||
bool owns;
|
||||
VFS* parent;
|
||||
VFSPath path;
|
||||
VFSPath ToParent(VFSPath path);
|
||||
VFSPath FromParent(VFSPath path);
|
||||
public:
|
||||
SubdirFilesystem(VFS* parent, VFSPath path, bool owns);
|
||||
Tesses::Framework::Streams::Stream* OpenFile(VFSPath path, std::string mode);
|
||||
void CreateDirectory(VFSPath path);
|
||||
void DeleteDirectory(VFSPath path);
|
||||
bool SpecialFileExists(VFSPath path);
|
||||
bool FileExists(VFSPath path);
|
||||
bool RegularFileExists(VFSPath path);
|
||||
bool SymlinkExists(VFSPath path);
|
||||
bool CharacterDeviceExists(VFSPath path);
|
||||
bool BlockDeviceExists(VFSPath path);
|
||||
bool SocketFileExists(VFSPath path);
|
||||
bool FIFOFileExists(VFSPath path);
|
||||
bool DirectoryExists(VFSPath path);
|
||||
void DeleteFile(VFSPath path);
|
||||
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
|
||||
void GetPaths(VFSPath path, std::vector<VFSPath>& paths);
|
||||
void CreateHardlink(VFSPath existingFile, VFSPath newName);
|
||||
void MoveFile(VFSPath src, VFSPath dest);
|
||||
void MoveDirectory(VFSPath src, VFSPath dest);
|
||||
void DeleteDirectoryRecurse(VFSPath path);
|
||||
VFSPath ReadLink(VFSPath path);
|
||||
std::string VFSPathToSystem(VFSPath path);
|
||||
VFSPath SystemToVFSPath(std::string path);
|
||||
~SubdirFilesystem();
|
||||
};
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
#pragma once
|
||||
#include "../Common.hpp"
|
||||
#include "../Streams/Stream.hpp"
|
||||
namespace Tesses::Framework::Filesystem
|
||||
{
|
||||
class VFSPath {
|
||||
public:
|
||||
static VFSPath RelativeCurrentDirectory();
|
||||
bool relative;
|
||||
static std::vector<std::string> SplitPath(std::string path,bool native=false);
|
||||
std::vector<std::string> path;
|
||||
VFSPath();
|
||||
VFSPath(std::vector<std::string> path);
|
||||
VFSPath(std::string path);
|
||||
VFSPath(VFSPath p, std::string subent);
|
||||
VFSPath(VFSPath p, VFSPath p2);
|
||||
VFSPath GetParent();
|
||||
VFSPath CollapseRelativeParents();
|
||||
std::string GetFileName();
|
||||
std::string ToString();
|
||||
};
|
||||
class VFS {
|
||||
public:
|
||||
|
||||
virtual Tesses::Framework::Streams::Stream* OpenFile(VFSPath path, std::string mode)=0;
|
||||
virtual void CreateDirectory(VFSPath path)=0;
|
||||
virtual void DeleteDirectory(VFSPath path)=0;
|
||||
virtual bool RegularFileExists(VFSPath path)=0;
|
||||
virtual bool SymlinkExists(VFSPath path);
|
||||
virtual bool CharacterDeviceExists(VFSPath path);
|
||||
virtual bool BlockDeviceExists(VFSPath path);
|
||||
virtual bool SocketFileExists(VFSPath path);
|
||||
virtual bool FIFOFileExists(VFSPath path);
|
||||
virtual bool FileExists(VFSPath path);
|
||||
virtual bool SpecialFileExists(VFSPath path);
|
||||
virtual void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
|
||||
virtual void CreateHardlink(VFSPath existingFile, VFSPath newName);
|
||||
virtual bool DirectoryExists(VFSPath path)=0;
|
||||
virtual void DeleteFile(VFSPath path)=0;
|
||||
virtual void DeleteDirectoryRecurse(VFSPath path);
|
||||
virtual void GetPaths(VFSPath path, std::vector<VFSPath>& paths)=0;
|
||||
virtual void MoveFile(VFSPath src, VFSPath dest)=0;
|
||||
virtual void MoveDirectory(VFSPath src, VFSPath dest);
|
||||
virtual VFSPath ReadLink(VFSPath path);
|
||||
virtual std::string VFSPathToSystem(VFSPath path)=0;
|
||||
virtual VFSPath SystemToVFSPath(std::string path)=0;
|
||||
|
||||
virtual ~VFS();
|
||||
};
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
#include "../Common.hpp"
|
||||
namespace Tesses::Framework::Http
|
||||
{
|
||||
class ContentDisposition {
|
||||
public:
|
||||
std::string filename;
|
||||
std::string type;
|
||||
std::string fieldName;
|
||||
static bool TryParse(std::string str, ContentDisposition& cd);
|
||||
std::string ToString();
|
||||
};
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
#include "../Filesystem/VFS.hpp"
|
||||
#include "HttpServer.hpp"
|
||||
|
||||
namespace Tesses::Framework::Http
|
||||
{
|
||||
class FileServer : public IHttpServer
|
||||
{
|
||||
Tesses::Framework::Filesystem::VFS* vfs;
|
||||
bool ownsVFS;
|
||||
|
||||
|
||||
bool SendFile(ServerContext& ctx,Tesses::Framework::Filesystem::VFSPath path);
|
||||
public:
|
||||
bool allowListing;
|
||||
bool spa;
|
||||
std::vector<std::string> defaultNames;
|
||||
FileServer(std::filesystem::path path,bool allowListing,bool spa);
|
||||
FileServer(std::filesystem::path path,bool allowListing, bool spa, std::vector<std::string> defaultNames);
|
||||
FileServer(Tesses::Framework::Filesystem::VFS* fs, bool owns, bool allowListing, bool spa);
|
||||
FileServer(Tesses::Framework::Filesystem::VFS* fs, bool owns, bool allowListing, bool spa, std::vector<std::string> defaultNames);
|
||||
bool Handle(ServerContext& ctx);
|
||||
~FileServer();
|
||||
};
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
#pragma once
|
||||
#include "../Streams/Stream.hpp"
|
||||
#include "HttpUtils.hpp"
|
||||
|
||||
namespace Tesses::Framework::Http
|
||||
{
|
||||
|
||||
class HttpRequestBody {
|
||||
public:
|
||||
virtual void HandleHeaders(HttpDictionary& dict);
|
||||
virtual void Write(Tesses::Framework::Streams::Stream* strm)=0;
|
||||
};
|
||||
|
||||
class StreamHttpRequestBody : public HttpRequestBody {
|
||||
Tesses::Framework::Streams::Stream* strm;
|
||||
bool owns;
|
||||
std::string mimeType;
|
||||
public:
|
||||
StreamHttpRequestBody(Tesses::Framework::Streams::Stream* strm, bool owns, std::string mimeType);
|
||||
void HandleHeaders(HttpDictionary& dict);
|
||||
void Write(Tesses::Framework::Streams::Stream* strm);
|
||||
~StreamHttpRequestBody();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class HttpRequest {
|
||||
public:
|
||||
HttpRequest();
|
||||
std::string trusted_root_cert_bundle;
|
||||
bool ignoreSSLErrors;
|
||||
bool followRedirects;
|
||||
|
||||
std::string method;
|
||||
std::string url;
|
||||
HttpDictionary requestHeaders;
|
||||
HttpRequestBody* body;
|
||||
|
||||
static Tesses::Framework::Streams::Stream* EstablishConnection(Uri uri,bool ignoreSSLErrors,std::string trusted_root_cert_bundle);
|
||||
|
||||
void SendRequest(Tesses::Framework::Streams::Stream* strm);
|
||||
};
|
||||
|
||||
class HttpResponse {
|
||||
private:
|
||||
bool owns;
|
||||
Tesses::Framework::Streams::Stream* handleStrm;
|
||||
public:
|
||||
HttpResponse(Tesses::Framework::Streams::Stream* strm, bool owns);
|
||||
HttpResponse(HttpRequest& request);
|
||||
std::string version;
|
||||
StatusCode statusCode;
|
||||
HttpDictionary responseHeaders;
|
||||
std::string ReadAsString();
|
||||
Tesses::Framework::Streams::Stream* ReadAsStream();
|
||||
void CopyToStream(Tesses::Framework::Streams::Stream* strm);
|
||||
|
||||
~HttpResponse();
|
||||
};
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
#pragma once
|
||||
#include "../Streams/NetworkStream.hpp"
|
||||
|
||||
#include "HttpUtils.hpp"
|
||||
#include "../Threading/Thread.hpp"
|
||||
namespace Tesses::Framework::Http
|
||||
{
|
||||
|
||||
class ServerContext {
|
||||
bool sent;
|
||||
Tesses::Framework::Streams::Stream* strm;
|
||||
public:
|
||||
HttpDictionary requestHeaders;
|
||||
HttpDictionary responseHeaders;
|
||||
HttpDictionary queryParams;
|
||||
std::string path;
|
||||
std::string originalPath;
|
||||
std::string method;
|
||||
StatusCode statusCode;
|
||||
std::string ip;
|
||||
uint16_t port;
|
||||
std::string version;
|
||||
bool encrypted;
|
||||
ServerContext(Tesses::Framework::Streams::Stream* strm);
|
||||
Tesses::Framework::Streams::Stream& GetStream();
|
||||
std::string GetOriginalPathWithQuery();
|
||||
std::string GetUrlWithQuery();
|
||||
bool Sent();
|
||||
bool NeedToParseFormData();
|
||||
void ParseFormData(std::function<Tesses::Framework::Streams::Stream*(std::string mime, std::string filename, std::string name)> cb);
|
||||
void ReadStream(Tesses::Framework::Streams::Stream& strm);
|
||||
void ReadStream(Tesses::Framework::Streams::Stream* strm);
|
||||
std::string ReadString();
|
||||
void SendBytes(std::vector<uint8_t> buffer);
|
||||
void SendText(std::string text);
|
||||
void SendStream(Tesses::Framework::Streams::Stream& strm);
|
||||
void SendStream(Tesses::Framework::Streams::Stream* strm);
|
||||
void SendErrorPage(bool showPath);
|
||||
void SendNotFound();
|
||||
void SendBadRequest();
|
||||
void SendException(std::exception& ex);
|
||||
Tesses::Framework::Streams::Stream* OpenResponseStream();
|
||||
Tesses::Framework::Streams::Stream* OpenRequestStream();
|
||||
ServerContext& WithHeader(std::string key, std::string value);
|
||||
ServerContext& WithSingleHeader(std::string key, std::string value);
|
||||
ServerContext& WithMimeType(std::string mime);
|
||||
ServerContext& WithContentDisposition(std::string filename, bool isInline);
|
||||
ServerContext& WriteHeaders();
|
||||
};
|
||||
|
||||
class IHttpServer {
|
||||
public:
|
||||
virtual bool Handle(ServerContext& ctx)=0;
|
||||
virtual ~IHttpServer();
|
||||
};
|
||||
|
||||
class HttpServer {
|
||||
Tesses::Framework::Streams::TcpServer* server;
|
||||
IHttpServer* http;
|
||||
Tesses::Framework::Threading::Thread* thrd;
|
||||
bool owns;
|
||||
uint16_t port;
|
||||
public:
|
||||
HttpServer(uint16_t port, IHttpServer& http);
|
||||
HttpServer(uint16_t port, IHttpServer* http, bool owns);
|
||||
void StartAccepting();
|
||||
static void Process(Tesses::Framework::Streams::Stream& strm, IHttpServer& server, std::string ip, uint16_t port, bool encrypted);
|
||||
~HttpServer();
|
||||
};
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
#include "../Streams/Stream.hpp"
|
||||
|
||||
namespace Tesses::Framework::Http
|
||||
{
|
||||
class HttpStream : public Tesses::Framework::Streams::Stream {
|
||||
Tesses::Framework::Streams::Stream* strm;
|
||||
|
||||
size_t offset;
|
||||
size_t read;
|
||||
int64_t length;
|
||||
int64_t position;
|
||||
|
||||
bool owns;
|
||||
bool recv;
|
||||
bool http1_1;
|
||||
|
||||
bool done;
|
||||
|
||||
public:
|
||||
HttpStream(Tesses::Framework::Streams::Stream* strm, bool owns, int64_t length, bool recv, bool http1_1);
|
||||
HttpStream(Tesses::Framework::Streams::Stream& strm, int64_t length, bool recv,bool http1_1);
|
||||
bool CanRead();
|
||||
bool CanWrite();
|
||||
bool EndOfStream();
|
||||
int64_t GetLength();
|
||||
int64_t GetPosition();
|
||||
size_t Read(uint8_t* buffer, size_t len);
|
||||
size_t Write(const uint8_t* buffer, size_t len);
|
||||
~HttpStream();
|
||||
};
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
#pragma once
|
||||
#include "../Common.hpp"
|
||||
|
||||
namespace Tesses::Framework::Http
|
||||
{
|
||||
typedef enum StatusCode {
|
||||
Continue=100,
|
||||
SwitchingProtocols=101,
|
||||
Processing=102,
|
||||
EarlyHints=103,
|
||||
OK=200,
|
||||
Created=201,
|
||||
Accepted=202,
|
||||
NonAuthoritativeInformation=203,
|
||||
NoContent=204,
|
||||
ResetContent=205,
|
||||
PartialContent=206,
|
||||
MultiStatus=207,
|
||||
AlreadyReported=208,
|
||||
IMUsed=226,
|
||||
MultipleChoices=300,
|
||||
MovedPermanently=301,
|
||||
Found=302,
|
||||
SeeOther=303,
|
||||
NotModified=304,
|
||||
UseProxy=305,
|
||||
TemporaryRedirect=307,
|
||||
PermanentRedirect=308,
|
||||
BadRequest=400,
|
||||
Unauthorized=401,
|
||||
PaymentRequired=402,
|
||||
Forbidden=403,
|
||||
NotFound=404,
|
||||
MethodNotAllowed=405,
|
||||
NotAcceptable=406,
|
||||
ProxyAuthenticationRequired=407,
|
||||
RequestTimeout=408,
|
||||
Conflict=409,
|
||||
Gone=410,
|
||||
LengthRequired=411,
|
||||
PreconditionFailed=412,
|
||||
PayloadTooLarge=413,
|
||||
URITooLong=414,
|
||||
UnsupportedMediaType=415,
|
||||
RangeNotSatisfiable=416,
|
||||
ExpectationFailed=417,
|
||||
ImATeapot=418,
|
||||
MisdirectedRequest=421,
|
||||
UnprocessableContent=422,
|
||||
Locked=423,
|
||||
FailedDependency=424,
|
||||
TooEarly=425,
|
||||
UpgradeRequired=426,
|
||||
PreconditionRequired=428,
|
||||
TooManyRequests=429,
|
||||
RequestHeaderFieldsTooLarge=431,
|
||||
UnavailableForLegalReasons=451,
|
||||
InternalServerError=500,
|
||||
NotImplemented=501,
|
||||
BadGateway=502,
|
||||
ServiceUnavailable=503,
|
||||
GatewayTimeout=504,
|
||||
HTTPVersionNotSupported=505,
|
||||
VariantAlsoNegotiates=506,
|
||||
InsufficientStorage=507,
|
||||
LoopDetected=508,
|
||||
NotExtended=510,
|
||||
NetworkAuthenticationRequired=511
|
||||
} StatusCode;
|
||||
class HttpDictionary {
|
||||
public:
|
||||
std::map<std::string,std::vector<std::string>> kvp;
|
||||
void Clear();
|
||||
void Clear(std::string key, bool kvpExistsAfter);
|
||||
void SetValue(std::string key, std::string value);
|
||||
void SetValue(std::string key, std::vector<std::string> value);
|
||||
template<typename Itterator>
|
||||
void SetValue(std::string key, Itterator begin, Itterator end)
|
||||
{
|
||||
Clear(key,true);
|
||||
AddValue(key, begin, end);
|
||||
}
|
||||
void AddValue(std::string key, std::string value);
|
||||
void AddValue(std::string key, std::vector<std::string> value);
|
||||
|
||||
template<typename Itterator>
|
||||
void AddValue(std::string key, Itterator begin, Itterator end)
|
||||
{
|
||||
auto& ls = kvp[key];
|
||||
ls.insert(ls.end(), begin, end);
|
||||
}
|
||||
|
||||
bool TryGetFirst(std::string key, std::string& value);
|
||||
|
||||
bool TryGetFirstInt(std::string key, int64_t& value);
|
||||
|
||||
bool TryGetFirstDouble(std::string key, double& value);
|
||||
|
||||
bool GetFirstBoolean(std::string key);
|
||||
};
|
||||
|
||||
class Uri {
|
||||
public:
|
||||
std::string GetQuery();
|
||||
std::string GetPathAndQuery();
|
||||
uint16_t GetPort();
|
||||
std::string HostPort();
|
||||
bool Relative(std::string url, Uri& uri);
|
||||
std::string ToString();
|
||||
static bool TryParse(std::string url, Uri& uri);
|
||||
std::string scheme;
|
||||
std::string host;
|
||||
uint16_t port;
|
||||
std::string path;
|
||||
HttpDictionary query;
|
||||
std::string hash;
|
||||
};
|
||||
|
||||
class HttpUtils
|
||||
{
|
||||
public:
|
||||
static char NibbleToHex(uint8_t nibble);
|
||||
static uint8_t HexToNibble(char c);
|
||||
static std::string MimeType(std::filesystem::path p);
|
||||
static bool Invalid(char c);
|
||||
static std::string Sanitise(std::string text);
|
||||
static void QueryParamsDecode(HttpDictionary& dict,std::string query);
|
||||
static std::string Join(std::string joinStr, std::vector<std::string> ents);
|
||||
static std::string QueryParamsEncode(HttpDictionary& dict);
|
||||
static std::string UrlDecode(std::string v);
|
||||
static std::string UrlEncode(std::string v);
|
||||
static std::string UrlPathDecode(std::string v);
|
||||
static std::string UrlPathEncode(std::string v, bool ignoreSpace=false);
|
||||
static std::string HtmlEncode(std::string v);
|
||||
static std::vector<std::string> SplitString(std::string text, std::string delimiter,std::size_t maxCnt = std::string::npos);
|
||||
static std::string StatusCodeString(StatusCode code);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
#pragma once
|
||||
#include "Stream.hpp"
|
||||
|
||||
namespace Tesses::Framework::Streams
|
||||
{
|
||||
class BufferedStream : public Stream
|
||||
{
|
||||
private:
|
||||
Stream* strm;
|
||||
bool owns;
|
||||
uint8_t* buffer;
|
||||
size_t bufferSize;
|
||||
size_t offset;
|
||||
size_t read;
|
||||
public:
|
||||
BufferedStream(Stream* strm, bool owns, size_t bufferSize=1024);
|
||||
BufferedStream(Stream& strm, size_t bufferSize=1024);
|
||||
bool EndOfStream();
|
||||
bool CanRead();
|
||||
bool CanWrite();
|
||||
size_t Read(uint8_t* buff, size_t sz);
|
||||
size_t Write(const uint8_t* buff, size_t sz);
|
||||
|
||||
~BufferedStream();
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
#pragma once
|
||||
#include "Stream.hpp"
|
||||
#include <cstdio>
|
||||
namespace Tesses::Framework::Streams
|
||||
{
|
||||
class FileStream : public Stream {
|
||||
bool canRead;
|
||||
bool canWrite;
|
||||
bool canSeek;
|
||||
bool owns;
|
||||
FILE* f;
|
||||
void SetMode(std::string mode);
|
||||
public:
|
||||
FileStream(std::filesystem::path p, std::string mode);
|
||||
FileStream(FILE* f, bool owns, std::string mode , bool canSeek=true);
|
||||
size_t Read(uint8_t* buff, size_t sz);
|
||||
size_t Write(const uint8_t* buff, size_t sz);
|
||||
bool CanRead();
|
||||
bool CanWrite();
|
||||
bool CanSeek();
|
||||
int64_t GetPosition();
|
||||
void Flush();
|
||||
void Seek(int64_t pos, SeekOrigin whence);
|
||||
~FileStream();
|
||||
|
||||
};
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
#include "Stream.hpp"
|
||||
namespace Tesses::Framework::Streams
|
||||
{
|
||||
class MemoryStream : public Stream {
|
||||
std::vector<uint8_t> buffer;
|
||||
size_t offset;
|
||||
bool writable;
|
||||
public:
|
||||
MemoryStream(bool isWritable);
|
||||
std::vector<uint8_t>& GetBuffer();
|
||||
size_t Read(uint8_t* buff, size_t sz);
|
||||
size_t Write(const uint8_t* buff, size_t sz);
|
||||
bool CanRead();
|
||||
bool CanWrite();
|
||||
bool CanSeek();
|
||||
int64_t GetLength();
|
||||
int64_t GetPosition();
|
||||
void Seek(int64_t pos, SeekOrigin whence);
|
||||
|
||||
};
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
#include "Stream.hpp"
|
||||
|
||||
namespace Tesses::Framework::Streams
|
||||
{
|
||||
class NetworkStream;
|
||||
|
||||
class TcpServer {
|
||||
int32_t sock;
|
||||
bool owns;
|
||||
bool valid;
|
||||
public:
|
||||
TcpServer(int32_t sock,bool owns);
|
||||
TcpServer(uint16_t port, int32_t backlog);
|
||||
TcpServer(std::string ip, uint16_t port, int32_t backlog);
|
||||
NetworkStream* GetStream(std::string& ip, uint16_t& port);
|
||||
~TcpServer();
|
||||
void Close();
|
||||
};
|
||||
class NetworkStream : public Stream {
|
||||
int32_t sock;
|
||||
bool owns;
|
||||
bool success;
|
||||
bool endOfStream;
|
||||
public:
|
||||
bool EndOfStream();
|
||||
bool CanRead();
|
||||
bool CanWrite();
|
||||
NetworkStream(bool ipV6,bool datagram);
|
||||
NetworkStream(std::string ipOrFqdn, uint16_t port, bool datagram,bool broadcast,bool supportIPv6);
|
||||
NetworkStream(int32_t sock, bool owns);
|
||||
void Listen(int32_t backlog);
|
||||
void Bind(std::string ip, uint16_t port);
|
||||
void SetBroadcast(bool bC);
|
||||
NetworkStream* Accept(std::string& ip, uint16_t& port);
|
||||
size_t Read(uint8_t* buff, size_t sz);
|
||||
size_t Write(const uint8_t* buff, size_t sz);
|
||||
size_t ReadFrom(uint8_t* buff, size_t sz, std::string& ip, uint16_t& port);
|
||||
size_t WriteTo(const uint8_t* buff, size_t sz, std::string ip, uint16_t port);
|
||||
static std::vector<std::pair<std::string,std::string>> GetIPs(bool ipV6=false);
|
||||
~NetworkStream();
|
||||
};
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
#include "../Common.hpp"
|
||||
namespace Tesses::Framework::Streams
|
||||
{
|
||||
enum class SeekOrigin : uint8_t {
|
||||
Begin=0,
|
||||
Current=1,
|
||||
End=2
|
||||
};
|
||||
class Stream {
|
||||
public:
|
||||
int32_t ReadByte();
|
||||
void WriteByte(uint8_t b);
|
||||
|
||||
virtual bool EndOfStream();
|
||||
virtual size_t Read(uint8_t* buff, size_t sz);
|
||||
virtual size_t Write(const uint8_t* buff, size_t sz);
|
||||
size_t ReadBlock(uint8_t* buff, size_t sz);
|
||||
void WriteBlock(const uint8_t* buff, size_t sz);
|
||||
virtual bool CanRead();
|
||||
virtual bool CanWrite();
|
||||
virtual bool CanSeek();
|
||||
virtual int64_t GetPosition();
|
||||
virtual int64_t GetLength();
|
||||
virtual void Flush();
|
||||
virtual void Seek(int64_t pos, SeekOrigin whence);
|
||||
void CopyTo(Stream* strm, size_t buffSize=1024);
|
||||
void CopyTo(Stream& strm, size_t buffSize=1024);
|
||||
virtual ~Stream();
|
||||
};
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
#include "Http/HttpServer.hpp"
|
||||
#include "Http/HttpClient.hpp"
|
||||
#include "Http/FileServer.hpp"
|
||||
#include "Http/ContentDisposition.hpp"
|
||||
#include "Streams/FileStream.hpp"
|
||||
#include "Streams/MemoryStream.hpp"
|
||||
#include "Streams/NetworkStream.hpp"
|
||||
#include "Streams/BufferedStream.hpp"
|
||||
#include "TextStreams/StreamReader.hpp"
|
||||
#include "TextStreams/StreamWriter.hpp"
|
||||
#include "Threading/Thread.hpp"
|
||||
#include "Filesystem/LocalFS.hpp"
|
||||
#include "Filesystem/SubdirFilesystem.hpp"
|
||||
#include "Filesystem/NullFilesystem.hpp"
|
||||
#include "Filesystem/MountableFilesystem.hpp"
|
||||
#include "Crypto/ClientTLSStream.hpp"
|
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
#include "TextReader.hpp"
|
||||
#include "../Streams/Stream.hpp"
|
||||
namespace Tesses::Framework |