Change html to dark mode by default and stat in vfs

This commit is contained in:
2026-04-19 23:07:17 -05:00
parent 5435280209
commit c5cf13e1b7
40 changed files with 1110 additions and 1956 deletions

View File

@@ -2,7 +2,7 @@ name: Build and Deploy on Tag
on: on:
push: push:
tags: tags:
- 'v*' - "v*"
env: env:
GITEA_AUTH: ${{ secrets.MY_GITEA_AUTH }} GITEA_AUTH: ${{ secrets.MY_GITEA_AUTH }}
@@ -20,24 +20,3 @@ jobs:
- run: chown build:build /home/build/PKGBUILD - run: chown build:build /home/build/PKGBUILD
- run: chown build:build /home/build/build-arch.sh - run: chown build:build /home/build/build-arch.sh
- run: su build -c /home/build/build-arch.sh - run: su build -c /home/build/build-arch.sh
build-jammy:
runs-on: deb-builder-jammy
steps:
- uses: actions/checkout@v4
- name: Build for jammy, noble
run: |
bash build-ubuntu-jammy.sh
bash push-ubuntu-jammy.sh
working-directory: ./Packaging/Linux
build-plucky:
runs-on: deb-builder-plucky
steps:
- uses: actions/checkout@v4
- name: Build for plucky, resolute
run: |
bash build-ubuntu-plucky.sh
bash push-ubuntu-plucky.sh
working-directory: ./Packaging/Linux
- uses: akkuman/gitea-release-action@v1
env:
NODE_OPTIONS: '--experimental-fetch' # if nodejs < 18

View File

@@ -1,52 +0,0 @@
version: 43
jobs:
- name: Build for x86_64
steps:
- type: CheckoutStep
name: Checkout
cloneCredential:
type: DefaultCredential
withLfs: true
withSubmodules: false
condition: SUCCESSFUL
optional: false
- type: CommandStep
name: Execute build
runInContainer: true
image: onedev.site.tesses.net/dependencies/dependencies:latest
interpreter:
type: DefaultInterpreter
commands: |
mkdir build
cd build
cmake -S .. -B . -DTESSESFRAMEWORK_FETCHCONTENT=OFF
make -j12
make install DESTDIR=out
useTTY: true
condition: SUCCESSFUL
optional: false
- type: BuildImageStep
name: Build Docker Image
dockerfile: Dockerfile.run
output:
type: RegistryOutput
tags: onedev.site.tesses.net/tesses-framework/tesses-framework:latest onedev.site.tesses.net/tesses-framework/tesses-framework:@commit_hash@ git.tesseslanguage.com/tesses50/tesses-framework:latest git.tesseslanguage.com/tesses50/tesses-framework:@commit_hash@
registryLogins:
- registryUrl: '@server_url@'
userName: '@job_token@'
passwordSecret: dockersecret
- registryUrl: git.tesseslanguage.com
userName: tesses50
passwordSecret: GITEA_AUTH
platforms: linux/amd64
condition: SUCCESSFUL
optional: false
triggers:
- type: BranchUpdateTrigger
branches: master
userMatch: anyone
projects: tesses-framework
retryCondition: never
maxRetries: 3
retryDelay: 30
timeout: 14400

View File

@@ -7,68 +7,7 @@ set(TESSESFRAMEWORK_PATCH_VERSION 2)
project(TessesFramework VERSION ${TESSESFRAMEWORK_MAJOR_VERSION}.${TESSESFRAMEWORK_MINOR_VERSION}.${TESSESFRAMEWORK_PATCH_VERSION}) project(TessesFramework VERSION ${TESSESFRAMEWORK_MAJOR_VERSION}.${TESSESFRAMEWORK_MINOR_VERSION}.${TESSESFRAMEWORK_PATCH_VERSION})
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
include(cmake/sources.cmake)
list(APPEND TESSESFRAMEWORK_SOURCE
src/Random.cpp
src/Date/Date.cpp
src/Http/FileServer.cpp
src/Http/MountableServer.cpp
src/Http/RouteServer.cpp
src/Http/CallbackServer.cpp
src/Http/HttpServer.cpp
src/Http/HttpUtils.cpp
src/Http/HttpClient.cpp
src/Http/HttpStream.cpp
src/Http/ContentDisposition.cpp
src/Http/WebSocket.cpp
src/Http/ChangeableServer.cpp
src/Http/BasicAuthServer.cpp
src/Http/CGIServer.cpp
src/Mail/Smtp.cpp
src/Serialization/Json.cpp
src/Serialization/SQLite.cpp
src/Serialization/BitConverter.cpp
src/Serialization/Bencode.cpp
src/Platform/Environment.cpp
src/Platform/Process.cpp
src/Streams/FileStream.cpp
src/Streams/MemoryStream.cpp
src/Streams/NetworkStream.cpp
src/Streams/Stream.cpp
src/Streams/BufferedStream.cpp
src/Streams/ByteReader.cpp
src/Streams/ByteWriter.cpp
src/Streams/PtyStream.cpp
src/Text/StringConverter.cpp
src/Text/HeaderGenerator.cpp
src/TextStreams/StreamReader.cpp
src/TextStreams/StreamWriter.cpp
src/TextStreams/TextReader.cpp
src/TextStreams/TextWriter.cpp
src/TextStreams/StdIOReader.cpp
src/TextStreams/StdIOWriter.cpp
src/TextStreams/StringReader.cpp
src/TextStreams/StringWriter.cpp
src/Threading/Thread.cpp
src/Threading/Mutex.cpp
src/Threading/ThreadPool.cpp
src/Filesystem/VFS.cpp
src/Filesystem/LocalFS.cpp
src/Filesystem/MemoryFilesystem.cpp
src/Filesystem/SubdirFilesystem.cpp
src/Filesystem/NullFilesystem.cpp
src/Filesystem/MountableFilesystem.cpp
src/Filesystem/FSHelpers.cpp
src/Filesystem/TempFS.cpp
src/Crypto/MbedTLS/ClientTLSStream.cpp
src/Crypto/MbedTLS/Crypto.cpp
src/Args.cpp
src/TF_Init.cpp
src/HiddenField.cpp
src/Uuid.cpp
src/BitTorrent/TorrentFile.cpp
src/BitTorrent/TorrentStream.cpp
)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
@@ -82,7 +21,7 @@ option(TESSESFRAMEWORK_ENABLE_PROCESS "Enable process api" ON)
option(TESSESFRAMEWORK_ENABLE_RPATH "Enable RPATH" ON) option(TESSESFRAMEWORK_ENABLE_RPATH "Enable RPATH" ON)
if(TESSESFRAMEWORK_ENABLE_SQLITE) if(TESSESFRAMEWORK_ENABLE_SQLITE)
list(APPEND TESSESFRAMEWORK_SOURCE list(APPEND TESSESFRAMEWORK_SOURCE
src/Serialization/sqlite/sqlite3-mod.c src/Serialization/sqlite/sqlite3-mod.c
src/Serialization/sqlite/vfs.c src/Serialization/sqlite/vfs.c
) )
@@ -145,12 +84,12 @@ endif()
FetchContent_Declare( FetchContent_Declare(
mbedtls mbedtls
URL https://downloads.tesses.net/cache/libraries/source/mbedtls-3.6.4.tar.bz2 URL https://downloads.tesses.net/cache/libraries/source/mbedtls-3.6.4.tar.bz2
) )
FetchContent_MakeAvailable(mbedtls) FetchContent_MakeAvailable(mbedtls)
else() else()
set(MBEDTLS_DIR "" CACHE PATH "Mbed tls directory") find_package(MbedTLS REQUIRED)
endif() endif()
endif() endif()
@@ -280,7 +219,7 @@ if(TESSESFRAMEWORK_FETCHCONTENT)
target_link_libraries(tessesframework_shared PUBLIC mbedtls mbedx509 mbedcrypto everest p256m) target_link_libraries(tessesframework_shared PUBLIC mbedtls mbedx509 mbedcrypto everest p256m)
else() else()
target_link_libraries(tessesframework_shared PUBLIC mbedtls mbedx509 mbedcrypto) target_link_libraries(tessesframework_shared PUBLIC MbedTLS::mbedcrypto MbedTLS::mbedtls MbedTLS::mbedx509)
endif() endif()
endif() endif()
@@ -300,7 +239,7 @@ endif()
if(TESSESFRAMEWORK_INSTALL_DEVELOPMENT) if(TESSESFRAMEWORK_INSTALL_DEVELOPMENT)
install(TARGETS ${TessesFrameworkLibs} install(TARGETS ${TessesFrameworkLibs}
EXPORT TessesFrameworkTargets EXPORT TessesFrameworkTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
@@ -329,6 +268,8 @@ DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/TessesFramework)
endif() endif()
if(TESSESFRAMEWORK_ENABLE_EXAMPLES) if(TESSESFRAMEWORK_ENABLE_EXAMPLES)
add_executable(timer examples/timer.cpp)
target_link_libraries(timer PUBLIC tessesframework)
add_executable(copyfile examples/copyfile.cpp) add_executable(copyfile examples/copyfile.cpp)
target_link_libraries(copyfile PUBLIC tessesframework) target_link_libraries(copyfile PUBLIC tessesframework)
@@ -351,8 +292,6 @@ if(TESSESFRAMEWORK_ENABLE_EXAMPLES)
add_executable(wsecho examples/wsecho.cpp) add_executable(wsecho examples/wsecho.cpp)
target_link_libraries(wsecho PUBLIC tessesframework) target_link_libraries(wsecho PUBLIC tessesframework)
add_executable(runevent examples/runevent.cpp)
target_link_libraries(runevent PUBLIC tessesframework)
add_executable(tests examples/tests.cpp) add_executable(tests examples/tests.cpp)
target_link_libraries(tests PUBLIC tessesframework) target_link_libraries(tests PUBLIC tessesframework)
@@ -434,4 +373,4 @@ set(CPACK_PACKAGE_VERSION_MINOR "${TessesFramework_VERSION_MINOR}")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libmbedtls-dev (>= 2.28.8)") set(CPACK_DEBIAN_PACKAGE_DEPENDS "libmbedtls-dev (>= 2.28.8)")
include(CPack) include(CPack)
add_subdirectory(pkgconfig) add_subdirectory(pkgconfig)

View File

@@ -1,5 +0,0 @@
FROM ubuntu:noble
RUN apt update && apt install -y cmake g++ gcc libmbedtls-dev build-essential git ca-certificates
RUN mkdir /src && cd /src && git clone https://onedev.site.tesses.net/tesses-framework . && mkdir build && cd build && cmake -S .. -B . && make -j12 && make install && cd / && rm -r /src

View File

@@ -1,3 +0,0 @@
FROM onedev.site.tesses.net/dependencies/dependencies:latest
COPY build/out /

View File

@@ -1,16 +1,16 @@
# Maintainer: Mike Nolan <tesses@tesses.net> # Maintainer: Mike Nolan <tesses@tesses.net>
pkgname=tesses-framework # '-bzr', '-git', '-hg' or '-svn' pkgname=tessesframework # '-bzr', '-git', '-hg' or '-svn'
pkgver=0.0.2 pkgver=0.0.3
pkgrel=1 pkgrel=1
pkgdesc="" pkgdesc=""
arch=('x86_64' 'powerpc') arch=('x86_64' 'powerpc')
url="https://onedev.site.tesses.net/tesses-framework" url="https://git.tesses.org/tessesframework"
license=('MIT') license=('MIT')
groups=() groups=()
depends=('mbedtls') depends=('mbedtls')
makedepends=('git' 'cmake' 'make' 'base-devel' 'wget') # 'bzr', 'git', 'mercurial' or 'subversion' makedepends=('git' 'cmake' 'make' 'base-devel' 'wget') # 'bzr', 'git', 'mercurial' or 'subversion'
install= install=
source=('tesses-framework::git+https://onedev.site.tesses.net/tesses-framework') source=('tessesframework::git+https://git.tesses.org/tesses-framework')
noextract=() noextract=()
sha256sums=('SKIP') sha256sums=('SKIP')
if [[ -z "$CMAKE_TOOLCHAIN" ]]; then if [[ -z "$CMAKE_TOOLCHAIN" ]]; then
@@ -22,22 +22,21 @@ fi
prepare() { prepare() {
cd "$srcdir/${pkgname}" cd "$srcdir/${pkgname}"
wget https://downloads.tesses.net/ShellPackage.crvm
} }
build() { build() {
cd "$srcdir/${pkgname}" cd "$srcdir/${pkgname}"
mkdir build mkdir build
if [[ -z "$CMAKE_TOOLCHAIN" ]]; then if [[ -z "$CMAKE_TOOLCHAIN" ]]; then
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_BUILD_TYPE=Release
else else
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_TOOLCHAIN_FILE="$CMAKE_TOOLCHAIN" cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE="$CMAKE_TOOLCHAIN"
fi fi
cd build cd build
make -j`nproc` make -j`nproc`
} }
@@ -47,4 +46,3 @@ package() {
cd "$srcdir/${pkgname}/build" cd "$srcdir/${pkgname}/build"
make install DESTDIR="$pkgdir/" make install DESTDIR="$pkgdir/"
} }

View File

@@ -6,7 +6,7 @@ cp ../PKGBUILD .
makepkg makepkg
curl --user tesses50:$GITEA_AUTH \ curl --user tesses50:$GITEA_AUTH \
--upload-file *.pkg.tar.zst \ --upload-file *.pkg.tar.zst \
https://git.tesseslanguage.com/api/packages/tesses50/arch/core https://git.tesses.org/api/packages/tesses50/arch/core
cd .. cd ..
mkdir powerpc mkdir powerpc
cd powerpc cd powerpc
@@ -14,4 +14,4 @@ cp ../PKGBUILD .
CARCH=powerpc CMAKE_TOOLCHAIN=/opt/cross/ppc/toolchain.cmake makepkg CARCH=powerpc CMAKE_TOOLCHAIN=/opt/cross/ppc/toolchain.cmake makepkg
curl --user tesses50:$GITEA_AUTH \ curl --user tesses50:$GITEA_AUTH \
--upload-file *.pkg.tar.zst \ --upload-file *.pkg.tar.zst \
https://git.tesseslanguage.com/api/packages/tesses50/arch/core https://git.tesses.org/api/packages/tesses50/arch/core

View File

@@ -1,46 +0,0 @@
#!/bin/bash
source ./version.sh
mkdir -p build/jammy
cd build/jammy
mkdir build-amd64
cmake -S ../../../../ -B build-amd64 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF
cd build-amd64
make -j`nproc`
make install DESTDIR=../tessesframework_$DEB_VERSION\_amd64
mkdir -p ../tessesframework_$DEB_VERSION\_amd64/DEBIAN
bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_amd64/DEBIAN/control amd64
cd ../
dpkg-deb --build tessesframework_$DEB_VERSION\_amd64
# ARM64
mkdir build-arm64
cmake -S ../../../../ -B build-arm64 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/arm64.cmake
cd build-arm64
make -j`nproc`
make install DESTDIR=../tessesframework_$DEB_VERSION\_arm64
mkdir -p ../tessesframework_$DEB_VERSION\_arm64/DEBIAN
bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_arm64/DEBIAN/control arm64
cd ../
dpkg-deb --build tessesframework_$DEB_VERSION\_arm64
# RISCV64
mkdir build-riscv64
cmake -S ../../../../ -B build-riscv64 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/riscv64.cmake
cd build-riscv64
make -j`nproc`
make install DESTDIR=../tessesframework_$DEB_VERSION\_riscv64
mkdir -p ../tessesframework_$DEB_VERSION\_riscv64/DEBIAN
bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_riscv64/DEBIAN/control riscv64
cd ../
dpkg-deb --build tessesframework_$DEB_VERSION\_riscv64
# ARMHF
mkdir build-armhf
cmake -S ../../../../ -B build-armhf -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/armhf.cmake
cd build-armhf
make -j`nproc`
make install DESTDIR=../tessesframework_$DEB_VERSION\_armhf
mkdir -p ../tessesframework_$DEB_VERSION\_armhf/DEBIAN
bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_armhf/DEBIAN/control armhf
cd ../
dpkg-deb --build tessesframework_$DEB_VERSION\_armhf

View File

@@ -1,57 +0,0 @@
#!/bin/bash
source ./version.sh
mkdir -p build/plucky
cd build/plucky
mkdir build-amd64
cmake -S ../../../../ -B build-amd64 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF
cd build-amd64
make -j`nproc`
make install DESTDIR=../tessesframework_$DEB_VERSION\_amd64
mkdir -p ../tessesframework_$DEB_VERSION\_amd64/DEBIAN
bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_amd64/DEBIAN/control amd64
cd ../
dpkg-deb --build tessesframework_$DEB_VERSION\_amd64
# ARM64
mkdir build-arm64
cmake -S ../../../../ -B build-arm64 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/arm64.cmake
cd build-arm64
make -j`nproc`
make install DESTDIR=../tessesframework_$DEB_VERSION\_arm64
mkdir -p ../tessesframework_$DEB_VERSION\_arm64/DEBIAN
bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_arm64/DEBIAN/control arm64
cd ../
dpkg-deb --build tessesframework_$DEB_VERSION\_arm64
# RISCV64
mkdir build-riscv64
cmake -S ../../../../ -B build-riscv64 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/riscv64.cmake
cd build-riscv64
make -j`nproc`
make install DESTDIR=../tessesframework_$DEB_VERSION\_riscv64
mkdir -p ../tessesframework_$DEB_VERSION\_riscv64/DEBIAN
bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_riscv64/DEBIAN/control riscv64
cd ../
dpkg-deb --build tessesframework_$DEB_VERSION\_riscv64
# ARMHF
mkdir build-armhf
cmake -S ../../../../ -B build-armhf -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/armhf.cmake
cd build-armhf
make -j`nproc`
make install DESTDIR=../tessesframework_$DEB_VERSION\_armhf
mkdir -p ../tessesframework_$DEB_VERSION\_armhf/DEBIAN
bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_armhf/DEBIAN/control armhf
cd ../
dpkg-deb --build tessesframework_$DEB_VERSION\_armhf
# I386
mkdir build-i386
cmake -S ../../../../ -B build-i386 -DCMAKE_INSTALL_PREFIX=/usr -DTESSESFRAMEWORK_VENDERCERTCHAIN=OFF -DTESSESFRAMEWORK_FETCHCONTENT=OFF -DCMAKE_TOOLCHAIN_FILE=/opt/toolchains/i386.cmake
cd build-i386
make -j`nproc`
make install DESTDIR=../tessesframework_$DEB_VERSION\_i386
mkdir -p ../tessesframework_$DEB_VERSION\_i386/DEBIAN
bash ../../../make-control.sh ../tessesframework_$DEB_VERSION\_i386/DEBIAN/control i386
cd ../
dpkg-deb --build tessesframework_$DEB_VERSION\_i386

View File

@@ -1,8 +0,0 @@
echo "Package: tessesframework" > "$1"
echo "Version: $DEB_VERSION" >> "$1"
echo "Architecture: $2" >> "$1"
echo "Essential: no" >> "$1"
echo "Priority: optional" >> "$1"
echo "Depends: libmbedtls-dev" >> "$1"
echo "Maintainer: Mike Nolan" >> "$1"
echo "Description: A cross platform wrapper library" >> "$1"

View File

@@ -1,22 +0,0 @@
#!/bin/bash
source ./version.sh
curl --user tesses50:$GITEA_AUTH -X DELETE \
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/tessesframework/$DEB_VERSION/amd64
curl --user tesses50:$GITEA_AUTH -X DELETE \
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/tessesframework/$DEB_VERSION/arm64
curl --user tesses50:$GITEA_AUTH -X DELETE \
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/tessesframework/$DEB_VERSION/riscv64
curl --user tesses50:$GITEA_AUTH -X DELETE \
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/tessesframework/$DEB_VERSION/armhf
curl --user tesses50:$GITEA_AUTH \
--upload-file build/jammy/tessesframework_$DEB_VERSION\_amd64.deb \
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/upload
curl --user tesses50:$GITEA_AUTH \
--upload-file build/jammy/tessesframework_$DEB_VERSION\_arm64.deb \
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/upload
curl --user tesses50:$GITEA_AUTH \
--upload-file build/jammy/tessesframework_$DEB_VERSION\_riscv64.deb \
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/upload
curl --user tesses50:$GITEA_AUTH \
--upload-file build/jammy/tessesframework_$DEB_VERSION\_armhf.deb \
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/jammy/main/upload

View File

@@ -1,27 +0,0 @@
#!/bin/bash
source ./version.sh
curl --user tesses50:$GITEA_AUTH -X DELETE \
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/tessesframework/$DEB_VERSION/amd64
curl --user tesses50:$GITEA_AUTH -X DELETE \
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/tessesframework/$DEB_VERSION/arm64
curl --user tesses50:$GITEA_AUTH -X DELETE \
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/tessesframework/$DEB_VERSION/i386
curl --user tesses50:$GITEA_AUTH -X DELETE \
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/tessesframework/$DEB_VERSION/riscv64
curl --user tesses50:$GITEA_AUTH -X DELETE \
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/tessesframework/$DEB_VERSION/armhf
curl --user tesses50:$GITEA_AUTH \
--upload-file build/plucky/tessesframework_$DEB_VERSION\_amd64.deb \
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/upload
curl --user tesses50:$GITEA_AUTH \
--upload-file build/plucky/tessesframework_$DEB_VERSION\_arm64.deb \
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/upload
curl --user tesses50:$GITEA_AUTH \
--upload-file build/plucky/tessesframework_$DEB_VERSION\_i386.deb \
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/upload
curl --user tesses50:$GITEA_AUTH \
--upload-file build/plucky/tessesframework_$DEB_VERSION\_riscv64.deb \
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/upload
curl --user tesses50:$GITEA_AUTH \
--upload-file build/plucky/tessesframework_$DEB_VERSION\_armhf.deb \
https://git.tesseslanguage.com/api/packages/tesses50/debian/pool/plucky/main/upload

View File

@@ -1 +0,0 @@
export DEB_VERSION=0.0.2

View File

@@ -21,9 +21,9 @@ int main(int argc, char** argv)
.SendText( .SendText(
"<!DOCTYPE html>" "<!DOCTYPE html>"
"<html>" "<html>"
"<head><meta charset=\"UTF-8\"><title>AnonyDump</title></head>" "<head><meta charset=\"UTF-8\"><title>AnonyDrop</title><meta name=\"color-scheme\" content=\"dark light\"></head>"
"<body>" "<body>"
"<h1>AnonyDump</h1>" "<h1>AnonyDrop</h1>"
"<a href=\"./files/\">Files</a>" "<a href=\"./files/\">Files</a>"
"<form action=\"./upload\" method=\"post\" enctype=\"multipart/form-data\" accept-charset=\"UTF-8\">" "<form action=\"./upload\" method=\"post\" enctype=\"multipart/form-data\" accept-charset=\"UTF-8\">"
"<input type=\"file\" name=\"file\" multiple>" "<input type=\"file\" name=\"file\" multiple>"
@@ -43,19 +43,18 @@ int main(int argc, char** argv)
if(name != "file") return nullptr; if(name != "file") return nullptr;
VFSPath path("/"+filename); VFSPath path("/"+filename);
auto strm = vfs->OpenFile(path,"wb"); auto strm = vfs->OpenFile(path,"wb");
return strm; return strm;
}); });
ctx.WithMimeType("text/html") ctx.WithMimeType("text/html")
.SendText( .SendText(
"<!DOCTYPE html>" "<!DOCTYPE html>"
"<html>" "<html>"
"<head><title>AnonyDump - Uploaded successfully</title>" "<head><title>AnonyDrop - Uploaded successfully</title>"
"<body>" "<body>"
"<h1>Uploaded successfully</h1>" "<h1>Uploaded successfully</h1>"
"<a href=\"./\">Back</a>" "<a href=\"./\">Back</a>"
"</form>"
"</body>" "</body>"
"</html>" "</html>"
); );
@@ -71,7 +70,7 @@ int main(int argc, char** argv)
"<body>" "<body>"
"<h1>Error: Must contain multipart and POST</h1>" "<h1>Error: Must contain multipart and POST</h1>"
"<a href=\"./\">Back</a>" "<a href=\"./\">Back</a>"
"</form>" "</form>"
"</body>" "</body>"
"</html>" "</html>"
@@ -91,4 +90,4 @@ int main(int argc, char** argv)
TF_Quit(); TF_Quit();
return 0; return 0;
} }

60
cmake/sources.cmake Normal file
View File

@@ -0,0 +1,60 @@
list(APPEND TESSESFRAMEWORK_SOURCE
src/Random.cpp
src/Date/Date.cpp
src/Http/FileServer.cpp
src/Http/MountableServer.cpp
src/Http/RouteServer.cpp
src/Http/CallbackServer.cpp
src/Http/HttpServer.cpp
src/Http/HttpUtils.cpp
src/Http/HttpClient.cpp
src/Http/HttpStream.cpp
src/Http/ContentDisposition.cpp
src/Http/WebSocket.cpp
src/Http/ChangeableServer.cpp
src/Http/BasicAuthServer.cpp
src/Http/CGIServer.cpp
src/Mail/Smtp.cpp
src/Serialization/Json.cpp
src/Serialization/SQLite.cpp
src/Serialization/BitConverter.cpp
src/Serialization/Bencode.cpp
src/Platform/Environment.cpp
src/Platform/Process.cpp
src/Streams/FileStream.cpp
src/Streams/MemoryStream.cpp
src/Streams/NetworkStream.cpp
src/Streams/Stream.cpp
src/Streams/BufferedStream.cpp
src/Streams/ByteReader.cpp
src/Streams/ByteWriter.cpp
src/Streams/PtyStream.cpp
src/Text/StringConverter.cpp
src/Text/HeaderGenerator.cpp
src/TextStreams/StreamReader.cpp
src/TextStreams/StreamWriter.cpp
src/TextStreams/TextReader.cpp
src/TextStreams/TextWriter.cpp
src/TextStreams/StdIOReader.cpp
src/TextStreams/StdIOWriter.cpp
src/TextStreams/StringReader.cpp
src/TextStreams/StringWriter.cpp
src/Threading/Thread.cpp
src/Threading/Mutex.cpp
src/Threading/ThreadPool.cpp
src/Filesystem/VFS.cpp
src/Filesystem/LocalFS.cpp
src/Filesystem/SubdirFilesystem.cpp
src/Filesystem/NullFilesystem.cpp
src/Filesystem/MountableFilesystem.cpp
src/Filesystem/FSHelpers.cpp
src/Filesystem/TempFS.cpp
src/Crypto/MbedTLS/ClientTLSStream.cpp
src/Crypto/MbedTLS/Crypto.cpp
src/Args.cpp
src/TF_Init.cpp
src/HiddenField.cpp
src/Uuid.cpp
src/BitTorrent/TorrentFile.cpp
src/BitTorrent/TorrentStream.cpp
)

View File

@@ -1,5 +1,5 @@
services: services:
portable-json: portable-json:
image: onedev.site.tesses.net/tesses-framework/portable-json-creator:latest image: git.tesses.org/tesses50/portable-json-creator:latest
ports: ports:
- "4999:4999" - "4999:4999"

View File

@@ -1,22 +0,0 @@
#include "TessesFramework/TessesFramework.hpp"
using namespace Tesses::Framework;
int main(int argc, char** argv)
{
TF_Init();
auto event = std::make_shared<FunctionalEvent<uint64_t>>([](uint64_t n)->void {
std::cout << n << std::endl;
});
OnItteraton += event;
auto event2 = std::make_shared<FunctionalEvent<uint64_t>>([&event](uint64_t n)->void{
if(n == 10000) OnItteraton -= event;
});
OnItteraton += event2;
TF_RunEventLoop();
return 0;
}

17
examples/timer.cpp Normal file
View File

@@ -0,0 +1,17 @@
#include "TessesFramework/Common.hpp"
#include "TessesFramework/TessesFramework.hpp"
int main(int argc, char** argv)
{
using namespace Tesses::Framework;
TF_Init();
auto timer = TF_Timer([]()->void {
std::cout << "Hi, I am a timer" << std::endl;
});
TF_RunEventLoop();
TF_Quit();
}

View File

@@ -1,5 +1,8 @@
#include "TessesFramework/TessesFramework.hpp" #include "TessesFramework/TessesFramework.hpp"
#include <TessesFramework/Platform/Environment.hpp>
#include <exception>
#include <iostream> #include <iostream>
#include <stdexcept>
using namespace Tesses::Framework; using namespace Tesses::Framework;
using namespace Tesses::Framework::Http; using namespace Tesses::Framework::Http;
using namespace Tesses::Framework::Streams; using namespace Tesses::Framework::Streams;
@@ -26,7 +29,7 @@ class MyWebServer : public IHttpServer {
if(ctx.path == "/") if(ctx.path == "/")
{ {
std::shared_ptr<FileStream> fs = std::make_shared<FileStream>("index.html","rb"); std::shared_ptr<FileStream> fs = std::make_shared<FileStream>("index.html","rb");
ctx ctx
.WithMimeType("text/html") .WithMimeType("text/html")
.SendStream(fs); .SendStream(fs);
@@ -62,7 +65,7 @@ class MyWebServer : public IHttpServer {
for(size_t i=0;i<10000; i++) for(size_t i=0;i<10000; i++)
{ {
writer.WriteLine("<li>" + std::to_string(i) + "</li>"); writer.WriteLine("<li>" + std::to_string(i) + "</li>");
} }
writer.WriteLine("</ul>"); writer.WriteLine("</ul>");
@@ -75,7 +78,7 @@ class MyWebServer : public IHttpServer {
{ {
std::shared_ptr<FileStream> fs = std::make_shared<FileStream>("main.js","rb"); std::shared_ptr<FileStream> fs = std::make_shared<FileStream>("main.js","rb");
ctx ctx
.WithMimeType("text/js") .WithMimeType("text/js")
.SendStream(fs); .SendStream(fs);
@@ -92,10 +95,10 @@ class MyWebServer : public IHttpServer {
Johnny* data = ctx.GetServerContentData<Johnny>("mytag"); Johnny* data = ctx.GetServerContentData<Johnny>("mytag");
data->text = "Demi Lovato"; data->text = "Demi Lovato";
} }
return false; return false;
} }
}; };
class MyOtherWebServer : public IHttpServer class MyOtherWebServer : public IHttpServer
{ {
@@ -115,10 +118,30 @@ class MyOtherWebServer : public IHttpServer
.WithContentDisposition(HttpUtils::Sanitise(name) + ".txt",false) .WithContentDisposition(HttpUtils::Sanitise(name) + ".txt",false)
.SendText(name + " is cool."); .SendText(name + " is cool.");
//do something with q //do something with q
return true; return true;
} }
} }
else if(ctx.path == "/status")
{
int64_t num;
if(ctx.queryParams.TryGetFirstInt("code", num))
{
ctx.statusCode = (StatusCode)num;
}
ctx.SendErrorPage(true);
return true;
}
else if(ctx.path == "/error")
{
throw std::runtime_error("This is a error");
}
else if(ctx.path == "/error-debug")
{
ctx.WithDebug(true);
throw std::runtime_error("Platform is " + Tesses::Framework::Platform::Environment::GetPlatform());
}
else if(ctx.path == "/mymount/steve") else if(ctx.path == "/mymount/steve")
{ {
Johnny* data = ctx.GetServerContentData<Johnny>("mytag"); Johnny* data = ctx.GetServerContentData<Johnny>("mytag");
@@ -131,7 +154,7 @@ class MyOtherWebServer : public IHttpServer
ctx.WithMimeType("text/html").SendText(txt); ctx.WithMimeType("text/html").SendText(txt);
return true; return true;
} }
return false; return false;
} }
}; };
@@ -172,4 +195,4 @@ int main(int argc, char** argv)
server.StartAccepting(); server.StartAccepting();
TF_RunEventLoop(); TF_RunEventLoop();
std::cout << "Closing server" << std::endl; std::cout << "Closing server" << std::endl;
} }

View File

@@ -1,8 +1,11 @@
#pragma once #pragma once
#include <chrono>
#include <cstring> #include <cstring>
#include <cstdint> #include <cstdint>
#include <cstddef> #include <cstddef>
#include <memory>
#include <ratio>
#include <string> #include <string>
#include <filesystem> #include <filesystem>
#include <map> #include <map>
@@ -15,83 +18,55 @@
namespace Tesses::Framework namespace Tesses::Framework
{ {
template<typename...TArgs>
class Event {
public:
virtual void Invoke(TArgs... args)=0;
virtual ~Event()
{}
};
template<typename...TArgs>
class FunctionalEvent : public Event<TArgs...> {
std::function<void(TArgs...)> cb;
public:
FunctionalEvent(std::function<void(TArgs...)> cb)
{
this->cb = cb;
}
void Invoke(TArgs... args)
{
this->cb(args...);
}
};
template<typename...TArgs>
class EventList : public Event<TArgs...> {
Threading::Mutex mtx;
std::vector<std::shared_ptr<Event<TArgs...>>> items;
public:
void operator+=(std::shared_ptr<Event<TArgs...>> event)
{
mtx.Lock();
for(std::shared_ptr<Event<TArgs...>>& item : this->items)
{
if(item.get() == event.get()) {
mtx.Unlock();
return;
}
}
this->items.push_back(event);
mtx.Unlock();
}
void operator-=(std::shared_ptr<Event<TArgs...>> event)
{
mtx.Lock();
for(auto i = this->items.begin(); i != this->items.end(); i++)
{
if(i->get() == event.get())
{
this->items.erase(i);
mtx.Unlock();
return;
}
}
mtx.Unlock();
}
void Invoke(TArgs... args)
{
mtx.Lock();
for(auto& item : this->items)
{
item->Invoke(args...);
}
mtx.Unlock();
}
void Remove(std::function<bool(std::shared_ptr<Event<TArgs...>>)> cb)
{
for(auto index = this->items.begin(); index != this->items.end(); index++)
{
if(cb(*index))
{
this->items.erase(index);
index--;
}
}
}
};
extern EventList<uint64_t> OnItteraton;
std::optional<std::string> TF_GetCommandName(); std::optional<std::string> TF_GetCommandName();
class TF_Timer_Handle;
//Used for internal purposes, don't use unless you want to run timer events on another thread
class TF_Timer_Handler {
private:
std::vector<std::weak_ptr<TF_Timer_Handle>> handles;
public:
void Update();
static std::shared_ptr<TF_Timer_Handle> Make(std::shared_ptr<TF_Timer_Handler> handler);
friend class TF_Timer_Handle;
};
class TF_Timer_Handle {
private:
std::shared_ptr<TF_Timer_Handler> timerHandler;
std::function<void()> cb;
std::chrono::milliseconds interval;
std::chrono::time_point<std::chrono::steady_clock, std::chrono::milliseconds> last;
bool enabled;
TF_Timer_Handle() = delete;
TF_Timer_Handle(std::shared_ptr<TF_Timer_Handler> timerHandler);
public:
void SetCallback(std::function<void()> cb);
int64_t GetIntervalMilliseconds();
std::chrono::duration<int64_t,std::milli> GetIntervalDuration();
void SetIntervalFromMilliseconds(int64_t ms);
void SetIntervalFromDuration(std::chrono::milliseconds dur);
void SetEnabled(bool enabled);
bool GetEnabled();
friend class TF_Timer_Handler;
};
std::shared_ptr<TF_Timer_Handle> TF_Timer();
std::shared_ptr<TF_Timer_Handle> TF_Timer(std::function<void()> cb, int64_t interval=1000, bool enabled=true);
std::shared_ptr<TF_Timer_Handle> TF_Timer(std::function<void()> cb, std::chrono::milliseconds interval, bool enabled=true);
void TF_Init(); void TF_Init();
void TF_InitWithConsole(); void TF_InitWithConsole();

View File

@@ -1,50 +1,46 @@
#pragma once #pragma once
#include "VFS.hpp" #include "VFS.hpp"
#include "VFSFix.hpp" #include "VFSFix.hpp"
namespace Tesses::Framework::Filesystem namespace Tesses::Framework::Filesystem
{ {
class LocalFilesystem : public VFS class LocalFilesystem : public VFS
{ {
public: public:
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode); std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode);
void CreateDirectory(VFSPath path); void CreateDirectory(VFSPath path);
void DeleteDirectory(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 DeleteFile(VFSPath path);
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile); void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
VFSPathEnumerator EnumeratePaths(VFSPath path); VFSPathEnumerator EnumeratePaths(VFSPath path);
void CreateHardlink(VFSPath existingFile, VFSPath newName); void CreateHardlink(VFSPath existingFile, VFSPath newName);
void MoveFile(VFSPath src, VFSPath dest); void MoveFile(VFSPath src, VFSPath dest);
void MoveDirectory(VFSPath src, VFSPath dest); void MoveDirectory(VFSPath src, VFSPath dest);
VFSPath ReadLink(VFSPath path); VFSPath ReadLink(VFSPath path);
std::string VFSPathToSystem(VFSPath path); std::string VFSPathToSystem(VFSPath path);
VFSPath SystemToVFSPath(std::string path); VFSPath SystemToVFSPath(std::string path);
void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess);
void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
bool Stat(VFSPath path, StatData& stat);
bool StatVFS(VFSPath path, StatVFSData& vfsData); bool StatVFS(VFSPath path, StatVFSData& vfsData);
void Chmod(VFSPath path, uint32_t mode); void Chmod(VFSPath path, uint32_t mode);
void Chown(VFSPath path, uint32_t uid, uint32_t gid);
void Lock(VFSPath path); void Lock(VFSPath path);
void Unlock(VFSPath path); void Unlock(VFSPath path);
FIFOCreationResult CreateFIFO(VFSPath path, uint32_t mod);
protected: protected:
std::shared_ptr<FSWatcher> CreateWatcher(std::shared_ptr<VFS> vfs, VFSPath path); std::shared_ptr<FSWatcher> CreateWatcher(std::shared_ptr<VFS> vfs, VFSPath path);
}; };
extern std::shared_ptr<LocalFilesystem> LocalFS; extern std::shared_ptr<LocalFilesystem> LocalFS;
} }

View File

@@ -1,100 +0,0 @@
#pragma once
#include "VFS.hpp"
#include "VFSFix.hpp"
#include "../Threading/Mutex.hpp"
#include <atomic>
namespace Tesses::Framework::Filesystem
{
class MemoryEntry {
public:
std::string name;
virtual ~MemoryEntry();
};
class MemoryFileData {
public:
MemoryFileData();
Date::DateTime lastWrite;
bool canAccess;
size_t readers;
std::vector<uint8_t> file;
};
class MemoryFile : public MemoryEntry
{
public:
std::shared_ptr<MemoryFileData> data;
~MemoryFile();
};
class MemoryDirectory : public MemoryEntry
{
public:
MemoryDirectory();
Date::DateTime lastWrite;
std::vector<MemoryEntry*> entries;
~MemoryDirectory();
};
class MemorySymlink : public MemoryEntry
{
public:
Date::DateTime lastWrite;
VFSPath linkedTo;
};
class MemoryFilesystemStream : public Streams::Stream
{
public:
std::shared_ptr<Tesses::Framework::Threading::Mutex> mtx;
std::shared_ptr<MemoryFileData> data;
bool canRead;
bool canWrite;
bool canSeek;
int64_t pos;
MemoryFilesystemStream(std::shared_ptr<Tesses::Framework::Threading::Mutex> mtx, std::shared_ptr<MemoryFileData> data,bool canRead, bool canWrite, bool canSeek);
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, Streams::SeekOrigin whence);
~MemoryFilesystemStream();
};
class MemoryFilesystem : public VFS
{
std::shared_ptr<Tesses::Framework::Threading::Mutex> mtx;
MemoryDirectory root;
MemoryEntry* GetEntry(VFSPath path,bool followSymlink);
public:
MemoryFilesystem();
std::shared_ptr<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 DirectoryExists(VFSPath path);
void DeleteFile(VFSPath path);
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
VFSPathEnumerator EnumeratePaths(VFSPath path);
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);
void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess);
void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
~MemoryFilesystem();
};
};

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include "VFS.hpp" #include "VFS.hpp"
#include "VFSFix.hpp" #include "VFSFix.hpp"
namespace Tesses::Framework::Filesystem namespace Tesses::Framework::Filesystem
{ {
class MountableDirectory { class MountableDirectory {
@@ -19,10 +19,10 @@ namespace Tesses::Framework::Filesystem
std::shared_ptr<VFS> root; std::shared_ptr<VFS> root;
std::vector<MountableDirectory*> directories; std::vector<MountableDirectory*> directories;
void GetFS(VFSPath srcPath, VFSPath& destRoot, VFSPath& destPath, std::shared_ptr<VFS>& vfs); void GetFS(VFSPath srcPath, VFSPath& destRoot, VFSPath& destPath, std::shared_ptr<VFS>& vfs);
public: public:
MountableFilesystem(); MountableFilesystem();
MountableFilesystem(std::shared_ptr<VFS> root); MountableFilesystem(std::shared_ptr<VFS> root);
@@ -31,15 +31,7 @@ namespace Tesses::Framework::Filesystem
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode); std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode);
void CreateDirectory(VFSPath path); void CreateDirectory(VFSPath path);
void DeleteDirectory(VFSPath path); void DeleteDirectory(VFSPath path);
bool SpecialFileExists(VFSPath path); bool Stat(VFSPath path, StatData& data);
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 DeleteFile(VFSPath path);
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile); void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
VFSPathEnumerator EnumeratePaths(VFSPath path); VFSPathEnumerator EnumeratePaths(VFSPath path);
@@ -50,14 +42,18 @@ namespace Tesses::Framework::Filesystem
std::string VFSPathToSystem(VFSPath path); std::string VFSPathToSystem(VFSPath path);
VFSPath SystemToVFSPath(std::string path); VFSPath SystemToVFSPath(std::string path);
~MountableFilesystem(); ~MountableFilesystem();
void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess);
void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess); void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
bool StatVFS(VFSPath path, StatVFSData& vfsData); bool StatVFS(VFSPath path, StatVFSData& vfsData);
void Chmod(VFSPath path, uint32_t mode); void Chmod(VFSPath path, uint32_t mode);
void Chown(VFSPath path, uint32_t uid, uint32_t gid);
FIFOCreationResult CreateFIFO(VFSPath path, uint32_t mode);
void Lock(VFSPath path); void Lock(VFSPath path);
void Unlock(VFSPath path); void Unlock(VFSPath path);
}; };
} }

View File

@@ -1,21 +1,16 @@
#pragma once #pragma once
#include "VFS.hpp" #include "VFS.hpp"
#include "VFSFix.hpp" #include "VFSFix.hpp"
namespace Tesses::Framework::Filesystem namespace Tesses::Framework::Filesystem
{ {
class NullFilesystem : public VFS class NullFilesystem : public VFS
{ {
public: public:
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode); std::shared_ptr<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);
VFSPathEnumerator EnumeratePaths(VFSPath path); VFSPathEnumerator EnumeratePaths(VFSPath path);
void MoveFile(VFSPath src, VFSPath dest); bool Stat(VFSPath path, StatData& data);
std::string VFSPathToSystem(VFSPath path); std::string VFSPathToSystem(VFSPath path);
VFSPath SystemToVFSPath(std::string path); VFSPath SystemToVFSPath(std::string path);
}; };
} }

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include "VFS.hpp" #include "VFS.hpp"
#include "VFSFix.hpp" #include "VFSFix.hpp"
namespace Tesses::Framework::Filesystem namespace Tesses::Framework::Filesystem
{ {
class SubdirFilesystem : public VFS class SubdirFilesystem : public VFS
@@ -15,15 +15,6 @@ namespace Tesses::Framework::Filesystem
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode); std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode);
void CreateDirectory(VFSPath path); void CreateDirectory(VFSPath path);
void DeleteDirectory(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 DeleteFile(VFSPath path);
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile); void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
VFSPathEnumerator EnumeratePaths(VFSPath path); VFSPathEnumerator EnumeratePaths(VFSPath path);
@@ -35,13 +26,14 @@ namespace Tesses::Framework::Filesystem
std::string VFSPathToSystem(VFSPath path); std::string VFSPathToSystem(VFSPath path);
VFSPath SystemToVFSPath(std::string path); VFSPath SystemToVFSPath(std::string path);
~SubdirFilesystem(); ~SubdirFilesystem();
void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess);
void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess); void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
bool StatVFS(VFSPath path, StatVFSData& vfsData); bool StatVFS(VFSPath path, StatVFSData& vfsData);
bool Stat(VFSPath path, StatData& data);
void Chown(VFSPath path, uint32_t uid, uint32_t gid);
void Chmod(VFSPath path, uint32_t mode); void Chmod(VFSPath path, uint32_t mode);
FIFOCreationResult CreateFIFO(VFSPath path, uint32_t mode);
void Lock(VFSPath path); void Lock(VFSPath path);
void Unlock(VFSPath path); void Unlock(VFSPath path);
}; };
} }

View File

@@ -2,7 +2,7 @@
#include "../Common.hpp" #include "../Common.hpp"
#include "VFS.hpp" #include "VFS.hpp"
#include "VFSFix.hpp" #include "VFSFix.hpp"
namespace Tesses::Framework::Filesystem namespace Tesses::Framework::Filesystem
{ {
void UniqueString(std::string& text); void UniqueString(std::string& text);
@@ -20,15 +20,6 @@ namespace Tesses::Framework::Filesystem
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode); std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode);
void CreateDirectory(VFSPath path); void CreateDirectory(VFSPath path);
void DeleteDirectory(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 DeleteFile(VFSPath path);
void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile); void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
VFSPathEnumerator EnumeratePaths(VFSPath path); VFSPathEnumerator EnumeratePaths(VFSPath path);
@@ -39,16 +30,19 @@ namespace Tesses::Framework::Filesystem
VFSPath ReadLink(VFSPath path); VFSPath ReadLink(VFSPath path);
std::string VFSPathToSystem(VFSPath path); std::string VFSPathToSystem(VFSPath path);
VFSPath SystemToVFSPath(std::string path); VFSPath SystemToVFSPath(std::string path);
void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess);
void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess); void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
bool StatVFS(VFSPath path, StatVFSData& vfsData); bool StatVFS(VFSPath path, StatVFSData& vfsData);
bool Stat(VFSPath path, StatData& data);
void Chmod(VFSPath path, uint32_t mode); void Chmod(VFSPath path, uint32_t mode);
void Chown(VFSPath path, uint32_t uid, uint32_t gid);
FIFOCreationResult CreateFIFO(VFSPath path, uint32_t mode);
void Close(); void Close();
void Lock(VFSPath path); void Lock(VFSPath path);
void Unlock(VFSPath path); void Unlock(VFSPath path);
~TempFS(); ~TempFS();
}; };
} }

View File

@@ -1,16 +1,18 @@
#pragma once #pragma once
#include "../Common.hpp" #include "../Common.hpp"
#include "../Streams/Stream.hpp" #include "../Streams/Stream.hpp"
#include <TessesFramework/Common.hpp>
#include <TessesFramework/Date/Date.hpp>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include "../Date/Date.hpp" #include "../Date/Date.hpp"
#include "VFSFix.hpp" #include "VFSFix.hpp"
namespace Tesses::Framework::Filesystem namespace Tesses::Framework::Filesystem
{ {
class StatVFSData { struct StatVFSData {
public:
uint64_t BlockSize; uint64_t BlockSize;
uint64_t FragmentSize; uint64_t FragmentSize;
uint64_t Blocks; uint64_t Blocks;
@@ -23,12 +25,94 @@ namespace Tesses::Framework::Filesystem
uint64_t Flags; uint64_t Flags;
uint64_t MaxNameLength; uint64_t MaxNameLength;
}; };
constexpr uint32_t MODE_USER_READ = 0400;
constexpr uint32_t MODE_USER_WRITE = 0200;
constexpr uint32_t MODE_USER_EXEC = 0100;
constexpr uint32_t MODE_GROUP_READ = (MODE_USER_READ >> 3);
constexpr uint32_t MODE_GROUP_WRITE = (MODE_USER_WRITE >> 3);
constexpr uint32_t MODE_GROUP_EXEC = (MODE_USER_EXEC >> 3);
constexpr uint32_t MODE_OTHER_READ = (MODE_GROUP_READ >> 3);
constexpr uint32_t MODE_OTHER_WRITE = (MODE_GROUP_WRITE >> 3);
constexpr uint32_t MODE_OTHER_EXEC = (MODE_GROUP_EXEC >> 3);
constexpr uint32_t MODE_REGULAR = 0100000;
constexpr uint32_t MODE_DIRECTORY = 0040000;
constexpr uint32_t MODE_CHAR_DEVICE = 0020000;
constexpr uint32_t MODE_BLOCK_DEVICE = 0060000;
constexpr uint32_t MODE_SOCKET = 0140000;
constexpr uint32_t MODE_FIFO = 0010000;
constexpr uint32_t MODE_SYMLINK = 0120000;
struct StatData {
uint64_t Device;
uint64_t Inode;
uint32_t Mode;
uint64_t HardLinks;
uint32_t UserId;
uint32_t GroupId;
uint64_t DeviceId;
uint64_t Size;
uint64_t BlockSize;
uint64_t BlockCount;
Date::DateTime LastAccess;
Date::DateTime LastModified;
Date::DateTime LastStatus;
bool IsRegularFile()
{
return (Mode & MODE_REGULAR) > 0;
}
bool IsDirectory()
{
return (Mode & MODE_DIRECTORY) > 0;
}
bool IsCharDevice()
{
return (Mode & MODE_CHAR_DEVICE) > 0;
}
bool IsBlockDevice()
{
return (Mode & MODE_BLOCK_DEVICE) > 0;
}
bool IsSocket()
{
return (Mode & MODE_SOCKET) > 0;
}
bool IsFIFO()
{
return (Mode & MODE_FIFO) > 0;
}
bool IsSymlink()
{
return (Mode & MODE_SYMLINK) > 0;
}
bool IsSpecial()
{
if(IsRegularFile()) return false;
if(IsDirectory()) return false;
return true;
}
std::string ToSizeString(bool usesBin=true)
{
return TF_FileSize(this->Size, usesBin);
}
};
class VFSPath { class VFSPath {
public: public:
static VFSPath CurrentDirectoryAsRelative(); static VFSPath CurrentDirectoryAsRelative();
bool relative; bool relative;
static std::vector<std::string> SplitPath(std::string path); static std::vector<std::string> SplitPath(std::string path);
std::vector<std::string> path; std::vector<std::string> path;
VFSPath(); VFSPath();
explicit VFSPath(const char* path) : VFSPath(std::string(path)) explicit VFSPath(const char* path) : VFSPath(std::string(path))
{} {}
@@ -36,7 +120,7 @@ namespace Tesses::Framework::Filesystem
VFSPath(std::string path); VFSPath(std::string path);
VFSPath(VFSPath p, std::string subent); VFSPath(VFSPath p, std::string subent);
VFSPath(VFSPath p, VFSPath p2); VFSPath(VFSPath p, VFSPath p2);
//does not check for ? //does not check for ?
static VFSPath ParseUriPath(std::string path); static VFSPath ParseUriPath(std::string path);
@@ -52,7 +136,7 @@ namespace Tesses::Framework::Filesystem
static VFSPath GetAbsoluteCurrentDirectory(); static VFSPath GetAbsoluteCurrentDirectory();
static void SetAbsoluteCurrentDirectory(VFSPath path); static void SetAbsoluteCurrentDirectory(VFSPath path);
VFSPath MakeAbsolute() const; VFSPath MakeAbsolute() const;
VFSPath MakeAbsolute(VFSPath curDir) const; VFSPath MakeAbsolute(VFSPath curDir) const;
VFSPath MakeRelative() const; VFSPath MakeRelative() const;
VFSPath MakeRelative(VFSPath toMakeRelativeTo) const; VFSPath MakeRelative(VFSPath toMakeRelativeTo) const;
@@ -98,10 +182,10 @@ namespace Tesses::Framework::Filesystem
VFSPathEnumeratorItterator& operator++(); VFSPathEnumeratorItterator& operator++();
VFSPathEnumeratorItterator& operator++(int); VFSPathEnumeratorItterator& operator++(int);
VFSPath& operator*(); VFSPath& operator*();
VFSPath* operator->(); VFSPath* operator->();
bool operator!=(VFSPathEnumeratorItterator right); bool operator!=(VFSPathEnumeratorItterator right);
bool operator==(VFSPathEnumeratorItterator right); bool operator==(VFSPathEnumeratorItterator right);
}; };
@@ -185,48 +269,60 @@ namespace Tesses::Framework::Filesystem
std::shared_ptr<VFS> GetFilesystem(); std::shared_ptr<VFS> GetFilesystem();
const VFSPath& GetPath(); const VFSPath& GetPath();
virtual ~FSWatcher() = default; virtual ~FSWatcher() = default;
static std::shared_ptr<FSWatcher> Create(std::shared_ptr<VFS> vfs, VFSPath path); static std::shared_ptr<FSWatcher> Create(std::shared_ptr<VFS> vfs, VFSPath path);
};
enum class FIFOCreationResult {
Success=0,
Exists = 1,
ReadOnlyFS = 2,
Denied = 3,
OutOfInodes = 4,
UnknownError = 5,
Unsupported = 255
}; };
class VFS { class VFS {
public: public:
virtual std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode)=0; virtual std::shared_ptr<Tesses::Framework::Streams::Stream> OpenFile(VFSPath path, std::string mode)=0;
virtual void CreateDirectory(VFSPath path)=0; virtual void CreateDirectory(VFSPath path);
virtual void DeleteDirectory(VFSPath path)=0; virtual void DeleteDirectory(VFSPath path);
virtual bool RegularFileExists(VFSPath path)=0; bool DirectoryExists(VFSPath path);
virtual bool SymlinkExists(VFSPath path); bool RegularFileExists(VFSPath path);
virtual bool CharacterDeviceExists(VFSPath path); bool SymlinkExists(VFSPath path);
virtual bool BlockDeviceExists(VFSPath path); bool CharacterDeviceExists(VFSPath path);
virtual bool SocketFileExists(VFSPath path); bool BlockDeviceExists(VFSPath path);
virtual bool FIFOFileExists(VFSPath path); bool SocketFileExists(VFSPath path);
virtual bool FileExists(VFSPath path); bool FIFOFileExists(VFSPath path);
virtual bool SpecialFileExists(VFSPath path); bool FileExists(VFSPath path);
bool SpecialFileExists(VFSPath path);
virtual void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile); virtual void CreateSymlink(VFSPath existingFile, VFSPath symlinkFile);
virtual void CreateHardlink(VFSPath existingFile, VFSPath newName); virtual void CreateHardlink(VFSPath existingFile, VFSPath newName);
virtual bool DirectoryExists(VFSPath path)=0; virtual void DeleteFile(VFSPath path);
virtual void DeleteFile(VFSPath path)=0;
virtual void DeleteDirectoryRecurse(VFSPath path); virtual void DeleteDirectoryRecurse(VFSPath path);
virtual VFSPathEnumerator EnumeratePaths(VFSPath path) = 0; virtual VFSPathEnumerator EnumeratePaths(VFSPath path) = 0;
virtual void MoveFile(VFSPath src, VFSPath dest)=0; virtual void MoveFile(VFSPath src, VFSPath dest);
virtual void MoveDirectory(VFSPath src, VFSPath dest); virtual void MoveDirectory(VFSPath src, VFSPath dest);
virtual VFSPath ReadLink(VFSPath path); virtual VFSPath ReadLink(VFSPath path);
virtual std::string VFSPathToSystem(VFSPath path)=0; virtual std::string VFSPathToSystem(VFSPath path)=0;
virtual VFSPath SystemToVFSPath(std::string path)=0; virtual VFSPath SystemToVFSPath(std::string path)=0;
virtual void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess); void GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess);
virtual void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess); virtual void SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess);
virtual bool Stat(VFSPath path, StatData& data) = 0;
virtual bool StatVFS(VFSPath path, StatVFSData& data); virtual bool StatVFS(VFSPath path, StatVFSData& data);
virtual void Chmod(VFSPath path, uint32_t mode); virtual void Chmod(VFSPath path, uint32_t mode);
virtual void Chown(VFSPath path, uint32_t userId, uint32_t groupId);
virtual void Lock(VFSPath path); virtual void Lock(VFSPath path);
virtual void Unlock(VFSPath path); virtual void Unlock(VFSPath path);
virtual FIFOCreationResult CreateFIFO(VFSPath path, uint32_t mode);
virtual ~VFS(); virtual ~VFS();
virtual void Close(); virtual void Close();
@@ -236,7 +332,6 @@ namespace Tesses::Framework::Filesystem
friend class FSWatcher; friend class FSWatcher;
}; };
namespace Literals namespace Literals
{ {
@@ -246,4 +341,3 @@ namespace Tesses::Framework::Filesystem
} }
} }
} }

View File

@@ -6,6 +6,7 @@
#include "../Date/Date.hpp" #include "../Date/Date.hpp"
#include <unordered_map> #include <unordered_map>
#include "WebSocket.hpp" #include "WebSocket.hpp"
#include <queue>
namespace Tesses::Framework::Http namespace Tesses::Framework::Http
{ {
class ServerContextData { class ServerContextData {
@@ -13,12 +14,14 @@ namespace Tesses::Framework::Http
virtual ~ServerContextData(); virtual ~ServerContextData();
}; };
class ServerContext { class ServerContext {
bool sent; bool sent;
bool debug;
std::shared_ptr<Tesses::Framework::Streams::Stream> strm; std::shared_ptr<Tesses::Framework::Streams::Stream> strm;
std::map<std::string,ServerContextData*> data; std::map<std::string,ServerContextData*> data;
std::queue<std::function<bool(ServerContext& ctx)>> headerhandlers;
public: public:
HttpDictionary requestHeaders; HttpDictionary requestHeaders;
HttpDictionary responseHeaders; HttpDictionary responseHeaders;
@@ -34,7 +37,7 @@ namespace Tesses::Framework::Http
uint16_t serverPort; uint16_t serverPort;
std::string version; std::string version;
bool encrypted; bool encrypted;
ServerContext(std::shared_ptr<Tesses::Framework::Streams::Stream> strm); ServerContext(std::shared_ptr<Tesses::Framework::Streams::Stream> strm, bool debug=false);
~ServerContext(); ~ServerContext();
std::shared_ptr<Tesses::Framework::Streams::Stream> GetStream(); std::shared_ptr<Tesses::Framework::Streams::Stream> GetStream();
std::string GetOriginalPathWithQuery(); std::string GetOriginalPathWithQuery();
@@ -53,6 +56,7 @@ namespace Tesses::Framework::Http
void SendException(std::exception& ex); void SendException(std::exception& ex);
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenResponseStream(); std::shared_ptr<Tesses::Framework::Streams::Stream> OpenResponseStream();
std::shared_ptr<Tesses::Framework::Streams::Stream> OpenRequestStream(); std::shared_ptr<Tesses::Framework::Streams::Stream> OpenRequestStream();
ServerContext& WithStatusCode(StatusCode code);
ServerContext& WithLastModified(Date::DateTime time); ServerContext& WithLastModified(Date::DateTime time);
ServerContext& WithHeader(std::string key, std::string value); ServerContext& WithHeader(std::string key, std::string value);
ServerContext& WithSingleHeader(std::string key, std::string value); ServerContext& WithSingleHeader(std::string key, std::string value);
@@ -61,6 +65,9 @@ namespace Tesses::Framework::Http
ServerContext& WriteHeaders(); ServerContext& WriteHeaders();
ServerContext& WithLocationHeader(std::string url); ServerContext& WithLocationHeader(std::string url);
ServerContext& WithLocationHeader(std::string url,StatusCode sc); ServerContext& WithLocationHeader(std::string url,StatusCode sc);
ServerContext& WithHeaderIntercepter(std::function<bool(ServerContext&)> cb);
ServerContext& WithDebug(bool debug=true);
bool Debug();
void StartWebSocketSession(std::function<void(std::function<void(WebSocketMessage&)>,std::function<void()>,std::function<void()>)> onOpen, std::function<void(WebSocketMessage&)> onReceive, std::function<void(bool)> onClose); void StartWebSocketSession(std::function<void(std::function<void(WebSocketMessage&)>,std::function<void()>,std::function<void()>)> onOpen, std::function<void(WebSocketMessage&)> onReceive, std::function<void(bool)> onClose);
void StartWebSocketSession(std::shared_ptr<WebSocketConnection> connection); void StartWebSocketSession(std::shared_ptr<WebSocketConnection> connection);
std::string GetServerRoot(); std::string GetServerRoot();
@@ -68,7 +75,7 @@ namespace Tesses::Framework::Http
void SendRedirect(std::string url); void SendRedirect(std::string url);
void SendRedirect(std::string url, StatusCode sc); void SendRedirect(std::string url, StatusCode sc);
template<class T> template<class T>
T* GetServerContentData(std::string tag) T* GetServerContentData(std::string tag)
{ {
@@ -95,14 +102,15 @@ namespace Tesses::Framework::Http
bool showIPs; bool showIPs;
bool showARTL; bool showARTL;
bool debug;
public: public:
HttpServer(std::shared_ptr<Tesses::Framework::Streams::TcpServer> tcpServer, std::shared_ptr<IHttpServer> http, bool showIPs=true); HttpServer(std::shared_ptr<Tesses::Framework::Streams::TcpServer> tcpServer, std::shared_ptr<IHttpServer> http, bool showIPs=true, bool debug=false);
HttpServer(uint16_t port, std::shared_ptr<IHttpServer> http, bool showIPs=true); HttpServer(uint16_t port, std::shared_ptr<IHttpServer> http, bool showIPs=true, bool debug=false);
HttpServer(std::string unixPath, std::shared_ptr<IHttpServer> http); HttpServer(std::string unixPath, std::shared_ptr<IHttpServer> http, bool debug=false);
uint16_t GetPort(); uint16_t GetPort();
void StartAccepting(); void StartAccepting();
static void Process(std::shared_ptr<Tesses::Framework::Streams::Stream> strm, std::shared_ptr<IHttpServer> server, std::string ip, uint16_t port,uint16_t serverPort, bool encrypted); static void Process(std::shared_ptr<Tesses::Framework::Streams::Stream> strm, std::shared_ptr<IHttpServer> server, std::string ip, uint16_t port,uint16_t serverPort, bool encrypted, bool debug=false);
~HttpServer(); ~HttpServer();
}; };
} }

View File

@@ -31,7 +31,6 @@
#include "Filesystem/SubdirFilesystem.hpp" #include "Filesystem/SubdirFilesystem.hpp"
#include "Filesystem/NullFilesystem.hpp" #include "Filesystem/NullFilesystem.hpp"
#include "Filesystem/MountableFilesystem.hpp" #include "Filesystem/MountableFilesystem.hpp"
#include "Filesystem/MemoryFilesystem.hpp"
#include "Filesystem/FSHelpers.hpp" #include "Filesystem/FSHelpers.hpp"
#include "Crypto/ClientTLSStream.hpp" #include "Crypto/ClientTLSStream.hpp"
#include "Crypto/Crypto.hpp" #include "Crypto/Crypto.hpp"
@@ -46,4 +45,4 @@
#include "Serialization/BitConverter.hpp" #include "Serialization/BitConverter.hpp"
#include "Args.hpp" #include "Args.hpp"
#include "BitTorrent/TorrentFile.hpp" #include "BitTorrent/TorrentFile.hpp"
#include "Random.hpp" #include "Random.hpp"

View File

@@ -2,7 +2,7 @@ set(PKGCONFIG_INCLUDEDIR "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
set(PKGCONFIG_LIBDIR "\${prefix}/${CMAKE_INSTALL_LIBDIR}") set(PKGCONFIG_LIBDIR "\${prefix}/${CMAKE_INSTALL_LIBDIR}")
set(PKGCONFIG_PROJECT_DESCRIPTION "A cross platform wrapper library") set(PKGCONFIG_PROJECT_DESCRIPTION "A cross platform wrapper library")
set(PKGCONFIG_PROJECT_HOMEPAGE_URL "https://onedev.site.tesses.net/tesses-framework") set(PKGCONFIG_PROJECT_HOMEPAGE_URL "https://git.tesses.org/tessesframework")
if(TESSESFRAMEWORK_ENABLE_MBED) if(TESSESFRAMEWORK_ENABLE_MBED)
set(PKGCONFIG_DEPS "Requires: mbedtls") set(PKGCONFIG_DEPS "Requires: mbedtls")
@@ -22,4 +22,4 @@ configure_file(tessesframework.pc.in tessesframework.pc @ONLY)
install(FILES install(FILES
${CMAKE_CURRENT_BINARY_DIR}/tessesframework.pc ${CMAKE_CURRENT_BINARY_DIR}/tessesframework.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
endif() endif()

View File

@@ -1,7 +1,10 @@
#include "TessesFramework/Filesystem/LocalFS.hpp" #include "TessesFramework/Filesystem/LocalFS.hpp"
#include "TessesFramework/Streams/FileStream.hpp" #include "TessesFramework/Streams/FileStream.hpp"
#include <cerrno>
#include <filesystem>
#include <iostream> #include <iostream>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h>
#if defined(_WIN32) #if defined(_WIN32)
#include <windows.h> #include <windows.h>
#include "TessesFramework/Filesystem/VFSFix.hpp" #include "TessesFramework/Filesystem/VFSFix.hpp"
@@ -27,16 +30,31 @@ namespace Tesses::Framework::Filesystem
pft->dwHighDateTime = time_value.HighPart; pft->dwHighDateTime = time_value.HighPart;
} }
#endif #endif
void LocalFilesystem::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess) bool LocalFilesystem::Stat(VFSPath path, StatData& sfs)
{ {
std::string s = VFSPathToSystem(path); std::string s = VFSPathToSystem(path);
struct stat st; struct stat st;
if(stat(s.c_str(),&st) == 0) if(stat(s.c_str(),&st) == 0)
{ {
lastAccess = Date::DateTime((int64_t)st.st_atime);
lastWrite = Date::DateTime((int64_t)st.st_mtime); sfs.Device = (uint64_t)st.st_dev;
sfs.Inode = (uint64_t)st.st_ino;
sfs.Mode = (uint32_t)st.st_mode;
sfs.HardLinks = (uint64_t)st.st_nlink;
sfs.UserId = (uint32_t)st.st_uid;
sfs.GroupId = (uint32_t)st.st_gid;
sfs.DeviceId = (uint64_t)st.st_rdev;
sfs.Size = (uint64_t)st.st_size;
sfs.BlockSize = (uint64_t)st.st_blksize;
sfs.BlockCount = (uint64_t)st.st_blocks;
sfs.LastAccess = Date::DateTime((int64_t)st.st_atime);
sfs.LastModified = Date::DateTime((int64_t)st.st_mtime);
sfs.LastStatus = Date::DateTime((int64_t)st.st_ctime);
return true;
} }
return false;
} }
void LocalFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess) void LocalFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess)
{ {
std::string s = VFSPathToSystem(path); std::string s = VFSPathToSystem(path);
@@ -44,7 +62,7 @@ namespace Tesses::Framework::Filesystem
#if defined(_WIN32) #if defined(_WIN32)
FILETIME lastWriteF; FILETIME lastWriteF;
FILETIME lastAccessF; FILETIME lastAccessF;
TimetToFileTime((time_t)lastWrite.ToEpoch(),&lastWriteF); TimetToFileTime((time_t)lastWrite.ToEpoch(),&lastWriteF);
TimetToFileTime((time_t)lastAccess.ToEpoch(),&lastAccessF); TimetToFileTime((time_t)lastAccess.ToEpoch(),&lastAccessF);
HANDLE hFile = CreateFileA( HANDLE hFile = CreateFileA(
@@ -96,34 +114,6 @@ namespace Tesses::Framework::Filesystem
{ {
std::filesystem::create_directories(VFSPathToSystem(path)); std::filesystem::create_directories(VFSPathToSystem(path));
} }
bool LocalFilesystem::DirectoryExists(VFSPath path)
{
return std::filesystem::is_directory(VFSPathToSystem(path));
}
bool LocalFilesystem::RegularFileExists(VFSPath path)
{
return std::filesystem::is_regular_file(VFSPathToSystem(path));
}
bool LocalFilesystem::SymlinkExists(VFSPath path)
{
return std::filesystem::is_symlink(VFSPathToSystem(path));
}
bool LocalFilesystem::BlockDeviceExists(VFSPath path)
{
return std::filesystem::is_block_file(VFSPathToSystem(path));
}
bool LocalFilesystem::CharacterDeviceExists(VFSPath path)
{
return std::filesystem::is_character_file(VFSPathToSystem(path));
}
bool LocalFilesystem::SocketFileExists(VFSPath path)
{
return std::filesystem::is_socket(VFSPathToSystem(path));
}
bool LocalFilesystem::FIFOFileExists(VFSPath path)
{
return std::filesystem::is_fifo(VFSPathToSystem(path));
}
void LocalFilesystem::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile) void LocalFilesystem::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile)
{ {
if(std::filesystem::is_directory(VFSPathToSystem(existingFile))) if(std::filesystem::is_directory(VFSPathToSystem(existingFile)))
@@ -182,10 +172,13 @@ namespace Tesses::Framework::Filesystem
} }
return p; return p;
} }
VFSPathEnumerator LocalFilesystem::EnumeratePaths(VFSPath path) VFSPathEnumerator LocalFilesystem::EnumeratePaths(VFSPath path)
{ {
auto dir = new std::filesystem::directory_iterator(VFSPathToSystem(path)); std::filesystem::path sysPath = VFSPathToSystem(path);
if(!std::filesystem::is_directory(sysPath)) return VFSPathEnumerator();
auto dir = new std::filesystem::directory_iterator(sysPath);
return VFSPathEnumerator([dir,path](VFSPath& path0)->bool { return VFSPathEnumerator([dir,path](VFSPath& path0)->bool {
std::filesystem::directory_iterator& ittr = *dir; std::filesystem::directory_iterator& ittr = *dir;
if(ittr != std::filesystem::directory_iterator()) if(ittr != std::filesystem::directory_iterator())
@@ -236,8 +229,47 @@ namespace Tesses::Framework::Filesystem
chmod(pathStr.c_str(), (mode_t)mode); chmod(pathStr.c_str(), (mode_t)mode);
#endif #endif
} }
void LocalFilesystem::Chown(VFSPath path, uint32_t uid, uint32_t gid)
{
auto pathStr = this->VFSPathToSystem(path);
#if defined(_WIN32)
#else
chown(pathStr.c_str(), (uid_t)uid, (gid_t)gid);
#endif
}
FIFOCreationResult LocalFilesystem::CreateFIFO(VFSPath path, uint32_t mod)
{
auto pathStr = this->VFSPathToSystem(path);
#if defined(_WIN32)
return FIFOCreationResult::Unsupported;
#else
int res = mkfifo(pathStr.c_str(), (mode_t)mod);
if(res == 0) return FIFOCreationResult::Success;
else if(res == -1)
{
switch(res)
{
case EEXIST:
return FIFOCreationResult::Exists;
case ENOTSUP:
return FIFOCreationResult::Unsupported;
case EACCES:
return FIFOCreationResult::Denied;
case ENOSPC:
return FIFOCreationResult::OutOfInodes;
case EROFS:
return FIFOCreationResult::ReadOnlyFS;
}
}
return FIFOCreationResult::UnknownError;
#endif
}
void LocalFilesystem::Lock(VFSPath path) void LocalFilesystem::Lock(VFSPath path)
{ {
auto p2 = VFSPathToSystem(path); auto p2 = VFSPathToSystem(path);
@@ -275,7 +307,7 @@ namespace Tesses::Framework::Filesystem
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::MoveOld) != 0) ? IN_MOVED_FROM : 0; lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::MoveOld) != 0) ? IN_MOVED_FROM : 0;
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::MoveNew) != 0) ? IN_MOVED_TO : 0; lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::MoveNew) != 0) ? IN_MOVED_TO : 0;
lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::Opened) != 0) ? IN_OPEN : 0; lflags |= (((uint32_t)flags & (uint32_t)FSWatcherEventType::Opened) != 0) ? IN_OPEN : 0;
return lflags; return lflags;
} }
static FSWatcherEventType from_linux_mask(uint32_t lflags) static FSWatcherEventType from_linux_mask(uint32_t lflags)
@@ -293,7 +325,7 @@ namespace Tesses::Framework::Filesystem
flags |= ((lflags & IN_MOVED_FROM) != 0) ? (uint32_t)FSWatcherEventType::MoveOld : 0; flags |= ((lflags & IN_MOVED_FROM) != 0) ? (uint32_t)FSWatcherEventType::MoveOld : 0;
flags |= ((lflags & IN_MOVED_TO) != 0) ? (uint32_t)FSWatcherEventType::MoveNew : 0; flags |= ((lflags & IN_MOVED_TO) != 0) ? (uint32_t)FSWatcherEventType::MoveNew : 0;
flags |= ((lflags & IN_OPEN) != 0) ? (uint32_t)FSWatcherEventType::Opened : 0; flags |= ((lflags & IN_OPEN) != 0) ? (uint32_t)FSWatcherEventType::Opened : 0;
return (FSWatcherEventType)flags; return (FSWatcherEventType)flags;
} }
public: public:
@@ -303,7 +335,7 @@ namespace Tesses::Framework::Filesystem
} }
protected: protected:
void SetEnabledImpl(bool enabled) void SetEnabledImpl(bool enabled)
{ {
if(enabled) if(enabled)
@@ -325,7 +357,7 @@ namespace Tesses::Framework::Filesystem
__attribute__ ((aligned(__alignof__(struct inotify_event)))); __attribute__ ((aligned(__alignof__(struct inotify_event))));
const struct inotify_event *event; const struct inotify_event *event;
ssize_t size; ssize_t size;
bool fail=false; bool fail=false;
FSWatcherEvent evt; FSWatcherEvent evt;
@@ -397,12 +429,12 @@ namespace Tesses::Framework::Filesystem
close(fd); close(fd);
return; return;
} }
} }
} }
} }
} }
} }
close(fd); close(fd);
}); });
@@ -420,8 +452,8 @@ namespace Tesses::Framework::Filesystem
} }
}; };
#endif #endif
std::shared_ptr<FSWatcher> LocalFilesystem::CreateWatcher(std::shared_ptr<VFS> vfs, VFSPath path) std::shared_ptr<FSWatcher> LocalFilesystem::CreateWatcher(std::shared_ptr<VFS> vfs, VFSPath path)
{ {

View File

@@ -1,669 +0,0 @@
#include "TessesFramework/Filesystem/MemoryFilesystem.hpp"
#include <iostream>
namespace Tesses::Framework::Filesystem
{
MemoryFilesystemStream::MemoryFilesystemStream(std::shared_ptr<Tesses::Framework::Threading::Mutex> mtx, std::shared_ptr<MemoryFileData> data,bool canRead, bool canWrite, bool canSeek)
{
this->mtx = mtx;
this->data = data;
this->canRead = canRead;
this->canWrite = canWrite;
this->canSeek = canSeek;
this->pos=0;
}
size_t MemoryFilesystemStream::Read(uint8_t* buff, size_t sz)
{
if(!this->canRead) return 0;
if(this->pos >= this->data->file.size()) return 0;
size_t toRead = std::min(sz, (size_t)(this->data->file.size()-this->pos));
memcpy(buff, this->data->file.data() + this->pos, toRead);
this->pos += toRead;
return toRead;
}
size_t MemoryFilesystemStream::Write(const uint8_t* buff, size_t sz)
{
if(!this->canWrite) return 0;
if(this->canSeek)
{
if(this->pos > this->data->file.size())
{
this->data->file.resize(this->pos+sz);
}
this->data->file.insert(this->data->file.begin()+this->pos, buff, buff+sz);
this->pos+=sz;
}
else
{
this->data->file.insert(this->data->file.end(), buff, buff+sz);
}
return sz;
}
bool MemoryFilesystemStream::CanRead()
{
return canRead;
}
bool MemoryFilesystemStream::CanWrite()
{
return canWrite;
}
bool MemoryFilesystemStream::CanSeek()
{
return canSeek;
}
int64_t MemoryFilesystemStream::GetPosition()
{
if(!this->canSeek) return (int64_t)this->data->file.size();
return pos;
}
void MemoryFilesystemStream::Flush()
{
//its already flushed
}
void MemoryFilesystemStream::Seek(int64_t pos, Streams::SeekOrigin whence)
{
if(canSeek) return;
switch(whence)
{
case Streams::SeekOrigin::Begin:
this->pos = (size_t)pos;
break;
case Streams::SeekOrigin::Current:
this->pos += (size_t)pos;
break;
case Streams::SeekOrigin::End:
this->pos = (size_t)(this->data->file.size() + pos);
break;
}
}
MemoryFilesystemStream::~MemoryFilesystemStream()
{
mtx->Lock();
if(this->canWrite) this->data->canAccess=true;
this->data->readers--;
mtx->Unlock();
}
MemoryEntry* MemoryFilesystem::GetEntry(VFSPath path,bool followSymlink)
{
if(path.relative) return nullptr;
if(path.path.empty()) return &this->root;
auto entry = GetEntry(path.GetParent(),true);
if(entry == nullptr) return nullptr;
auto dir = dynamic_cast<MemoryDirectory*>(entry);
if(dir != nullptr)
{
for(auto item : dir->entries)
{
if(item->name == path.GetFileName())
{
auto link = dynamic_cast<MemorySymlink*>(item);
if(followSymlink && link != nullptr)
{
item = GetEntry(link->linkedTo,true);
}
return item;
}
}
}
return nullptr;
}
std::shared_ptr<Streams::Stream> MemoryFilesystem::OpenFile(VFSPath path, std::string mode)
{
bool canRead=false;
bool canWrite=false;
bool canSeek=true;
bool mustExist=false;
bool truncate=false;
if(mode.size() >= 1)
{
if(mode[0] == 'r')
{
canRead = true;
mustExist=true;
}
else if(mode[0] == 'w')
{
canWrite = true;
truncate=true;
}
else if(mode[0] == 'a')
{
canSeek = false;
canWrite = true;
}
}
if(((mode.size() >= 2 && mode[1] == '+') || (mode.size() >= 2 && mode[1] == 'b' && mode[2] == '+')))
{
canRead = true;
canWrite = true;
}
mtx->Lock();
if(mustExist)
{
auto file = GetEntry(path,true);
if(file == nullptr)
{
mtx->Unlock();
return nullptr;
}
auto f = dynamic_cast<MemoryFile*>(file);
if(f == nullptr)
{
mtx->Unlock();
return nullptr;
}
if(!f->data->canAccess)
{
mtx->Unlock();
return nullptr;
}
if(canWrite && f->data->readers > 0)
{
mtx->Unlock();
return nullptr;
}
f->data->readers++;
if(canWrite) f->data->canAccess=false;
mtx->Unlock();
return std::make_shared<MemoryFilesystemStream>(mtx,f->data,canRead,canWrite,canSeek);
}
else
{
auto file = dynamic_cast<MemoryFile*>(GetEntry(path,true));
if(file != nullptr)
{
if(!file->data->canAccess)
{
mtx->Unlock();
return nullptr;
}
if(file->data->readers > 0)
{
mtx->Unlock();
return nullptr;
}
file->data->canAccess=false;
file->data->readers++;
if(truncate) {file->data->file.clear(); file->data->lastWrite=Date::DateTime::NowUTC();}
mtx->Unlock();
return std::make_shared<MemoryFilesystemStream>(mtx,file->data,canRead,canWrite,canSeek);
}
auto dir = GetEntry(path.GetParent(),true);
if(dir == nullptr)
{
mtx->Unlock();
return nullptr;
}
auto myDir = dynamic_cast<MemoryDirectory*>(dir);
if(myDir == nullptr)
{
mtx->Unlock();
return nullptr;
}
MemoryFile* thefile=nullptr;
for(auto f : myDir->entries)
{
if(f->name == path.GetFileName())
{
auto symlink = dynamic_cast<MemorySymlink*>(f);
while(symlink != nullptr)
{
auto ent = GetEntry(symlink->name,false);
auto sym = dynamic_cast<MemorySymlink*>(f);
if(sym != nullptr)
symlink = sym;
else
{
auto myDir0 = dynamic_cast<MemoryDirectory*>(GetEntry(symlink->linkedTo.GetParent(),true));
if(myDir0 != nullptr)
{
for(auto f2 : myDir0->entries)
{
if(f2->name == symlink->linkedTo.GetFileName())
{
auto myFile = dynamic_cast<MemoryFile*>(f2);
if(myFile != nullptr)
{
thefile = myFile;
break;
}
else
{
mtx->Unlock();
return nullptr;
}
}
}
myDir = myDir0;
}
else
{
mtx->Unlock();
return nullptr;
}
break;
}
}
break;
}
}
if(thefile == nullptr)
{
MemoryFile* f = new MemoryFile();
f->name = path.GetFileName();
f->data = std::make_shared<MemoryFileData>();
f->data->canAccess=false;
f->data->readers++;
myDir->entries.push_back(f);
mtx->Unlock();
return std::make_shared<MemoryFilesystemStream>(mtx,f->data,canRead,canWrite,canSeek);
}
if(thefile != nullptr)
{
if(!thefile->data->canAccess)
{
mtx->Unlock();
return nullptr;
}
if(thefile->data->readers > 0)
{
mtx->Unlock();
return nullptr;
}
thefile->data->canAccess=false;
thefile->data->readers++;
if(truncate) {thefile->data->file.clear(); thefile->data->lastWrite=Date::DateTime::NowUTC();}
mtx->Unlock();
return std::make_shared<MemoryFilesystemStream>(mtx,thefile->data,canRead,canWrite,canSeek);
}
}
mtx->Unlock();
return nullptr;
}
void MemoryFilesystem::CreateDirectory(VFSPath path)
{
if(path.relative) return;
if(path.path.empty()) return;
mtx->Lock();
MemoryDirectory* dir=&root;
for(auto part : path.path)
{
bool have=false;
for(auto dirent : dir->entries)
{
if(dirent->name == part)
{
auto symlink = dynamic_cast<MemorySymlink*>(dirent);
if(symlink != nullptr)
{
dirent = GetEntry(symlink->linkedTo,true);
}
auto dirdirent = dynamic_cast<MemoryDirectory*>(dirent);
if(dirdirent != nullptr)
{
dir = dirdirent;
have=true;
break;
}
else
{
mtx->Unlock();
return;
}
}
}
if(!have)
{
MemoryDirectory* dir2 = new MemoryDirectory();
dir2->name = part;
dir2->lastWrite=Date::DateTime::NowUTC();
dir->entries.push_back(dir2);
dir->lastWrite=Date::DateTime::NowUTC();
dir=dir2;
}
}
mtx->Unlock();
}
void MemoryFilesystem::DeleteFile(VFSPath path)
{
if(path.relative || path.path.empty()) return;
mtx->Lock();
MemoryDirectory* dir=&root;
if(path.path.size() > 1)
{
dir = dynamic_cast<MemoryDirectory*>(GetEntry(path.GetParent(),true));
}
if(dir == nullptr)
{
mtx->Unlock();
return;
}
std::string fname = path.GetFileName();
for(auto index = dir->entries.begin(); index < dir->entries.end(); index++)
{
auto item = *index;
if(item->name == fname)
{
auto p = dynamic_cast<MemoryDirectory*>(item);
if(p == nullptr)
{
delete item;
dir->entries.erase(index);
dir->lastWrite=Date::DateTime::NowUTC();
}
break;
}
}
mtx->Unlock();
}
bool MemoryFilesystem::RegularFileExists(VFSPath path)
{
if(path.relative) return false;
if(path.path.empty()) return false;
mtx->Lock();
auto f = GetEntry(path,false);
mtx->Unlock();
return dynamic_cast<MemoryFile*>(f) != nullptr;
}
bool MemoryFilesystem::SymlinkExists(VFSPath path)
{
if(path.relative) return false;
if(path.path.empty()) return false;
mtx->Lock();
auto f = GetEntry(path,false);
mtx->Unlock();
return dynamic_cast<MemorySymlink*>(f) != nullptr;
}
bool MemoryFilesystem::DirectoryExists(VFSPath path)
{
if(path.relative) return false;
if(path.path.empty()) return true;
mtx->Lock();
auto f = GetEntry(path,false);
mtx->Unlock();
return dynamic_cast<MemoryDirectory*>(f) != nullptr;
}
void MemoryFilesystem::DeleteDirectory(VFSPath path)
{
if(path.relative || path.path.empty()) return;
mtx->Lock();
MemoryDirectory* dir=&root;
if(path.path.size() > 1)
{
dir = dynamic_cast<MemoryDirectory*>(GetEntry(path.GetParent(),true));
}
if(dir == nullptr)
{
mtx->Unlock();
return;
}
std::string fname = path.GetFileName();
for(auto index = dir->entries.begin(); index < dir->entries.end(); index++)
{
auto item = *index;
if(item->name == fname)
{
auto p = dynamic_cast<MemoryDirectory*>(item);
if(p != nullptr)
{
delete item;
dir->entries.erase(index);
dir->lastWrite=Date::DateTime::NowUTC();
}
break;
}
}
mtx->Unlock();
}
void MemoryFilesystem::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile)
{
if(existingFile.relative || symlinkFile.relative || symlinkFile.path.empty()) return;
mtx->Lock();
MemoryDirectory* dir=&root;
if(symlinkFile.path.size() > 1)
{
dir = dynamic_cast<MemoryDirectory*>(GetEntry(symlinkFile.GetParent(),true));
}
if(dir == nullptr)
{
mtx->Unlock();
return;
}
std::string fname = symlinkFile.GetFileName();
for(auto index = dir->entries.begin(); index < dir->entries.end(); index++)
{
auto item = *index;
if(item->name == fname)
{
auto p = dynamic_cast<MemorySymlink*>(item);
if(p != nullptr)
{
p->linkedTo = existingFile;
p->lastWrite = Date::DateTime::NowUTC();
}
mtx->Unlock();
return;
}
}
MemorySymlink* symlink = new MemorySymlink();
symlink->name = fname;
symlink->linkedTo = existingFile;
symlink->lastWrite = Date::DateTime::NowUTC();
dir->entries.push_back(symlink);
dir->lastWrite = Date::DateTime::NowUTC();
mtx->Unlock();
}
VFSPathEnumerator MemoryFilesystem::EnumeratePaths(VFSPath path)
{
std::pair<size_t,std::vector<std::string>>* paths=new std::pair<size_t,std::vector<std::string>>();
paths->first=0;
mtx->Lock();
auto dir = dynamic_cast<MemoryDirectory*>(GetEntry(path,true));
if(dir != nullptr)
{
for(auto item : dir->entries) paths->second.push_back(item->name);
}
mtx->Unlock();
return VFSPathEnumerator([paths,path](VFSPath& _path)->bool{
if(paths->first < paths->second.size())
{
_path = path / paths->second[paths->first++];
return true;
}
return false;
},[paths]()->void{
delete paths;
});
}
void MemoryFilesystem::CreateHardlink(VFSPath existingFile, VFSPath newName)
{
mtx->Lock();
auto existing = dynamic_cast<MemoryFile*>(GetEntry(existingFile,true));
if(existing == nullptr)
{
mtx->Unlock();
return;
}
MemoryDirectory* dir=&root;
if(newName.path.size() > 1)
{
dir = dynamic_cast<MemoryDirectory*>(GetEntry(newName.GetParent(),true));
}
if(dir == nullptr)
{
mtx->Unlock();
return;
}
std::string fname = newName.GetFileName();
for(auto index = dir->entries.begin(); index < dir->entries.end(); index++)
{
auto item = *index;
if(item->name == fname)
{
mtx->Unlock();
return;
}
}
MemoryFile* memFile = new MemoryFile();
memFile->name = fname;
memFile->data = existing->data;
dir->entries.push_back(memFile);
dir->lastWrite=Date::DateTime::NowUTC();
mtx->Unlock();
}
void MemoryFilesystem::MoveFile(VFSPath src, VFSPath dest)
{
DeleteFile(dest);
CreateHardlink(src,dest);
DeleteFile(src);
}
void MemoryFilesystem::MoveDirectory(VFSPath src, VFSPath dest)
{
CreateDirectory(dest);
for(auto ent : EnumeratePaths(src))
{
VFSPath destPath = dest / ent.GetFileName();
if(FileExists(ent)) MoveFile(ent,destPath);
if(DirectoryExists(ent)) MoveDirectory(ent,destPath);
}
DeleteDirectory(src);
}
VFSPath MemoryFilesystem::ReadLink(VFSPath p)
{
mtx->Lock();
VFSPath p2;
auto symlink = dynamic_cast<MemorySymlink*>(GetEntry(p,false));
if(symlink != nullptr)
{
p2 = symlink->linkedTo;
}
mtx->Unlock();
return p2;
}
std::string MemoryFilesystem::VFSPathToSystem(VFSPath path)
{
return path.ToString();
}
VFSPath MemoryFilesystem::SystemToVFSPath(std::string path)
{
return path;
}
void MemoryFilesystem::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess)
{
mtx->Lock();
auto node = GetEntry(path,false);
auto dir = dynamic_cast<MemoryDirectory*>(node);
auto file = dynamic_cast<MemoryFile*>(node);
auto sym = dynamic_cast<MemorySymlink*>(node);
if(dir != nullptr) lastWrite = dir->lastWrite;
if(file != nullptr) lastWrite = file->data->lastWrite;
if(sym != nullptr) lastWrite = sym->lastWrite;
mtx->Unlock();
lastAccess = lastWrite;
}
void MemoryFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess)
{
mtx->Lock();
auto node = GetEntry(path,false);
auto dir = dynamic_cast<MemoryDirectory*>(node);
auto file = dynamic_cast<MemoryFile*>(node);
auto sym = dynamic_cast<MemorySymlink*>(node);
if(dir != nullptr) dir->lastWrite = lastWrite;
if(file != nullptr) file->data->lastWrite = lastWrite;
if(sym != nullptr) sym->lastWrite = lastWrite;
mtx->Unlock();
}
MemoryFilesystem::~MemoryFilesystem()
{
}
MemoryFilesystem::MemoryFilesystem()
{
mtx = std::make_shared<Threading::Mutex>();
}
MemoryEntry::~MemoryEntry()
{
}
MemoryFile::~MemoryFile()
{
}
MemoryDirectory::MemoryDirectory()
{
this->lastWrite = Date::DateTime::NowUTC();
}
MemoryDirectory::~MemoryDirectory()
{
for(auto item : this->entries) delete item;
}
MemoryFileData::MemoryFileData()
{
this->lastWrite = Date::DateTime::NowUTC();
this->canAccess=true;
this->readers=0;
}
}

View File

@@ -24,7 +24,7 @@ namespace Tesses::Framework::Filesystem
void MountableFilesystem::GetFS(VFSPath srcPath, VFSPath& destRoot, VFSPath& destPath, std::shared_ptr<VFS>& vfs) void MountableFilesystem::GetFS(VFSPath srcPath, VFSPath& destRoot, VFSPath& destPath, std::shared_ptr<VFS>& vfs)
{ {
if(srcPath.path.empty()) return; if(srcPath.path.empty()) return;
for(auto item : this->directories) for(auto item : this->directories)
@@ -38,8 +38,8 @@ namespace Tesses::Framework::Filesystem
srcPath1.relative=false; srcPath1.relative=false;
destPath = srcPath1; destPath = srcPath1;
destRoot = VFSPath(VFSPath(),item->name); destRoot = VFSPath(VFSPath(),item->name);
} }
VFSPath srcPath2(std::vector(srcPath.path.begin()+1,srcPath.path.end())); VFSPath srcPath2(std::vector(srcPath.path.begin()+1,srcPath.path.end()));
srcPath2.relative=false; srcPath2.relative=false;
@@ -49,9 +49,9 @@ namespace Tesses::Framework::Filesystem
} }
} }
void MountableDirectory::GetFS(VFSPath srcPath, VFSPath curDir, VFSPath& destRoot, VFSPath& destPath, std::shared_ptr<VFS>& vfs) void MountableDirectory::GetFS(VFSPath srcPath, VFSPath curDir, VFSPath& destRoot, VFSPath& destPath, std::shared_ptr<VFS>& vfs)
{ {
if(srcPath.path.empty()) return; if(srcPath.path.empty()) return;
for(auto item : this->dirs) for(auto item : this->dirs)
@@ -61,13 +61,13 @@ namespace Tesses::Framework::Filesystem
if(item->vfs != nullptr) if(item->vfs != nullptr)
{ {
vfs = item->vfs; vfs = item->vfs;
VFSPath srcPath1(std::vector(srcPath.path.begin()+1,srcPath.path.end())); VFSPath srcPath1(std::vector(srcPath.path.begin()+1,srcPath.path.end()));
srcPath1.relative=false; srcPath1.relative=false;
destPath = srcPath1; destPath = srcPath1;
destRoot = curDir; destRoot = curDir;
} }
VFSPath srcPath2(std::vector(srcPath.path.begin()+1,srcPath.path.end())); VFSPath srcPath2(std::vector(srcPath.path.begin()+1,srcPath.path.end()));
srcPath2.relative=false; srcPath2.relative=false;
@@ -83,7 +83,7 @@ namespace Tesses::Framework::Filesystem
VFSPath destRoot; VFSPath destRoot;
VFSPath destPath = path; VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root; std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs); GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr) if(vfs != nullptr)
return VFSPath(destRoot,vfs->ReadLink(destPath)); return VFSPath(destRoot,vfs->ReadLink(destPath));
@@ -96,24 +96,65 @@ namespace Tesses::Framework::Filesystem
VFSPath destRoot; VFSPath destRoot;
VFSPath destPath = path; VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root; std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs); GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr) if(vfs != nullptr)
return vfs->StatVFS(destPath,data); return vfs->StatVFS(destPath,data);
return false; return false;
} }
bool MountableFilesystem::Stat(VFSPath path, StatData& data)
{
path = path.CollapseRelativeParents();
VFSPath destRoot;
VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr)
return vfs->Stat(destPath,data);
return false;
}
void MountableFilesystem::Chmod(VFSPath path, uint32_t mode) void MountableFilesystem::Chmod(VFSPath path, uint32_t mode)
{ {
path = path.CollapseRelativeParents(); path = path.CollapseRelativeParents();
VFSPath destRoot; VFSPath destRoot;
VFSPath destPath = path; VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root; std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs); GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr) if(vfs != nullptr)
vfs->Chmod(destPath,mode); vfs->Chmod(destPath,mode);
} }
void MountableFilesystem::Chown(VFSPath path, uint32_t uid, uint32_t gid)
{
path = path.CollapseRelativeParents();
VFSPath destRoot;
VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr)
vfs->Chown(destPath,uid, gid);
}
FIFOCreationResult MountableFilesystem::CreateFIFO(VFSPath path, uint32_t mod)
{
path = path.CollapseRelativeParents();
VFSPath destRoot;
VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr)
return vfs->CreateFIFO(destPath,mod);
return FIFOCreationResult::UnknownError;
}
std::shared_ptr<Tesses::Framework::Streams::Stream> MountableFilesystem::OpenFile(VFSPath path, std::string mode) std::shared_ptr<Tesses::Framework::Streams::Stream> MountableFilesystem::OpenFile(VFSPath path, std::string mode)
{ {
@@ -121,7 +162,7 @@ namespace Tesses::Framework::Filesystem
VFSPath destRoot; VFSPath destRoot;
VFSPath destPath = path; VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root; std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs); GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr) if(vfs != nullptr)
@@ -131,238 +172,92 @@ namespace Tesses::Framework::Filesystem
void MountableFilesystem::CreateDirectory(VFSPath path) void MountableFilesystem::CreateDirectory(VFSPath path)
{ {
path = path.CollapseRelativeParents(); path = path.CollapseRelativeParents();
VFSPath destRoot; VFSPath destRoot;
VFSPath destPath = path; VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root; std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs); GetFS(path, destRoot, destPath, vfs);
if(destPath.path.empty()) return; if(destPath.path.empty()) return;
if(vfs != nullptr) if(vfs != nullptr)
vfs->CreateDirectory(destPath); vfs->CreateDirectory(destPath);
} }
void MountableFilesystem::DeleteDirectory(VFSPath path) void MountableFilesystem::DeleteDirectory(VFSPath path)
{ {
path = path.CollapseRelativeParents(); path = path.CollapseRelativeParents();
VFSPath destRoot; VFSPath destRoot;
VFSPath destPath = path; VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root; std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs); GetFS(path, destRoot, destPath, vfs);
if(destPath.path.empty()) return; if(destPath.path.empty()) return;
if(vfs != nullptr) if(vfs != nullptr)
vfs->DeleteDirectory(destPath); vfs->DeleteDirectory(destPath);
}
bool MountableFilesystem::SpecialFileExists(VFSPath path)
{
path = path.CollapseRelativeParents();
VFSPath destRoot;
VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr)
return vfs->SpecialFileExists(destPath);
return false;
}
bool MountableFilesystem::FileExists(VFSPath path)
{
path = path.CollapseRelativeParents();
VFSPath destRoot;
VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr)
return vfs->FileExists(destPath);
return false;
}
bool MountableFilesystem::RegularFileExists(VFSPath path)
{
path = path.CollapseRelativeParents();
VFSPath destRoot;
VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr)
return vfs->RegularFileExists(destPath);
return false;
}
bool MountableFilesystem::SymlinkExists(VFSPath path)
{
path = path.CollapseRelativeParents();
VFSPath destRoot;
VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr)
return vfs->SymlinkExists(destPath);
return false;
}
bool MountableFilesystem::CharacterDeviceExists(VFSPath path)
{
path = path.CollapseRelativeParents();
VFSPath destRoot;
VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr)
return vfs->CharacterDeviceExists(destPath);
return false;
}
bool MountableFilesystem::BlockDeviceExists(VFSPath path)
{
path = path.CollapseRelativeParents();
VFSPath destRoot;
VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr)
return vfs->BlockDeviceExists(destPath);
return false;
}
bool MountableFilesystem::SocketFileExists(VFSPath path)
{
path = path.CollapseRelativeParents();
VFSPath destRoot;
VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr)
return vfs->SocketFileExists(destPath);
return false;
}
bool MountableFilesystem::FIFOFileExists(VFSPath path)
{
path = path.CollapseRelativeParents();
VFSPath destRoot;
VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr)
return vfs->FIFOFileExists(destPath);
return false;
} }
bool MountableFilesystem::DirectoryExists(VFSPath path)
{
path = path.CollapseRelativeParents();
VFSPath destRoot;
VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs);
if(destPath.path.empty()) return true;
if(vfs != nullptr)
return vfs->DirectoryExists(destPath);
return false;
}
void MountableFilesystem::DeleteFile(VFSPath path) void MountableFilesystem::DeleteFile(VFSPath path)
{ {
path = path.CollapseRelativeParents(); path = path.CollapseRelativeParents();
VFSPath destRoot; VFSPath destRoot;
VFSPath destPath = path; VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root; std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs); GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr) if(vfs != nullptr)
vfs->DeleteFile(destPath); vfs->DeleteFile(destPath);
} }
void MountableFilesystem::Lock(VFSPath path) void MountableFilesystem::Lock(VFSPath path)
{ {
path = path.CollapseRelativeParents(); path = path.CollapseRelativeParents();
VFSPath destRoot; VFSPath destRoot;
VFSPath destPath = path; VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root; std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs); GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr) if(vfs != nullptr)
vfs->Lock(destPath); vfs->Lock(destPath);
} }
void MountableFilesystem::Unlock(VFSPath path) void MountableFilesystem::Unlock(VFSPath path)
{ {
path = path.CollapseRelativeParents(); path = path.CollapseRelativeParents();
VFSPath destRoot; VFSPath destRoot;
VFSPath destPath = path; VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root; std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs); GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr) if(vfs != nullptr)
vfs->Unlock(destPath); vfs->Unlock(destPath);
}
void MountableFilesystem::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess)
{
path = path.CollapseRelativeParents();
VFSPath destRoot;
VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr)
vfs->GetDate(destPath,lastWrite,lastAccess);
} }
void MountableFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess) void MountableFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess)
{ {
path = path.CollapseRelativeParents(); path = path.CollapseRelativeParents();
VFSPath destRoot; VFSPath destRoot;
VFSPath destPath = path; VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root; std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs); GetFS(path, destRoot, destPath, vfs);
if(vfs != nullptr) if(vfs != nullptr)
@@ -372,17 +267,17 @@ namespace Tesses::Framework::Filesystem
{ {
existingFile = existingFile.CollapseRelativeParents(); existingFile = existingFile.CollapseRelativeParents();
symlinkFile = existingFile.CollapseRelativeParents(); symlinkFile = existingFile.CollapseRelativeParents();
VFSPath existingDestRoot; VFSPath existingDestRoot;
VFSPath existingDestPath = existingFile; VFSPath existingDestPath = existingFile;
std::shared_ptr<VFS> existingVFS = root; std::shared_ptr<VFS> existingVFS = root;
VFSPath symlinkDestRoot; VFSPath symlinkDestRoot;
VFSPath symlinkDestPath = symlinkFile; VFSPath symlinkDestPath = symlinkFile;
std::shared_ptr<VFS> symlinkVFS = root; std::shared_ptr<VFS> symlinkVFS = root;
GetFS(existingFile, existingDestRoot, existingDestPath, existingVFS); GetFS(existingFile, existingDestRoot, existingDestPath, existingVFS);
GetFS(symlinkFile, symlinkDestRoot, symlinkDestPath, symlinkVFS); GetFS(symlinkFile, symlinkDestRoot, symlinkDestPath, symlinkVFS);
if(existingVFS != nullptr && existingVFS == symlinkVFS) if(existingVFS != nullptr && existingVFS == symlinkVFS)
existingVFS->CreateSymlink(existingDestPath, symlinkDestPath); existingVFS->CreateSymlink(existingDestPath, symlinkDestPath);
} }
@@ -391,17 +286,17 @@ namespace Tesses::Framework::Filesystem
{ {
src = src.CollapseRelativeParents(); src = src.CollapseRelativeParents();
dest = dest.CollapseRelativeParents(); dest = dest.CollapseRelativeParents();
VFSPath srcDestRoot; VFSPath srcDestRoot;
VFSPath srcDestPath = src; VFSPath srcDestPath = src;
std::shared_ptr<VFS> srcVFS = root; std::shared_ptr<VFS> srcVFS = root;
VFSPath destDestRoot; VFSPath destDestRoot;
VFSPath destDestPath = dest; VFSPath destDestPath = dest;
std::shared_ptr<VFS> destVFS = root; std::shared_ptr<VFS> destVFS = root;
GetFS(src, srcDestRoot, srcDestPath, srcVFS); GetFS(src, srcDestRoot, srcDestPath, srcVFS);
GetFS(dest, destDestRoot, destDestPath, destVFS); GetFS(dest, destDestRoot, destDestPath, destVFS);
if(srcVFS != nullptr && srcVFS == destVFS) if(srcVFS != nullptr && srcVFS == destVFS)
srcVFS->MoveDirectory(srcDestPath, destDestPath); srcVFS->MoveDirectory(srcDestPath, destDestPath);
} }
@@ -409,17 +304,17 @@ namespace Tesses::Framework::Filesystem
{ {
src = src.CollapseRelativeParents(); src = src.CollapseRelativeParents();
dest = dest.CollapseRelativeParents(); dest = dest.CollapseRelativeParents();
VFSPath srcDestRoot; VFSPath srcDestRoot;
VFSPath srcDestPath = src; VFSPath srcDestPath = src;
std::shared_ptr<VFS> srcVFS = root; std::shared_ptr<VFS> srcVFS = root;
VFSPath destDestRoot; VFSPath destDestRoot;
VFSPath destDestPath = dest; VFSPath destDestPath = dest;
std::shared_ptr<VFS> destVFS = root; std::shared_ptr<VFS> destVFS = root;
GetFS(src, srcDestRoot, srcDestPath, srcVFS); GetFS(src, srcDestRoot, srcDestPath, srcVFS);
GetFS(dest, destDestRoot, destDestPath, destVFS); GetFS(dest, destDestRoot, destDestPath, destVFS);
if(srcVFS != nullptr && srcVFS == destVFS) if(srcVFS != nullptr && srcVFS == destVFS)
srcVFS->MoveFile(srcDestPath, destDestPath); srcVFS->MoveFile(srcDestPath, destDestPath);
} }
@@ -427,17 +322,17 @@ namespace Tesses::Framework::Filesystem
{ {
existingFile = existingFile.CollapseRelativeParents(); existingFile = existingFile.CollapseRelativeParents();
newName = existingFile.CollapseRelativeParents(); newName = existingFile.CollapseRelativeParents();
VFSPath existingDestRoot; VFSPath existingDestRoot;
VFSPath existingDestPath = existingFile; VFSPath existingDestPath = existingFile;
std::shared_ptr<VFS> existingVFS = root; std::shared_ptr<VFS> existingVFS = root;
VFSPath newNameRoot; VFSPath newNameRoot;
VFSPath newNamePath = newName; VFSPath newNamePath = newName;
std::shared_ptr<VFS> newNameVFS = root; std::shared_ptr<VFS> newNameVFS = root;
GetFS(existingFile, existingDestRoot, existingDestPath, existingVFS); GetFS(existingFile, existingDestRoot, existingDestPath, existingVFS);
GetFS(newName, newNameRoot, newNamePath, newNameVFS); GetFS(newName, newNameRoot, newNamePath, newNameVFS);
if(existingVFS != nullptr && existingVFS == newNameVFS) if(existingVFS != nullptr && existingVFS == newNameVFS)
existingVFS->CreateHardlink(existingDestPath, newNamePath); existingVFS->CreateHardlink(existingDestPath, newNamePath);
} }
@@ -449,17 +344,17 @@ namespace Tesses::Framework::Filesystem
}; };
VFSPathEnumerator MountableFilesystem::EnumeratePaths(VFSPath path) VFSPathEnumerator MountableFilesystem::EnumeratePaths(VFSPath path)
{ {
path = path.CollapseRelativeParents(); path = path.CollapseRelativeParents();
bool mydirs = path.path.empty(); bool mydirs = path.path.empty();
std::vector<MountableDirectory*>* dirs = &this->directories; std::vector<MountableDirectory*>* dirs = &this->directories;
if(!path.path.empty()) if(!path.path.empty())
for(auto p : path.path) for(auto p : path.path)
{ {
mydirs=true; mydirs=true;
bool hasSet=false; bool hasSet=false;
for(auto itm : *dirs) for(auto itm : *dirs)
{ {
if(itm->name == p) if(itm->name == p)
@@ -476,13 +371,13 @@ namespace Tesses::Framework::Filesystem
break; break;
} }
} }
VFSPath destRoot; VFSPath destRoot;
VFSPath destPath = path; VFSPath destPath = path;
std::shared_ptr<VFS> vfs = root; std::shared_ptr<VFS> vfs = root;
GetFS(path, destRoot, destPath, vfs); GetFS(path, destRoot, destPath, vfs);
MountableEnumerationState* state = new MountableEnumerationState(); MountableEnumerationState* state = new MountableEnumerationState();
state->dirs = *dirs; state->dirs = *dirs;
@@ -493,11 +388,11 @@ namespace Tesses::Framework::Filesystem
state->enumerator = nullptr; state->enumerator = nullptr;
return VFSPathEnumerator([state,path](VFSPath& path0)->bool{ return VFSPathEnumerator([state,path](VFSPath& path0)->bool{
while(state->enumerator != nullptr && state->enumerator->MoveNext()) while(state->enumerator != nullptr && state->enumerator->MoveNext())
{ {
auto fname = state->enumerator->Current.GetFileName(); auto fname = state->enumerator->Current.GetFileName();
bool mustContinue=false; bool mustContinue=false;
for(auto item : state->dirs) for(auto item : state->dirs)
{ {
@@ -527,11 +422,11 @@ namespace Tesses::Framework::Filesystem
delete state; delete state;
}); });
} }
void MountableFilesystem::Mount(VFSPath path, std::shared_ptr<VFS> fs) void MountableFilesystem::Mount(VFSPath path, std::shared_ptr<VFS> fs)
{ {
path = path.CollapseRelativeParents(); path = path.CollapseRelativeParents();
if(path.path.empty()) if(path.path.empty())
{ {
return; return;
@@ -557,12 +452,12 @@ namespace Tesses::Framework::Filesystem
dir->name = *index; dir->name = *index;
dir->owns=false; dir->owns=false;
dir->vfs=NULL; dir->vfs=NULL;
fsLs->push_back(dir); fsLs->push_back(dir);
fsLs = &(dir->dirs); fsLs = &(dir->dirs);
} }
} }
needToCreate=true; needToCreate=true;
std::string lastDir = path.GetFileName(); std::string lastDir = path.GetFileName();
@@ -571,7 +466,7 @@ namespace Tesses::Framework::Filesystem
if(item->name == lastDir) if(item->name == lastDir)
{ {
needToCreate=false; needToCreate=false;
item->vfs = fs; item->vfs = fs;
break; break;
} }
@@ -581,7 +476,7 @@ namespace Tesses::Framework::Filesystem
{ {
MountableDirectory* dir = new MountableDirectory(); MountableDirectory* dir = new MountableDirectory();
dir->name = lastDir; dir->name = lastDir;
dir->vfs=fs; dir->vfs=fs;
fsLs->push_back(dir); fsLs->push_back(dir);
} }
@@ -590,11 +485,11 @@ namespace Tesses::Framework::Filesystem
static bool myumount(MountableDirectory* dir,VFSPath path) static bool myumount(MountableDirectory* dir,VFSPath path)
{ {
if(path.path.empty()) if(path.path.empty())
{ {
dir->vfs = nullptr; dir->vfs = nullptr;
} }
if(dir->dirs.empty()) if(dir->dirs.empty())
{ {
delete dir; delete dir;
@@ -608,8 +503,8 @@ namespace Tesses::Framework::Filesystem
{ {
VFSPath srcPath2(std::vector(path.path.begin()+1,path.path.end())); VFSPath srcPath2(std::vector(path.path.begin()+1,path.path.end()));
if(myumount(item,srcPath2)) if(myumount(item,srcPath2))
{ {
dir->dirs.erase(index); dir->dirs.erase(index);
@@ -629,14 +524,14 @@ namespace Tesses::Framework::Filesystem
void MountableFilesystem::Unmount(VFSPath path) void MountableFilesystem::Unmount(VFSPath path)
{ {
path = path.CollapseRelativeParents(); path = path.CollapseRelativeParents();
for(auto index = this->directories.begin(); index < this->directories.end(); index++) for(auto index = this->directories.begin(); index < this->directories.end(); index++)
{ {
auto item = *index; auto item = *index;
if(!path.path.empty() && path.path.front() == item->name) if(!path.path.empty() && path.path.front() == item->name)
{ {
VFSPath srcPath2(std::vector(path.path.begin()+1,path.path.end())); VFSPath srcPath2(std::vector(path.path.begin()+1,path.path.end()));
if(myumount(item,srcPath2)) if(myumount(item,srcPath2))
{ {
this->directories.erase(index); this->directories.erase(index);
@@ -654,4 +549,4 @@ namespace Tesses::Framework::Filesystem
{ {
return VFSPath(path); return VFSPath(path);
} }
} }

View File

@@ -6,33 +6,11 @@ namespace Tesses::Framework::Filesystem
{ {
return nullptr; return nullptr;
} }
void NullFilesystem::CreateDirectory(VFSPath path)
{
}
void NullFilesystem::DeleteDirectory(VFSPath path)
{
}
bool NullFilesystem::RegularFileExists(VFSPath path)
{
return false;
}
bool NullFilesystem::DirectoryExists(VFSPath path)
{
return false;
}
void NullFilesystem::DeleteFile(VFSPath path)
{
}
VFSPathEnumerator NullFilesystem::EnumeratePaths(VFSPath path) VFSPathEnumerator NullFilesystem::EnumeratePaths(VFSPath path)
{ {
return VFSPathEnumerator(); return VFSPathEnumerator();
}
void NullFilesystem::MoveFile(VFSPath src, VFSPath dest)
{
} }
std::string NullFilesystem::VFSPathToSystem(VFSPath path) std::string NullFilesystem::VFSPathToSystem(VFSPath path)
{ {
@@ -42,4 +20,9 @@ namespace Tesses::Framework::Filesystem
{ {
return VFSPath(path); return VFSPath(path);
} }
}
bool NullFilesystem::Stat(VFSPath path, StatData& data)
{
return false;
}
}

View File

@@ -13,7 +13,7 @@ namespace Tesses::Framework::Filesystem
// /a/b/c // /a/b/c
VFSPath newPath; VFSPath newPath;
newPath.relative=false; newPath.relative=false;
if(path.path.size() >= this->path.path.size()) if(path.path.size() >= this->path.path.size())
{ {
newPath.path.reserve(path.path.size()-this->path.path.size()); newPath.path.reserve(path.path.size()-this->path.path.size());
@@ -41,7 +41,7 @@ namespace Tesses::Framework::Filesystem
} }
else else
this->path = path; this->path = path;
} }
std::shared_ptr<Tesses::Framework::Streams::Stream> SubdirFilesystem::OpenFile(VFSPath path, std::string mode) std::shared_ptr<Tesses::Framework::Streams::Stream> SubdirFilesystem::OpenFile(VFSPath path, std::string mode)
{ {
@@ -55,34 +55,6 @@ namespace Tesses::Framework::Filesystem
{ {
this->parent->DeleteDirectory(ToParent(path)); this->parent->DeleteDirectory(ToParent(path));
} }
bool SubdirFilesystem::RegularFileExists(VFSPath path)
{
return this->parent->RegularFileExists(ToParent(path));
}
bool SubdirFilesystem::SymlinkExists(VFSPath path)
{
return this->parent->SymlinkExists(ToParent(path));
}
bool SubdirFilesystem::CharacterDeviceExists(VFSPath path)
{
return this->parent->CharacterDeviceExists(ToParent(path));
}
bool SubdirFilesystem::BlockDeviceExists(VFSPath path)
{
return this->parent->BlockDeviceExists(ToParent(path));
}
bool SubdirFilesystem::SocketFileExists(VFSPath path)
{
return this->parent->SocketFileExists(ToParent(path));
}
bool SubdirFilesystem::FIFOFileExists(VFSPath path)
{
return this->parent->FIFOFileExists(ToParent(path));
}
bool SubdirFilesystem::DirectoryExists(VFSPath path)
{
return this->parent->DirectoryExists(ToParent(path));
}
void SubdirFilesystem::DeleteFile(VFSPath path) void SubdirFilesystem::DeleteFile(VFSPath path)
{ {
this->parent->DeleteFile(ToParent(path)); this->parent->DeleteFile(ToParent(path));
@@ -116,15 +88,12 @@ namespace Tesses::Framework::Filesystem
delete enumerator; delete enumerator;
}); });
} }
void SubdirFilesystem::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess)
{
this->parent->GetDate(ToParent(path),lastWrite,lastAccess);
}
void SubdirFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess) void SubdirFilesystem::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess)
{ {
this->parent->SetDate(ToParent(path),lastWrite,lastAccess); this->parent->SetDate(ToParent(path),lastWrite,lastAccess);
} }
void SubdirFilesystem::CreateHardlink(VFSPath existingFile, VFSPath newName) void SubdirFilesystem::CreateHardlink(VFSPath existingFile, VFSPath newName)
{ {
this->parent->CreateHardlink(ToParent(existingFile),ToParent(newName)); this->parent->CreateHardlink(ToParent(existingFile),ToParent(newName));
@@ -142,34 +111,39 @@ namespace Tesses::Framework::Filesystem
return this->parent->VFSPathToSystem(ToParent(path)); return this->parent->VFSPathToSystem(ToParent(path));
} }
VFSPath SubdirFilesystem::SystemToVFSPath(std::string path) VFSPath SubdirFilesystem::SystemToVFSPath(std::string path)
{ {
return FromParent(this->parent->SystemToVFSPath(path)); return FromParent(this->parent->SystemToVFSPath(path));
} }
void SubdirFilesystem::DeleteDirectoryRecurse(VFSPath path) void SubdirFilesystem::DeleteDirectoryRecurse(VFSPath path)
{ {
this->parent->DeleteDirectoryRecurse(ToParent(path)); this->parent->DeleteDirectoryRecurse(ToParent(path));
} }
bool SubdirFilesystem::SpecialFileExists(VFSPath path)
{
return this->parent->SpecialFileExists(ToParent(path));
}
bool SubdirFilesystem::FileExists(VFSPath path)
{
return this->parent->FileExists(ToParent(path));
}
SubdirFilesystem::~SubdirFilesystem() SubdirFilesystem::~SubdirFilesystem()
{ {
} }
bool SubdirFilesystem::StatVFS(VFSPath path, StatVFSData& vfsData) bool SubdirFilesystem::StatVFS(VFSPath path, StatVFSData& vfsData)
{ {
return this->parent->StatVFS(ToParent(path), vfsData); return this->parent->StatVFS(ToParent(path), vfsData);
} }
bool SubdirFilesystem::Stat(VFSPath path, StatData& data)
{
return this->parent->Stat(ToParent(path), data);
}
void SubdirFilesystem::Chmod(VFSPath path, uint32_t mode) void SubdirFilesystem::Chmod(VFSPath path, uint32_t mode)
{ {
return this->parent->Chmod(ToParent(path), mode); return this->parent->Chmod(ToParent(path), mode);
} }
void SubdirFilesystem::Chown(VFSPath path, uint32_t uid, uint32_t gid)
{
return this->parent->Chown(ToParent(path), uid, gid);
}
FIFOCreationResult SubdirFilesystem::CreateFIFO(VFSPath path, uint32_t mod)
{
return this->parent->CreateFIFO(path, mod);
}
} }

View File

@@ -7,12 +7,12 @@ namespace Tesses::Framework::Filesystem {
Tesses::Framework::Threading::Mutex umtx; Tesses::Framework::Threading::Mutex umtx;
int64_t uidx=0; int64_t uidx=0;
void UniqueString(std::string& text) void UniqueString(std::string& text)
{ {
umtx.Lock(); umtx.Lock();
text += std::to_string((int64_t)time(NULL)); text += std::to_string((int64_t)time(NULL));
text += "_"; text += "_";
text += std::to_string(uidx); text += std::to_string(uidx);
uidx++; uidx++;
umtx.Unlock(); umtx.Unlock();
@@ -54,56 +54,7 @@ namespace Tesses::Framework::Filesystem {
if(this->vfs == nullptr) return; if(this->vfs == nullptr) return;
this->vfs->DeleteDirectory(path); this->vfs->DeleteDirectory(path);
} }
bool TempFS::SpecialFileExists(VFSPath path)
{
if(this->vfs == nullptr) return false;
return this->vfs->SpecialFileExists(path);
}
bool TempFS::FileExists(VFSPath path)
{
if(this->vfs == nullptr) return false;
return this->vfs->FileExists(path);
}
bool TempFS::RegularFileExists(VFSPath path)
{
if(this->vfs == nullptr) return false;
return this->vfs->RegularFileExists(path);
}
bool TempFS::SymlinkExists(VFSPath path)
{
if(this->vfs == nullptr) return false;
return this->vfs->SymlinkExists(path);
}
bool TempFS::CharacterDeviceExists(VFSPath path)
{
if(this->vfs == nullptr) return false;
return this->vfs->CharacterDeviceExists(path);
}
bool TempFS::BlockDeviceExists(VFSPath path)
{
if(this->vfs == nullptr) return false;
return this->vfs->BlockDeviceExists(path);
}
bool TempFS::SocketFileExists(VFSPath path)
{
if(this->vfs == nullptr) return false;
return this->vfs->SocketFileExists(path);
}
bool TempFS::FIFOFileExists(VFSPath path)
{
if(this->vfs == nullptr) return false;
return this->vfs->FIFOFileExists(path);
}
bool TempFS::DirectoryExists(VFSPath path)
{
if(this->vfs == nullptr) return false;
return this->vfs->DirectoryExists(path);
}
void TempFS::DeleteFile(VFSPath path) void TempFS::DeleteFile(VFSPath path)
{ {
if(this->vfs == nullptr) return; if(this->vfs == nullptr) return;
@@ -126,7 +77,7 @@ namespace Tesses::Framework::Filesystem {
} }
VFSPathEnumerator TempFS::EnumeratePaths(VFSPath path) VFSPathEnumerator TempFS::EnumeratePaths(VFSPath path)
{ {
if(this->vfs == nullptr) return VFSPathEnumerator(); if(this->vfs == nullptr) return VFSPathEnumerator();
return this->vfs->EnumeratePaths(path); return this->vfs->EnumeratePaths(path);
@@ -172,13 +123,7 @@ namespace Tesses::Framework::Filesystem {
if(this->vfs == nullptr) return VFSPath(); if(this->vfs == nullptr) return VFSPath();
return this->vfs->SystemToVFSPath(path); return this->vfs->SystemToVFSPath(path);
} }
void TempFS::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess)
{
if(this->vfs == nullptr) return;
this->vfs->GetDate(path,lastWrite,lastAccess);
}
void TempFS::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess) void TempFS::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess)
{ {
@@ -187,10 +132,16 @@ namespace Tesses::Framework::Filesystem {
} }
bool TempFS::StatVFS(VFSPath path, StatVFSData& vfsData) bool TempFS::StatVFS(VFSPath path, StatVFSData& vfsData)
{ {
if(this->vfs == nullptr) return false; if(this->vfs == nullptr) return false;
return this->vfs->StatVFS(path, vfsData); return this->vfs->StatVFS(path, vfsData);
} }
bool TempFS::Stat(VFSPath path, StatData& data)
{
if(this->vfs == nullptr) return false;
return this->vfs->Stat(path, data);
}
void TempFS::Chmod(VFSPath path, uint32_t mode) void TempFS::Chmod(VFSPath path, uint32_t mode)
{ {
@@ -198,6 +149,17 @@ namespace Tesses::Framework::Filesystem {
if(this->vfs == nullptr) return; if(this->vfs == nullptr) return;
this->vfs->Chmod(path,mode); this->vfs->Chmod(path,mode);
} }
void TempFS::Chown(VFSPath path, uint32_t uid, uint32_t gid)
{
if(this->vfs == nullptr) return;
this->vfs->Chown(path,uid, gid);
}
FIFOCreationResult TempFS::CreateFIFO(VFSPath path, uint32_t mod)
{
if(this->vfs == nullptr) return FIFOCreationResult::UnknownError;
return this->vfs->CreateFIFO(path, mod);
}
void TempFS::Close() void TempFS::Close()
{ {
@@ -218,5 +180,5 @@ namespace Tesses::Framework::Filesystem {
this->parent->DeleteDirectoryRecurse(p); this->parent->DeleteDirectoryRecurse(p);
} }
} }

View File

@@ -1,6 +1,7 @@
#include "TessesFramework/Filesystem/VFS.hpp" #include "TessesFramework/Filesystem/VFS.hpp"
#include "TessesFramework/Http/HttpUtils.hpp" #include "TessesFramework/Http/HttpUtils.hpp"
#include "TessesFramework/Filesystem/LocalFS.hpp" #include "TessesFramework/Filesystem/LocalFS.hpp"
#include <TessesFramework/Filesystem/FSHelpers.hpp>
namespace Tesses::Framework::Filesystem namespace Tesses::Framework::Filesystem
{ {
VFSPathEnumeratorItterator::VFSPathEnumeratorItterator() VFSPathEnumeratorItterator::VFSPathEnumeratorItterator()
@@ -21,12 +22,12 @@ namespace Tesses::Framework::Filesystem
enumerator->MoveNext(); enumerator->MoveNext();
return *this; return *this;
} }
VFSPath& VFSPathEnumeratorItterator::operator*() VFSPath& VFSPathEnumeratorItterator::operator*()
{ {
std::filesystem::directory_iterator i; std::filesystem::directory_iterator i;
if(enumerator != nullptr) if(enumerator != nullptr)
return enumerator->Current; return enumerator->Current;
return this->e; return this->e;
@@ -46,7 +47,7 @@ namespace Tesses::Framework::Filesystem
if(right.enumerator == nullptr) if(right.enumerator == nullptr)
{ {
auto r = !enumerator->IsDone(); auto r = !enumerator->IsDone();
return r; return r;
} }
return true; return true;
@@ -88,7 +89,7 @@ namespace Tesses::Framework::Filesystem
} }
bool VFSPathEnumerator::IsDone() bool VFSPathEnumerator::IsDone()
{ {
if(this->data) if(this->data)
{ {
return data->eof; return data->eof;
@@ -132,7 +133,7 @@ namespace Tesses::Framework::Filesystem
{ {
mid.append(p.path.back()); mid.append(p.path.back());
} }
if(!p2.path.empty()) if(!p2.path.empty())
{ {
mid.append(p2.path.front()); mid.append(p2.path.front());
@@ -169,7 +170,7 @@ namespace Tesses::Framework::Filesystem
for(size_t i = 0; i < p.path.size(); i++) for(size_t i = 0; i < p.path.size(); i++)
if(p.path[i] != p2.path[i]) return true; if(p.path[i] != p2.path[i]) return true;
return false; return false;
} }
bool operator==(std::string p,VFSPath p2) bool operator==(std::string p,VFSPath p2)
{ {
@@ -216,13 +217,98 @@ namespace Tesses::Framework::Filesystem
{ {
return MakeRelative(GetAbsoluteCurrentDirectory()); return MakeRelative(GetAbsoluteCurrentDirectory());
} }
FIFOCreationResult VFS::CreateFIFO(VFSPath path, uint32_t mode)
{
return FIFOCreationResult::Unsupported;
}
bool VFS::DirectoryExists(VFSPath path)
{
StatData data;
if(this->Stat(path, data))
{
return data.IsDirectory();
}
return false;
}
bool VFS::RegularFileExists(VFSPath path)
{
StatData data;
if(this->Stat(path, data))
{
return data.IsRegularFile();
}
return false;
}
bool VFS::SymlinkExists(VFSPath path)
{
StatData data;
if(this->Stat(path, data))
{
return data.IsSymlink();
}
return false;
}
bool VFS::CharacterDeviceExists(VFSPath path)
{
StatData data;
if(this->Stat(path, data))
{
return data.IsCharDevice();
}
return false;
}
bool VFS::BlockDeviceExists(VFSPath path)
{
StatData data;
if(this->Stat(path, data))
{
return data.IsBlockDevice();
}
return false;
}
bool VFS::SocketFileExists(VFSPath path)
{
StatData data;
if(this->Stat(path, data))
{
return data.IsSocket();
}
return false;
}
bool VFS::FIFOFileExists(VFSPath path)
{
StatData data;
if(this->Stat(path, data))
{
return data.IsFIFO();
}
return false;
}
bool VFS::FileExists(VFSPath path)
{
StatData data;
if(this->Stat(path, data))
{
return !data.IsDirectory();
}
return false;
}
bool VFS::SpecialFileExists(VFSPath path)
{
StatData data;
if(this->Stat(path, data))
{
return data.IsSpecial();
}
return false;
}
VFSPath VFSPath::MakeRelative(VFSPath toMakeRelativeTo) const VFSPath VFSPath::MakeRelative(VFSPath toMakeRelativeTo) const
{ {
if(this->relative) return *this; if(this->relative) return *this;
size_t i; size_t i;
size_t len = std::min(toMakeRelativeTo.path.size(),this->path.size()); size_t len = std::min(toMakeRelativeTo.path.size(),this->path.size());
for(i = 0; i < len; i++) for(i = 0; i < len; i++)
@@ -239,7 +325,7 @@ namespace Tesses::Framework::Filesystem
} }
std::vector<std::string> parts(this->path.begin()+i, this->path.end()); std::vector<std::string> parts(this->path.begin()+i, this->path.end());
if(i < toMakeRelativeTo.path.size()) if(i < toMakeRelativeTo.path.size())
{ {
for(; i < toMakeRelativeTo.path.size();i++) for(; i < toMakeRelativeTo.path.size();i++)
@@ -264,7 +350,7 @@ namespace Tesses::Framework::Filesystem
parts.erase(parts.end()-1); parts.erase(parts.end()-1);
} }
} }
else if(item == ".") else if(item == ".")
{ {
//do nothing but don't emit this //do nothing but don't emit this
} }
@@ -284,7 +370,7 @@ namespace Tesses::Framework::Filesystem
path.relative=true; path.relative=true;
return path; return path;
} }
std::vector<std::string> VFSPath::SplitPath(std::string path) std::vector<std::string> VFSPath::SplitPath(std::string path)
{ {
std::vector<std::string> parts; std::vector<std::string> parts;
@@ -386,7 +472,7 @@ namespace Tesses::Framework::Filesystem
str = str.substr(0,index); str = str.substr(0,index);
} }
if(ext.empty()) return; if(ext.empty()) return;
if(ext[0] != '.') if(ext[0] != '.')
{ {
str += '.'; str += '.';
str += ext; str += ext;
@@ -400,7 +486,7 @@ namespace Tesses::Framework::Filesystem
{ {
ChangeExtension({}); ChangeExtension({});
} }
VFSPath::VFSPath(std::string str) VFSPath::VFSPath(std::string str)
{ {
this->path = SplitPath(str); this->path = SplitPath(str);
@@ -418,13 +504,21 @@ namespace Tesses::Framework::Filesystem
if(!firstPartPath.empty() && firstPartPath.back() == ':') this->relative=false; if(!firstPartPath.empty() && firstPartPath.back() == ':') this->relative=false;
} }
} }
}
void VFS::CreateDirectory(VFSPath path)
{
}
void VFS::DeleteDirectory(VFSPath path)
{
} }
VFSPath::VFSPath(VFSPath p1, VFSPath p2) VFSPath::VFSPath(VFSPath p1, VFSPath p2)
{ {
this->relative = p1.relative; this->relative = p1.relative;
this->path.insert(this->path.end(),p1.path.begin(),p1.path.end()); this->path.insert(this->path.end(),p1.path.begin(),p1.path.end());
this->path.insert(this->path.end(),p2.path.begin(),p2.path.end()); this->path.insert(this->path.end(),p2.path.begin(),p2.path.end());
} }
VFSPath::VFSPath(VFSPath p1, std::string subpath) : VFSPath(p1, VFSPath(subpath)) VFSPath::VFSPath(VFSPath p1, std::string subpath) : VFSPath(p1, VFSPath(subpath))
{ {
@@ -462,20 +556,30 @@ namespace Tesses::Framework::Filesystem
} }
return p; return p;
} }
void VFS::DeleteFile(VFSPath path)
{
}
void VFS::MoveFile(VFSPath src, VFSPath dest)
{
{
auto srcStrm = this->OpenFile(src, "rb");
if(!srcStrm->CanRead()) return;
auto destStrm = this->OpenFile(dest, "wb");
if(!destStrm->CanWrite()) return;
srcStrm->CopyTo(destStrm);
}
VFS::DeleteFile(src);
}
VFS::~VFS() VFS::~VFS()
{ {
} }
bool VFS::FIFOFileExists(VFSPath path) {return false;}
bool VFS::SocketFileExists(VFSPath path) {return false;}
bool VFS::CharacterDeviceExists(VFSPath path) {return false;}
bool VFS::BlockDeviceExists(VFSPath path) {return false;}
bool VFS::SymlinkExists(VFSPath path) {return false;}
void VFS::MoveDirectory(VFSPath src, VFSPath dest) void VFS::MoveDirectory(VFSPath src, VFSPath dest)
{ {
for(auto item : EnumeratePaths(src)) for(auto item : EnumeratePaths(src))
{ {
if(DirectoryExists(item)) if(DirectoryExists(item))
@@ -488,7 +592,7 @@ namespace Tesses::Framework::Filesystem
} }
} }
DeleteDirectory(src); DeleteDirectory(src);
} }
void VFS::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile) void VFS::CreateSymlink(VFSPath existingFile, VFSPath symlinkFile)
{ {
@@ -496,22 +600,14 @@ namespace Tesses::Framework::Filesystem
} }
void VFS::CreateHardlink(VFSPath existingFile, VFSPath newName) void VFS::CreateHardlink(VFSPath existingFile, VFSPath newName)
{ {
}
bool VFS::SpecialFileExists(VFSPath path)
{
return SymlinkExists(path) || BlockDeviceExists(path) || CharacterDeviceExists(path) || SocketFileExists(path) || FIFOFileExists(path);
}
bool VFS::FileExists(VFSPath path)
{
return RegularFileExists(path) || SpecialFileExists(path);
} }
void VFS::DeleteDirectoryRecurse(VFSPath path) void VFS::DeleteDirectoryRecurse(VFSPath path)
{ {
if(!DirectoryExists(path)) return; if(!DirectoryExists(path)) return;
for(auto item : EnumeratePaths(path)) for(auto item : EnumeratePaths(path))
{ {
if(DirectoryExists(item)) if(DirectoryExists(item))
@@ -527,7 +623,12 @@ namespace Tesses::Framework::Filesystem
} }
void VFS::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess) void VFS::GetDate(VFSPath path, Date::DateTime& lastWrite, Date::DateTime& lastAccess)
{ {
StatData data;
if(Stat(path, data))
{
lastWrite = data.LastModified;
lastAccess = data.LastAccess;
}
} }
void VFS::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess) void VFS::SetDate(VFSPath path, Date::DateTime lastWrite, Date::DateTime lastAccess)
{ {
@@ -550,9 +651,12 @@ namespace Tesses::Framework::Filesystem
} }
void VFS::Chmod(VFSPath path, uint32_t mode) { void VFS::Chmod(VFSPath path, uint32_t mode) {
}
void VFS::Chown(VFSPath path, uint32_t uid, uint32_t gid) {
} }
void VFS::Close() { void VFS::Close() {
} }
void VFS::Lock(VFSPath path) void VFS::Lock(VFSPath path)
{ {
@@ -560,7 +664,7 @@ namespace Tesses::Framework::Filesystem
} }
void VFS::Unlock(VFSPath path) void VFS::Unlock(VFSPath path)
{ {
} }
@@ -599,7 +703,7 @@ namespace Tesses::Framework::Filesystem
{ {
} }
std::shared_ptr<FSWatcher> FSWatcher::Create(std::shared_ptr<VFS> vfs, VFSPath path) std::shared_ptr<FSWatcher> FSWatcher::Create(std::shared_ptr<VFS> vfs, VFSPath path)
{ {
return vfs->CreateWatcher(vfs,path); return vfs->CreateWatcher(vfs,path);
@@ -671,4 +775,4 @@ namespace Tesses::Framework::Filesystem
return ""; return "";
} }
} }

View File

@@ -24,7 +24,7 @@ namespace Tesses::Framework::Http
} }
FileServer::FileServer(std::shared_ptr<Tesses::Framework::Filesystem::VFS> fs, bool allowListing,bool spa) : FileServer(fs,allowListing,spa,{"index.html","default.html","index.htm","default.htm"}) FileServer::FileServer(std::shared_ptr<Tesses::Framework::Filesystem::VFS> fs, bool allowListing,bool spa) : FileServer(fs,allowListing,spa,{"index.html","default.html","index.htm","default.htm"})
{ {
} }
FileServer::FileServer(std::shared_ptr<Tesses::Framework::Filesystem::VFS> fs, bool allowListing, bool spa, std::vector<std::string> defaultNames) FileServer::FileServer(std::shared_ptr<Tesses::Framework::Filesystem::VFS> fs, bool allowListing, bool spa, std::vector<std::string> defaultNames)
{ {
@@ -44,7 +44,7 @@ namespace Tesses::Framework::Http
this->vfs->GetDate(path,lw,la); this->vfs->GetDate(path,lw,la);
ctx.WithLastModified(lw).WithMimeType(HttpUtils::MimeType(path.GetFileName())).SendStream(strm); ctx.WithLastModified(lw).WithMimeType(HttpUtils::MimeType(path.GetFileName())).SendStream(strm);
retVal = true; retVal = true;
} }
return retVal; return retVal;
} }
@@ -52,8 +52,8 @@ namespace Tesses::Framework::Http
bool FileServer::Handle(ServerContext& ctx) bool FileServer::Handle(ServerContext& ctx)
{ {
auto path = ((VFSPath)HttpUtils::UrlPathDecode(ctx.path)).CollapseRelativeParents(); auto path = ((VFSPath)HttpUtils::UrlPathDecode(ctx.path)).CollapseRelativeParents();
if(this->vfs->DirectoryExists(path)) if(this->vfs->DirectoryExists(path))
{ {
TF_LOG("Directory exists"); TF_LOG("Directory exists");
@@ -73,10 +73,10 @@ namespace Tesses::Framework::Http
std::string p = HttpUtils::HtmlEncode(ctx.originalPath); std::string p = HttpUtils::HtmlEncode(ctx.originalPath);
std::string html = "<!DOCTYPE html><html><head><meta charset=\"UTF-8\"><title>Index of "; std::string html = "<!DOCTYPE html><html><head><meta charset=\"UTF-8\"><title>Index of ";
html.append(p); html.append(p);
html.append("</title></head><body><h1>Index of "); html.append("</title><meta name=\"color-scheme\" content=\"dark light\"></head><body><h1>Index of ");
html.append(p); html.append(p);
html.append("</h1><hr><pre><a href=\"../\">../</a>\r\n"); html.append("</h1><hr><pre><a href=\"../\">../</a>\r\n");
for(auto item : vfs->EnumeratePaths(path)) for(auto item : vfs->EnumeratePaths(path))
{ {
@@ -103,7 +103,7 @@ namespace Tesses::Framework::Http
} }
html.append("</pre><hr></body></html>"); html.append("</pre><hr></body></html>");
ctx.WithMimeType("text/html").SendText(html); ctx.WithMimeType("text/html").SendText(html);
return true; return true;
} }
@@ -126,6 +126,6 @@ namespace Tesses::Framework::Http
} }
FileServer::~FileServer() FileServer::~FileServer()
{ {
} }
} }

View File

@@ -13,6 +13,7 @@
#include "TessesFramework/Filesystem/VFSFix.hpp" #include "TessesFramework/Filesystem/VFSFix.hpp"
#include "TessesFramework/Filesystem/VFS.hpp" #include "TessesFramework/Filesystem/VFS.hpp"
#include <TessesFramework/Http/HttpUtils.hpp>
#include <iostream> #include <iostream>
using FileStream = Tesses::Framework::Streams::FileStream; using FileStream = Tesses::Framework::Streams::FileStream;
using Stream = Tesses::Framework::Streams::Stream; using Stream = Tesses::Framework::Streams::Stream;
@@ -26,7 +27,7 @@ using namespace Tesses::Framework::TextStreams;
namespace Tesses::Framework::Http namespace Tesses::Framework::Http
{ {
class WSServer class WSServer
{ {
public: public:
Threading::Mutex mtx; Threading::Mutex mtx;
@@ -43,9 +44,9 @@ namespace Tesses::Framework::Http
uint8_t firstByte= finField | 0x8; uint8_t firstByte= finField | 0x8;
strm->WriteByte(firstByte); strm->WriteByte(firstByte);
strm->WriteByte(0); strm->WriteByte(0);
this->strm = nullptr; this->strm = nullptr;
mtx.Unlock(); mtx.Unlock();
this->conn->OnClose(true); this->conn->OnClose(true);
} }
void write_len_bytes(uint64_t len) void write_len_bytes(uint64_t len)
@@ -84,7 +85,7 @@ namespace Tesses::Framework::Http
{ {
uint8_t buff[8]; uint8_t buff[8];
if(strm->ReadBlock(buff,sizeof(buff)) != sizeof(buff)) return 0; if(strm->ReadBlock(buff,sizeof(buff)) != sizeof(buff)) return 0;
uint64_t v = 0; uint64_t v = 0;
v |= (uint64_t)buff[0] << 56; v |= (uint64_t)buff[0] << 56;
v |= (uint64_t)buff[1] << 48; v |= (uint64_t)buff[1] << 48;
@@ -100,7 +101,7 @@ namespace Tesses::Framework::Http
{ {
uint8_t buff[2]; uint8_t buff[2];
if(strm->ReadBlock(buff,sizeof(buff)) != sizeof(buff)) return 0; if(strm->ReadBlock(buff,sizeof(buff)) != sizeof(buff)) return 0;
uint16_t v = 0; uint16_t v = 0;
v |= (uint16_t)buff[0] << 8; v |= (uint16_t)buff[0] << 8;
v |= (uint16_t)buff[1]; v |= (uint16_t)buff[1];
@@ -110,7 +111,7 @@ namespace Tesses::Framework::Http
{ {
while(!hasInit); while(!hasInit);
mtx.Lock(); mtx.Lock();
uint8_t opcode = msg->isBinary ? 0x2 : 0x1; uint8_t opcode = msg->isBinary ? 0x2 : 0x1;
size_t lengthLastByte = msg->data.size() % 4096; size_t lengthLastByte = msg->data.size() % 4096;
@@ -123,21 +124,21 @@ namespace Tesses::Framework::Http
uint8_t finField = fin ? 0b10000000 : 0; uint8_t finField = fin ? 0b10000000 : 0;
uint8_t opcode2 = i == 0 ? opcode : 0; uint8_t opcode2 = i == 0 ? opcode : 0;
uint8_t firstByte = finField | (opcode2 & 0xF); uint8_t firstByte = finField | (opcode2 & 0xF);
size_t len = std::min((size_t)4096,msg->data.size()- offset); size_t len = std::min((size_t)4096,msg->data.size()- offset);
strm->WriteByte(firstByte); strm->WriteByte(firstByte);
write_len_bytes((uint64_t)len); write_len_bytes((uint64_t)len);
strm->WriteBlock(msg->data.data() + offset,len); strm->WriteBlock(msg->data.data() + offset,len);
offset += len; offset += len;
} }
mtx.Unlock(); mtx.Unlock();
} }
void ping_send(std::vector<uint8_t>& pData) void ping_send(std::vector<uint8_t>& pData)
{ {
mtx.Lock(); mtx.Lock();
uint8_t finField = 0b10000000 ; uint8_t finField = 0b10000000 ;
uint8_t firstByte= finField | 0x9; uint8_t firstByte= finField | 0x9;
strm->WriteByte(firstByte); strm->WriteByte(firstByte);
@@ -148,7 +149,7 @@ namespace Tesses::Framework::Http
void pong_send(std::vector<uint8_t>& pData) void pong_send(std::vector<uint8_t>& pData)
{ {
mtx.Lock(); mtx.Lock();
uint8_t finField = 0b10000000 ; uint8_t finField = 0b10000000 ;
uint8_t firstByte= finField | 0xA; uint8_t firstByte= finField | 0xA;
strm->WriteByte(firstByte); strm->WriteByte(firstByte);
@@ -158,7 +159,7 @@ namespace Tesses::Framework::Http
} }
bool read_packet(uint8_t len,std::vector<uint8_t>& data) bool read_packet(uint8_t len,std::vector<uint8_t>& data)
{ {
uint8_t realLen=len & 127; uint8_t realLen=len & 127;
bool masked=(len & 0b10000000) > 0; bool masked=(len & 0b10000000) > 0;
uint64_t reallen2 = realLen >= 126 ? realLen > 126 ? get_long() : get_short() : realLen; uint64_t reallen2 = realLen >= 126 ? realLen > 126 ? get_long() : get_short() : realLen;
@@ -180,7 +181,7 @@ namespace Tesses::Framework::Http
} }
return true; return true;
} }
WSServer(ServerContext* ctx,std::shared_ptr<WebSocketConnection> conn) WSServer(ServerContext* ctx,std::shared_ptr<WebSocketConnection> conn)
{ {
this->ctx = ctx; this->ctx = ctx;
@@ -188,7 +189,7 @@ namespace Tesses::Framework::Http
this->strm = this->ctx->GetStream(); this->strm = this->ctx->GetStream();
this->hasInit=false; this->hasInit=false;
} }
void Start() void Start()
{ {
@@ -198,7 +199,7 @@ namespace Tesses::Framework::Http
{ {
key.append("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); key.append("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
auto res = Crypto::Sha1::ComputeHash((const uint8_t*)key.c_str(),key.size()); auto res = Crypto::Sha1::ComputeHash((const uint8_t*)key.c_str(),key.size());
if(res.empty()) return; if(res.empty()) return;
key = Crypto::Base64_Encode(res); key = Crypto::Base64_Encode(res);
@@ -206,7 +207,7 @@ namespace Tesses::Framework::Http
return; return;
} }
if(!ctx->requestHeaders.AnyEquals("Upgrade","websocket")) if(!ctx->requestHeaders.AnyEquals("Upgrade","websocket"))
{ {
@@ -221,7 +222,7 @@ namespace Tesses::Framework::Http
ctx->responseHeaders.SetValue("Connection","Upgrade"); ctx->responseHeaders.SetValue("Connection","Upgrade");
ctx->responseHeaders.SetValue("Upgrade","websocket"); ctx->responseHeaders.SetValue("Upgrade","websocket");
ctx->responseHeaders.SetValue("Sec-WebSocket-Accept",key); ctx->responseHeaders.SetValue("Sec-WebSocket-Accept",key);
ctx->WriteHeaders(); ctx->WriteHeaders();
bool hasMessage =false; bool hasMessage =false;
@@ -232,11 +233,11 @@ namespace Tesses::Framework::Http
while( !strm->EndOfStream()) while( !strm->EndOfStream())
{ {
uint8_t frame_start[2]; uint8_t frame_start[2];
if( strm->ReadBlock(frame_start,2) != 2) return; if( strm->ReadBlock(frame_start,2) != 2) return;
uint8_t opcode = frame_start[0] & 0xF; uint8_t opcode = frame_start[0] & 0xF;
bool fin = (frame_start[0] & 0b10000000) > 0; bool fin = (frame_start[0] & 0b10000000) > 0;
switch(opcode) switch(opcode)
@@ -250,7 +251,7 @@ namespace Tesses::Framework::Http
hasMessage=true; hasMessage=true;
message.data = {}; message.data = {};
message.isBinary = opcode == 0x2; message.isBinary = opcode == 0x2;
read_packet(frame_start[1], message.data); read_packet(frame_start[1], message.data);
break; break;
case 0x8: case 0x8:
@@ -280,7 +281,7 @@ namespace Tesses::Framework::Http
} }
this->conn->OnClose(false); this->conn->OnClose(false);
} }
}; };
/* /*
static int _header_field(multipart_parser* p, const char *at, size_t length) static int _header_field(multipart_parser* p, const char *at, size_t length)
{ {
@@ -362,7 +363,7 @@ namespace Tesses::Framework::Http
strm2->CopyTo(strm); strm2->CopyTo(strm);
} }
} }
std::string ServerContext::ReadString() std::string ServerContext::ReadString()
{ {
if(strm == nullptr) return {}; if(strm == nullptr) return {};
@@ -390,7 +391,7 @@ namespace Tesses::Framework::Http
{ {
bool hasMore=true; bool hasMore=true;
uint8_t* checkBuffer = new uint8_t[boundary.size()]; uint8_t* checkBuffer = new uint8_t[boundary.size()];
int b; int b;
size_t i = 0; size_t i = 0;
size_t i2 = 0; size_t i2 = 0;
@@ -429,21 +430,21 @@ namespace Tesses::Framework::Http
{ {
dest->Write(buffer, sizeof(buffer)); dest->Write(buffer, sizeof(buffer));
offsetInMem=0; offsetInMem=0;
} }
buffer[offsetInMem++] = checkBuffer[idx]; buffer[offsetInMem++] = checkBuffer[idx];
idx++; idx++;
} }
i = 0; i = 0;
if(offsetInMem >= sizeof(buffer)) if(offsetInMem >= sizeof(buffer))
{ {
dest->Write(buffer, sizeof(buffer)); dest->Write(buffer, sizeof(buffer));
offsetInMem=0; offsetInMem=0;
} }
buffer[offsetInMem++] = (uint8_t)b; buffer[offsetInMem++] = (uint8_t)b;
@@ -455,7 +456,7 @@ namespace Tesses::Framework::Http
dest->Write(buffer,offsetInMem); dest->Write(buffer,offsetInMem);
} }
delete[] checkBuffer; delete[] checkBuffer;
return hasMore; return hasMore;
} }
@@ -466,7 +467,7 @@ namespace Tesses::Framework::Http
std::string line; std::string line;
while(reader.ReadLineHttp(line)) while(reader.ReadLineHttp(line))
{ {
auto v = HttpUtils::SplitString(line,": ", 2); auto v = HttpUtils::SplitString(line,": ", 2);
if(v.size() == 2) if(v.size() == 2)
req.AddValue(v[0],v[1]); req.AddValue(v[0],v[1]);
line.clear(); line.clear();
@@ -475,7 +476,7 @@ namespace Tesses::Framework::Http
std::string cd0; std::string cd0;
ContentDisposition cd1; ContentDisposition cd1;
std::string ct; std::string ct;
if(!req.TryGetFirst("Content-Type",ct)) if(!req.TryGetFirst("Content-Type",ct))
ct = "application/octet-stream"; ct = "application/octet-stream";
if(req.TryGetFirst("Content-Disposition", cd0) && ContentDisposition::TryParse(cd0,cd1)) if(req.TryGetFirst("Content-Disposition", cd0) && ContentDisposition::TryParse(cd0,cd1))
@@ -494,10 +495,10 @@ namespace Tesses::Framework::Http
} }
else else
{ {
auto strm = cb(ct, cd1.filename, cd1.fieldName); auto strm = cb(ct, cd1.filename, cd1.fieldName);
if(strm == nullptr) strm = std::make_shared<Stream>(); if(strm == nullptr) strm = std::make_shared<Stream>();
bool retVal = parseUntillBoundaryEnd(ctx->GetStream(),strm,boundary); bool retVal = parseUntillBoundaryEnd(ctx->GetStream(),strm,boundary);
return retVal; return retVal;
} }
} }
@@ -521,9 +522,9 @@ namespace Tesses::Framework::Http
parseUntillBoundaryEnd(this->strm,nullStrm, ct); parseUntillBoundaryEnd(this->strm,nullStrm, ct);
while(parseSection(this, ct, cb)); while(parseSection(this, ct, cb));
} }
HttpServer::HttpServer(std::shared_ptr<Tesses::Framework::Streams::TcpServer> tcpServer, std::shared_ptr<IHttpServer> http, bool showIPs) HttpServer::HttpServer(std::shared_ptr<Tesses::Framework::Streams::TcpServer> tcpServer, std::shared_ptr<IHttpServer> http, bool showIPs, bool debug)
{ {
this->server = tcpServer; this->server = tcpServer;
this->http = http; this->http = http;
@@ -531,19 +532,20 @@ namespace Tesses::Framework::Http
this->showIPs = showIPs; this->showIPs = showIPs;
this->thrd=nullptr; this->thrd=nullptr;
this->showARTL = showIPs; this->showARTL = showIPs;
this->debug = debug;
} }
HttpServer::HttpServer(uint16_t port, std::shared_ptr<IHttpServer> http, bool showIPs) : HttpServer(std::make_shared<TcpServer>(port,10),http,showIPs) HttpServer::HttpServer(uint16_t port, std::shared_ptr<IHttpServer> http, bool showIPs, bool debug) : HttpServer(std::make_shared<TcpServer>(port,10),http,showIPs, debug)
{ {
} }
HttpServer::HttpServer(std::string unixPath, std::shared_ptr<IHttpServer> http) : HttpServer(std::make_shared<TcpServer>(unixPath,10),http,false) HttpServer::HttpServer(std::string unixPath, std::shared_ptr<IHttpServer> http, bool debug) : HttpServer(std::make_shared<TcpServer>(unixPath,10),http,false, debug)
{ {
this->showARTL=true; this->showARTL=true;
} }
uint16_t HttpServer::GetPort() uint16_t HttpServer::GetPort()
{ {
@@ -557,7 +559,7 @@ namespace Tesses::Framework::Http
int64_t length = -1; int64_t length = -1;
if(!this->responseHeaders.TryGetFirstInt("Content-Length",length)) if(!this->responseHeaders.TryGetFirstInt("Content-Length",length))
length = -1; length = -1;
if(this->version == "HTTP/1.1" && length == -1) if(this->version == "HTTP/1.1" && length == -1)
this->responseHeaders.SetValue("Transfer-Encoding","chunked"); this->responseHeaders.SetValue("Transfer-Encoding","chunked");
@@ -584,27 +586,29 @@ namespace Tesses::Framework::Http
auto serverPort = this->server->GetPort(); auto serverPort = this->server->GetPort();
auto http = this->http; auto http = this->http;
TF_LOG("Before Creating Thread"); TF_LOG("Before Creating Thread");
thrd = new Threading::Thread([svr,http,serverPort]()->void { bool debug = this->debug;
thrd = new Threading::Thread([svr,http,serverPort,debug]()->void {
while(TF_IsRunning()) while(TF_IsRunning())
{ {
TF_LOG("after TF_IsRunning"); TF_LOG("after TF_IsRunning");
std::string ip; std::string ip;
uint16_t port; uint16_t port;
auto sock =svr->GetStream(ip,port); auto sock =svr->GetStream(ip,port);
TF_LOG("New Host IP: " + ip + ":" + std::to_string(port)); TF_LOG("New Host IP: " + ip + ":" + std::to_string(port));
if(sock == nullptr) if(sock == nullptr)
{ {
std::cout << "STREAM ERROR" << std::endl; std::cout << "STREAM ERROR" << std::endl;
return; return;
} }
TF_LOG("Before entering socket thread"); TF_LOG("Before entering socket thread");
Threading::Thread thrd2([sock,http,ip,port,serverPort]()->void {
Threading::Thread thrd2([sock,http,ip,port,serverPort,debug]()->void {
TF_LOG("In thread to process"); TF_LOG("In thread to process");
HttpServer::Process(sock,http,ip,port,serverPort,false); HttpServer::Process(sock,http,ip,port,serverPort,false, debug);
TF_LOG("In thread after process"); TF_LOG("In thread after process");
}); });
TF_LOG("Before attach"); TF_LOG("Before attach");
thrd2.Detach(); thrd2.Detach();
@@ -614,7 +618,7 @@ namespace Tesses::Framework::Http
if(this->showIPs) if(this->showIPs)
{ {
TF_LOG("Before printing interfaces"); TF_LOG("Before printing interfaces");
StdOut() << "\x1B[34mInterfaces:" << NewLine(); StdOut() << "\x1B[34mInterfaces:" << NewLine();
for(auto _ip : NetworkStream::GetIPs()) for(auto _ip : NetworkStream::GetIPs())
{ {
@@ -623,15 +627,15 @@ namespace Tesses::Framework::Http
<< "\x1B[35mhttp://" << "\x1B[35mhttp://"
<< _ip.second << ":" << (uint64_t)this->GetPort() << "/" << NewLine(); << _ip.second << ":" << (uint64_t)this->GetPort() << "/" << NewLine();
} }
} }
if(this->showARTL) if(this->showARTL)
{ {
if(!svr->IsValid()) std::cout << "\x1B[31mError, we failed to bind or something\x1B[39m\n" << std::endl; if(!svr->IsValid()) std::cout << "\x1B[31mError, we failed to bind or something\x1B[39m\n" << std::endl;
StdOut() << "\x1B[31mAlmost Ready to Listen\x1B[39m" << NewLine(); StdOut() << "\x1B[31mAlmost Ready to Listen\x1B[39m" << NewLine();
} }
TF_LOG("After printing interfaces"); TF_LOG("After printing interfaces");
} }
HttpServer::~HttpServer() HttpServer::~HttpServer()
@@ -644,18 +648,20 @@ namespace Tesses::Framework::Http
this->thrd->Join(); this->thrd->Join();
delete this->thrd; delete this->thrd;
} }
} }
IHttpServer::~IHttpServer() IHttpServer::~IHttpServer()
{ {
} }
ServerContext::ServerContext(std::shared_ptr<Stream> strm) ServerContext::ServerContext(std::shared_ptr<Stream> strm, bool debug)
{ {
this->statusCode = OK; this->statusCode = OK;
this->strm = strm; this->strm = strm;
this->debug = debug;
this->sent = false; this->sent = false;
this->queryParams.SetCaseSensitive(true); this->queryParams.SetCaseSensitive(true);
this->pathArguments.SetCaseSensitive(true);
this->responseHeaders.AddValue("Server","TessesFrameworkWebServer"); this->responseHeaders.AddValue("Server","TessesFrameworkWebServer");
} }
std::shared_ptr<Stream> ServerContext::GetStream() std::shared_ptr<Stream> ServerContext::GetStream()
@@ -677,7 +683,7 @@ namespace Tesses::Framework::Http
void ServerContext::SendText(std::string text) void ServerContext::SendText(std::string text)
{ {
std::shared_ptr<MemoryStream> strm=std::make_shared<MemoryStream>(false); std::shared_ptr<MemoryStream> strm=std::make_shared<MemoryStream>(false);
auto& buff= strm->GetBuffer(); auto& buff= strm->GetBuffer();
buff.insert(buff.end(),text.begin(),text.end()); buff.insert(buff.end(),text.begin(),text.end());
SendStream(strm); SendStream(strm);
@@ -685,11 +691,13 @@ namespace Tesses::Framework::Http
void ServerContext::SendErrorPage(bool showPath) void ServerContext::SendErrorPage(bool showPath)
{ {
if(sent) return; if(sent) return;
std::string errorHtml = showPath ? ("<html><head><title>File " + HttpUtils::HtmlEncode(this->originalPath) + " " + HttpUtils::StatusCodeString(this->statusCode) + "</title></head><body><h1>" + std::to_string((int)this->statusCode) + " " + HttpUtils::StatusCodeString(this->statusCode) + "</h1><h4>" + HttpUtils::HtmlEncode(this->originalPath) + "</h4></body></html>") : ""; std::string errorHtml = showPath ? ("<html><head><title>File " + HttpUtils::HtmlEncode(this->originalPath) + " " + HttpUtils::StatusCodeString(this->statusCode) + "</title><meta name=\"color-scheme\" content=\"dark light\"></head><body><h1>" + std::to_string((int)this->statusCode) + " " + HttpUtils::StatusCodeString(this->statusCode) + "</h1><h4>" + HttpUtils::HtmlEncode(this->originalPath) + "</h4></body></html>") : (
"<html><head><title>" + std::to_string(this->statusCode) + " " + HttpUtils::StatusCodeString(this->statusCode) + "</title><meta name=\"color-scheme\" content=\"dark light\"></head><body><h1>" + std::to_string((int)this->statusCode) + " " + HttpUtils::StatusCodeString(this->statusCode) + "</h1></body></html>"
);
WithMimeType("text/html").SendText(errorHtml); WithMimeType("text/html").SendText(errorHtml);
} }
ServerContext::~ServerContext() ServerContext::~ServerContext()
{ {
for(auto item : this->data) for(auto item : this->data)
@@ -699,7 +707,7 @@ namespace Tesses::Framework::Http
} }
ServerContextData::~ServerContextData() ServerContextData::~ServerContextData()
{ {
} }
void ServerContext::SendStream(std::shared_ptr<Stream> strm) void ServerContext::SendStream(std::shared_ptr<Stream> strm)
{ {
@@ -722,7 +730,7 @@ namespace Tesses::Framework::Http
return; return;
} }
res = HttpUtils::SplitString(res[1],", ",2); res = HttpUtils::SplitString(res[1],", ",2);
if(res.size() != 1) if(res.size() != 1)
{ {
this->statusCode = BadRequest; this->statusCode = BadRequest;
this->WriteHeaders(); this->WriteHeaders();
@@ -764,7 +772,7 @@ namespace Tesses::Framework::Http
if(end == -1) if(end == -1)
{ {
end = len-1; end = len-1;
} }
if(end > len-1) if(end > len-1)
@@ -796,7 +804,7 @@ namespace Tesses::Framework::Http
uint8_t buffer[1024]; uint8_t buffer[1024];
size_t read=0; size_t read=0;
do { do {
read = sizeof(buffer); read = sizeof(buffer);
myLen = (end - begin)+1; myLen = (end - begin)+1;
@@ -809,7 +817,7 @@ namespace Tesses::Framework::Http
begin += read; begin += read;
} while(read > 0 && !this->strm->EndOfStream()); } while(read > 0 && !this->strm->EndOfStream());
} }
} }
else else
{ {
@@ -833,19 +841,19 @@ namespace Tesses::Framework::Http
} }
else else
{ {
auto chunkedStream = this->OpenResponseStream(); auto chunkedStream = this->OpenResponseStream();
if(method != "HEAD") if(method != "HEAD")
strm->CopyTo(chunkedStream); strm->CopyTo(chunkedStream);
} }
} }
ServerContext& ServerContext::WithHeader(std::string key, std::string value) ServerContext& ServerContext::WithHeader(std::string key, std::string value)
{ {
this->responseHeaders.AddValue(key, value); this->responseHeaders.AddValue(key, value);
return *this; return *this;
} }
ServerContext& ServerContext::WithSingleHeader(std::string key, std::string value) ServerContext& ServerContext::WithSingleHeader(std::string key, std::string value)
{ {
@@ -900,24 +908,40 @@ namespace Tesses::Framework::Http
statusCode = StatusCode::BadRequest; statusCode = StatusCode::BadRequest;
SendErrorPage(false); SendErrorPage(false);
} }
ServerContext& ServerContext::WithStatusCode(StatusCode code)
{
this->statusCode = code;
return *this;
}
void ServerContext::SendException(std::exception& ex) void ServerContext::SendException(std::exception& ex)
{ {
/*<!DOCTYPE html> if(this->debug)
<html lang="en"> {
<head>
<meta charset="UTF-8"> this->WithMimeType("text/html").WithStatusCode(StatusCode::InternalServerError).SendText("<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>Internal Server Error at " + HttpUtils::HtmlEncode(this->originalPath) + "</title><meta name=\"color-scheme\" content=\"dark light\"></head><body><h1>Internal Server Error at " + HttpUtils::HtmlEncode(this->originalPath) + "</h1><p>what(): " + HttpUtils::HtmlEncode(ex.what()) + "</p></body></html>");
<meta name="viewport" content="width=device-width, initial-scale=1.0"> }
<title>Internal Server Error at /</title> else {
</head> this->WithStatusCode(StatusCode::InternalServerError).SendErrorPage(true);
<body> }
<h1>Internal Server Error at /</h1>
<p>what(): std::exception</p>
</body>
</html>*/
this->WithMimeType("text/html").SendText("<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>Internal Server Error at " + HttpUtils::HtmlEncode(this->originalPath) + "</title></head><body><h1>Internal Server Error at " + HttpUtils::HtmlEncode(this->originalPath) + "</h1><p>what(): " + HttpUtils::HtmlEncode(ex.what()) + "</p></body></html>");
} }
ServerContext& ServerContext::WithHeaderIntercepter(std::function<bool(ServerContext&)> cb)
{
this->headerhandlers.push(cb);
return *this;
}
ServerContext& ServerContext::WriteHeaders() ServerContext& ServerContext::WriteHeaders()
{ {
if(this->sent) return *this;
while(!this->headerhandlers.empty())
{
auto header = this->headerhandlers.front();
this->headerhandlers.pop();
if(header(*this)) {
break;
}
}
if(this->sent) return *this; if(this->sent) return *this;
this->sent = true; this->sent = true;
@@ -933,22 +957,20 @@ namespace Tesses::Framework::Http
} }
} }
writer.WriteLine(); writer.WriteLine();
return *this; return *this;
} }
void HttpServer::Process(std::shared_ptr<Stream> strm, std::shared_ptr<IHttpServer> server, std::string ip, uint16_t port,uint16_t serverPort, bool encrypted) void HttpServer::Process(std::shared_ptr<Stream> strm, std::shared_ptr<IHttpServer> server, std::string ip, uint16_t port,uint16_t serverPort, bool encrypted, bool debug)
{ {
TF_LOG("In process"); TF_LOG("In process");
while(true) std::shared_ptr<BufferedStream> bStrm = std::make_shared<BufferedStream>(strm);
{ StreamReader reader(bStrm);
std::shared_ptr<BufferedStream> bStrm = std::make_shared<BufferedStream>(strm); ServerContext ctx(bStrm);
StreamReader reader(bStrm); ctx.ip = ip;
ServerContext ctx(bStrm); ctx.port = port;
ctx.ip = ip; ctx.encrypted = encrypted;
ctx.port = port; ctx.serverPort = serverPort;
ctx.encrypted = encrypted; try{
ctx.serverPort = serverPort;
try{
bool firstLine = true; bool firstLine = true;
std::string line; std::string line;
while(reader.ReadLineHttp(line)) while(reader.ReadLineHttp(line))
@@ -987,9 +1009,9 @@ namespace Tesses::Framework::Http
ctx.WithMimeType("text/plain").SendText("Header line is not 2 elements"); ctx.WithMimeType("text/plain").SendText("Header line is not 2 elements");
return; return;
} }
ctx.requestHeaders.AddValue(v[0],v[1]); ctx.requestHeaders.AddValue(v[0],v[1]);
} }
line.clear(); line.clear();
firstLine=false; firstLine=false;
@@ -1009,12 +1031,15 @@ namespace Tesses::Framework::Http
delete[] buffer; delete[] buffer;
HttpUtils::QueryParamsDecode(ctx.queryParams, query); HttpUtils::QueryParamsDecode(ctx.queryParams, query);
} }
if(!server->Handle(ctx)) if(!server->Handle(ctx))
{ {
ctx.SendNotFound(); if((int)ctx.statusCode < 400)
ctx.SendNotFound();
else
ctx.SendErrorPage(true);
} }
} }
catch(std::exception& ex) catch(std::exception& ex)
{ {
@@ -1033,26 +1058,23 @@ namespace Tesses::Framework::Http
catch(...) catch(...)
{ {
std::runtime_error ex("An unknown error occurred"); std::runtime_error ex("An unknown error occurred");
ctx.SendException(ex); ctx.SendException(ex);
} }
if(ctx.version != "HTTP/1.1" ) return;
std::string connection;
if(ctx.requestHeaders.TryGetFirst("Connection", connection))
{
if(HttpUtils::ToLower(connection) != "keep-alive") return;
}
if(ctx.responseHeaders.TryGetFirst("Connection", connection))
{
if(HttpUtils::ToLower(connection) != "keep-alive") return;
}
if(bStrm->EndOfStream()) { }
return;
} bool ServerContext::Debug()
} {
return this->debug;
}
ServerContext& ServerContext::WithDebug(bool debug)
{
this->debug = debug;
return *this;
} }
WebSocketConnection::~WebSocketConnection() WebSocketConnection::~WebSocketConnection()
@@ -1064,7 +1086,7 @@ namespace Tesses::Framework::Http
std::shared_ptr<CallbackWebSocketConnection> wsc = std::make_shared<CallbackWebSocketConnection>(onOpen,onReceive,onClose); std::shared_ptr<CallbackWebSocketConnection> wsc = std::make_shared<CallbackWebSocketConnection>(onOpen,onReceive,onClose);
StartWebSocketSession(wsc); StartWebSocketSession(wsc);
} }
void ServerContext::StartWebSocketSession(std::shared_ptr<WebSocketConnection> connection) void ServerContext::StartWebSocketSession(std::shared_ptr<WebSocketConnection> connection)
{ {
WSServer svr(this,connection); WSServer svr(this,connection);
@@ -1080,7 +1102,7 @@ namespace Tesses::Framework::Http
} }
}); });
svr.Start(); svr.Start();
thrd.Join(); thrd.Join();
} }
@@ -1105,4 +1127,3 @@ namespace Tesses::Framework::Http
} }

View File

@@ -6,11 +6,15 @@
#include "TessesFramework/Filesystem/FSHelpers.hpp" #include "TessesFramework/Filesystem/FSHelpers.hpp"
#include "TessesFramework/Serialization/Json.hpp" #include "TessesFramework/Serialization/Json.hpp"
#include <atomic> #include <atomic>
#include <chrono>
#include <csignal> #include <csignal>
#include <functional>
#include <iostream> #include <iostream>
#include <memory>
#include <queue> #include <queue>
#include <ratio>
#if defined(TESSESFRAMEWORK_ENABLE_SQLITE) #if defined(TESSESFRAMEWORK_ENABLE_SQLITE)
extern "C" { extern "C" {
#include "Serialization/sqlite/sqlite3.h" #include "Serialization/sqlite/sqlite3.h"
} }
@@ -52,8 +56,6 @@ static GXRModeObj *rmode = NULL;
namespace Tesses::Framework namespace Tesses::Framework
{ {
EventList<uint64_t> OnItteraton;
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(GEKKO) || defined(__SWITCH__)) #if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(GEKKO) || defined(__SWITCH__))
namespace Threading namespace Threading
{ {
@@ -64,13 +66,14 @@ namespace Tesses::Framework
volatile static bool isRunningSig=true; volatile static bool isRunningSig=true;
volatile static std::atomic<bool> isRunning; volatile static std::atomic<bool> isRunning;
volatile static std::atomic<bool> gaming_console_events=true; volatile static std::atomic<bool> gaming_console_events=true;
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) #if defined(TESSESFRAMEWORK_ENABLE_THREADING)
Threading::Mutex timers_mtx;
Threading::Mutex invokings_mtx; Threading::Mutex invokings_mtx;
std::queue<std::function<void()>> invokings; std::queue<std::function<void()>> invokings;
#endif #endif
void TF_Invoke(std::function<void()> cb) void TF_Invoke(std::function<void()> cb)
{ {
@@ -86,7 +89,7 @@ namespace Tesses::Framework
void TF_ConnectToSelf(uint16_t port) void TF_ConnectToSelf(uint16_t port)
{ {
Tesses::Framework::Streams::NetworkStream ns("127.0.0.1",port,false,false,false); Tesses::Framework::Streams::NetworkStream ns("127.0.0.1",port,false,false,false);
} }
bool TF_IsRunning() bool TF_IsRunning()
{ {
@@ -106,16 +109,142 @@ namespace Tesses::Framework
} }
#if defined(__SWITCH__) #if defined(__SWITCH__)
bool initedConsole=false; bool initedConsole=false;
PadState default_pad; PadState default_pad;
#endif #endif
uint64_t ittr=0; uint64_t ittr=0;
static std::shared_ptr<TF_Timer_Handler> timer_handler = std::make_shared<TF_Timer_Handler>();
std::shared_ptr<TF_Timer_Handle> TF_Timer_Handler::Make(std::shared_ptr<TF_Timer_Handler> handler)
{
auto timer = new TF_Timer_Handle(handler);
std::shared_ptr<TF_Timer_Handle> handle(timer);
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
timers_mtx.Lock();
#endif
handler->handles.push_back(handle);
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
timers_mtx.Unlock();
#endif
return handle;
}
std::shared_ptr<TF_Timer_Handle> TF_Timer()
{
return TF_Timer_Handler::Make(timer_handler);
}
std::shared_ptr<TF_Timer_Handle> TF_Timer(std::function<void()> cb, int64_t interval, bool enabled)
{
auto handle = TF_Timer();
handle->SetCallback(cb);
handle->SetIntervalFromMilliseconds(interval);
handle->SetEnabled(enabled);
return handle;
}
std::shared_ptr<TF_Timer_Handle> TF_Timer(std::function<void()> cb, std::chrono::duration<int64_t,std::milli> interval, bool enabled)
{
auto handle = TF_Timer();
handle->SetCallback(cb);
handle->SetIntervalFromDuration(interval);
handle->SetEnabled(enabled);
return handle;
}
void TF_Timer_Handler::Update()
{
std::chrono::time_point<std::chrono::steady_clock,std::chrono::milliseconds> cur = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now());
std::vector<std::function<void()>> cbs;
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
timers_mtx.Lock();
#endif
for(auto index = this->handles.begin(); index != this->handles.end(); index++)
{
if(index->expired())
{
this->handles.erase(index);
index--;
}
else {
auto handle = index->lock();
if(handle && handle->enabled && (handle->last + handle->interval) <= cur && handle->cb)
{
handle->last = cur;
cbs.push_back(handle->cb);
}
}
}
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
timers_mtx.Unlock();
#endif
for(auto item : cbs)
{
item();
}
}
void TF_Timer_Handle::SetCallback(std::function<void()> cb)
{
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
timers_mtx.Lock();
#endif
this->cb = cb;
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
timers_mtx.Unlock();
#endif
}
TF_Timer_Handle::TF_Timer_Handle(std::shared_ptr<TF_Timer_Handler> handler) : timerHandler(handler)
{
}
void TF_Timer_Handle::SetEnabled(bool enabled)
{
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
timers_mtx.Lock();
#endif
this->enabled = enabled;
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
timers_mtx.Unlock();
#endif
}
bool TF_Timer_Handle::GetEnabled()
{
return this->enabled;
}
void TF_Timer_Handle::SetIntervalFromDuration(std::chrono::milliseconds ms)
{
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
timers_mtx.Lock();
#endif
this->interval = ms;
#if defined(TESSESFRAMEWORK_ENABLE_THREADING)
timers_mtx.Unlock();
#endif
}
void TF_Timer_Handle::SetIntervalFromMilliseconds(int64_t ms)
{
SetIntervalFromDuration(std::chrono::milliseconds(ms));
}
std::chrono::duration<int64_t,std::milli> TF_Timer_Handle::GetIntervalDuration()
{
return this->interval;
}
int64_t TF_Timer_Handle::GetIntervalMilliseconds()
{
return this->interval.count();
}
void TF_RunEventLoopItteration() void TF_RunEventLoopItteration()
{ {
OnItteraton.Invoke(ittr++);
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(GEKKO) || defined(__SWITCH__)) #if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(GEKKO) || defined(__SWITCH__))
Tesses::Framework::Threading::LookForFinishedThreads(); Tesses::Framework::Threading::LookForFinishedThreads();
#endif #endif
#if defined(TESSESFRAMEWORK_ENABLE_THREADING) #if defined(TESSESFRAMEWORK_ENABLE_THREADING)
invokings_mtx.Lock(); invokings_mtx.Lock();
@@ -125,10 +254,10 @@ namespace Tesses::Framework
{ {
invokes.front()(); invokes.front()();
invokes.pop(); invokes.pop();
} }
#endif #endif
if(!isRunningSig) isRunning=false; if(!isRunningSig) isRunning=false;
#if defined(GEKKO) #if defined(GEKKO)
if(gaming_console_events) if(gaming_console_events)
@@ -140,7 +269,7 @@ namespace Tesses::Framework
if(gaming_console_events) if(gaming_console_events)
{ {
if(!appletMainLoop()) isRunning=false; if(!appletMainLoop()) isRunning=false;
padUpdate(&default_pad); padUpdate(&default_pad);
u64 kDown = padGetButtonsDown(&default_pad); u64 kDown = padGetButtonsDown(&default_pad);
@@ -163,7 +292,9 @@ namespace Tesses::Framework
isRunning = false; isRunning = false;
} }
#endif #endif
timer_handler->Update();
} }
void TF_SetIsRunning(bool _isRunning) void TF_SetIsRunning(bool _isRunning)
@@ -200,7 +331,7 @@ namespace Tesses::Framework
signal(SIGINT, _sigInt); signal(SIGINT, _sigInt);
signal(SIGTERM, _sigInt); signal(SIGTERM, _sigInt);
#endif #endif
isRunning=true; isRunning=true;
#if defined(_WIN32) #if defined(_WIN32)
WSADATA wsaData; WSADATA wsaData;
@@ -230,9 +361,9 @@ if (iResult != 0) {
// Initialize the default gamepad (which reads handheld mode inputs as well as the first connected controller) // Initialize the default gamepad (which reads handheld mode inputs as well as the first connected controller)
#else #else
signal(SIGPIPE,SIG_IGN); signal(SIGPIPE,SIG_IGN);
#endif #endif
} }
bool TF_GetConsoleEventsEnabled() bool TF_GetConsoleEventsEnabled()
{ {
@@ -332,7 +463,7 @@ if (iResult != 0) {
} }
std::optional<std::string> _argv0=std::nullopt; std::optional<std::string> _argv0=std::nullopt;
void TF_AllowPortable(std::string argv0) void TF_AllowPortable(std::string argv0)
{ {
@@ -346,7 +477,7 @@ if (iResult != 0) {
auto portable=dir / "portable.json"; auto portable=dir / "portable.json";
if(LocalFS->FileExists(portable)) if(LocalFS->FileExists(portable))
{ {
std::string portable_str; std::string portable_str;
Helpers::ReadAllText(LocalFS,portable, portable_str); Helpers::ReadAllText(LocalFS,portable, portable_str);
auto jsonObj=Json::Decode(portable_str); auto jsonObj=Json::Decode(portable_str);
@@ -403,7 +534,7 @@ if (iResult != 0) {
{ {
if(paf_data) if(paf_data)
portable_config.user = LocalFS->SystemToVFSPath(*paf_data) / "TF_User"; portable_config.user = LocalFS->SystemToVFSPath(*paf_data) / "TF_User";
} }
else if(portable_str == "documents") else if(portable_str == "documents")
{ {
if(paf_documents) if(paf_documents)
@@ -416,7 +547,7 @@ if (iResult != 0) {
{ {
if(portable_config.user) if(portable_config.user)
portable_config.desktop = *(portable_config.user) / "Desktop"; portable_config.desktop = *(portable_config.user) / "Desktop";
} }
else if(portable_str == "documents") else if(portable_str == "documents")
{ {
if(paf_documents) if(paf_documents)
@@ -429,7 +560,7 @@ if (iResult != 0) {
{ {
if(portable_config.user) if(portable_config.user)
portable_config.downloads = *(portable_config.user) / "Downloads"; portable_config.downloads = *(portable_config.user) / "Downloads";
} }
else if(portable_str == "documents") else if(portable_str == "documents")
{ {
if(paf_documents) if(paf_documents)
@@ -466,21 +597,21 @@ if (iResult != 0) {
{ {
if(dict2.TryGetValueAsType("user",portable_str)) if(dict2.TryGetValueAsType("user",portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
auto userDir = dir / portable_str; auto userDir = dir / portable_str;
portable_config.user = userDir.CollapseRelativeParents(); portable_config.user = userDir.CollapseRelativeParents();
} }
} }
if(dict2.TryGetValueAsType("documents", portable_str)) if(dict2.TryGetValueAsType("documents", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -490,7 +621,7 @@ if (iResult != 0) {
portable_config.documents = *(portable_config.user) / "Documents"; portable_config.documents = *(portable_config.user) / "Documents";
} }
} }
else else
{ {
auto userDir = dir / portable_str; auto userDir = dir / portable_str;
portable_config.documents = userDir.CollapseRelativeParents(); portable_config.documents = userDir.CollapseRelativeParents();
@@ -500,7 +631,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("downloads", portable_str)) if(dict2.TryGetValueAsType("downloads", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -510,7 +641,7 @@ if (iResult != 0) {
portable_config.downloads = *(portable_config.user) / "Downloads"; portable_config.downloads = *(portable_config.user) / "Downloads";
} }
} }
else else
{ {
auto userDir = dir / portable_str; auto userDir = dir / portable_str;
portable_config.downloads = userDir.CollapseRelativeParents(); portable_config.downloads = userDir.CollapseRelativeParents();
@@ -520,7 +651,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("desktop", portable_str)) if(dict2.TryGetValueAsType("desktop", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -530,7 +661,7 @@ if (iResult != 0) {
portable_config.desktop = *(portable_config.user) / "Desktop"; portable_config.desktop = *(portable_config.user) / "Desktop";
} }
} }
else else
{ {
auto userDir = dir / portable_str; auto userDir = dir / portable_str;
portable_config.desktop = userDir.CollapseRelativeParents(); portable_config.desktop = userDir.CollapseRelativeParents();
@@ -540,7 +671,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("pictures", portable_str)) if(dict2.TryGetValueAsType("pictures", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -550,7 +681,7 @@ if (iResult != 0) {
portable_config.pictures = *(portable_config.user) / "Pictures"; portable_config.pictures = *(portable_config.user) / "Pictures";
} }
} }
else else
{ {
auto userDir = dir / portable_str; auto userDir = dir / portable_str;
portable_config.pictures = userDir.CollapseRelativeParents(); portable_config.pictures = userDir.CollapseRelativeParents();
@@ -560,7 +691,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("videos", portable_str)) if(dict2.TryGetValueAsType("videos", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -570,7 +701,7 @@ if (iResult != 0) {
portable_config.videos = *(portable_config.user) / "Videos"; portable_config.videos = *(portable_config.user) / "Videos";
} }
} }
else else
{ {
auto userDir = dir / portable_str; auto userDir = dir / portable_str;
portable_config.videos = userDir.CollapseRelativeParents(); portable_config.videos = userDir.CollapseRelativeParents();
@@ -580,7 +711,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("music", portable_str)) if(dict2.TryGetValueAsType("music", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -590,7 +721,7 @@ if (iResult != 0) {
portable_config.music = *(portable_config.user) / "Music"; portable_config.music = *(portable_config.user) / "Music";
} }
} }
else else
{ {
auto userDir = dir / portable_str; auto userDir = dir / portable_str;
portable_config.music = userDir.CollapseRelativeParents(); portable_config.music = userDir.CollapseRelativeParents();
@@ -600,7 +731,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("config", portable_str)) if(dict2.TryGetValueAsType("config", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -610,7 +741,7 @@ if (iResult != 0) {
portable_config.config = *(portable_config.user) / "Config"; portable_config.config = *(portable_config.user) / "Config";
} }
} }
else else
{ {
auto userDir = dir / portable_str; auto userDir = dir / portable_str;
portable_config.config = userDir.CollapseRelativeParents(); portable_config.config = userDir.CollapseRelativeParents();
@@ -620,7 +751,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("cache", portable_str)) if(dict2.TryGetValueAsType("cache", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -630,7 +761,7 @@ if (iResult != 0) {
portable_config.cache = *(portable_config.user) / "Cache"; portable_config.cache = *(portable_config.user) / "Cache";
} }
} }
else else
{ {
auto userDir = dir / portable_str; auto userDir = dir / portable_str;
portable_config.cache = userDir.CollapseRelativeParents(); portable_config.cache = userDir.CollapseRelativeParents();
@@ -640,7 +771,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("data", portable_str)) if(dict2.TryGetValueAsType("data", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -650,7 +781,7 @@ if (iResult != 0) {
portable_config.data = *(portable_config.user) / "Data"; portable_config.data = *(portable_config.user) / "Data";
} }
} }
else else
{ {
auto userDir = dir / portable_str; auto userDir = dir / portable_str;
portable_config.data = userDir.CollapseRelativeParents(); portable_config.data = userDir.CollapseRelativeParents();
@@ -660,7 +791,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("state", portable_str)) if(dict2.TryGetValueAsType("state", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -670,7 +801,7 @@ if (iResult != 0) {
portable_config.state = *(portable_config.user) / "State"; portable_config.state = *(portable_config.user) / "State";
} }
} }
else else
{ {
auto userDir = dir / portable_str; auto userDir = dir / portable_str;
portable_config.state = userDir.CollapseRelativeParents(); portable_config.state = userDir.CollapseRelativeParents();
@@ -680,7 +811,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("temp", portable_str)) if(dict2.TryGetValueAsType("temp", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -690,7 +821,7 @@ if (iResult != 0) {
portable_config.temp = *(portable_config.user) / "Temp"; portable_config.temp = *(portable_config.user) / "Temp";
} }
} }
else else
{ {
auto userDir = dir / portable_str; auto userDir = dir / portable_str;
portable_config.temp = userDir.CollapseRelativeParents(); portable_config.temp = userDir.CollapseRelativeParents();
@@ -698,40 +829,40 @@ if (iResult != 0) {
} }
} }
} }
} }
else if(portable_str == "absolute") else if(portable_str == "absolute")
{ {
if(dict2.TryGetValueAsType("user",portable_str)) if(dict2.TryGetValueAsType("user",portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
VFSPath userDir = portable_str; VFSPath userDir = portable_str;
portable_config.user = userDir.CollapseRelativeParents(); portable_config.user = userDir.CollapseRelativeParents();
} }
} }
if(dict2.TryGetValueAsType("documents", portable_str)) if(dict2.TryGetValueAsType("documents", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -741,7 +872,7 @@ if (iResult != 0) {
portable_config.documents = *(portable_config.user) / "Documents"; portable_config.documents = *(portable_config.user) / "Documents";
} }
} }
else else
{ {
VFSPath userDir = portable_str; VFSPath userDir = portable_str;
portable_config.documents = userDir.CollapseRelativeParents(); portable_config.documents = userDir.CollapseRelativeParents();
@@ -751,7 +882,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("downloads", portable_str)) if(dict2.TryGetValueAsType("downloads", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -761,7 +892,7 @@ if (iResult != 0) {
portable_config.downloads = *(portable_config.user) / "Downloads"; portable_config.downloads = *(portable_config.user) / "Downloads";
} }
} }
else else
{ {
VFSPath userDir = portable_str; VFSPath userDir = portable_str;
portable_config.downloads = userDir.CollapseRelativeParents(); portable_config.downloads = userDir.CollapseRelativeParents();
@@ -771,7 +902,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("desktop", portable_str)) if(dict2.TryGetValueAsType("desktop", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -781,7 +912,7 @@ if (iResult != 0) {
portable_config.desktop = *(portable_config.user) / "Desktop"; portable_config.desktop = *(portable_config.user) / "Desktop";
} }
} }
else else
{ {
VFSPath userDir = portable_str; VFSPath userDir = portable_str;
portable_config.desktop = userDir.CollapseRelativeParents(); portable_config.desktop = userDir.CollapseRelativeParents();
@@ -791,7 +922,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("pictures", portable_str)) if(dict2.TryGetValueAsType("pictures", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -801,7 +932,7 @@ if (iResult != 0) {
portable_config.pictures = *(portable_config.user) / "Pictures"; portable_config.pictures = *(portable_config.user) / "Pictures";
} }
} }
else else
{ {
VFSPath userDir = portable_str; VFSPath userDir = portable_str;
portable_config.pictures = userDir.CollapseRelativeParents(); portable_config.pictures = userDir.CollapseRelativeParents();
@@ -811,7 +942,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("videos", portable_str)) if(dict2.TryGetValueAsType("videos", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -821,7 +952,7 @@ if (iResult != 0) {
portable_config.videos = *(portable_config.user) / "Videos"; portable_config.videos = *(portable_config.user) / "Videos";
} }
} }
else else
{ {
VFSPath userDir = portable_str; VFSPath userDir = portable_str;
portable_config.videos = userDir.CollapseRelativeParents(); portable_config.videos = userDir.CollapseRelativeParents();
@@ -831,7 +962,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("music", portable_str)) if(dict2.TryGetValueAsType("music", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -841,7 +972,7 @@ if (iResult != 0) {
portable_config.music = *(portable_config.user) / "Music"; portable_config.music = *(portable_config.user) / "Music";
} }
} }
else else
{ {
VFSPath userDir = portable_str; VFSPath userDir = portable_str;
portable_config.music = userDir.CollapseRelativeParents(); portable_config.music = userDir.CollapseRelativeParents();
@@ -851,7 +982,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("config", portable_str)) if(dict2.TryGetValueAsType("config", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -861,7 +992,7 @@ if (iResult != 0) {
portable_config.config = *(portable_config.user) / "Config"; portable_config.config = *(portable_config.user) / "Config";
} }
} }
else else
{ {
VFSPath userDir = portable_str; VFSPath userDir = portable_str;
portable_config.config = userDir.CollapseRelativeParents(); portable_config.config = userDir.CollapseRelativeParents();
@@ -871,7 +1002,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("cache", portable_str)) if(dict2.TryGetValueAsType("cache", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -881,7 +1012,7 @@ if (iResult != 0) {
portable_config.cache = *(portable_config.user) / "Cache"; portable_config.cache = *(portable_config.user) / "Cache";
} }
} }
else else
{ {
VFSPath userDir = portable_str; VFSPath userDir = portable_str;
portable_config.cache = userDir.CollapseRelativeParents(); portable_config.cache = userDir.CollapseRelativeParents();
@@ -891,7 +1022,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("data", portable_str)) if(dict2.TryGetValueAsType("data", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -901,7 +1032,7 @@ if (iResult != 0) {
portable_config.data = *(portable_config.user) / "Data"; portable_config.data = *(portable_config.user) / "Data";
} }
} }
else else
{ {
VFSPath userDir = portable_str; VFSPath userDir = portable_str;
portable_config.data = userDir.CollapseRelativeParents(); portable_config.data = userDir.CollapseRelativeParents();
@@ -911,7 +1042,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("state", portable_str)) if(dict2.TryGetValueAsType("state", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -921,7 +1052,7 @@ if (iResult != 0) {
portable_config.state = *(portable_config.user) / "State"; portable_config.state = *(portable_config.user) / "State";
} }
} }
else else
{ {
VFSPath userDir = portable_str; VFSPath userDir = portable_str;
portable_config.state = userDir.CollapseRelativeParents(); portable_config.state = userDir.CollapseRelativeParents();
@@ -931,7 +1062,7 @@ if (iResult != 0) {
} }
if(dict2.TryGetValueAsType("temp", portable_str)) if(dict2.TryGetValueAsType("temp", portable_str))
{ {
if(portable_str != "system") if(portable_str != "system")
{ {
if(portable_str == "default") if(portable_str == "default")
@@ -941,7 +1072,7 @@ if (iResult != 0) {
portable_config.temp = *(portable_config.user) / "Temp"; portable_config.temp = *(portable_config.user) / "Temp";
} }
} }
else else
{ {
VFSPath userDir = portable_str; VFSPath userDir = portable_str;
portable_config.temp = userDir.CollapseRelativeParents(); portable_config.temp = userDir.CollapseRelativeParents();
@@ -949,7 +1080,7 @@ if (iResult != 0) {
} }
} }
} }
} }
} }
} }