Compare commits
No commits in common. "main" and "v0.0.27" have entirely different histories.
@ -1,3 +1,4 @@
|
|||||||
.git
|
.svn
|
||||||
db.sqlite*
|
db.sqlite
|
||||||
out/
|
out/**/*.o
|
||||||
|
out/**/*.d
|
||||||
|
@ -6,48 +6,15 @@ jobs:
|
|||||||
Build-All:
|
Build-All:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: node:23-bookworm-slim
|
valid_volumes: ['/opt/keys']
|
||||||
valid_volumes:
|
|
||||||
- '/opt/keys'
|
|
||||||
- '/opt/deps'
|
|
||||||
volumes:
|
volumes:
|
||||||
- /opt/keys:/opt/keys
|
- /opt/keys:/opt/keys
|
||||||
- /opt/deps:/opt/deps
|
|
||||||
steps:
|
steps:
|
||||||
- name: Install build dependencies
|
- name: check out code
|
||||||
run: >
|
|
||||||
apt update && apt install -y \
|
|
||||||
build-essential \
|
|
||||||
clang \
|
|
||||||
cmake \
|
|
||||||
curl \
|
|
||||||
docker.io \
|
|
||||||
doxygen \
|
|
||||||
file \
|
|
||||||
gcc-aarch64-linux-gnu \
|
|
||||||
git \
|
|
||||||
graphviz \
|
|
||||||
libgpgme11 \
|
|
||||||
libssl-dev \
|
|
||||||
mingw-w64 \
|
|
||||||
rsync \
|
|
||||||
unzip \
|
|
||||||
zip \
|
|
||||||
zlib1g-dev
|
|
||||||
- name: Get code
|
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Setup environment
|
- run: ln -s /opt/keys .keys
|
||||||
run: |
|
|
||||||
ln -s /opt/keys .keys
|
|
||||||
ln -s /opt/deps/ios_toolchain deps/ios_toolchain
|
|
||||||
- name: Build documentation
|
|
||||||
run: |
|
|
||||||
mkdir -p out/html/ ~/.ssh/
|
|
||||||
make docs
|
|
||||||
echo 'pildefriends ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKD3Kde5vDO0TrMBDK0IGGeNGe/XinWAZkSQ/rXxwUjt' >> ~/.ssh/known_hosts
|
|
||||||
rsync -avP --delete -e "ssh -i /opt/keys/ssh.ed25519" out/html/ tfdocs@pildefriends:docs/html/
|
|
||||||
- name: Setup JDK
|
- name: Setup JDK
|
||||||
uses: actions/setup-java@v3
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
@ -57,12 +24,14 @@ jobs:
|
|||||||
uses: android-actions/setup-android@v3
|
uses: android-actions/setup-android@v3
|
||||||
with:
|
with:
|
||||||
packages: 'tools platform-tools build-tools;34.0.0 platforms;android-34 ndk;26.3.11579264'
|
packages: 'tools platform-tools build-tools;34.0.0 platforms;android-34 ndk;26.3.11579264'
|
||||||
- name: Docker build
|
- run: sudo apt update && sudo apt install -y doxygen graphviz mingw-w64 libgpgme11 gcc-aarch64-linux-gnu
|
||||||
run: DOCKER_BUILDKIT=1 docker build .
|
- run: ANDROID_SDK=$HOME/.android/sdk make -j`nproc` all docs
|
||||||
- name: Build
|
- run: docker build .
|
||||||
run: ANDROID_SDK=$HOME/.android/sdk make -j`nproc` all dist docs
|
- uses: actions/upload-artifact@v3
|
||||||
- name: Upload artifacts
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
with:
|
||||||
name: dist
|
path: |
|
||||||
path: dist/*
|
out/TildeFriends-release.fdroid.apk
|
||||||
|
out/winrelease/tildefriends.standalone.exe
|
||||||
|
out/tildefriends-x86_64.AppImage
|
||||||
|
out/release/tildefriends.standalone
|
||||||
|
out/armrelease/tildefriends.standalone
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,7 +2,6 @@ build/
|
|||||||
*.core
|
*.core
|
||||||
db.*
|
db.*
|
||||||
deps/ios_toolchain/
|
deps/ios_toolchain/
|
||||||
deps/macos_toolchain/
|
|
||||||
deps/openssl/
|
deps/openssl/
|
||||||
dist/
|
dist/
|
||||||
.flatpak-builder
|
.flatpak-builder
|
||||||
|
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -26,6 +26,6 @@
|
|||||||
[submodule "deps/c-ares"]
|
[submodule "deps/c-ares"]
|
||||||
path = deps/c-ares
|
path = deps/c-ares
|
||||||
url = https://github.com/c-ares/c-ares.git
|
url = https://github.com/c-ares/c-ares.git
|
||||||
[submodule "deps/zsign"]
|
[submodule "docs"]
|
||||||
path = deps/zsign
|
path = docs
|
||||||
url = https://github.com/zhlynn/zsign.git
|
url = https://dev.tildefriends.net/cory/tildefriends.wiki.git
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
FROM bitnami/minideb:bookworm AS build
|
FROM bitnami/minideb:bullseye AS build
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y --no-install-recommends \
|
apt-get install -y --no-install-recommends \
|
||||||
gcc \
|
gcc \
|
||||||
libc6-dev \
|
libc6-dev \
|
||||||
perl \
|
libssl-dev \
|
||||||
make
|
make
|
||||||
|
|
||||||
COPY . /app
|
COPY . /app
|
||||||
RUN make -C /app -j $(nproc) release
|
RUN make -C /app -j $(nproc) release
|
||||||
|
|
||||||
FROM bitnami/minideb:bookworm
|
FROM bitnami/minideb:bullseye
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends \
|
||||||
|
libssl1.1
|
||||||
|
|
||||||
COPY --from=build /app/out/release/tildefriends /app/out/release/tildefriends
|
COPY --from=build /app/out/release/tildefriends /app/out/release/tildefriends
|
||||||
COPY --from=build /app/apps /app/apps
|
COPY --from=build /app/apps /app/apps
|
||||||
|
4
Doxyfile
4
Doxyfile
@ -943,7 +943,7 @@ WARN_LOGFILE =
|
|||||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||||
# Note: If this tag is empty the current directory is searched.
|
# Note: If this tag is empty the current directory is searched.
|
||||||
|
|
||||||
INPUT = README.md docs/ src/
|
INPUT = src/
|
||||||
|
|
||||||
# This tag can be used to specify the character encoding of the source files
|
# This tag can be used to specify the character encoding of the source files
|
||||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||||
@ -1110,7 +1110,7 @@ FILTER_SOURCE_PATTERNS =
|
|||||||
# (index.html). This can be useful if you have a project on for instance GitHub
|
# (index.html). This can be useful if you have a project on for instance GitHub
|
||||||
# and want to reuse the introduction page also for the doxygen output.
|
# and want to reuse the introduction page also for the doxygen output.
|
||||||
|
|
||||||
USE_MDFILE_AS_MAINPAGE = README.md
|
USE_MDFILE_AS_MAINPAGE =
|
||||||
|
|
||||||
# The Fortran standard specifies that for fixed formatted Fortran code all
|
# The Fortran standard specifies that for fixed formatted Fortran code all
|
||||||
# characters from position 72 are to be considered as comment. A common
|
# characters from position 72 are to be considered as comment. A common
|
||||||
|
245
GNUmakefile
245
GNUmakefile
@ -16,8 +16,8 @@ MAKEFLAGS += --no-builtin-rules
|
|||||||
## LD := Linker.
|
## LD := Linker.
|
||||||
## ANDROID_SDK := Path to the Android SDK.
|
## ANDROID_SDK := Path to the Android SDK.
|
||||||
|
|
||||||
VERSION_CODE := 33
|
VERSION_CODE := 32
|
||||||
VERSION_NUMBER := 0.0.28-wip
|
VERSION_NUMBER := 0.0.27
|
||||||
VERSION_NAME := This program kills fascists.
|
VERSION_NAME := This program kills fascists.
|
||||||
|
|
||||||
SQLITE_URL := https://www.sqlite.org/2025/sqlite-amalgamation-3480000.zip
|
SQLITE_URL := https://www.sqlite.org/2025/sqlite-amalgamation-3480000.zip
|
||||||
@ -33,23 +33,21 @@ UNAME_M := $(shell uname -m)
|
|||||||
ANDROID_SDK ?= ~/Android/Sdk
|
ANDROID_SDK ?= ~/Android/Sdk
|
||||||
BUNDLETOOL = out/bundletool.jar
|
BUNDLETOOL = out/bundletool.jar
|
||||||
|
|
||||||
HAVE_WIN :=
|
HAVE_WIN := 0
|
||||||
HAVE_CROSS_AARCH64 :=
|
HAVE_CROSS_AARCH64 := 0
|
||||||
USE_SYSTEM_SSL :=
|
|
||||||
|
|
||||||
export SOURCE_DATE_EPOCH=1
|
export SOURCE_DATE_EPOCH=1
|
||||||
export TZ=UTC
|
export TZ=UTC
|
||||||
|
|
||||||
ifeq ($(UNAME_S),Darwin)
|
ifeq ($(UNAME_S),Darwin)
|
||||||
BUILD_TYPES := debug release iosdebug iosrelease iossimdebug iossimrelease
|
BUILD_TYPES := macosdebug macosrelease iosdebug iosrelease iossimdebug iossimrelease
|
||||||
else ifeq ($(UNAME_S),Linux)
|
else ifeq ($(UNAME_S),Linux)
|
||||||
BUILD_TYPES := debug release
|
BUILD_TYPES := debug release
|
||||||
HAVE_ANDROID = $(if $(shell which $(ANDROID_SDK)/platform-tools/adb),1)
|
HAVE_ANDROID = $(if $(shell which $(ANDROID_SDK)/platform-tools/adb),1,0)
|
||||||
HAVE_LINUX_IOS = $(if $(shell which deps/ios_toolchain/target/bin deps/ios_toolchain/target/bin/arm-apple-darwin11-clang),1)
|
HAVE_LINUX_IOS = $(if $(shell which deps/ios_toolchain/target/bin deps/ios_toolchain/target/bin/arm-apple-darwin11-clang),1,0)
|
||||||
HAVE_LINUX_MACOS = $(if $(shell which deps/macos_toolchain/bin/oa64-clang),1)
|
HAVE_WIN = $(if $(shell which x86_64-w64-mingw32-gcc-win32),1,0)
|
||||||
HAVE_WIN = $(if $(shell which x86_64-w64-mingw32-gcc-win32),1)
|
|
||||||
ifneq ($(UNAME_M),aarch64)
|
ifneq ($(UNAME_M),aarch64)
|
||||||
HAVE_CROSS_AARCH64 = $(if $(shell which aarch64-linux-gnu-gcc),1)
|
HAVE_CROSS_AARCH64 = $(if $(shell which aarch64-linux-gnu-gcc),1,0)
|
||||||
endif
|
endif
|
||||||
else ifeq ($(UNAME_S),Haiku)
|
else ifeq ($(UNAME_S),Haiku)
|
||||||
BUILD_TYPES := debug release
|
BUILD_TYPES := debug release
|
||||||
@ -58,7 +56,6 @@ LDFLAGS += \
|
|||||||
-lbsd \
|
-lbsd \
|
||||||
-lnetwork \
|
-lnetwork \
|
||||||
-Wno-stringop-overflow
|
-Wno-stringop-overflow
|
||||||
USE_SYSTEM_SSL := 1
|
|
||||||
else ifeq ($(UNAME_S),OpenBSD)
|
else ifeq ($(UNAME_S),OpenBSD)
|
||||||
BUILD_TYPES := debug release
|
BUILD_TYPES := debug release
|
||||||
CFLAGS += \
|
CFLAGS += \
|
||||||
@ -66,17 +63,12 @@ CFLAGS += \
|
|||||||
LDFLAGS += \
|
LDFLAGS += \
|
||||||
-lexecinfo \
|
-lexecinfo \
|
||||||
-lc++abi
|
-lc++abi
|
||||||
HAVE_ANDROID :=
|
HAVE_ANDROID := 0
|
||||||
HAVE_LINUX_IOS :=
|
HAVE_LINUX_IOS := 0
|
||||||
HAVE_LINUX_MACOS :=
|
|
||||||
USE_SYSTEM_SSL := 1
|
|
||||||
else
|
else
|
||||||
$(error Unexpected host platform $(UNAME_S).)
|
$(error Unexpected host platform $(UNAME_S).)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Everything is set above.
|
|
||||||
$(info Building Tilde Friends $(VERSION_NUMBER) android=$(if $(HAVE_ANDROID),1,0) win=$(if $(HAVE_WIN),1,0) cross_aarch64=$(if $(HAVE_CROSS_AARCH64),1,0) cross_ios=$(if $(HAVE_LINUX_IOS),1,0) cross_macos=$(if $(HAVE_LINUX_MACOS),1,0) system_ssl=$(if $(USE_SYSTEM_SSL),1,0))
|
|
||||||
|
|
||||||
CFLAGS += \
|
CFLAGS += \
|
||||||
-std=gnu11 \
|
-std=gnu11 \
|
||||||
-Wall \
|
-Wall \
|
||||||
@ -144,26 +136,12 @@ ifeq ($(HAVE_CROSS_AARCH64),1)
|
|||||||
BUILD_TYPES += armdebug armrelease
|
BUILD_TYPES += armdebug armrelease
|
||||||
endif
|
endif
|
||||||
|
|
||||||
HOST_TARGETS := \
|
LINUX_TARGETS := \
|
||||||
out/debug/tildefriends \
|
out/debug/tildefriends \
|
||||||
out/release/tildefriends
|
out/release/tildefriends
|
||||||
ifeq ($(UNAME_S),Darwin)
|
|
||||||
MACOS_TARGETS := \
|
MACOS_TARGETS := \
|
||||||
out/debug/tildefriends \
|
out/macosdebug/tildefriends \
|
||||||
out/release/tildefriends
|
out/macosrelease/tildefriends
|
||||||
else ifeq ($(UNAME_S),Linux)
|
|
||||||
ifeq ($(HAVE_LINUX_MACOS),1)
|
|
||||||
MACOS_TARGETS := \
|
|
||||||
out/macosdebug-arm/tildefriends \
|
|
||||||
out/macosrelease-arm/tildefriends \
|
|
||||||
out/macosdebug-x86_64/tildefriends \
|
|
||||||
out/macosrelease-x86_64/tildefriends
|
|
||||||
else
|
|
||||||
MACOS_TARGETS :=
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
MACOS_TARGETS :=
|
|
||||||
endif
|
|
||||||
IOS_TARGETS := \
|
IOS_TARGETS := \
|
||||||
out/iosdebug/tildefriends \
|
out/iosdebug/tildefriends \
|
||||||
out/iosrelease/tildefriends
|
out/iosrelease/tildefriends
|
||||||
@ -177,14 +155,6 @@ ifeq ($(HAVE_LINUX_IOS),1)
|
|||||||
BUILD_TYPES += iosdebug iosrelease
|
BUILD_TYPES += iosdebug iosrelease
|
||||||
all: $(IOS_APPS)
|
all: $(IOS_APPS)
|
||||||
endif
|
endif
|
||||||
ifeq ($(HAVE_LINUX_MACOS),1)
|
|
||||||
BUILD_TYPES += \
|
|
||||||
macosdebug-arm \
|
|
||||||
macosrelease-arm \
|
|
||||||
macosdebug-x86_64 \
|
|
||||||
macosrelease-x86_64
|
|
||||||
all: $(IOS_APPS)
|
|
||||||
endif
|
|
||||||
ifeq ($(UNAME_S),Darwin)
|
ifeq ($(UNAME_S),Darwin)
|
||||||
all: $(IOS_APPS) \
|
all: $(IOS_APPS) \
|
||||||
out/tildefriends-iossimdebug.app/tildefriends \
|
out/tildefriends-iossimdebug.app/tildefriends \
|
||||||
@ -199,30 +169,29 @@ DEBUG_TARGETS := \
|
|||||||
out/windebug/tildefriends.exe \
|
out/windebug/tildefriends.exe \
|
||||||
out/iosdebug/tildefriends \
|
out/iosdebug/tildefriends \
|
||||||
out/iossimdebug/tildefriends \
|
out/iossimdebug/tildefriends \
|
||||||
|
out/macosdebug/tildefriends \
|
||||||
out/androiddebug/tildefriends \
|
out/androiddebug/tildefriends \
|
||||||
out/androiddebug-armv7a/tildefriends \
|
out/androiddebug-armv7a/tildefriends \
|
||||||
out/androiddebug-x86_64/tildefriends \
|
out/androiddebug-x86_64/tildefriends \
|
||||||
out/androiddebug-x86/tildefriends \
|
out/androiddebug-x86/tildefriends \
|
||||||
out/armdebug/tildefriends \
|
out/armdebug/tildefriends
|
||||||
out/macosdebug-arm/tildefriends \
|
|
||||||
out/macosdebug-x86_64/tildefriends
|
|
||||||
RELEASE_TARGETS := \
|
RELEASE_TARGETS := \
|
||||||
out/release/tildefriends \
|
out/release/tildefriends \
|
||||||
out/winrelease/tildefriends.exe \
|
out/winrelease/tildefriends.exe \
|
||||||
out/iosrelease/tildefriends \
|
out/iosrelease/tildefriends \
|
||||||
out/iossimrelease/tildefriends \
|
out/iossimrelease/tildefriends \
|
||||||
|
out/macosrelease/tildefriends \
|
||||||
out/androidrelease/tildefriends \
|
out/androidrelease/tildefriends \
|
||||||
out/androidrelease-armv7a/tildefriends \
|
out/androidrelease-armv7a/tildefriends \
|
||||||
out/androidrelease-x86_64/tildefriends \
|
out/androidrelease-x86_64/tildefriends \
|
||||||
out/androidrelease-x86/tildefriends \
|
out/androidrelease-x86/tildefriends \
|
||||||
out/armrelease/tildefriends \
|
out/armrelease/tildefriends
|
||||||
out/macosrelease-arm/tildefriends \
|
|
||||||
out/macosrelease-x86_64/tildefriends
|
|
||||||
ALL_TARGETS = $(DEBUG_TARGETS) $(RELEASE_TARGETS)
|
ALL_TARGETS = $(DEBUG_TARGETS) $(RELEASE_TARGETS)
|
||||||
ANDROID_RELEASE_TARGETS := $(filter-out $(DEBUG_TARGETS),$(ANDROID_TARGETS))
|
ANDROID_RELEASE_TARGETS := $(filter-out $(DEBUG_TARGETS),$(ANDROID_TARGETS))
|
||||||
NONANDROID_RELEASE_TARGETS := $(filter-out $(ANDROID_ARM64_TARGETS),$(RELEASE_TARGETS))
|
NONANDROID_RELEASE_TARGETS := $(filter-out $(ANDROID_ARM64_TARGETS),$(RELEASE_TARGETS))
|
||||||
NONANDROID_TARGETS := $(filter-out $(ANDROID_TARGETS),$(ALL_TARGETS))
|
NONANDROID_TARGETS := $(filter-out $(ANDROID_TARGETS),$(ALL_TARGETS))
|
||||||
NONMACOS_TARGETS := $(filter-out $(MACOS_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS),$(ALL_TARGETS))
|
NONMACOS_TARGETS := $(filter-out $(MACOS_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS),$(ALL_TARGETS))
|
||||||
|
DEADSTRIP_TARGETS := $(filter-out $(ANDROID_TARGETS),$(NONMACOS_TARGETS))
|
||||||
ifneq ($(UNAME_S),OpenBSD)
|
ifneq ($(UNAME_S),OpenBSD)
|
||||||
$(NONMACOS_TARGETS): LDFLAGS += -static-libgcc
|
$(NONMACOS_TARGETS): LDFLAGS += -static-libgcc
|
||||||
endif
|
endif
|
||||||
@ -252,29 +221,25 @@ $(WINDOWS_TARGETS): CFLAGS += \
|
|||||||
-D_WIN32_WINNT=0x0A00 \
|
-D_WIN32_WINNT=0x0A00 \
|
||||||
-DWINVER=0x0A00 \
|
-DWINVER=0x0A00 \
|
||||||
-DNTDDI_VERSION=NTDDI_WIN10 \
|
-DNTDDI_VERSION=NTDDI_WIN10 \
|
||||||
-Iout/openssl/$(UNAME_S)/mingw64/usr/local/include
|
-Ideps/openssl/mingw64/usr/local/include
|
||||||
$(WINDOWS_TARGETS): LDFLAGS += \
|
$(WINDOWS_TARGETS): LDFLAGS += \
|
||||||
-static \
|
-static \
|
||||||
-lm \
|
-lm \
|
||||||
-Lout/openssl/$(UNAME_S)/mingw64/usr/local/lib
|
-Ldeps/openssl/mingw64/usr/local/lib
|
||||||
$(AARCH64_TARGETS): CC = aarch64-linux-gnu-gcc
|
$(AARCH64_TARGETS): CC = aarch64-linux-gnu-gcc
|
||||||
$(AARCH64_TARGETS): AS = $(CC)
|
$(AARCH64_TARGETS): AS = $(CC)
|
||||||
$(AARCH64_TARGETS): CFLAGS += -Iout/openssl/Linux/aarch64/usr/local/include
|
$(AARCH64_TARGETS): CFLAGS += -Ideps/openssl/Linux/aarch64/usr/local/include
|
||||||
$(AARCH64_TARGETS): LDFLAGS += -Lout/openssl/Linux/aarch64/usr/local/lib
|
$(AARCH64_TARGETS): LDFLAGS += -Ldeps/openssl/Linux/aarch64/usr/local/lib
|
||||||
ifeq ($(UNAME_S),Darwin)
|
ifeq ($(UNAME_S),Darwin)
|
||||||
$(HOST_TARGETS): CC = xcrun clang
|
$(MACOS_TARGETS): CC = xcrun clang
|
||||||
$(IOS_TARGETS): IOS_SYSROOT := $(shell xcrun --sdk iphoneos --show-sdk-path)
|
$(IOS_TARGETS): IOS_SYSROOT := $(shell xcrun --sdk iphoneos --show-sdk-path)
|
||||||
$(IOS_TARGETS): CC = xcrun --sdk iphoneos clang -isysroot $(IOS_SYSROOT) -arch arm64
|
$(IOS_TARGETS): CC = xcrun --sdk iphoneos clang -isysroot $(IOS_SYSROOT) -arch arm64
|
||||||
$(IOSSIM_TARGETS): IOSSIM_SYSROOT := $(shell xcrun --sdk iphonesimulator --show-sdk-path)
|
$(IOSSIM_TARGETS): IOSSIM_SYSROOT := $(shell xcrun --sdk iphonesimulator --show-sdk-path)
|
||||||
$(IOSSIM_TARGETS): CC = xcrun --sdk iphonesimulator clang -isysroot $(IOSSIM_SYSROOT) -arch x86_64
|
$(IOSSIM_TARGETS): CC = xcrun --sdk iphonesimulator clang -isysroot $(IOSSIM_SYSROOT) -arch x86_64
|
||||||
else ifeq ($(UNAME_S),Linux)
|
else ifeq ($(UNAME_S),Linux)
|
||||||
$(IOS_TARGETS): CFLAGS += -isysroot deps/ios_toolchain/target/SDKs/iPhoneOS18.2.sdk -arch arm64 -DTARGET_OS_IPHONE=1
|
$(IOS_TARGETS): CFLAGS += -isysroot deps/ios_toolchain/target/SDKs/iPhoneOS18.2.sdk -arch arm64
|
||||||
$(IOS_TARGETS): LDFLAGS += -isysroot deps/ios_toolchain/target/SDKs/iPhoneOS18.2.sdk
|
$(IOS_TARGETS): LDFLAGS += -isysroot deps/ios_toolchain/target/SDKs/iPhoneOS18.2.sdk
|
||||||
$(IOS_TARGETS): CC = PATH=$$PATH:deps/ios_toolchain/target/bin LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:deps/ios_toolchain/target/lib deps/ios_toolchain/target/bin/arm-apple-darwin11-clang
|
$(IOS_TARGETS): CC = PATH=$$PATH:deps/ios_toolchain/target/bin deps/ios_toolchain/target/bin/arm-apple-darwin11-clang
|
||||||
$(filter $(BUILD_DIR)/macosdebug-x86_64/%,$(ALL_TARGETS)): CC = PATH=deps/macos_toolchain/bin:$$PATH deps/macos_toolchain/bin/o64-clang
|
|
||||||
$(filter $(BUILD_DIR)/macosdebug-arm/%,$(ALL_TARGETS)): CC = PATH=deps/macos_toolchain/bin:$$PATH deps/macos_toolchain/bin/oa64-clang
|
|
||||||
$(filter $(BUILD_DIR)/macosrelease-x86_64/%,$(ALL_TARGETS)): CC = PATH=deps/macos_toolchain/bin:$$PATH deps/macos_toolchain/bin/o64-clang
|
|
||||||
$(filter $(BUILD_DIR)/macosrelease-arm/%,$(ALL_TARGETS)): CC = PATH=deps/macos_toolchain/bin:$$PATH deps/macos_toolchain/bin/oa64-clang
|
|
||||||
endif
|
endif
|
||||||
$(ANDROID_X86_64_TARGETS): ANDROID_NDK_TARGET_TRIPLE := x86_64-linux-android
|
$(ANDROID_X86_64_TARGETS): ANDROID_NDK_TARGET_TRIPLE := x86_64-linux-android
|
||||||
$(ANDROID_X86_TARGETS): ANDROID_NDK_TARGET_TRIPLE := i686-linux-android
|
$(ANDROID_X86_TARGETS): ANDROID_NDK_TARGET_TRIPLE := i686-linux-android
|
||||||
@ -285,35 +250,30 @@ $(ANDROID_TARGETS): AS = $(CC)
|
|||||||
$(ANDROID_TARGETS): CFLAGS += \
|
$(ANDROID_TARGETS): CFLAGS += \
|
||||||
-target $(ANDROID_NDK_TARGET_TRIPLE)$(ANDROID_MIN_SDK_VERSION) \
|
-target $(ANDROID_NDK_TARGET_TRIPLE)$(ANDROID_MIN_SDK_VERSION) \
|
||||||
-Wno-unknown-warning-option
|
-Wno-unknown-warning-option
|
||||||
$(ANDROID_ARMV7A_TARGETS): CFLAGS += -Iout/openssl/android/armeabi-v7a/usr/local/include
|
$(ANDROID_ARMV7A_TARGETS): CFLAGS += -Ideps/openssl/android/armeabi-v7a/usr/local/include
|
||||||
$(ANDROID_ARMV7A_TARGETS): LDFLAGS += -Lout/openssl/android/armeabi-v7a/usr/local/lib
|
$(ANDROID_ARMV7A_TARGETS): LDFLAGS += -Ldeps/openssl/android/armeabi-v7a/usr/local/lib
|
||||||
$(ANDROID_ARM64_TARGETS): CFLAGS += -Iout/openssl/android/arm64-v8a/usr/local/include
|
$(ANDROID_ARM64_TARGETS): CFLAGS += -Ideps/openssl/android/arm64-v8a/usr/local/include
|
||||||
$(ANDROID_ARM64_TARGETS): LDFLAGS += -Lout/openssl/android/arm64-v8a/usr/local/lib
|
$(ANDROID_ARM64_TARGETS): LDFLAGS += -Ldeps/openssl/android/arm64-v8a/usr/local/lib
|
||||||
$(ANDROID_X86_TARGETS): CFLAGS += -Iout/openssl/android/x86/usr/local/include
|
$(ANDROID_X86_TARGETS): CFLAGS += -Ideps/openssl/android/x86/usr/local/include
|
||||||
$(ANDROID_X86_TARGETS): CFLAGS += -Wno-atomic-alignment
|
$(ANDROID_X86_TARGETS): CFLAGS += -Wno-atomic-alignment
|
||||||
$(ANDROID_X86_TARGETS): LDFLAGS += -Lout/openssl/android/x86/usr/local/lib
|
$(ANDROID_X86_TARGETS): LDFLAGS += -Ldeps/openssl/android/x86/usr/local/lib
|
||||||
$(ANDROID_X86_64_TARGETS): CFLAGS += -Iout/openssl/android/x86_64/usr/local/include
|
$(ANDROID_X86_64_TARGETS): CFLAGS += -Ideps/openssl/android/x86_64/usr/local/include
|
||||||
$(ANDROID_X86_64_TARGETS): LDFLAGS += -Lout/openssl/android/x86_64/usr/local/lib
|
$(ANDROID_X86_64_TARGETS): LDFLAGS += -Ldeps/openssl/android/x86_64/usr/local/lib
|
||||||
$(NONMACOS_TARGETS): CFLAGS += -Wno-cast-function-type
|
$(NONMACOS_TARGETS): CFLAGS += -Wno-cast-function-type
|
||||||
$(MACOS_TARGETS): LDFLAGS += -Wl,-dead_strip
|
$(DEADSTRIP_TARGETS): LDFLAGS += -Wl,--gc-sections
|
||||||
$(NONMACOS_TARGETS): LDFLAGS += -Wl,--gc-sections -Wl,--as-needed
|
|
||||||
$(IOS_TARGETS): CFLAGS += -miphoneos-version-min=9.0
|
$(IOS_TARGETS): CFLAGS += -miphoneos-version-min=9.0
|
||||||
$(IOS_TARGETS): LDFLAGS += -miphoneos-version-min=9.0
|
$(IOS_TARGETS): LDFLAGS += -miphoneos-version-min=9.0
|
||||||
ifeq ($(UNAME_S),Darwin)
|
ifeq ($(UNAME_S),Darwin)
|
||||||
$(IOS_TARGETS): CFLAGS += -Iout/openssl/ios/ios64-xcrun/usr/local/include
|
$(IOS_TARGETS): CFLAGS += -Ideps/openssl/ios/ios64-xcrun/usr/local/include
|
||||||
$(IOS_TARGETS): LDFLAGS += -Lout/openssl/ios/ios64-xcrun/usr/local/lib
|
$(IOS_TARGETS): LDFLAGS += -Ldeps/openssl/ios/ios64-xcrun/usr/local/lib
|
||||||
else
|
else
|
||||||
$(IOS_TARGETS): CFLAGS += -Iout/openssl/$(UNAME_S)/ios64-cross/usr/local/include
|
$(IOS_TARGETS): CFLAGS += -Ideps/openssl/$(UNAME_S)/ios64-cross/usr/local/include
|
||||||
$(IOS_TARGETS): LDFLAGS += -Lout/openssl/$(UNAME_S)/ios64-cross/usr/local/lib
|
$(IOS_TARGETS): LDFLAGS += -Ldeps/openssl/$(UNAME_S)/ios64-cross/usr/local/lib
|
||||||
$(filter $(BUILD_DIR)/macosdebug-x86_64/%,$(ALL_TARGETS)): CFLAGS += -Iout/openssl/$(UNAME_S)/macos-x86_64/usr/local/include
|
|
||||||
$(filter $(BUILD_DIR)/macosdebug-arm/%,$(ALL_TARGETS)): CFLAGS += -Iout/openssl/$(UNAME_S)/macos-arm/usr/local/include
|
|
||||||
$(filter $(BUILD_DIR)/macosdebug-x86_64/%,$(ALL_TARGETS)): LDFLAGS += -Lout/openssl/$(UNAME_S)/macos-x86_64/usr/local/lib
|
|
||||||
$(filter $(BUILD_DIR)/macosdebug-arm/%,$(ALL_TARGETS)): LDFLAGS += -Lout/openssl/$(UNAME_S)/macos-arm/usr/local/lib
|
|
||||||
endif
|
endif
|
||||||
$(IOSSIM_TARGETS): CFLAGS += -Iout/openssl/ios/iossimulator-xcrun/usr/local/include
|
$(IOSSIM_TARGETS): CFLAGS += -Ideps/openssl/ios/iossimulator-xcrun/usr/local/include
|
||||||
$(IOSSIM_TARGETS): LDFLAGS += -Lout/openssl/ios/iossimulator-xcrun/usr/local/lib
|
$(IOSSIM_TARGETS): LDFLAGS += -Ldeps/openssl/ios/iossimulator-xcrun/usr/local/lib
|
||||||
$(HOST_TARGETS): CFLAGS += -Iout/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/include
|
$(LINUX_TARGETS) $(MACOS_TARGETS): CFLAGS += -Ideps/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/include
|
||||||
$(HOST_TARGETS): LDFLAGS += -Lout/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/lib
|
$(LINUX_TARGETS) $(MACOS_TARGETS): LDFLAGS += -Ldeps/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/lib
|
||||||
|
|
||||||
ifeq ($(UNAME_M),x86_64)
|
ifeq ($(UNAME_M),x86_64)
|
||||||
ifeq ($(UNAME_S),Linux)
|
ifeq ($(UNAME_S),Linux)
|
||||||
@ -332,14 +292,13 @@ endif
|
|||||||
|
|
||||||
get_objs = \
|
get_objs = \
|
||||||
$(foreach build_type,$(BUILD_TYPES),$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)))))) \
|
$(foreach build_type,$(BUILD_TYPES),$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)))))) \
|
||||||
|
$(foreach build_type,debug release armdebug armrelease,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_unix))))) \
|
||||||
$(foreach build_type,windebug winrelease,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_win))))) \
|
$(foreach build_type,windebug winrelease,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_win))))) \
|
||||||
$(foreach build_type,androiddebug androidrelease androiddebug-x86 androidrelease-x86 androiddebug-x86_64 androidrelease-x86_64 androiddebug-armv7a androidrelease-armv7a,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_android))))) \
|
$(foreach build_type,androiddebug androidrelease androiddebug-x86 androidrelease-x86 androiddebug-x86_64 androidrelease-x86_64 androiddebug-armv7a androiddebug-armv7a,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_android))))) \
|
||||||
$(foreach build_type,androiddebug androidrelease androiddebug-x86 androidrelease-x86 androiddebug-x86_64 androidrelease-x86_64 androiddebug-armv7a androidrelease-armv7a,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_unix))))) \
|
$(foreach build_type,androiddebug androidrelease androiddebug-x86 androidrelease-x86 androiddebug-x86_64 androidrelease-x86_64 androiddebug-armv7a androidrelease-armv7a,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_unix))))) \
|
||||||
|
$(foreach build_type,macosdebug macosrelease iosdebug iosrelease iossimdebug iossimrelease,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_macos))))) \
|
||||||
$(foreach build_type,iosdebug iosrelease iossimdebug iossimrelease,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_ios))))) \
|
$(foreach build_type,iosdebug iosrelease iossimdebug iossimrelease,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_ios))))) \
|
||||||
$(foreach build_type,iosdebug iosrelease iossimdebug iossimrelease macosdebug-arm macosrelease-arm macosdebug-x86_64 macosrelease-x86_64,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_macos))))) \
|
$(foreach build_type,androiddebug-x86 androidrelease-x86,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_x86)))))
|
||||||
$(foreach build_type,androiddebug-x86 androidrelease-x86,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_x86))))) \
|
|
||||||
$(if $(findstring Darwin,$(UNAME_S)),$(foreach build_type,debug release,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_macos)))))) \
|
|
||||||
$(if $(findstring Darwin,$(UNAME_S)),,$(foreach build_type,debug release armdebug armrelease,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_unix))))))
|
|
||||||
|
|
||||||
APP_SOURCES := $(wildcard src/*.c)
|
APP_SOURCES := $(wildcard src/*.c)
|
||||||
APP_SOURCES_ios := $(wildcard src/*.m)
|
APP_SOURCES_ios := $(wildcard src/*.m)
|
||||||
@ -361,12 +320,10 @@ $(APP_OBJS): CFLAGS += \
|
|||||||
-Ideps/valgrind \
|
-Ideps/valgrind \
|
||||||
-Wdouble-promotion \
|
-Wdouble-promotion \
|
||||||
-Werror
|
-Werror
|
||||||
ifneq ($(UNAME_S),Darwin)
|
|
||||||
ifeq ($(UNAME_M),x86_64)
|
ifeq ($(UNAME_M),x86_64)
|
||||||
$(filter-out $(BUILD_DIR)/android% $(BUILD_DIR)/ios% $(BUILD_DIR)/macos%,$(APP_OBJS)): CFLAGS += \
|
$(filter-out $(BUILD_DIR)/android% $(BUILD_DIR)/macos% $(BUILD_DIR)/ios%,$(APP_OBJS)): CFLAGS += \
|
||||||
-fanalyzer
|
-fanalyzer
|
||||||
endif
|
endif
|
||||||
endif
|
|
||||||
|
|
||||||
ARES_SOURCES := \
|
ARES_SOURCES := \
|
||||||
deps/c-ares/src/lib/ares_addrinfo2hostent.c \
|
deps/c-ares/src/lib/ares_addrinfo2hostent.c \
|
||||||
@ -799,12 +756,12 @@ $(MINIUNZIP_OBJS): CFLAGS += \
|
|||||||
LDFLAGS += \
|
LDFLAGS += \
|
||||||
-pthread \
|
-pthread \
|
||||||
-lm
|
-lm
|
||||||
$(HOST_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS) $(AARCH64_TARGETS) $(MACOS_TARGETS): LDFLAGS += \
|
$(LINUX_TARGETS) $(MACOS_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS) $(AARCH64_TARGETS): LDFLAGS += \
|
||||||
-lssl \
|
-lssl \
|
||||||
-lcrypto
|
-lcrypto
|
||||||
ifneq ($(UNAME_S),Haiku)
|
ifneq ($(UNAME_S),Haiku)
|
||||||
ifneq ($(UNAME_S),OpenBSD)
|
ifneq ($(UNAME_S),OpenBSD)
|
||||||
$(HOST_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS): LDFLAGS += \
|
debug release $(MACOS_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS): LDFLAGS += \
|
||||||
-ldl
|
-ldl
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
@ -837,15 +794,27 @@ $(IOS_TARGETS) $(IOSSIM_TARGETS): LDFLAGS += \
|
|||||||
##
|
##
|
||||||
## Common targets:
|
## Common targets:
|
||||||
##
|
##
|
||||||
all: $(BUILD_TYPES) ## Build all targets that appear possible to build on this machine.
|
debug: ## Build a debug executable for the current platform.
|
||||||
debug: ## Build a debug executable for the current host platform.
|
release: ## Build a release executable for the current platform.
|
||||||
release: ## Build a release executable for the current host platform.
|
|
||||||
armdebug: ## Cross-compile aarch64 debug on Linux.
|
armdebug: ## Cross-compile aarch64 debug on Linux.
|
||||||
armrelease: ## Cross-compile aarch64 release on Linux.
|
armrelease: ## Cross-compile aarch64 release on Linux.
|
||||||
windebug: ## Cross-compile a debug win32 executable on Linux.
|
all: $(BUILD_TYPES) ## Build all targets that appear possible to build on this machine.
|
||||||
winrelease: ## Cross-compile a release win32 executable on Linux.
|
unix: debug release ## Build all UNIX targets.
|
||||||
|
win: windebug winrelease ## Build all Windows targets.
|
||||||
.PHONY: all win unix
|
.PHONY: all win unix
|
||||||
|
|
||||||
|
##
|
||||||
|
## Windows targets:
|
||||||
|
##
|
||||||
|
windebug: ## Build a debug win32 executable.
|
||||||
|
winrelease: ## Build a release win32 executable.
|
||||||
|
|
||||||
|
##
|
||||||
|
## MacOS targets:
|
||||||
|
##
|
||||||
|
macosdebug: ## Build a MacOS debug executable.
|
||||||
|
macosrelease: ## Build a MacOS release executable.
|
||||||
|
|
||||||
ALL_APP_OBJS := \
|
ALL_APP_OBJS := \
|
||||||
$(APP_OBJS) \
|
$(APP_OBJS) \
|
||||||
$(ARES_OBJS) \
|
$(ARES_OBJS) \
|
||||||
@ -1017,7 +986,7 @@ out/TildeFriends.aab: out/apk/classes.dex $(filter-out %debug%, $(ANDROID_TARGET
|
|||||||
@cp -r deps/codemirror/ out/aab/staging/root/deps/
|
@cp -r deps/codemirror/ out/aab/staging/root/deps/
|
||||||
@cd out/aab/staging/; zip -r ../base.zip *; cd ../../../
|
@cd out/aab/staging/; zip -r ../base.zip *; cd ../../../
|
||||||
@java -jar $(BUNDLETOOL) build-bundle --overwrite --config=src/android/BundleConfig.json --modules=out/aab/base.zip --output=$@
|
@java -jar $(BUNDLETOOL) build-bundle --overwrite --config=src/android/BundleConfig.json --modules=out/aab/base.zip --output=$@
|
||||||
@$(ANDROID_BUILD_TOOLS)/apksigner sign -ks .keys/android.jks --ks-key-alias androidKey -ks-pass pass:android --min-sdk-version=$(ANDROID_MIN_SDK_VERSION) $@
|
@jarsigner -keystore .keys/android.jks $@ androidKey -storepass android
|
||||||
|
|
||||||
aab: out/TildeFriends.aab ## Build an Android App Bundle.
|
aab: out/TildeFriends.aab ## Build an Android App Bundle.
|
||||||
.PHONY: aab
|
.PHONY: aab
|
||||||
@ -1123,18 +1092,12 @@ out/data.zip: $(RAW_FILES)
|
|||||||
@echo [zip] $@
|
@echo [zip] $@
|
||||||
@zip -u $@ -q -9 $(RAW_FILES)
|
@zip -u $@ -q -9 $(RAW_FILES)
|
||||||
|
|
||||||
out/zsign_build/zsign: $(wildcard deps/zsign/*.cpp deps/zsign/*.h deps/zsign/*.txt deps/zsign/common/*)
|
out/tildefriends-%.app/tildefriends: out/%/tildefriends out/tildefriends-%.app/Info.plist out/tildefriends-%.app/tildefriends.png out/data.zip
|
||||||
@+echo [cmake] $@
|
|
||||||
@cmake -B out/zsign_build deps/zsign
|
|
||||||
@cmake --build out/zsign_build -- COLOR=0 VERBOSE=0 MAKESILENT=-s
|
|
||||||
|
|
||||||
out/tildefriends-%.app/tildefriends: out/%/tildefriends out/tildefriends-%.app/Info.plist out/tildefriends-%.app/tildefriends.png out/data.zip $(if $(HAVE_LINUX_IOS),out/zsign_build/zsign)
|
|
||||||
@mkdir -p $(dir $@)
|
@mkdir -p $(dir $@)
|
||||||
@cp -v $(filter-out out/zsign%,$<) $@
|
@cp -v $< $@
|
||||||
@cp -v out/data.zip $(@D)/
|
@cp -v out/data.zip $(@D)/
|
||||||
ifeq ($(HAVE_LINUX_IOS),1)
|
ifeq ($(HAVE_LINUX_IOS),1)
|
||||||
@mkdir -p $(realpath $(dir $@))/_CodeSignature
|
@zsign -q -k .keys/apple.p12 -f -m src/ios/embedded.mobileprovision $(realpath $(dir $@))
|
||||||
@out/zsign_build/zsign -q -k .keys/apple.p12 -f -m src/ios/embedded.mobileprovision $(realpath $(dir $@))
|
|
||||||
endif
|
endif
|
||||||
.SECONDARY:
|
.SECONDARY:
|
||||||
out/tildefriends-%.ipa: out/tildefriends-ios%.app/tildefriends
|
out/tildefriends-%.ipa: out/tildefriends-ios%.app/tildefriends
|
||||||
@ -1172,34 +1135,26 @@ iossimdebuggo: out/tildefriends-iossimdebug.app/tildefriends ## Build, install,
|
|||||||
xcrun simctl launch booted com.unprompted.tildefriends
|
xcrun simctl launch booted com.unprompted.tildefriends
|
||||||
.PHONY: iossimdebuggo
|
.PHONY: iossimdebuggo
|
||||||
|
|
||||||
ANDROID_DEPS := out/openssl/android/arm64-v8a/usr/local/lib/libssl.a
|
ANDROID_DEPS := deps/openssl/android/arm64-v8a/usr/local/lib/libssl.a
|
||||||
$(ANDROID_DEPS):
|
$(ANDROID_DEPS):
|
||||||
+@export ANDROID_NDK_ROOT=$(ANDROID_NDK)
|
+@ANDROID_NDK_ROOT=$(ANDROID_NDK) tools/ssl-android
|
||||||
+@export BUILD_PLATFORM=android
|
|
||||||
+@export TOOLCHAIN=$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64
|
|
||||||
+@PATH="$$TOOLCHAIN/x86_64-linux-android/bin:$$TOOLCHAIN/bin:$$PATH" BUILD_TARGET=x86_64 SSL_TARGET=android-x86_64 OPTIONS="-D__ANDROID_API__=$(ANDROID_MIN_SDK_VERSION) -Wno-macro-redefined" tools/ssl-local
|
|
||||||
+@PATH="$$TOOLCHAIN/i686-linux-android/bin:$$TOOLCHAIN/bin:$$PATH" BUILD_TARGET=x86 SSL_TARGET=android-x86 OPTIONS="-D__ANDROID_API__=$(ANDROID_MIN_SDK_VERSION) -Wno-macro-redefined" tools/ssl-local
|
|
||||||
+@PATH="$$TOOLCHAIN/arm-linux-androideabi/bin:$$TOOLCHAIN/bin:$$PATH" BUILD_TARGET=armeabi-v7a SSL_TARGET=android-arm OPTIONS="--target=armv7a-linux-androideabi -Wl,--fix-cortex-a8 -D__ANDROID_API__=$(ANDROID_MIN_SDK_VERSION) -Wno-macro-redefined" tools/ssl-local
|
|
||||||
+@PATH="$$TOOLCHAIN/aarch64-linux-android/bin:$$TOOLCHAIN/bin:$$PATH" BUILD_TARGET=arm64-v8a SSL_TARGET=android-arm64 OPTIONS="-D__ANDROID_API__=$(ANDROID_MIN_SDK_VERSION) -Wno-macro-redefined" tools/ssl-local
|
|
||||||
$(filter $(BUILD_DIR)/android%,$(APP_OBJS)): | $(ANDROID_DEPS)
|
$(filter $(BUILD_DIR)/android%,$(APP_OBJS)): | $(ANDROID_DEPS)
|
||||||
|
|
||||||
ifeq ($(UNAME_S),Linux)
|
ifeq ($(UNAME_S),Linux)
|
||||||
ifneq ($(USE_SYSTEM_SSL),1)
|
LOCAL_DEPS := deps/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/lib/libssl.a
|
||||||
LOCAL_DEPS := out/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/lib/libssl.a
|
|
||||||
$(LOCAL_DEPS):
|
$(LOCAL_DEPS):
|
||||||
+@tools/ssl-local
|
+@/usr/bin/env bash tools/ssl-local
|
||||||
$(filter $(BUILD_DIR)/debug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/release/%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
$(filter $(BUILD_DIR)/debug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/release/%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(HAVE_CROSS_AARCH64),1)
|
ifeq ($(HAVE_CROSS_AARCH64),1)
|
||||||
LOCAL_DEPS := out/openssl/$(UNAME_S)/aarch64/usr/local/lib/libssl.a
|
LOCAL_DEPS := deps/openssl/$(UNAME_S)/aarch64/usr/local/lib/libssl.a
|
||||||
$(LOCAL_DEPS):
|
$(LOCAL_DEPS):
|
||||||
+@OPTIONS="--cross-compile-prefix=aarch64-linux-gnu-" BUILD_TARGET=aarch64 SSL_TARGET=linux-aarch64 tools/ssl-local
|
+@OPTIONS="--cross-compile-prefix=aarch64-linux-gnu-" BUILD_TARGET=aarch64 tools/ssl-local
|
||||||
$(filter $(BUILD_DIR)/armdebug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/armrelease/%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
$(filter $(BUILD_DIR)/armdebug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/armrelease/%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(HAVE_LINUX_IOS),1)
|
ifeq ($(HAVE_LINUX_IOS),1)
|
||||||
LOCAL_DEPS := out/openssl/$(UNAME_S)/ios64-cross/usr/local/lib/libssl.a
|
LOCAL_DEPS := deps/openssl/$(UNAME_S)/ios64-cross/usr/local/lib/libssl.a
|
||||||
$(LOCAL_DEPS):
|
$(LOCAL_DEPS):
|
||||||
+@PATH=deps/ios_toolchain/target/bin:$$PATH \
|
+@PATH=deps/ios_toolchain/target/bin:$$PATH \
|
||||||
BUILD_TARGET=ios64-cross \
|
BUILD_TARGET=ios64-cross \
|
||||||
@ -1212,51 +1167,26 @@ $(LOCAL_DEPS):
|
|||||||
tools/ssl-local
|
tools/ssl-local
|
||||||
$(filter $(BUILD_DIR)/ios%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
$(filter $(BUILD_DIR)/ios%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(HAVE_LINUX_MACOS),1)
|
|
||||||
LOCAL_DEPS := out/openssl/$(UNAME_S)/macos-arm/usr/local/lib/libssl.a
|
|
||||||
$(LOCAL_DEPS):
|
|
||||||
+@PATH=../../deps/macos_toolchain/bin:$$PATH \
|
|
||||||
BUILD_TARGET=macos-arm \
|
|
||||||
SSL_TARGET=darwin64-arm64 \
|
|
||||||
CC=../../deps/macos_toolchain/bin/oa64-clang \
|
|
||||||
RANLIB=../../deps/macos_toolchain/bin/x86_64-apple-darwin24-ranlib \
|
|
||||||
AR=../../deps/macos_toolchain/bin/arm64-apple-darwin24-ar \
|
|
||||||
tools/ssl-local
|
|
||||||
$(filter $(BUILD_DIR)/macosrelease-arm/% $(BUILD_DIR)/macosdebug-arm/%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
|
||||||
|
|
||||||
LOCAL_DEPS := out/openssl/$(UNAME_S)/macos-x86_64/usr/local/lib/libssl.a
|
|
||||||
$(LOCAL_DEPS):
|
|
||||||
+@PATH=../../deps/macos_toolchain/bin:$$PATH \
|
|
||||||
BUILD_TARGET=macos-x86_64 \
|
|
||||||
SSL_TARGET=darwin64-x86_64 \
|
|
||||||
CC=../../deps/macos_toolchain/bin/o64-clang \
|
|
||||||
RANLIB=../../deps/macos_toolchain/bin/x86_64-apple-darwin24-ranlib \
|
|
||||||
AR=../../deps/macos_toolchain/bin/x86_64-apple-darwin24-ar \
|
|
||||||
tools/ssl-local
|
|
||||||
$(filter $(BUILD_DIR)/macosrelease-x86_64/% $(BUILD_DIR)/macosdebug-x86_64/%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(UNAME_S),Darwin)
|
ifeq ($(UNAME_S),Darwin)
|
||||||
LOCAL_DEPS := out/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/lib/libssl.a
|
LOCAL_DEPS := deps/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/lib/libssl.a
|
||||||
$(LOCAL_DEPS):
|
$(LOCAL_DEPS):
|
||||||
+@tools/ssl-local
|
+@tools/ssl-local
|
||||||
$(filter $(BUILD_DIR)/debug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/release/%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
$(filter $(BUILD_DIR)/macosdebug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/macosrelease/%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(HAVE_WIN),1)
|
ifeq ($(HAVE_WIN),1)
|
||||||
WINDOWS_DEPS := out/openssl/$(UNAME_S)/mingw64/usr/local/lib/libssl.a
|
WINDOWS_DEPS := deps/openssl/mingw64/usr/local/lib/libssl.a
|
||||||
$(WINDOWS_DEPS):
|
$(WINDOWS_DEPS):
|
||||||
+@BUILD_TARGET=mingw64 SSL_TARGET=mingw64 OPTIONS="--cross-compile-prefix=x86_64-w64-mingw32-" tools/ssl-local
|
+@tools/ssl-mingw64
|
||||||
$(filter $(BUILD_DIR)/win%,$(APP_OBJS)): | $(WINDOWS_DEPS)
|
$(filter $(BUILD_DIR)/win%,$(APP_OBJS)): | $(WINDOWS_DEPS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(UNAME_S),Darwin)
|
ifeq ($(UNAME_S),Darwin)
|
||||||
IOS_DEPS := out/openssl/ios/ios64-xcrun/usr/local/lib/libssl.a
|
IOS_DEPS := deps/openssl/ios/ios64-xcrun/usr/local/lib/libssl.a
|
||||||
$(IOS_DEPS):
|
$(IOS_DEPS):
|
||||||
+@BUILD_PLATFORM=ios BUILD_TARGET=ios64-xcrun SSL_TARGET=ios64-xcrun OPTIONS="-fPIC -Wno-macro-redefined -miphoneos-version-min=9.0" tools/ssl-local
|
+@tools/ssl-ios
|
||||||
+@BUILD_PLATFORM=ios BUILD_TARGET=iossimulator-xcrun SSL_TARGET=iossimulator-xcrun OPTIONS="-fPIC -Wno-macro-redefined" tools/ssl-local
|
|
||||||
$(filter $(BUILD_DIR)/ios%,$(APP_OBJS)): | $(IOS_DEPS)
|
$(filter $(BUILD_DIR)/ios%,$(APP_OBJS)): | $(IOS_DEPS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -1328,6 +1258,7 @@ tarball: ## Build an all-inclusive source tarball (.tar.xz).
|
|||||||
--exclude=deps/libsodium/test \
|
--exclude=deps/libsodium/test \
|
||||||
--exclude=deps/libuv/docs \
|
--exclude=deps/libuv/docs \
|
||||||
--exclude=deps/libuv/test \
|
--exclude=deps/libuv/test \
|
||||||
|
--exclude=deps/openssl \
|
||||||
--exclude=deps/speedscope/*.map \
|
--exclude=deps/speedscope/*.map \
|
||||||
--exclude=deps/sqlite/shell.c \
|
--exclude=deps/sqlite/shell.c \
|
||||||
--exclude=deps/zlib/contrib/vstudio \
|
--exclude=deps/zlib/contrib/vstudio \
|
||||||
@ -1338,7 +1269,7 @@ tarball: ## Build an all-inclusive source tarball (.tar.xz).
|
|||||||
.PHONY: tarball
|
.PHONY: tarball
|
||||||
|
|
||||||
dist: ## Build versions of all distributables for release.
|
dist: ## Build versions of all distributables for release.
|
||||||
dist: release-apk $(if $(HAVE_LINUX_IOS), iosrelease-ipa) aab $(if $(HAVE_WIN), out/winrelease/tildefriends.standalone.exe) out/TildeFriends-release.fdroid.apk appimage tarball out/release/tildefriends.standalone $(if $(HAVE_CROSS_AARCH64), out/armrelease/tildefriends.standalone)
|
dist: release-apk iosrelease-ipa aab $(if $(HAVE_WIN), out/winrelease/tildefriends.standalone.exe) out/TildeFriends-release.fdroid.apk appimage tarball out/release/tildefriends.standalone $(if $(HAVE_CROSS_AARCH64), out/armrelease/tildefriends.standalone)
|
||||||
@mkdir -p dist/
|
@mkdir -p dist/
|
||||||
@echo "[cp] tildefriends-$(VERSION_NUMBER).tar.xz"
|
@echo "[cp] tildefriends-$(VERSION_NUMBER).tar.xz"
|
||||||
@cp out/tildefriends-$(VERSION_NUMBER).tar.xz dist/tildefriends-$(VERSION_NUMBER).tar.xz
|
@cp out/tildefriends-$(VERSION_NUMBER).tar.xz dist/tildefriends-$(VERSION_NUMBER).tar.xz
|
||||||
@ -1346,8 +1277,8 @@ dist: release-apk $(if $(HAVE_LINUX_IOS), iosrelease-ipa) aab $(if $(HAVE_WIN),
|
|||||||
@cp out/TildeFriends-x86-release.zopfli.apk dist/TildeFriends-x86-$(VERSION_NUMBER).apk
|
@cp out/TildeFriends-x86-release.zopfli.apk dist/TildeFriends-x86-$(VERSION_NUMBER).apk
|
||||||
@echo "[cp] TildeFriends-arm-$(VERSION_NUMBER).apk"
|
@echo "[cp] TildeFriends-arm-$(VERSION_NUMBER).apk"
|
||||||
@cp out/TildeFriends-arm-release.zopfli.apk dist/TildeFriends-arm-$(VERSION_NUMBER).apk
|
@cp out/TildeFriends-arm-release.zopfli.apk dist/TildeFriends-arm-$(VERSION_NUMBER).apk
|
||||||
@test $(HAVE_LINUX_IOS) && echo "[cp] TildeFriends-$(VERSION_NUMBER).ipa"
|
@echo "[cp] TildeFriends-$(VERSION_NUMBER).ipa"
|
||||||
@test $(HAVE_LINUX_IOS) && cp out/tildefriends-release.ipa dist/TildeFriends-$(VERSION_NUMBER).ipa
|
@cp out/tildefriends-release.ipa dist/TildeFriends-$(VERSION_NUMBER).ipa
|
||||||
@test $(HAVE_WIN) && echo "[cp] tildefriends-$(VERSION_NUMBER).exe"
|
@test $(HAVE_WIN) && echo "[cp] tildefriends-$(VERSION_NUMBER).exe"
|
||||||
@test $(HAVE_WIN) && cp out/winrelease/tildefriends.standalone.exe dist/tildefriends-$(VERSION_NUMBER).exe
|
@test $(HAVE_WIN) && cp out/winrelease/tildefriends.standalone.exe dist/tildefriends-$(VERSION_NUMBER).exe
|
||||||
@echo "[cp] TildeFriends-$(VERSION_NUMBER).aab"
|
@echo "[cp] TildeFriends-$(VERSION_NUMBER).aab"
|
||||||
|
22
README.md
22
README.md
@ -1,16 +1,18 @@
|
|||||||
# Tilde Friends
|
# Tilde Friends
|
||||||
|
|
||||||
Tilde Friends participates in the Secure Scuttlebutt decentralized social
|
Tilde Friends is a tool for making and sharing.
|
||||||
network while also functioning as a platform for making, sharing, and running
|
|
||||||
web applications.
|
|
||||||
|
|
||||||
A public instance lives at https://www.tildefriends.net/.
|
A public instance lives at https://www.tildefriends.net/.
|
||||||
|
|
||||||
|
It is both a peer-to-peer social network client, participating in Secure
|
||||||
|
Scuttlebutt, as well as a platform for writing and running web applications.
|
||||||
|
|
||||||
## Goals
|
## Goals
|
||||||
|
|
||||||
1. Be the fanciest, best-maintained Secure Scuttlebutt client in town.
|
1. Make it easy and fun to run all sorts of web applications.
|
||||||
1. Make it easy to make, share, and run all sorts of applications while
|
2. Provide security that is easy to understand and protects your data.
|
||||||
respecting the privacy and safety of your data.
|
3. Make creating and sharing web applications accessible to anyone with a
|
||||||
|
browser.
|
||||||
|
|
||||||
## Getting the Source
|
## Getting the Source
|
||||||
|
|
||||||
@ -38,7 +40,8 @@ dependencies in the right places.
|
|||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
|
|
||||||
System OpenSSL libraries are assumed to be available on Haiku and OpenSSL.
|
On Linux only, system OpenSSL libraries (`libssl-dev`, in debian-speak) are
|
||||||
|
assumed to be available.
|
||||||
|
|
||||||
On MacOS, Xcode's command-line tools are expected to be available.
|
On MacOS, Xcode's command-line tools are expected to be available.
|
||||||
|
|
||||||
@ -60,12 +63,13 @@ repository root as the current working directory. `tildefriends -h` lists
|
|||||||
further options.
|
further options.
|
||||||
|
|
||||||
The first user to create an account and log in will be granted administrative
|
The first user to create an account and log in will be granted administrative
|
||||||
privileges. Further administration can be done in the `admin` app at
|
privileges. Further administration can be done at
|
||||||
<http://localhost:12345/~core/admin/>.
|
<http://localhost:12345/~core/admin/>.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
Docs live here: <https://docs.tildefriends.net/>.
|
Docs are a work in progress:
|
||||||
|
<https://dev.tildefriends.net/cory/tildefriends/wiki>.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"type": "tildefriends-app",
|
"type": "tildefriends-app",
|
||||||
"emoji": "🦀",
|
"emoji": "🦀",
|
||||||
"previous": "&0ZtxnihH3oETfi0vhhEwc9O66SrjfiFcHDVBAIxICy0=.sha256"
|
"previous": "&m5ZrkzoyAjv7AY6AukzVoWIyUFUL97uuDDWCtxCloAU=.sha256"
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ class TfElement extends LitElement {
|
|||||||
channels_latest: {type: Object},
|
channels_latest: {type: Object},
|
||||||
guest: {type: Boolean},
|
guest: {type: Boolean},
|
||||||
url: {type: String},
|
url: {type: String},
|
||||||
private_messages: {type: Array},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,7 +334,7 @@ class TfElement extends LitElement {
|
|||||||
JSON.stringify(cache)
|
JSON.stringify(cache)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return [cache.latest, cache.messages];
|
return cache.latest;
|
||||||
}
|
}
|
||||||
|
|
||||||
async load_channels_latest(following) {
|
async load_channels_latest(following) {
|
||||||
@ -379,11 +378,9 @@ class TfElement extends LitElement {
|
|||||||
start_time = new Date();
|
start_time = new Date();
|
||||||
latest_private.then(function (latest) {
|
latest_private.then(function (latest) {
|
||||||
self.channels_latest = Object.assign({}, self.channels_latest, {
|
self.channels_latest = Object.assign({}, self.channels_latest, {
|
||||||
'🔐': latest[0],
|
'🔐': latest,
|
||||||
});
|
});
|
||||||
console.log('private took', (new Date() - start_time) / 1000.0);
|
console.log('private took', (new Date() - start_time) / 1000.0);
|
||||||
console.log(latest);
|
|
||||||
self.private_messages = latest[1];
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,7 +513,6 @@ class TfElement extends LitElement {
|
|||||||
.channels_unread=${this.channels_unread}
|
.channels_unread=${this.channels_unread}
|
||||||
@channelsetunread=${this.channel_set_unread}
|
@channelsetunread=${this.channel_set_unread}
|
||||||
.connections=${this.connections}
|
.connections=${this.connections}
|
||||||
.private_messages=${this.private_messages}
|
|
||||||
></tf-tab-news>
|
></tf-tab-news>
|
||||||
`;
|
`;
|
||||||
} else if (this.tab === 'connections') {
|
} else if (this.tab === 'connections') {
|
||||||
|
@ -775,9 +775,7 @@ class TfMessageElement extends LitElement {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return this.render_small_frame(
|
return this.render_small_frame(
|
||||||
html`<div class="w3-container">
|
html`<div class="w3-container"><b>type</b>: ${content.type}</div>`
|
||||||
<p><b>type</b>: ${content.type}</p>
|
|
||||||
</div>`
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (typeof this.message.content == 'string') {
|
} else if (typeof this.message.content == 'string') {
|
||||||
|
@ -17,7 +17,6 @@ class TfTabNewsFeedElement extends LitElement {
|
|||||||
loading: {type: Number},
|
loading: {type: Number},
|
||||||
time_range: {type: Array},
|
time_range: {type: Array},
|
||||||
time_loading: {type: Array},
|
time_loading: {type: Array},
|
||||||
private_messages: {type: Array},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,13 +148,13 @@ class TfTabNewsFeedElement extends LitElement {
|
|||||||
`
|
`
|
||||||
SELECT TRUE AS is_primary, messages.rowid, messages.id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
|
SELECT TRUE AS is_primary, messages.rowid, messages.id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
|
||||||
FROM messages
|
FROM messages
|
||||||
JOIN json_each(?1) AS private_messages ON messages.id = private_messages.value
|
JOIN json_each(?1) AS following ON messages.author = following.value
|
||||||
WHERE
|
WHERE
|
||||||
(?2 IS NULL OR (messages.timestamp >= ?2)) AND messages.timestamp < ?3 AND
|
(?2 IS NULL OR (messages.timestamp >= ?2)) AND messages.timestamp < ?3 AND
|
||||||
json(messages.content) LIKE '"%'
|
json(messages.content) LIKE '"%'
|
||||||
ORDER BY messages.sequence DESC LIMIT 20
|
ORDER BY messages.sequence DESC LIMIT 20
|
||||||
`,
|
`,
|
||||||
[JSON.stringify(this.private_messages), start_time, end_time]
|
[JSON.stringify(this.following), start_time, end_time]
|
||||||
);
|
);
|
||||||
result = (await this.decrypt(result)).filter((x) => x.decrypted);
|
result = (await this.decrypt(result)).filter((x) => x.decrypted);
|
||||||
} else {
|
} else {
|
||||||
@ -299,7 +298,7 @@ class TfTabNewsFeedElement extends LitElement {
|
|||||||
let now = new Date().valueOf();
|
let now = new Date().valueOf();
|
||||||
let start_time = now - 24 * 60 * 60 * 1000;
|
let start_time = now - 24 * 60 * 60 * 1000;
|
||||||
this.start_time = start_time;
|
this.start_time = start_time;
|
||||||
this.time_range = [now + 24 * 60 * 60 * 1000, now + 24 * 60 * 60 * 1000];
|
this.time_range = [this.start_time, now + 24 * 60 * 60 * 1000];
|
||||||
messages = await this.fetch_messages(null, this.time_range[1]);
|
messages = await this.fetch_messages(null, this.time_range[1]);
|
||||||
this.update_time_range_from_messages(
|
this.update_time_range_from_messages(
|
||||||
messages.filter((x) => x.timestamp < this.time_range[1])
|
messages.filter((x) => x.timestamp < this.time_range[1])
|
||||||
|
@ -23,7 +23,6 @@ class TfTabNewsElement extends LitElement {
|
|||||||
channels_unread: {type: Object},
|
channels_unread: {type: Object},
|
||||||
channels_latest: {type: Object},
|
channels_latest: {type: Object},
|
||||||
connections: {type: Array},
|
connections: {type: Array},
|
||||||
private_messages: {type: Array},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,7 +337,6 @@ class TfTabNewsElement extends LitElement {
|
|||||||
@tf-expand=${this.on_expand}
|
@tf-expand=${this.on_expand}
|
||||||
.channels_unread=${this.channels_unread}
|
.channels_unread=${this.channels_unread}
|
||||||
.channels_latest=${this.channels_latest}
|
.channels_latest=${this.channels_latest}
|
||||||
.private_messages=${this.private_messages}
|
|
||||||
></tf-tab-news-feed>
|
></tf-tab-news-feed>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"type": "tildefriends-app",
|
"type": "tildefriends-app",
|
||||||
"emoji": "👋",
|
"emoji": "👋",
|
||||||
"previous": "&wAb7J6E35xEXpiXsQ6t1RaWTGIvlatUnyH8ipF6pVic=.sha256"
|
"previous": "&7gFmLW5zSMhmxWWY1+jeRcHdullgujSqGJg94lVgr1k=.sha256"
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,17 @@
|
|||||||
<link rel="stylesheet" href="brands.min.css" />
|
<link rel="stylesheet" href="brands.min.css" />
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
body,
|
||||||
|
h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5 {
|
||||||
|
font-family: 'Poppins', sans-serif;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
img {
|
img {
|
||||||
margin-bottom: -8px;
|
margin-bottom: -8px;
|
||||||
}
|
}
|
||||||
@ -28,14 +39,11 @@
|
|||||||
<b>😎 Tilde Friends</b>
|
<b>😎 Tilde Friends</b>
|
||||||
</h1>
|
</h1>
|
||||||
<h1 class="w3-xxlarge w3-text-green">
|
<h1 class="w3-xxlarge w3-text-green">
|
||||||
<b
|
<b>Make apps and friends from the comfort of your web browser.</b>
|
||||||
>the Secure Scuttlebutt decentralized social network client that's
|
|
||||||
<i>fancy🎩</i></b
|
|
||||||
>
|
|
||||||
</h1>
|
</h1>
|
||||||
<p>
|
<p>
|
||||||
In addition to participating in Secure Scuttlebutt, Tilde Friends is
|
Tilde Friends is a platform for building, running, and sharing web
|
||||||
a platform for building, running, and sharing applications.
|
applications.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Available for lots of devices:
|
Available for lots of devices:
|
||||||
@ -52,7 +60,7 @@
|
|||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
class="w3-button w3-black w3-padding-large"
|
class="w3-button w3-black w3-padding-large"
|
||||||
href="https://www.tildefriends.net/~core/ssb/"
|
href="https://www.tildefriends.net/~cory/apps/"
|
||||||
><i class="fa fa-link"></i> Try It</a
|
><i class="fa fa-link"></i> Try It</a
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
@ -60,11 +68,6 @@
|
|||||||
href="https://dev.tildefriends.net/"
|
href="https://dev.tildefriends.net/"
|
||||||
><i class="fa fa-mug-hot"></i> Development</a
|
><i class="fa fa-mug-hot"></i> Development</a
|
||||||
>
|
>
|
||||||
<a
|
|
||||||
class="w3-button w3-black w3-padding-large"
|
|
||||||
href="https://docs.tildefriends.net/"
|
|
||||||
><i class="fa fa-book"></i> Documentation</a
|
|
||||||
>
|
|
||||||
<p>
|
<p>
|
||||||
<a
|
<a
|
||||||
class="w3-button w3-round-large w3-padding w3-blue-gray w3-margin-top"
|
class="w3-button w3-round-large w3-padding w3-blue-gray w3-margin-top"
|
||||||
@ -220,15 +223,16 @@
|
|||||||
|
|
||||||
<!-- Technlology Section -->
|
<!-- Technlology Section -->
|
||||||
<div class="w3-container w3-padding-64 w3-light-grey w3-center">
|
<div class="w3-container w3-padding-64 w3-light-grey w3-center">
|
||||||
<h1 class="w3-jumbo"><b>Built the Old Fashioned Way</b></h1>
|
<h1 class="w3-jumbo"><b>Boring Technology</b></h1>
|
||||||
<p>
|
<p>
|
||||||
Tilde Friends strives to use only simple and widely adopted dependencies
|
Tilde Friends is built using boring, trusted tech. Unless a better
|
||||||
in order to keep it easy to build for all sorts of platforms and
|
reason presents itself, it strives to use only simple and widely adopted
|
||||||
maintainable for a very long time.
|
dependencies in order to keep it easy to build for all sorts of
|
||||||
|
platforms and maintainable for a very long time.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Though of course for building Tilde Friends apps, you are free to use
|
Though of course for building Tilde Friends apps, you are free to use
|
||||||
whatever fits on top.
|
whatever fits.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="w3-row" style="margin-top: 64px">
|
<div class="w3-row" style="margin-top: 64px">
|
||||||
|
@ -81,8 +81,9 @@ App.prototype.send = function (message) {
|
|||||||
* TODOC
|
* TODOC
|
||||||
* @param {*} request
|
* @param {*} request
|
||||||
* @param {*} response
|
* @param {*} response
|
||||||
|
* @param {*} client
|
||||||
*/
|
*/
|
||||||
exports.app_socket = async function socket(request, response) {
|
async function socket(request, response, client) {
|
||||||
let process;
|
let process;
|
||||||
let options = {};
|
let options = {};
|
||||||
let credentials = await httpd.auth_query(request.headers);
|
let credentials = await httpd.auth_query(request.headers);
|
||||||
@ -244,6 +245,6 @@ exports.app_socket = async function socket(request, response) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
response.upgrade(100, {});
|
response.upgrade(100, {});
|
||||||
};
|
}
|
||||||
|
|
||||||
export {App};
|
export {socket, App};
|
||||||
|
56
core/core.js
56
core/core.js
@ -1,4 +1,5 @@
|
|||||||
import * as app from './app.js';
|
import * as app from './app.js';
|
||||||
|
import * as form from './form.js';
|
||||||
import * as http from './http.js';
|
import * as http from './http.js';
|
||||||
|
|
||||||
let gProcesses = {};
|
let gProcesses = {};
|
||||||
@ -834,4 +835,59 @@ exports.callAppHandler = async function callAppHandler(
|
|||||||
response.end(answer?.data);
|
response.end(answer?.data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODOC
|
||||||
|
*/
|
||||||
|
loadSettings()
|
||||||
|
.then(function (settings) {
|
||||||
|
if (tildefriends.https_port && settings.http_redirect) {
|
||||||
|
httpd.set_http_redirect(settings.http_redirect);
|
||||||
|
}
|
||||||
|
httpd.all('/app/socket', app.socket);
|
||||||
|
let port = httpd.start(tildefriends.http_port);
|
||||||
|
if (tildefriends.args.out_http_port_file) {
|
||||||
|
print('Writing the port file.');
|
||||||
|
File.writeFile(
|
||||||
|
tildefriends.args.out_http_port_file,
|
||||||
|
port.toString() + '\n'
|
||||||
|
)
|
||||||
|
.then(function (r) {
|
||||||
|
print(
|
||||||
|
'Wrote the port file:',
|
||||||
|
tildefriends.args.out_http_port_file,
|
||||||
|
r
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch(function () {
|
||||||
|
print('Failed to write the port file.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tildefriends.https_port) {
|
||||||
|
async function start_tls() {
|
||||||
|
const kCertificatePath = 'data/httpd/certificate.pem';
|
||||||
|
const kPrivateKeyPath = 'data/httpd/privatekey.pem';
|
||||||
|
let privateKey;
|
||||||
|
let certificate;
|
||||||
|
try {
|
||||||
|
privateKey = utf8Decode(await File.readFile(kPrivateKeyPath));
|
||||||
|
certificate = utf8Decode(await File.readFile(kCertificatePath));
|
||||||
|
} catch (e) {
|
||||||
|
print(`TLS disabled (${e.message}).`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let context = new TlsContext();
|
||||||
|
context.setPrivateKey(privateKey);
|
||||||
|
context.setCertificate(certificate);
|
||||||
|
httpd.start(tildefriends.https_port, context);
|
||||||
|
}
|
||||||
|
start_tls();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
print('Failed to load settings.');
|
||||||
|
printError({print: print}, error);
|
||||||
|
exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
export {invoke, getProcessBlob};
|
export {invoke, getProcessBlob};
|
||||||
|
44
core/form.js
Normal file
44
core/form.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* TODOC
|
||||||
|
* @param {*} encoded
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function decode(encoded) {
|
||||||
|
let result = '';
|
||||||
|
for (let i = 0; i < encoded.length; i++) {
|
||||||
|
let c = encoded[i];
|
||||||
|
if (c == '+') {
|
||||||
|
result += ' ';
|
||||||
|
} else if (c == '%') {
|
||||||
|
result += String.fromCharCode(parseInt(encoded.slice(i + 1, i + 3), 16));
|
||||||
|
i += 2;
|
||||||
|
} else {
|
||||||
|
result += c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODOC
|
||||||
|
* @param {*} encoded
|
||||||
|
* @param {*} initial
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function decodeForm(encoded, initial) {
|
||||||
|
let result = initial || {};
|
||||||
|
if (encoded) {
|
||||||
|
encoded = encoded.trim();
|
||||||
|
let items = encoded.split('&');
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
let item = items[i];
|
||||||
|
let equals = item.indexOf('=');
|
||||||
|
let key = decode(item.slice(0, equals));
|
||||||
|
let value = decode(item.slice(equals + 1));
|
||||||
|
result[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export {decodeForm};
|
@ -21,32 +21,31 @@
|
|||||||
}:
|
}:
|
||||||
pkgs.stdenv.mkDerivation rec {
|
pkgs.stdenv.mkDerivation rec {
|
||||||
pname = "tildefriends";
|
pname = "tildefriends";
|
||||||
version = "0.0.27.1";
|
version = "0.0.27";
|
||||||
|
|
||||||
src = pkgs.fetchFromGitea {
|
src = pkgs.fetchFromGitea {
|
||||||
domain = "dev.tildefriends.net";
|
domain = "dev.tildefriends.net";
|
||||||
owner = "cory";
|
owner = "cory";
|
||||||
repo = "tildefriends";
|
repo = "tildefriends";
|
||||||
rev = "v${version}";
|
rev = "v${version}";
|
||||||
hash = "sha256-3t1m9ZomQF3DteWyALJWrnCq0EAROEK8shKXh6Ao38c=";
|
hash = "sha256-NhoTBWYsWc206f1+M9haxHSJU6ZSGoP5nPStymAIyRk=";
|
||||||
fetchSubmodules = true;
|
fetchSubmodules = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
nativeBuildInputs = with pkgs; [
|
nativeBuildInputs = with pkgs; [
|
||||||
|
bash
|
||||||
glibc
|
glibc
|
||||||
gnumake
|
gnumake
|
||||||
openssl
|
|
||||||
which
|
which
|
||||||
];
|
];
|
||||||
|
|
||||||
buildInputs = with pkgs; [
|
buildInputs = with pkgs; [
|
||||||
glibc
|
glibc
|
||||||
openssl
|
|
||||||
which
|
which
|
||||||
];
|
];
|
||||||
|
|
||||||
buildPhase = ''
|
buildPhase = ''
|
||||||
make -j $NIX_BUILD_CORES release USE_SYSTEM_SSL=1
|
make -j $NIX_BUILD_CORES release
|
||||||
'';
|
'';
|
||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
|
2
deps/codemirror/cm6.js
vendored
2
deps/codemirror/cm6.js
vendored
File diff suppressed because one or more lines are too long
170
deps/codemirror_src/package-lock.json
generated
vendored
170
deps/codemirror_src/package-lock.json
generated
vendored
@ -125,9 +125,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@codemirror/state": {
|
"node_modules/@codemirror/state": {
|
||||||
"version": "6.5.2",
|
"version": "6.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.1.tgz",
|
||||||
"integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==",
|
"integrity": "sha512-3rA9lcwciEB47ZevqvD8qgbzhM9qMb8vCcQCNmDfVRPQG4JT9mSb0Jg8H7YjKGGQcFnLN323fj9jdnG59Kx6bg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@marijn/find-cluster-break": "^1.0.0"
|
"@marijn/find-cluster-break": "^1.0.0"
|
||||||
}
|
}
|
||||||
@ -344,9 +344,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.32.1.tgz",
|
||||||
"integrity": "sha512-gGi5adZWvjtJU7Axs//CWaQbQd/vGy8KGcnEaCWiyCqxWYDxwIlAHFuSe6Guoxtd0SRvSfVTDMPd5H+4KE2kKA==",
|
"integrity": "sha512-/pqA4DmqyCm8u5YIDzIdlLcEmuvxb0v8fZdFhVMszSpDTgbQKdw3/mB3eMUHIbubtJ6F9j+LtmyCnHTEqIHyzA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@ -356,9 +356,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm64": {
|
"node_modules/@rollup/rollup-android-arm64": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.32.1.tgz",
|
||||||
"integrity": "sha512-1aRlh1gqtF7vNPMnlf1vJKk72Yshw5zknR/ZAVh7zycRAGF2XBMVDAHmFQz/Zws5k++nux3LOq/Ejj1WrDR6xg==",
|
"integrity": "sha512-If3PDskT77q7zgqVqYuj7WG3WC08G1kwXGVFi9Jr8nY6eHucREHkfpX79c0ACAjLj3QIWKPJR7w4i+f5EdLH5Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -368,9 +368,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.32.1.tgz",
|
||||||
"integrity": "sha512-drHl+4qhFj+PV/jrQ78p9ch6A0MfNVZScl/nBps5a7u01aGf/GuBRrHnRegA9bP222CBDfjYbFdjkIJ/FurvSQ==",
|
"integrity": "sha512-zCpKHioQ9KgZToFp5Wvz6zaWbMzYQ2LJHQ+QixDKq52KKrF65ueu6Af4hLlLWHjX1Wf/0G5kSJM9PySW9IrvHA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -380,9 +380,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-x64": {
|
"node_modules/@rollup/rollup-darwin-x64": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.32.1.tgz",
|
||||||
"integrity": "sha512-hQqq/8QALU6t1+fbNmm6dwYsa0PDD4L5r3TpHx9dNl+aSEMnIksHZkSO3AVH+hBMvZhpumIGrTFj8XCOGuIXjw==",
|
"integrity": "sha512-sFvF+t2+TyUo/ZQqUcifrJIgznx58oFZbdHS9TvHq3xhPVL9nOp+yZ6LKrO9GWTP+6DbFtoyLDbjTpR62Mbr3Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -392,9 +392,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.32.1.tgz",
|
||||||
"integrity": "sha512-/L0LixBmbefkec1JTeAQJP0ETzGjFtNml2gpQXA8rpLo7Md+iXQzo9kwEgzyat5Q+OG/C//2B9Fx52UxsOXbzw==",
|
"integrity": "sha512-NbOa+7InvMWRcY9RG+B6kKIMD/FsnQPH0MWUvDlQB1iXnF/UcKSudCXZtv4lW+C276g3w5AxPbfry5rSYvyeYA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -404,9 +404,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.32.1.tgz",
|
||||||
"integrity": "sha512-6Rk3PLRK+b8L/M6m/x6Mfj60LhAUcLJ34oPaxufA+CfqkUrDoUPQYFdRrhqyOvtOKXLJZJwxlOLbQjNYQcRQfw==",
|
"integrity": "sha512-JRBRmwvHPXR881j2xjry8HZ86wIPK2CcDw0EXchE1UgU0ubWp9nvlT7cZYKc6bkypBt745b4bglf3+xJ7hXWWw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -416,9 +416,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.32.1.tgz",
|
||||||
"integrity": "sha512-kmT3x0IPRuXY/tNoABp2nDvI9EvdiS2JZsd4I9yOcLCCViKsP0gB38mVHOhluzx+SSVnM1KNn9k6osyXZhLoCA==",
|
"integrity": "sha512-PKvszb+9o/vVdUzCCjL0sKHukEQV39tD3fepXxYrHE3sTKrRdCydI7uldRLbjLmDA3TFDmh418XH19NOsDRH8g==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@ -428,9 +428,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.32.1.tgz",
|
||||||
"integrity": "sha512-3iSA9tx+4PZcJH/Wnwsvx/BY4qHpit/u2YoZoXugWVfc36/4mRkgGEoRbRV7nzNBSCOgbWMeuQ27IQWgJ7tRzw==",
|
"integrity": "sha512-9WHEMV6Y89eL606ReYowXuGF1Yb2vwfKWKdD1A5h+OYnPZSJvxbEjxTRKPgi7tkP2DSnW0YLab1ooy+i/FQp/Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@ -440,9 +440,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.32.1.tgz",
|
||||||
"integrity": "sha512-7CwSJW+sEhM9sESEk+pEREF2JL0BmyCro8UyTq0Kyh0nu1v0QPNY3yfLPFKChzVoUmaKj8zbdgBxUhBRR+xGxg==",
|
"integrity": "sha512-tZWc9iEt5fGJ1CL2LRPw8OttkCBDs+D8D3oEM8mH8S1ICZCtFJhD7DZ3XMGM8kpqHvhGUTvNUYVDnmkj4BDXnw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -452,9 +452,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.32.1.tgz",
|
||||||
"integrity": "sha512-GZdafB41/4s12j8Ss2izofjeFXRAAM7sHCb+S4JsI9vaONX/zQ8cXd87B9MRU/igGAJkKvmFmJJBeeT9jJ5Cbw==",
|
"integrity": "sha512-FTYc2YoTWUsBz5GTTgGkRYYJ5NGJIi/rCY4oK/I8aKowx1ToXeoVVbIE4LGAjsauvlhjfl0MYacxClLld1VrOw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -464,9 +464,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.32.1.tgz",
|
||||||
"integrity": "sha512-uuphLuw1X6ur11675c2twC6YxbzyLSpWggvdawTUamlsoUv81aAXRMPBC1uvQllnBGls0Qt5Siw8reSIBnbdqQ==",
|
"integrity": "sha512-F51qLdOtpS6P1zJVRzYM0v6MrBNypyPEN1GfMiz0gPu9jN8ScGaEFIZQwteSsGKg799oR5EaP7+B2jHgL+d+Kw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
@ -476,9 +476,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.32.1.tgz",
|
||||||
"integrity": "sha512-KvLEw1os2gSmD6k6QPCQMm2T9P2GYvsMZMRpMz78QpSoEevHbV/KOUbI/46/JRalhtSAYZBYLAnT9YE4i/l4vg==",
|
"integrity": "sha512-wO0WkfSppfX4YFm5KhdCCpnpGbtgQNj/tgvYzrVYFKDpven8w2N6Gg5nB6w+wAMO3AIfSTWeTjfVe+uZ23zAlg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
@ -488,9 +488,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.32.1.tgz",
|
||||||
"integrity": "sha512-wcpCLHGM9yv+3Dql/CI4zrY2mpQ4WFergD3c9cpRowltEh5I84pRT/EuHZsG0In4eBPPYthXnuR++HrFkeqwkA==",
|
"integrity": "sha512-iWswS9cIXfJO1MFYtI/4jjlrGb/V58oMu4dYJIKnR5UIwbkzR0PJ09O0PDZT0oJ3LYWXBSWahNf/Mjo6i1E5/g==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
@ -500,9 +500,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.32.1.tgz",
|
||||||
"integrity": "sha512-nLbfQp2lbJYU8obhRQusXKbuiqm4jSJteLwfjnunDT5ugBKdxqw1X9KWwk8xp1OMC6P5d0WbzxzhWoznuVK6XA==",
|
"integrity": "sha512-RKt8NI9tebzmEthMnfVgG3i/XeECkMPS+ibVZjZ6mNekpbbUmkNWuIN2yHsb/mBPyZke4nlI4YqIdFPgKuoyQQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
@ -512,9 +512,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.32.1.tgz",
|
||||||
"integrity": "sha512-JGejzEfVzqc/XNiCKZj14eb6s5w8DdWlnQ5tWUbs99kkdvfq9btxxVX97AaxiUX7xJTKFA0LwoS0KU8C2faZRg==",
|
"integrity": "sha512-WQFLZ9c42ECqEjwg/GHHsouij3pzLXkFdz0UxHa/0OM12LzvX7DzedlY0SIEly2v18YZLRhCRoHZDxbBSWoGYg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -524,9 +524,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.32.1.tgz",
|
||||||
"integrity": "sha512-/iFIbhzeyZZy49ozAWJ1ZR2KW6ZdYUbQXLT4O5n1cRZRoTpwExnHLjlurDXXPKEGxiAg0ujaR9JDYKljpr2fDg==",
|
"integrity": "sha512-BLoiyHDOWoS3uccNSADMza6V6vCNiphi94tQlVIL5de+r6r/CCQuNnerf+1g2mnk2b6edp5dk0nhdZ7aEjOBsA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -536,9 +536,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.32.1.tgz",
|
||||||
"integrity": "sha512-qORc3UzoD5UUTneiP2Afg5n5Ti1GAW9Gp5vHPxzvAFFA3FBaum9WqGvYXGf+c7beFdOKNos31/41PRMUwh1tpA==",
|
"integrity": "sha512-w2l3UnlgYTNNU+Z6wOR8YdaioqfEnwPjIsJ66KxKAf0p+AuL2FHeTX6qvM+p/Ue3XPBVNyVSfCrfZiQh7vZHLQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@ -548,9 +548,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.32.1.tgz",
|
||||||
"integrity": "sha512-5g7E2PHNK2uvoD5bASBD9aelm44nf1w4I5FEI7MPHLWcCSrR8JragXZWgKPXk5i2FU3JFfa6CGZLw2RrGBHs2Q==",
|
"integrity": "sha512-Am9H+TGLomPGkBnaPWie4F3x+yQ2rr4Bk2jpwy+iV+Gel9jLAu/KqT8k3X4jxFPW6Zf8OMnehyutsd+eHoq1WQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@ -560,9 +560,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.32.1.tgz",
|
||||||
"integrity": "sha512-p0scwGkR4kZ242xLPBuhSckrJ734frz6v9xZzD+kHVYRAkSUmdSLCIJRfql6H5//aF8Q10K+i7q8DiPfZp0b7A==",
|
"integrity": "sha512-ar80GhdZb4DgmW3myIS9nRFYcpJRSME8iqWgzH2i44u+IdrzmiXVxeFnExQ5v4JYUSpg94bWjevMG8JHf1Da5Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@ -733,9 +733,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rollup": {
|
"node_modules/rollup": {
|
||||||
"version": "4.34.4",
|
"version": "4.32.1",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.4.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.32.1.tgz",
|
||||||
"integrity": "sha512-spF66xoyD7rz3o08sHP7wogp1gZ6itSq22SGa/IZTcUDXDlOyrShwMwkVSB+BUxFRZZCUYqdb3KWDEOMVQZxuw==",
|
"integrity": "sha512-z+aeEsOeEa3mEbS1Tjl6sAZ8NE3+AalQz1RJGj81M+fizusbdDMoEJwdJNHfaB40Scr4qNu+welOfes7maKonA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "1.0.6"
|
"@types/estree": "1.0.6"
|
||||||
},
|
},
|
||||||
@ -747,25 +747,25 @@
|
|||||||
"npm": ">=8.0.0"
|
"npm": ">=8.0.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@rollup/rollup-android-arm-eabi": "4.34.4",
|
"@rollup/rollup-android-arm-eabi": "4.32.1",
|
||||||
"@rollup/rollup-android-arm64": "4.34.4",
|
"@rollup/rollup-android-arm64": "4.32.1",
|
||||||
"@rollup/rollup-darwin-arm64": "4.34.4",
|
"@rollup/rollup-darwin-arm64": "4.32.1",
|
||||||
"@rollup/rollup-darwin-x64": "4.34.4",
|
"@rollup/rollup-darwin-x64": "4.32.1",
|
||||||
"@rollup/rollup-freebsd-arm64": "4.34.4",
|
"@rollup/rollup-freebsd-arm64": "4.32.1",
|
||||||
"@rollup/rollup-freebsd-x64": "4.34.4",
|
"@rollup/rollup-freebsd-x64": "4.32.1",
|
||||||
"@rollup/rollup-linux-arm-gnueabihf": "4.34.4",
|
"@rollup/rollup-linux-arm-gnueabihf": "4.32.1",
|
||||||
"@rollup/rollup-linux-arm-musleabihf": "4.34.4",
|
"@rollup/rollup-linux-arm-musleabihf": "4.32.1",
|
||||||
"@rollup/rollup-linux-arm64-gnu": "4.34.4",
|
"@rollup/rollup-linux-arm64-gnu": "4.32.1",
|
||||||
"@rollup/rollup-linux-arm64-musl": "4.34.4",
|
"@rollup/rollup-linux-arm64-musl": "4.32.1",
|
||||||
"@rollup/rollup-linux-loongarch64-gnu": "4.34.4",
|
"@rollup/rollup-linux-loongarch64-gnu": "4.32.1",
|
||||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.34.4",
|
"@rollup/rollup-linux-powerpc64le-gnu": "4.32.1",
|
||||||
"@rollup/rollup-linux-riscv64-gnu": "4.34.4",
|
"@rollup/rollup-linux-riscv64-gnu": "4.32.1",
|
||||||
"@rollup/rollup-linux-s390x-gnu": "4.34.4",
|
"@rollup/rollup-linux-s390x-gnu": "4.32.1",
|
||||||
"@rollup/rollup-linux-x64-gnu": "4.34.4",
|
"@rollup/rollup-linux-x64-gnu": "4.32.1",
|
||||||
"@rollup/rollup-linux-x64-musl": "4.34.4",
|
"@rollup/rollup-linux-x64-musl": "4.32.1",
|
||||||
"@rollup/rollup-win32-arm64-msvc": "4.34.4",
|
"@rollup/rollup-win32-arm64-msvc": "4.32.1",
|
||||||
"@rollup/rollup-win32-ia32-msvc": "4.34.4",
|
"@rollup/rollup-win32-ia32-msvc": "4.32.1",
|
||||||
"@rollup/rollup-win32-x64-msvc": "4.34.4",
|
"@rollup/rollup-win32-x64-msvc": "4.32.1",
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -840,9 +840,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/terser": {
|
"node_modules/terser": {
|
||||||
"version": "5.38.0",
|
"version": "5.37.0",
|
||||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.38.0.tgz",
|
"resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz",
|
||||||
"integrity": "sha512-a4GD5R1TjEeuCT6ZRiYMHmIf7okbCPEuhQET8bczV6FrQMMlFXA1n+G0KKjdlFCm3TEHV77GxfZB3vZSUQGFpg==",
|
"integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/source-map": "^0.3.3",
|
"@jridgewell/source-map": "^0.3.3",
|
||||||
|
2
deps/libbacktrace
vendored
2
deps/libbacktrace
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 78af4ffa26e15532847c1ba854ece7b3bacc6b1a
|
Subproject commit d48f84034ce3e53e501d10593710d025cb1121db
|
1
deps/zsign
vendored
1
deps/zsign
vendored
@ -1 +0,0 @@
|
|||||||
Subproject commit d995d539ff16f28d985f5b2a1c62dd4eb9f029ea
|
|
1
docs
Submodule
1
docs
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit a40758cc4bef5ded4d214c2acf1c95e554e20564
|
@ -1,63 +0,0 @@
|
|||||||
# App Development Cheat Sheet
|
|
||||||
|
|
||||||
Making apps for the impatient tilde friend.
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
- either run your own instance or use [tildefriends.net](https://www.tildefriends.net/)
|
|
||||||
- register and login
|
|
||||||
- [optional] use the `ssb` app to create yourself an SSB identity
|
|
||||||
|
|
||||||
## Development Process
|
|
||||||
|
|
||||||
1. hit the `edit` link from any app or new app URL
|
|
||||||
2. make sure the path in the text box is under your username: `/~username/app/`
|
|
||||||
3. write server-side code in `app.js`
|
|
||||||
4. click the `save` button or press the save hotkey (Alt+S or _[browser-specific modifiers]_+S)
|
|
||||||
5. see the app reload on the right side
|
|
||||||
|
|
||||||
## Output
|
|
||||||
|
|
||||||
- `app.setDocument(html)` - send HTML to the browser
|
|
||||||
- `print(...)` - send values to the browser's developer console
|
|
||||||
|
|
||||||
## Persistence
|
|
||||||
|
|
||||||
- `app.localStorageGet(key)` -> `value`
|
|
||||||
- `app.localStorageSet(key, value)`
|
|
||||||
- `database()`, `shared_database(key)`, `my_shared_database(package, key)`
|
|
||||||
- `db.get(key)` -> `value`
|
|
||||||
- `db.set(key, value)`
|
|
||||||
- `db.exchange(key, expected, value)` -> `exchanged`
|
|
||||||
- `db.remove(key)`
|
|
||||||
- `db.getAll()` -> `[key1, ...]`
|
|
||||||
- `db.getLike(pattern)` -> `{key1: value1, ...}`
|
|
||||||
|
|
||||||
## SSB
|
|
||||||
|
|
||||||
- `ssb.createIdentity()` -> `id`
|
|
||||||
- `ssb.getIdentities()` -> `[id1, ...]`
|
|
||||||
- `ssb.appendMessageWithIdentity(id, content)` -> `message_id`
|
|
||||||
- `ssb.blobStore(blob)` -> `blob_id`
|
|
||||||
- `ssb.blobGet(id)` -> `blob`
|
|
||||||
- `ssb.sqlAsync(query, args, row_callback)`
|
|
||||||
|
|
||||||
## TF-RPC
|
|
||||||
|
|
||||||
Stock helper code for calling functions across the web server and browser boundary.
|
|
||||||
|
|
||||||
- on the server: `import * as tfrpc from "/tfrpc.js";`
|
|
||||||
- in the browser: `import * as tfrpc from "/static/tfrpc.js";`
|
|
||||||
- either direction:
|
|
||||||
- register a function: `tfrpc.register(function my_function() {});`
|
|
||||||
- call a remote function: `let promise = tfrpc.rpc.my_function();`
|
|
||||||
|
|
||||||
## Share
|
|
||||||
|
|
||||||
- give out web links: [https://www.tildefriends.net/~cory/screwble/](https://www.tildefriends.net/~cory/screwble/)
|
|
||||||
- use the `Attach App` button when composing a post in [the SSB app](https://www.tildefriends.net/~core/ssb/)
|
|
||||||
|
|
||||||
## More Docs
|
|
||||||
|
|
||||||
- [api reference](https://www.tildefriends.net/~cory/api/)
|
|
||||||
- [source code](https://dev.tildefriends.net/cory/tildefriends/releases)
|
|
@ -1,166 +0,0 @@
|
|||||||
# App Development Guide
|
|
||||||
|
|
||||||
A Tilde Friends application starts with code that runs on a Tilde Friends server, possibly far away from where you wrote it, in a little JavaScript environment, in its own restricted process, with the only access to the outside world being the ability to send messages to the server. This document gives some recipes showing how that can be used to build a functional user-facing application in light of the unique constraints present.
|
|
||||||
|
|
||||||
## Example 1: Hello, world!
|
|
||||||
|
|
||||||
Of course we must start with a classic.
|
|
||||||
|
|
||||||
### app.js
|
|
||||||
|
|
||||||
```js
|
|
||||||
app.setDocument('<h1 style="color: #fff">Hello, world!</h1>');
|
|
||||||
```
|
|
||||||
|
|
||||||
### Output
|
|
||||||
|
|
||||||
<h1 style="color: #fff">Hello, world!</h1>
|
|
||||||
|
|
||||||
### Explanation
|
|
||||||
|
|
||||||
At a glance, this might seem mundane, but for it to work:
|
|
||||||
|
|
||||||
- the server starts a real process for your app and loads your code into it
|
|
||||||
- your code runs
|
|
||||||
- `app.setDocument()` sends a message back to the server
|
|
||||||
- the server interprets the message and redirects it to the browser
|
|
||||||
- `core/client.js` in the browser receives the message and puts your HTML into an iframe
|
|
||||||
- your HTML is presented by the browser in an iframe sandbox
|
|
||||||
|
|
||||||
But you don't have to think about all that. Call a function, and you see the result.
|
|
||||||
|
|
||||||
## Example 2: Hit Counter
|
|
||||||
|
|
||||||
Let's take advantage of code running on the server and create a little hit counter using a key value store shared between all visitors.
|
|
||||||
|
|
||||||
### app.js
|
|
||||||
|
|
||||||
```js
|
|
||||||
async function main() {
|
|
||||||
let db = await shared_database('visitors');
|
|
||||||
let count = parseInt((await db.get('visitors')) ?? '0') + 1;
|
|
||||||
await db.set('visitors', count.toString());
|
|
||||||
await app.setDocument(`
|
|
||||||
<h1 style="color: #fff">Welcome, visitor #${count}!</h1>
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
|
|
||||||
main();
|
|
||||||
```
|
|
||||||
|
|
||||||
### Output
|
|
||||||
|
|
||||||
<h1 style="color: #fff">Welcome, visitor #1!</h1>
|
|
||||||
|
|
||||||
### Explanation
|
|
||||||
|
|
||||||
Just as pure browser apps have access to `localStorage`, Tilde Friends apps have access to key-value storage on the server.
|
|
||||||
|
|
||||||
The interface is a bit clunky and will likely change someday, but this example gets a database object, from which you can get and set string values by key. There are various on `shared_database` that let you store data that is private to the user or shared by different criteria.
|
|
||||||
|
|
||||||
Also, even though any browser-side code is sandboxed, it is allowed to access browser local storage by going through Tilde Friends API, because sometimes that is useful.
|
|
||||||
|
|
||||||
## Example 3: Files
|
|
||||||
|
|
||||||
Suppose you don't want to create your entire app in a single server-side file as we've done with the previous examples. There are some tools to allow you to begin to organize.
|
|
||||||
|
|
||||||
### app.js
|
|
||||||
|
|
||||||
```js
|
|
||||||
async function main() {
|
|
||||||
let html = utf8Decode(await getFile('index.html'));
|
|
||||||
app.setDocument(html);
|
|
||||||
}
|
|
||||||
|
|
||||||
main();
|
|
||||||
```
|
|
||||||
|
|
||||||
### index.html
|
|
||||||
|
|
||||||
```html
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<script type="module" src="script.js"></script>
|
|
||||||
</head>
|
|
||||||
<body style="color: #fff">
|
|
||||||
<h1>File Test</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
```
|
|
||||||
|
|
||||||
### script.js
|
|
||||||
|
|
||||||
```js
|
|
||||||
window.addEventListener('load', function() {
|
|
||||||
document.body.appendChild(document.createTextNode('Hello, world');
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Output
|
|
||||||
|
|
||||||
<h1>File Test</h1><p>Hello, world!</p>
|
|
||||||
|
|
||||||
### Explanation
|
|
||||||
|
|
||||||
On the server, `utf8Decode(await getFile(fileName))` lets you load a file from your app. In the browser, your app files are made available by HTTP, so you can `<script src="my_script.js"></script>` and such to access them.
|
|
||||||
|
|
||||||
## Example 4: Remote Procedure Call
|
|
||||||
|
|
||||||
While making calls between the client and the server, it is possible to pass functions across that boundary. `tfrpc.js` is a tiny script which builds on that feature to try to hide some of the complexities.
|
|
||||||
|
|
||||||
### app.js
|
|
||||||
|
|
||||||
```js
|
|
||||||
import * as tf from '/tfrpc.js';
|
|
||||||
|
|
||||||
function sum() {
|
|
||||||
let s = 0;
|
|
||||||
for (let x of arguments) {
|
|
||||||
s += x;
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
tf.register(sum);
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
app.setDocument(utf8Decode(await getFile('index.html')));
|
|
||||||
}
|
|
||||||
main();
|
|
||||||
```
|
|
||||||
|
|
||||||
### index.html
|
|
||||||
|
|
||||||
```html
|
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<h1 id="result">Calculating...</h1>
|
|
||||||
</body>
|
|
||||||
<script type="module" src="script.js"></script>
|
|
||||||
</html>
|
|
||||||
```
|
|
||||||
|
|
||||||
### script.js
|
|
||||||
|
|
||||||
```js
|
|
||||||
import * as tf from '/static/tfrpc.js';
|
|
||||||
|
|
||||||
window.addEventListener('load', async function () {
|
|
||||||
document.getElementById('result').innerText = await tf.rpc.sum(1, 2, 3);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### Output
|
|
||||||
|
|
||||||
<h1>6</h1>
|
|
||||||
|
|
||||||
### Explanation
|
|
||||||
|
|
||||||
Here the browser makes an asynchronous call to the server to do some basic math and update its DOM with the result.
|
|
||||||
|
|
||||||
With your favorite Vue/Lit/React/... library on the client-side and your favorite Tilde Friends API calls registered with tfrpc, it becomes pretty easy to start extracting interesting information from, say, SQL queries over Secure Scuttlebutt data, and generating complicated, dynamic user interface. These are the building blocks I used to make the current Tilde Friends SSB client interface.
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
Tilde Friends is currently a pile of all the parts that I thought I needed to build interesting web applications, tied together by code that tries to walk the fine line between being secure enough to let us safely run code on the same device and being usable enough that you can open a tab in your browser and start building just by typing code.
|
|
||||||
|
|
||||||
I don't claim it thoroughly accomplishes either yet, but I believe it is at a stage where it is showing how promising this approach can be, and I am excited for you to take it for a spin and share.
|
|
@ -1,15 +0,0 @@
|
|||||||
# Inspiration
|
|
||||||
|
|
||||||
This is an ever-growing list of software that is similar to what Tilde Friends tries to be but as far as I can tell don't quite fit the same niche.
|
|
||||||
|
|
||||||
- Secure Scuttlebutt Clients
|
|
||||||
- [Manyverse](https://www.manyver.se/)
|
|
||||||
- [Patchwork](https://github.com/ssbc/patchwork)
|
|
||||||
- [Patchfox](https://patchfox.org/#/)
|
|
||||||
- [Habitat](https://gitlab.com/quickdudley/habitat)
|
|
||||||
- [Āhau](https://gitlab.com/ahau/ahau/)
|
|
||||||
- [erlbutt](https://github.com/cmoid/erlbutt/)
|
|
||||||
- Web Application Platforms
|
|
||||||
- [Glitch](https://glitch.com/)
|
|
||||||
- [Val Town](https://www.val.town/)
|
|
||||||
- [Clace](https://clace.io/)
|
|
@ -1,19 +0,0 @@
|
|||||||
# Release Checklist
|
|
||||||
|
|
||||||
- make sure ci is passing
|
|
||||||
- run the tests
|
|
||||||
- format + prettier
|
|
||||||
- update metadata/en-US/changelogs
|
|
||||||
- git tag
|
|
||||||
- push
|
|
||||||
- make dist
|
|
||||||
- make a release on gitea
|
|
||||||
- upload the artifacts
|
|
||||||
- nix
|
|
||||||
- comment out the hash in default.nix
|
|
||||||
- update the version
|
|
||||||
- run `nix-build`
|
|
||||||
- update the hash
|
|
||||||
- bump the versions in GNUmakefile for the next release
|
|
||||||
- make
|
|
||||||
- commit
|
|
@ -1,64 +0,0 @@
|
|||||||
# Vision
|
|
||||||
|
|
||||||
Tilde Friends is a tool for making and sharing.
|
|
||||||
|
|
||||||
It is both a peer-to-peer social network client, participating in Secure
|
|
||||||
Scuttlebutt, and an environment for creating and running web applications.
|
|
||||||
|
|
||||||
## Why
|
|
||||||
|
|
||||||
This is a thing that I wanted to exist and wanted to work on. No other reason.
|
|
||||||
There is not a business model. I believe it is interesting and unique.
|
|
||||||
|
|
||||||
## Goals
|
|
||||||
|
|
||||||
1. Make it **easy and fun** to run all sorts of web applications.
|
|
||||||
|
|
||||||
2. Provide **security** that is easy to understand and protects your data.
|
|
||||||
|
|
||||||
3. Make **creating and sharing** web applications accessible to anyone with a
|
|
||||||
browser.
|
|
||||||
|
|
||||||
## Ways to Use Tilde Friends
|
|
||||||
|
|
||||||
1. **Social Network User**: This is a social network first. You are just here,
|
|
||||||
because your friends are. Or you like how we limit your message length or
|
|
||||||
short videos or whatever the trend is. If you are ambitious, you click links
|
|
||||||
and see interactive experiences (apps) that you wouldn't see elsewhere.
|
|
||||||
|
|
||||||
2. **Web Visitor**: You get links from a friend to meeting invites, polls, games,
|
|
||||||
lists, wiki pages, ..., and you interact with them as though they were
|
|
||||||
cloud-hosted by a megacorporation. They just work, and you don't think twice.
|
|
||||||
|
|
||||||
3. **Group leader**: You host or use a small public instance, installing apps for
|
|
||||||
a group of friends to use as web visitors.
|
|
||||||
|
|
||||||
4. **Developer**: You like to write code and make or improve apps for fun or to
|
|
||||||
solve problems. When you encounter a Tilde Friends app on a strange server,
|
|
||||||
you know you can trivially modify it or download it to your own instance.
|
|
||||||
|
|
||||||
## Future Goals / Endgame
|
|
||||||
|
|
||||||
1. Mobile apps. This can run on your old phone. Maybe you won't be hosting
|
|
||||||
the web interface publicly, but you can sync, install and edit apps, and
|
|
||||||
otherwise get the full experience from a tiny touch screen.
|
|
||||||
|
|
||||||
2. The universal application runtime. The web browser is the universal
|
|
||||||
platform, but even for the simplest application that you might want to host
|
|
||||||
for your friends, cloud hosting, containers, and complicated dependencies might
|
|
||||||
all enter the mix. Tilde Friends, though it is yet another thing to host,
|
|
||||||
includes everything you need out of the box to run a vast variety of interesting
|
|
||||||
apps.
|
|
||||||
|
|
||||||
Tilde Friends will be built out, gradually providing safe access to host
|
|
||||||
resources and client resources the same way web browsers extended access to
|
|
||||||
resources like GPU, persistent storage, cameras, ... over the years.
|
|
||||||
|
|
||||||
Not much effort has been put forward yet to having a robust, long-lasting API,
|
|
||||||
but since the client side longevity is already handled by web browsers, it
|
|
||||||
seems possible that the server-side API can be managed in a similar way.
|
|
||||||
|
|
||||||
3. An awesome development environment. Right now it runs JavaScript from the
|
|
||||||
first embeddable text editor I could poorly configure enough to edit code,
|
|
||||||
but it could incorporate a debugger, source control integration a la ssb-git,
|
|
||||||
merge tools, and transpiling from all sorts of different languages.
|
|
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.unprompted.tildefriends"
|
package="com.unprompted.tildefriends"
|
||||||
android:versionCode="33"
|
android:versionCode="32"
|
||||||
android:versionName="0.0.28-wip">
|
android:versionName="0.0.27">
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<application
|
<application
|
||||||
|
198
src/file.js.c
198
src/file.js.c
@ -18,6 +18,20 @@
|
|||||||
|
|
||||||
static JSValue _file_read_file(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
|
static JSValue _file_read_file(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
|
||||||
static JSValue _file_read_file_zip(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
|
static JSValue _file_read_file_zip(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
|
||||||
|
static JSValue _file_stat(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
|
||||||
|
static JSValue _file_stat_zip(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
|
||||||
|
static JSValue _file_write_file(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
|
||||||
|
|
||||||
|
static double _time_spec_to_double(const uv_timespec_t* time_spec);
|
||||||
|
static void _file_on_stat_complete(uv_fs_t* request);
|
||||||
|
|
||||||
|
typedef struct file_stat_t
|
||||||
|
{
|
||||||
|
void* _task;
|
||||||
|
JSContext* _context;
|
||||||
|
promiseid_t _promise;
|
||||||
|
uv_fs_t _request;
|
||||||
|
} file_stat_t;
|
||||||
|
|
||||||
typedef struct fs_req_t
|
typedef struct fs_req_t
|
||||||
{
|
{
|
||||||
@ -31,10 +45,12 @@ void tf_file_register(JSContext* context)
|
|||||||
{
|
{
|
||||||
JSValue global = JS_GetGlobalObject(context);
|
JSValue global = JS_GetGlobalObject(context);
|
||||||
JSValue file = JS_NewObject(context);
|
JSValue file = JS_NewObject(context);
|
||||||
tf_task_t* task = JS_GetContextOpaque(context);
|
void* task = JS_GetContextOpaque(context);
|
||||||
const char* zip = tf_task_get_zip_path(task);
|
const char* zip = tf_task_get_zip_path(task);
|
||||||
JS_SetPropertyStr(context, global, "File", file);
|
JS_SetPropertyStr(context, global, "File", file);
|
||||||
JS_SetPropertyStr(context, file, "readFile", JS_NewCFunction(context, zip ? _file_read_file_zip : _file_read_file, "readFile", 1));
|
JS_SetPropertyStr(context, file, "readFile", JS_NewCFunction(context, zip ? _file_read_file_zip : _file_read_file, "readFile", 1));
|
||||||
|
JS_SetPropertyStr(context, file, "writeFile", JS_NewCFunction(context, _file_write_file, "writeFile", 2));
|
||||||
|
JS_SetPropertyStr(context, file, "stat", JS_NewCFunction(context, zip ? _file_stat_zip : _file_stat, "stat", 1));
|
||||||
JS_FreeValue(context, global);
|
JS_FreeValue(context, global);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +65,105 @@ static void _file_async_close_callback(uv_fs_t* req)
|
|||||||
tf_free(req);
|
tf_free(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _file_write_write_callback(uv_fs_t* req)
|
||||||
|
{
|
||||||
|
uv_fs_req_cleanup(req);
|
||||||
|
fs_req_t* fsreq = (fs_req_t*)req;
|
||||||
|
tf_task_t* task = req->loop->data;
|
||||||
|
JSContext* context = tf_task_get_context(task);
|
||||||
|
promiseid_t promise = (promiseid_t)(intptr_t)req->data;
|
||||||
|
if (req->result >= 0)
|
||||||
|
{
|
||||||
|
tf_task_resolve_promise(task, promise, JS_NewInt64(context, req->result));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tf_task_reject_promise(task, promise, JS_ThrowInternalError(context, "Failed to write %s: %s", req->path, uv_strerror(req->result)));
|
||||||
|
}
|
||||||
|
int result = uv_fs_close(req->loop, req, fsreq->file, _file_async_close_callback);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
uv_fs_req_cleanup(req);
|
||||||
|
tf_free(fsreq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _file_write_open_callback(uv_fs_t* req)
|
||||||
|
{
|
||||||
|
fs_req_t* fsreq = (fs_req_t*)req;
|
||||||
|
const char* path = tf_strdup(req->path);
|
||||||
|
uv_fs_req_cleanup(req);
|
||||||
|
tf_task_t* task = req->loop->data;
|
||||||
|
JSContext* context = tf_task_get_context(task);
|
||||||
|
promiseid_t promise = (promiseid_t)(intptr_t)req->data;
|
||||||
|
if (req->result >= 0)
|
||||||
|
{
|
||||||
|
uv_buf_t buf = { .base = fsreq->buffer, .len = fsreq->size };
|
||||||
|
fsreq->file = req->result;
|
||||||
|
int result = uv_fs_write(req->loop, req, fsreq->file, &buf, 1, 0, _file_write_write_callback);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
uv_fs_req_cleanup(req);
|
||||||
|
tf_task_reject_promise(task, promise, JS_ThrowInternalError(context, "Failed to write %s: %s", path, uv_strerror(result)));
|
||||||
|
result = uv_fs_close(req->loop, req, fsreq->file, _file_async_close_callback);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
uv_fs_req_cleanup(req);
|
||||||
|
tf_free(fsreq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tf_task_reject_promise(task, promise, JS_ThrowInternalError(context, "%s", uv_strerror(req->result)));
|
||||||
|
tf_free(req);
|
||||||
|
}
|
||||||
|
tf_free((void*)path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue _file_write_file(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||||
|
{
|
||||||
|
void* task = JS_GetContextOpaque(context);
|
||||||
|
const char* file_name = JS_ToCString(context, argv[0]);
|
||||||
|
|
||||||
|
size_t size;
|
||||||
|
uint8_t* buffer = tf_util_try_get_array_buffer(context, &size, argv[1]);
|
||||||
|
bool is_array_buffer = false;
|
||||||
|
if (buffer)
|
||||||
|
{
|
||||||
|
is_array_buffer = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffer = (uint8_t*)JS_ToCStringLen(context, &size, argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
promiseid_t promise = -1;
|
||||||
|
JSValue promise_value = tf_task_allocate_promise(task, &promise);
|
||||||
|
fs_req_t* req = tf_malloc(sizeof(fs_req_t) + size);
|
||||||
|
*req = (fs_req_t)
|
||||||
|
{
|
||||||
|
.fs =
|
||||||
|
{
|
||||||
|
.data = (void*)(intptr_t)promise,
|
||||||
|
},
|
||||||
|
.size = size,
|
||||||
|
};
|
||||||
|
memcpy(req->buffer, buffer, size);
|
||||||
|
if (!is_array_buffer)
|
||||||
|
{
|
||||||
|
JS_FreeCString(context, (const char*)buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = uv_fs_open(tf_task_get_loop(task), &req->fs, file_name, UV_FS_O_CREAT | UV_FS_O_WRONLY, 0644, _file_write_open_callback);
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
tf_task_reject_promise(task, promise, JS_ThrowInternalError(context, "Failed to open %s for write: %s", file_name, uv_strerror(result)));
|
||||||
|
}
|
||||||
|
JS_FreeCString(context, file_name);
|
||||||
|
return promise_value;
|
||||||
|
}
|
||||||
|
|
||||||
static void _file_read_read_callback(uv_fs_t* req)
|
static void _file_read_read_callback(uv_fs_t* req)
|
||||||
{
|
{
|
||||||
fs_req_t* fsreq = (fs_req_t*)req;
|
fs_req_t* fsreq = (fs_req_t*)req;
|
||||||
@ -109,9 +224,8 @@ static void _file_read_open_callback(uv_fs_t* req)
|
|||||||
|
|
||||||
static JSValue _file_read_file(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
static JSValue _file_read_file(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||||
{
|
{
|
||||||
tf_task_t* task = JS_GetContextOpaque(context);
|
void* task = JS_GetContextOpaque(context);
|
||||||
const char* file_name = JS_ToCString(context, argv[0]);
|
const char* file_name = JS_ToCString(context, argv[0]);
|
||||||
const char* actual = tf_task_get_path_with_root(task, file_name);
|
|
||||||
|
|
||||||
promiseid_t promise = -1;
|
promiseid_t promise = -1;
|
||||||
JSValue promise_value = tf_task_allocate_promise(task, &promise);
|
JSValue promise_value = tf_task_allocate_promise(task, &promise);
|
||||||
@ -125,7 +239,7 @@ static JSValue _file_read_file(JSContext* context, JSValueConst this_val, int ar
|
|||||||
.size = k_file_read_max,
|
.size = k_file_read_max,
|
||||||
};
|
};
|
||||||
memset(req + 1, 0, k_file_read_max);
|
memset(req + 1, 0, k_file_read_max);
|
||||||
int result = uv_fs_open(tf_task_get_loop(task), &req->fs, actual, UV_FS_O_RDONLY, 0, _file_read_open_callback);
|
int result = uv_fs_open(tf_task_get_loop(task), &req->fs, file_name, UV_FS_O_RDONLY, 0, _file_read_open_callback);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
tf_task_reject_promise(task, promise, JS_ThrowInternalError(context, "Failed to open %s for read: %s", file_name, uv_strerror(result)));
|
tf_task_reject_promise(task, promise, JS_ThrowInternalError(context, "Failed to open %s for read: %s", file_name, uv_strerror(result)));
|
||||||
@ -133,7 +247,6 @@ static JSValue _file_read_file(JSContext* context, JSValueConst this_val, int ar
|
|||||||
tf_free(req);
|
tf_free(req);
|
||||||
}
|
}
|
||||||
JS_FreeCString(context, file_name);
|
JS_FreeCString(context, file_name);
|
||||||
tf_free((char*)actual);
|
|
||||||
return promise_value;
|
return promise_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,6 +365,81 @@ static JSValue _file_read_file_zip(JSContext* context, JSValueConst this_val, in
|
|||||||
return promise_value;
|
return promise_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JSValue _file_stat(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||||
|
{
|
||||||
|
void* task = JS_GetContextOpaque(context);
|
||||||
|
const char* path = JS_ToCString(context, argv[0]);
|
||||||
|
promiseid_t promise = -1;
|
||||||
|
JSValue promise_value = tf_task_allocate_promise(task, &promise);
|
||||||
|
|
||||||
|
file_stat_t* data = tf_malloc(sizeof(file_stat_t));
|
||||||
|
data->_task = task;
|
||||||
|
data->_promise = promise;
|
||||||
|
data->_request.data = data;
|
||||||
|
data->_context = context;
|
||||||
|
|
||||||
|
int result = uv_fs_stat(tf_task_get_loop(task), &data->_request, path, _file_on_stat_complete);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
tf_task_reject_promise(task, promise, JS_NewInt32(context, result));
|
||||||
|
uv_fs_req_cleanup(&data->_request);
|
||||||
|
tf_free(data);
|
||||||
|
}
|
||||||
|
JS_FreeCString(context, path);
|
||||||
|
return promise_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue _file_stat_zip(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||||
|
{
|
||||||
|
void* task = JS_GetContextOpaque(context);
|
||||||
|
promiseid_t promise = -1;
|
||||||
|
JSValue promise_value = tf_task_allocate_promise(task, &promise);
|
||||||
|
|
||||||
|
file_stat_t* data = tf_malloc(sizeof(file_stat_t));
|
||||||
|
data->_task = task;
|
||||||
|
data->_promise = promise;
|
||||||
|
data->_request.data = data;
|
||||||
|
data->_context = context;
|
||||||
|
|
||||||
|
/* Ignore the requested path and stat the zip itself. */
|
||||||
|
int result = uv_fs_stat(tf_task_get_loop(task), &data->_request, tf_task_get_zip_path(task), _file_on_stat_complete);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
tf_task_reject_promise(task, promise, JS_NewInt32(context, result));
|
||||||
|
uv_fs_req_cleanup(&data->_request);
|
||||||
|
tf_free(data);
|
||||||
|
}
|
||||||
|
return promise_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double _time_spec_to_double(const uv_timespec_t* time_spec)
|
||||||
|
{
|
||||||
|
return time_spec->tv_sec + (double)(time_spec->tv_nsec) / 1e9;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _file_on_stat_complete(uv_fs_t* request)
|
||||||
|
{
|
||||||
|
file_stat_t* data = (file_stat_t*)(request->data);
|
||||||
|
JSContext* context = data->_context;
|
||||||
|
|
||||||
|
if (request->result)
|
||||||
|
{
|
||||||
|
tf_task_reject_promise(data->_task, data->_promise, JS_NewInt32(context, request->result));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
JSValue result = JS_NewObject(context);
|
||||||
|
JS_SetPropertyStr(context, result, "mtime", JS_NewFloat64(context, _time_spec_to_double(&request->statbuf.st_mtim)));
|
||||||
|
JS_SetPropertyStr(context, result, "ctime", JS_NewFloat64(context, _time_spec_to_double(&request->statbuf.st_ctim)));
|
||||||
|
JS_SetPropertyStr(context, result, "atime", JS_NewFloat64(context, _time_spec_to_double(&request->statbuf.st_atim)));
|
||||||
|
JS_SetPropertyStr(context, result, "size", JS_NewFloat64(context, request->statbuf.st_size));
|
||||||
|
tf_task_resolve_promise(data->_task, data->_promise, result);
|
||||||
|
JS_FreeValue(context, result);
|
||||||
|
}
|
||||||
|
uv_fs_req_cleanup(request);
|
||||||
|
tf_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct _stat_t
|
typedef struct _stat_t
|
||||||
{
|
{
|
||||||
uv_fs_t request;
|
uv_fs_t request;
|
||||||
|
303
src/httpd.js.c
303
src/httpd.js.c
@ -7,7 +7,6 @@
|
|||||||
#include "ssb.db.h"
|
#include "ssb.db.h"
|
||||||
#include "ssb.h"
|
#include "ssb.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "tls.h"
|
|
||||||
#include "tlscontext.js.h"
|
#include "tlscontext.js.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "util.js.h"
|
#include "util.js.h"
|
||||||
@ -234,6 +233,46 @@ static JSValue _httpd_make_response_object(JSContext* context, tf_http_request_t
|
|||||||
return response_object;
|
return response_object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _httpd_callback_internal(tf_http_request_t* request, bool is_websocket)
|
||||||
|
{
|
||||||
|
http_handler_data_t* data = request->user_data;
|
||||||
|
JSContext* context = data->context;
|
||||||
|
JSValue request_object = JS_NewObject(context);
|
||||||
|
JS_SetPropertyStr(context, request_object, "method", JS_NewString(context, request->method));
|
||||||
|
JS_SetPropertyStr(context, request_object, "uri", JS_NewString(context, request->path));
|
||||||
|
JSValue headers = JS_NewObject(context);
|
||||||
|
for (int i = 0; i < request->headers_count; i++)
|
||||||
|
{
|
||||||
|
JS_SetPropertyStr(context, headers, request->headers[i].name, JS_NewString(context, request->headers[i].value));
|
||||||
|
}
|
||||||
|
JS_SetPropertyStr(context, request_object, "headers", headers);
|
||||||
|
if (request->query)
|
||||||
|
{
|
||||||
|
JS_SetPropertyStr(context, request_object, "query", JS_NewString(context, request->query));
|
||||||
|
}
|
||||||
|
if (request->body)
|
||||||
|
{
|
||||||
|
JS_SetPropertyStr(context, request_object, "body", tf_util_new_uint8_array(context, request->body, request->content_length));
|
||||||
|
}
|
||||||
|
|
||||||
|
JSValue client = JS_NewObject(context);
|
||||||
|
JS_SetPropertyStr(context, client, "tls", request->is_tls ? JS_TRUE : JS_FALSE);
|
||||||
|
JS_SetPropertyStr(context, request_object, "client", client);
|
||||||
|
|
||||||
|
JSValue response_object = _httpd_make_response_object(context, request);
|
||||||
|
/* The ref is owned by the JS object and will be released by the finalizer. */
|
||||||
|
tf_http_request_ref(request);
|
||||||
|
JSValue args[] = {
|
||||||
|
request_object,
|
||||||
|
response_object,
|
||||||
|
};
|
||||||
|
JSValue response = JS_Call(context, data->callback, JS_UNDEFINED, 2, args);
|
||||||
|
tf_util_report_error(context, response);
|
||||||
|
JS_FreeValue(context, request_object);
|
||||||
|
JS_FreeValue(context, response);
|
||||||
|
JS_FreeValue(context, response_object);
|
||||||
|
}
|
||||||
|
|
||||||
static bool _httpd_redirect(tf_http_request_t* request)
|
static bool _httpd_redirect(tf_http_request_t* request)
|
||||||
{
|
{
|
||||||
if (request->is_tls)
|
if (request->is_tls)
|
||||||
@ -253,6 +292,16 @@ static bool _httpd_redirect(tf_http_request_t* request)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _httpd_callback(tf_http_request_t* request)
|
||||||
|
{
|
||||||
|
if (_httpd_redirect(request))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_httpd_callback_internal(request, false);
|
||||||
|
}
|
||||||
|
|
||||||
static JSValue _httpd_websocket_upgrade(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
static JSValue _httpd_websocket_upgrade(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||||
{
|
{
|
||||||
tf_http_request_t* request = JS_GetOpaque(this_val, _httpd_request_class_id);
|
tf_http_request_t* request = JS_GetOpaque(this_val, _httpd_request_class_id);
|
||||||
@ -339,21 +388,73 @@ static JSValue _httpd_websocket_upgrade(JSContext* context, JSValueConst this_va
|
|||||||
return JS_UNDEFINED;
|
return JS_UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _httpd_cleanup_callback(void* user_data)
|
||||||
|
{
|
||||||
|
http_handler_data_t* data = user_data;
|
||||||
|
JS_FreeValue(data->context, data->callback);
|
||||||
|
tf_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue _httpd_endpoint_all(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||||
|
{
|
||||||
|
tf_http_t* http = JS_GetOpaque(this_val, _httpd_class_id);
|
||||||
|
const char* pattern = JS_ToCString(context, argv[0]);
|
||||||
|
http_handler_data_t* data = tf_malloc(sizeof(http_handler_data_t));
|
||||||
|
*data = (http_handler_data_t) { .context = context, .callback = JS_DupValue(context, argv[1]) };
|
||||||
|
tf_http_add_handler(http, pattern, _httpd_callback, _httpd_cleanup_callback, data);
|
||||||
|
JS_FreeCString(context, pattern);
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct _httpd_listener_t
|
typedef struct _httpd_listener_t
|
||||||
{
|
{
|
||||||
tf_tls_context_t* tls;
|
JSContext* context;
|
||||||
|
JSValue tls;
|
||||||
} httpd_listener_t;
|
} httpd_listener_t;
|
||||||
|
|
||||||
static void _httpd_listener_cleanup(void* user_data)
|
static void _httpd_listener_cleanup(void* user_data)
|
||||||
{
|
{
|
||||||
httpd_listener_t* listener = user_data;
|
httpd_listener_t* listener = user_data;
|
||||||
if (listener->tls)
|
JS_FreeValue(listener->context, listener->tls);
|
||||||
{
|
|
||||||
tf_tls_context_destroy(listener->tls);
|
|
||||||
}
|
|
||||||
tf_free(listener);
|
tf_free(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JSValue _httpd_endpoint_start(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||||
|
{
|
||||||
|
tf_http_t* http = JS_GetOpaque(this_val, _httpd_class_id);
|
||||||
|
int port = 0;
|
||||||
|
JS_ToInt32(context, &port, argv[0]);
|
||||||
|
|
||||||
|
httpd_listener_t* listener = tf_malloc(sizeof(httpd_listener_t));
|
||||||
|
*listener = (httpd_listener_t) { .context = context, .tls = JS_DupValue(context, argv[1]) };
|
||||||
|
tf_tls_context_t* tls = tf_tls_context_get(listener->tls);
|
||||||
|
int assigned_port = tf_http_listen(http, port, tls, _httpd_listener_cleanup, listener);
|
||||||
|
tf_printf(CYAN "~😎 Tilde Friends" RESET " " YELLOW VERSION_NUMBER RESET " is now up at " MAGENTA "http%s://127.0.0.1:%d/" RESET ".\n", tls ? "s" : "", assigned_port);
|
||||||
|
return JS_NewInt32(context, assigned_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _httpd_free_user_data(void* user_data)
|
||||||
|
{
|
||||||
|
tf_free(user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static JSValue _httpd_set_http_redirect(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||||
|
{
|
||||||
|
tf_http_t* http = JS_GetOpaque(this_val, _httpd_class_id);
|
||||||
|
http_user_data_t* user_data = tf_http_get_user_data(http);
|
||||||
|
if (!user_data)
|
||||||
|
{
|
||||||
|
user_data = tf_malloc(sizeof(http_user_data_t));
|
||||||
|
memset(user_data, 0, sizeof(http_user_data_t));
|
||||||
|
tf_http_set_user_data(http, user_data, _httpd_free_user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* redirect = JS_ToCString(context, argv[0]);
|
||||||
|
snprintf(user_data->redirect, sizeof(user_data->redirect), "%s", redirect ? redirect : "");
|
||||||
|
JS_FreeCString(context, redirect);
|
||||||
|
return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct _auth_query_work_t
|
typedef struct _auth_query_work_t
|
||||||
{
|
{
|
||||||
const char* settings;
|
const char* settings;
|
||||||
@ -682,24 +783,13 @@ typedef struct _http_file_t
|
|||||||
char etag[512];
|
char etag[512];
|
||||||
} http_file_t;
|
} http_file_t;
|
||||||
|
|
||||||
static bool _ends_with(const char* a, const char* suffix)
|
|
||||||
{
|
|
||||||
if (!a || !suffix)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
size_t alen = strlen(a);
|
|
||||||
size_t suffixlen = strlen(suffix);
|
|
||||||
return alen >= suffixlen && strcmp(a + alen - suffixlen, suffix) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _httpd_endpoint_static_read(tf_task_t* task, const char* path, int result, const void* data, void* user_data)
|
static void _httpd_endpoint_static_read(tf_task_t* task, const char* path, int result, const void* data, void* user_data)
|
||||||
{
|
{
|
||||||
http_file_t* file = user_data;
|
http_file_t* file = user_data;
|
||||||
tf_http_request_t* request = file->request;
|
tf_http_request_t* request = file->request;
|
||||||
if (result >= 0)
|
if (result >= 0)
|
||||||
{
|
{
|
||||||
if (strcmp(path, "core/tfrpc.js") == 0 || _ends_with(path, "core/tfrpc.js"))
|
if (strcmp(path, "core/tfrpc.js") == 0)
|
||||||
{
|
{
|
||||||
const char* content_type = _ext_to_content_type(strrchr(path, '.'), true);
|
const char* content_type = _ext_to_content_type(strrchr(path, '.'), true);
|
||||||
const char* headers[] = {
|
const char* headers[] = {
|
||||||
@ -841,10 +931,9 @@ static void _httpd_endpoint_static(tf_http_request_t* request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tf_task_t* task = request->user_data;
|
tf_task_t* task = request->user_data;
|
||||||
const char* root_path = tf_task_get_root_path(task);
|
size_t size = strlen(file_path) + strlen(after) + 1;
|
||||||
size_t size = (root_path ? strlen(root_path) + 1 : 0) + strlen(file_path) + strlen(after) + 1;
|
|
||||||
char* path = alloca(size);
|
char* path = alloca(size);
|
||||||
snprintf(path, size, "%s%s%s%s", root_path ? root_path : "", root_path ? "/" : "", file_path, after);
|
snprintf(path, size, "%s%s", file_path, after);
|
||||||
tf_http_request_ref(request);
|
tf_http_request_ref(request);
|
||||||
tf_file_stat(task, path, _httpd_endpoint_static_stat, request);
|
tf_file_stat(task, path, _httpd_endpoint_static_stat, request);
|
||||||
}
|
}
|
||||||
@ -2166,100 +2255,6 @@ static void _httpd_endpoint_logout(tf_http_request_t* request)
|
|||||||
tf_http_respond(request, 303, headers, tf_countof(headers) / 2, NULL, 0);
|
tf_http_respond(request, 303, headers, tf_countof(headers) / 2, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _httpd_endpoint_app_socket(tf_http_request_t* request)
|
|
||||||
{
|
|
||||||
tf_task_t* task = request->user_data;
|
|
||||||
tf_ssb_t* ssb = tf_task_get_ssb(task);
|
|
||||||
|
|
||||||
JSContext* context = tf_ssb_get_context(ssb);
|
|
||||||
JSValue global = JS_GetGlobalObject(context);
|
|
||||||
JSValue exports = JS_GetPropertyStr(context, global, "exports");
|
|
||||||
JSValue app_socket = JS_GetPropertyStr(context, exports, "app_socket");
|
|
||||||
|
|
||||||
JSValue request_object = JS_NewObject(context);
|
|
||||||
JSValue headers = JS_NewObject(context);
|
|
||||||
for (int i = 0; i < request->headers_count; i++)
|
|
||||||
{
|
|
||||||
JS_SetPropertyStr(context, headers, request->headers[i].name, JS_NewString(context, request->headers[i].value));
|
|
||||||
}
|
|
||||||
JS_SetPropertyStr(context, request_object, "headers", headers);
|
|
||||||
|
|
||||||
JSValue response = _httpd_make_response_object(context, request);
|
|
||||||
tf_http_request_ref(request);
|
|
||||||
|
|
||||||
JSValue args[] = {
|
|
||||||
request_object,
|
|
||||||
response,
|
|
||||||
};
|
|
||||||
|
|
||||||
JSValue result = JS_Call(context, app_socket, JS_NULL, tf_countof(args), args);
|
|
||||||
tf_util_report_error(context, result);
|
|
||||||
JS_FreeValue(context, result);
|
|
||||||
|
|
||||||
for (int i = 0; i < tf_countof(args); i++)
|
|
||||||
{
|
|
||||||
JS_FreeValue(context, args[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_FreeValue(context, app_socket);
|
|
||||||
JS_FreeValue(context, exports);
|
|
||||||
JS_FreeValue(context, global);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int _tf_httpd_get_tildefriends_int(JSContext* context, const char* arg)
|
|
||||||
{
|
|
||||||
JSValue global = JS_GetGlobalObject(context);
|
|
||||||
JSValue tildefriends = JS_GetPropertyStr(context, global, "tildefriends");
|
|
||||||
JSValue arg_value = JS_GetPropertyStr(context, tildefriends, arg);
|
|
||||||
int value = 0;
|
|
||||||
JS_ToInt32(context, &value, arg_value);
|
|
||||||
JS_FreeValue(context, arg_value);
|
|
||||||
JS_FreeValue(context, tildefriends);
|
|
||||||
JS_FreeValue(context, global);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char* _tf_httpd_get_tildefriends_arg_string(JSContext* context, const char* arg)
|
|
||||||
{
|
|
||||||
JSValue global = JS_GetGlobalObject(context);
|
|
||||||
JSValue tildefriends = JS_GetPropertyStr(context, global, "tildefriends");
|
|
||||||
JSValue args = JS_GetPropertyStr(context, tildefriends, "args");
|
|
||||||
JSValue arg_value = JS_GetPropertyStr(context, args, arg);
|
|
||||||
const char* value = !JS_IsUndefined(arg_value) ? JS_ToCString(context, arg_value) : NULL;
|
|
||||||
const char* result = value ? tf_strdup(value) : NULL;
|
|
||||||
JS_FreeCString(context, value);
|
|
||||||
JS_FreeValue(context, arg_value);
|
|
||||||
JS_FreeValue(context, args);
|
|
||||||
JS_FreeValue(context, tildefriends);
|
|
||||||
JS_FreeValue(context, global);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _httpd_free_user_data(void* user_data)
|
|
||||||
{
|
|
||||||
tf_free(user_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char* _httpd_read_file(tf_task_t* task, const char* path)
|
|
||||||
{
|
|
||||||
const char* actual = tf_task_get_path_with_root(task, path);
|
|
||||||
const size_t k_max_read = 8 * 1024 * 1024;
|
|
||||||
char* result = NULL;
|
|
||||||
char* buffer = tf_malloc(k_max_read);
|
|
||||||
FILE* file = fopen(actual, "rb");
|
|
||||||
if (file)
|
|
||||||
{
|
|
||||||
size_t size = fread(buffer, 1, k_max_read, file);
|
|
||||||
result = tf_malloc(size + 1);
|
|
||||||
memcpy(result, buffer, size);
|
|
||||||
result[size] = '\0';
|
|
||||||
fclose(file);
|
|
||||||
}
|
|
||||||
tf_free(buffer);
|
|
||||||
tf_free((char*)actual);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tf_httpd_register(JSContext* context)
|
void tf_httpd_register(JSContext* context)
|
||||||
{
|
{
|
||||||
JS_NewClassID(&_httpd_class_id);
|
JS_NewClassID(&_httpd_class_id);
|
||||||
@ -2280,41 +2275,15 @@ void tf_httpd_register(JSContext* context)
|
|||||||
{
|
{
|
||||||
fprintf(stderr, "Failed to register Request.\n");
|
fprintf(stderr, "Failed to register Request.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int http_port = _tf_httpd_get_tildefriends_int(context, "http_port");
|
|
||||||
int https_port = _tf_httpd_get_tildefriends_int(context, "https_port");
|
|
||||||
const char* out_http_port_file = _tf_httpd_get_tildefriends_arg_string(context, "out_http_port_file");
|
|
||||||
|
|
||||||
JSValue global = JS_GetGlobalObject(context);
|
JSValue global = JS_GetGlobalObject(context);
|
||||||
JSValue httpd = JS_NewObjectClass(context, _httpd_class_id);
|
JSValue httpd = JS_NewObjectClass(context, _httpd_class_id);
|
||||||
|
|
||||||
tf_task_t* task = tf_task_get(context);
|
tf_task_t* task = tf_task_get(context);
|
||||||
tf_ssb_t* ssb = tf_task_get_ssb(task);
|
|
||||||
uv_loop_t* loop = tf_task_get_loop(task);
|
uv_loop_t* loop = tf_task_get_loop(task);
|
||||||
tf_http_t* http = tf_http_create(loop);
|
tf_http_t* http = tf_http_create(loop);
|
||||||
tf_http_set_trace(http, tf_task_get_trace(task));
|
tf_http_set_trace(http, tf_task_get_trace(task));
|
||||||
JS_SetOpaque(httpd, http);
|
JS_SetOpaque(httpd, http);
|
||||||
|
|
||||||
if (https_port)
|
|
||||||
{
|
|
||||||
http_user_data_t* user_data = tf_http_get_user_data(http);
|
|
||||||
if (!user_data)
|
|
||||||
{
|
|
||||||
user_data = tf_malloc(sizeof(http_user_data_t));
|
|
||||||
memset(user_data, 0, sizeof(http_user_data_t));
|
|
||||||
tf_http_set_user_data(http, user_data, _httpd_free_user_data);
|
|
||||||
}
|
|
||||||
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
|
||||||
tf_ssb_db_get_global_setting_string(db, "http_redirect", user_data->redirect, sizeof(user_data->redirect));
|
|
||||||
tf_ssb_release_db_reader(ssb, db);
|
|
||||||
|
|
||||||
/* Workaround. */
|
|
||||||
if (strcmp(user_data->redirect, "0") == 0)
|
|
||||||
{
|
|
||||||
*user_data->redirect = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tf_http_add_handler(http, "/", _httpd_endpoint_root, NULL, task);
|
tf_http_add_handler(http, "/", _httpd_endpoint_root, NULL, task);
|
||||||
tf_http_add_handler(http, "/codemirror/*", _httpd_endpoint_static, NULL, task);
|
tf_http_add_handler(http, "/codemirror/*", _httpd_endpoint_static, NULL, task);
|
||||||
tf_http_add_handler(http, "/lit/*", _httpd_endpoint_static, NULL, task);
|
tf_http_add_handler(http, "/lit/*", _httpd_endpoint_static, NULL, task);
|
||||||
@ -2343,56 +2312,10 @@ void tf_httpd_register(JSContext* context)
|
|||||||
tf_http_add_handler(http, "/login/logout", _httpd_endpoint_logout, NULL, task);
|
tf_http_add_handler(http, "/login/logout", _httpd_endpoint_logout, NULL, task);
|
||||||
tf_http_add_handler(http, "/login", _httpd_endpoint_login, NULL, task);
|
tf_http_add_handler(http, "/login", _httpd_endpoint_login, NULL, task);
|
||||||
|
|
||||||
tf_http_add_handler(http, "/app/socket", _httpd_endpoint_app_socket, NULL, task);
|
JS_SetPropertyStr(context, httpd, "all", JS_NewCFunction(context, _httpd_endpoint_all, "all", 2));
|
||||||
|
JS_SetPropertyStr(context, httpd, "start", JS_NewCFunction(context, _httpd_endpoint_start, "start", 2));
|
||||||
|
JS_SetPropertyStr(context, httpd, "set_http_redirect", JS_NewCFunction(context, _httpd_set_http_redirect, "set_http_redirect", 1));
|
||||||
JS_SetPropertyStr(context, httpd, "auth_query", JS_NewCFunction(context, _httpd_auth_query, "auth_query", 1));
|
JS_SetPropertyStr(context, httpd, "auth_query", JS_NewCFunction(context, _httpd_auth_query, "auth_query", 1));
|
||||||
JS_SetPropertyStr(context, global, "httpd", httpd);
|
JS_SetPropertyStr(context, global, "httpd", httpd);
|
||||||
JS_FreeValue(context, global);
|
JS_FreeValue(context, global);
|
||||||
|
|
||||||
if (http_port > 0 || out_http_port_file)
|
|
||||||
{
|
|
||||||
httpd_listener_t* listener = tf_malloc(sizeof(httpd_listener_t));
|
|
||||||
*listener = (httpd_listener_t) { 0 };
|
|
||||||
int assigned_port = tf_http_listen(http, http_port, NULL, _httpd_listener_cleanup, listener);
|
|
||||||
tf_printf(CYAN "~😎 Tilde Friends" RESET " " YELLOW VERSION_NUMBER RESET " is now up at " MAGENTA "http://127.0.0.1:%d/" RESET ".\n", assigned_port);
|
|
||||||
|
|
||||||
if (out_http_port_file)
|
|
||||||
{
|
|
||||||
const char* actual_http_port_file = tf_task_get_path_with_root(task, out_http_port_file);
|
|
||||||
FILE* file = fopen(actual_http_port_file, "wb");
|
|
||||||
if (file)
|
|
||||||
{
|
|
||||||
fprintf(file, "%d", assigned_port);
|
|
||||||
fclose(file);
|
|
||||||
tf_printf("Wrote the port file: %s.\n", out_http_port_file);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tf_printf("Failed to open %s for write: %s.\n", out_http_port_file, strerror(errno));
|
|
||||||
}
|
|
||||||
tf_free((char*)actual_http_port_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (https_port)
|
|
||||||
{
|
|
||||||
const char* k_certificate = "data/httpd/certificate.pem";
|
|
||||||
const char* k_private_key = "data/httpd/privatekey.pem";
|
|
||||||
const char* certificate = _httpd_read_file(task, k_certificate);
|
|
||||||
const char* private_key = _httpd_read_file(task, k_private_key);
|
|
||||||
if (certificate && private_key)
|
|
||||||
{
|
|
||||||
tf_tls_context_t* tls = tf_tls_context_create();
|
|
||||||
tf_tls_context_set_certificate(tls, certificate);
|
|
||||||
tf_tls_context_set_private_key(tls, private_key);
|
|
||||||
httpd_listener_t* listener = tf_malloc(sizeof(httpd_listener_t));
|
|
||||||
*listener = (httpd_listener_t) { .tls = tls };
|
|
||||||
int assigned_port = tf_http_listen(http, https_port, tls, _httpd_listener_cleanup, listener);
|
|
||||||
tf_printf(CYAN "~😎 Tilde Friends" RESET " " YELLOW VERSION_NUMBER RESET " is now up at " MAGENTA "https://127.0.0.1:%d/" RESET ".\n", assigned_port);
|
|
||||||
}
|
|
||||||
tf_free((char*)certificate);
|
|
||||||
tf_free((char*)private_key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tf_free((void*)out_http_port_file);
|
|
||||||
}
|
}
|
||||||
|
1
src/index.md
Normal file
1
src/index.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
\mainpage Tilde Friends Source Documentation
|
73
src/main.c
73
src/main.c
@ -808,8 +808,8 @@ static int _tf_command_create_invite(const char* file, int argc, char* argv[])
|
|||||||
const char* default_db_path = _get_db_path();
|
const char* default_db_path = _get_db_path();
|
||||||
const char* db_path = default_db_path;
|
const char* db_path = default_db_path;
|
||||||
const char* identity = NULL;
|
const char* identity = NULL;
|
||||||
int use_count = 1;
|
int use_count = 0;
|
||||||
int expires = 3600;
|
int expires = 0;
|
||||||
bool show_usage = false;
|
bool show_usage = false;
|
||||||
const char* host = NULL;
|
const char* host = NULL;
|
||||||
int port = 0;
|
int port = 0;
|
||||||
@ -868,8 +868,8 @@ static int _tf_command_create_invite(const char* file, int argc, char* argv[])
|
|||||||
tf_printf(" -i, --identity identity Account from which to get latest sequence number.\n");
|
tf_printf(" -i, --identity identity Account from which to get latest sequence number.\n");
|
||||||
tf_printf(" -a, --address address Address to which the recipient will connect.\n");
|
tf_printf(" -a, --address address Address to which the recipient will connect.\n");
|
||||||
tf_printf(" -p, --port port Port to which the recipient will connect.\n");
|
tf_printf(" -p, --port port Port to which the recipient will connect.\n");
|
||||||
tf_printf(" -u, --use_count count Number of times this invite may be used (default: 1).\n");
|
tf_printf(" -u, --use_count count Number of times this invite may be used.\n");
|
||||||
tf_printf(" -e, --expires seconds How long this invite is valid in seconds (-1 for indefinitely, default: 1 hour).\n");
|
tf_printf(" -e, --expires seconds How long this invite is valid in seconds (-1 for indefinitely).\n");
|
||||||
tf_printf(" -h, --help Show this usage information.\n");
|
tf_printf(" -h, --help Show this usage information.\n");
|
||||||
tf_free((void*)default_db_path);
|
tf_free((void*)default_db_path);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
@ -1256,47 +1256,6 @@ static int _tf_run_task(const tf_run_args_t* args, int index)
|
|||||||
snprintf(db_path_buffer, sizeof(db_path_buffer), "%s.%d", args->db_path, index);
|
snprintf(db_path_buffer, sizeof(db_path_buffer), "%s.%d", args->db_path, index);
|
||||||
db_path = db_path_buffer;
|
db_path = db_path_buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* cwd = NULL;
|
|
||||||
if (!args->zip)
|
|
||||||
{
|
|
||||||
size_t cwd_size = 1;
|
|
||||||
uv_cwd((char[1]) { 0 }, &cwd_size);
|
|
||||||
cwd = alloca(cwd_size);
|
|
||||||
if (uv_cwd(cwd, &cwd_size) == 0)
|
|
||||||
{
|
|
||||||
size_t test_path_size = cwd_size + strlen("/core/core.js");
|
|
||||||
char* test_path = alloca(test_path_size);
|
|
||||||
|
|
||||||
uv_loop_t* loop = tf_task_get_loop(task);
|
|
||||||
uv_fs_t req = { 0 };
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
snprintf(test_path, test_path_size, "%s/core/core.js", cwd);
|
|
||||||
int r = uv_fs_access(loop, &req, test_path, 0000, NULL);
|
|
||||||
uv_fs_req_cleanup(&req);
|
|
||||||
if (r != UV_ENOENT)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
char* slash = strrchr(cwd, '/');
|
|
||||||
if (slash)
|
|
||||||
{
|
|
||||||
*slash = '\0';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tf_printf("Using %s as the working directory.\n", cwd);
|
|
||||||
}
|
|
||||||
if (!*cwd)
|
|
||||||
{
|
|
||||||
cwd = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tf_task_set_db_path(task, db_path);
|
tf_task_set_db_path(task, db_path);
|
||||||
tf_task_activate(task);
|
tf_task_activate(task);
|
||||||
tf_ssb_set_verbose(tf_task_get_ssb(task), args->verbose);
|
tf_ssb_set_verbose(tf_task_get_ssb(task), args->verbose);
|
||||||
@ -1307,33 +1266,13 @@ static int _tf_run_task(const tf_run_args_t* args, int index)
|
|||||||
{
|
{
|
||||||
tf_ssb_import_from_zip(tf_task_get_ssb(task), args->zip, "core", "apps");
|
tf_ssb_import_from_zip(tf_task_get_ssb(task), args->zip, "core", "apps");
|
||||||
}
|
}
|
||||||
else if (cwd)
|
|
||||||
{
|
|
||||||
size_t apps_path_size = strlen(cwd) + strlen("/apps") + 1;
|
|
||||||
char* apps_path = alloca(apps_path_size);
|
|
||||||
snprintf(apps_path, apps_path_size, "%s/apps", cwd);
|
|
||||||
tf_ssb_import(tf_task_get_ssb(task), "core", apps_path);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tf_ssb_import(tf_task_get_ssb(task), "core", "apps");
|
tf_ssb_import(tf_task_get_ssb(task), "core", "apps");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tf_ssb_set_main_thread(tf_task_get_ssb(task), true);
|
tf_ssb_set_main_thread(tf_task_get_ssb(task), true);
|
||||||
const char* script = args->script;
|
if (tf_task_execute(task, args->script))
|
||||||
if (!script && cwd)
|
|
||||||
{
|
|
||||||
size_t script_size = (cwd ? strlen(cwd) : 0) + strlen("/core/core.js") + 1;
|
|
||||||
char* script_buffer = alloca(script_size);
|
|
||||||
snprintf(script_buffer, script_size, "%s/core/core.js", cwd);
|
|
||||||
script = script_buffer;
|
|
||||||
}
|
|
||||||
else if (!script)
|
|
||||||
{
|
|
||||||
script = "core/core.js";
|
|
||||||
}
|
|
||||||
tf_task_set_root_path(task, cwd);
|
|
||||||
if (tf_task_execute(task, script))
|
|
||||||
{
|
{
|
||||||
tf_task_run(task);
|
tf_task_run(task);
|
||||||
result = 0;
|
result = 0;
|
||||||
@ -1417,6 +1356,7 @@ static int _tf_command_run(const char* file, int argc, char* argv[])
|
|||||||
const char* default_db_path = _get_db_path();
|
const char* default_db_path = _get_db_path();
|
||||||
tf_run_args_t args = {
|
tf_run_args_t args = {
|
||||||
.count = 1,
|
.count = 1,
|
||||||
|
.script = "core/core.js",
|
||||||
.http_port = 12345,
|
.http_port = 12345,
|
||||||
.https_port = 12346,
|
.https_port = 12346,
|
||||||
.ssb_port = 8008,
|
.ssb_port = 8008,
|
||||||
@ -1847,6 +1787,7 @@ void tf_run_thread_start(const char* zip_path)
|
|||||||
tf_run_thread_data_t* data = tf_malloc(sizeof(tf_run_thread_data_t));
|
tf_run_thread_data_t* data = tf_malloc(sizeof(tf_run_thread_data_t));
|
||||||
tf_run_args_t args = {
|
tf_run_args_t args = {
|
||||||
.count = 1,
|
.count = 1,
|
||||||
|
.script = "core/core.js",
|
||||||
.http_port = 12345,
|
.http_port = 12345,
|
||||||
.https_port = 12346,
|
.https_port = 12346,
|
||||||
.ssb_port = 8008,
|
.ssb_port = 8008,
|
||||||
|
20
src/ssb.c
20
src/ssb.c
@ -372,7 +372,7 @@ static void _tf_ssb_connection_finalizer(JSRuntime* runtime, JSValue value);
|
|||||||
static void _tf_ssb_connection_on_close(uv_handle_t* handle);
|
static void _tf_ssb_connection_on_close(uv_handle_t* handle);
|
||||||
static void _tf_ssb_nonce_inc(uint8_t* nonce);
|
static void _tf_ssb_nonce_inc(uint8_t* nonce);
|
||||||
static void _tf_ssb_notify_connections_changed(tf_ssb_t* ssb, tf_ssb_change_t change, tf_ssb_connection_t* connection);
|
static void _tf_ssb_notify_connections_changed(tf_ssb_t* ssb, tf_ssb_change_t change, tf_ssb_connection_t* connection);
|
||||||
static bool _tf_ssb_parse_connect_string(tf_ssb_t* ssb, const char* in_broadcast, tf_ssb_broadcast_t* out_broadcast);
|
static bool _tf_ssb_parse_connect_string(const char* in_broadcast, tf_ssb_broadcast_t* out_broadcast);
|
||||||
static void _tf_ssb_start_update_settings(tf_ssb_t* ssb);
|
static void _tf_ssb_start_update_settings(tf_ssb_t* ssb);
|
||||||
static void _tf_ssb_update_settings(tf_ssb_t* ssb);
|
static void _tf_ssb_update_settings(tf_ssb_t* ssb);
|
||||||
static void _tf_ssb_write(tf_ssb_connection_t* connection, void* data, size_t size);
|
static void _tf_ssb_write(tf_ssb_connection_t* connection, void* data, size_t size);
|
||||||
@ -1712,11 +1712,7 @@ static void _tf_ssb_connection_rpc_recv(tf_ssb_connection_t* connection, uint8_t
|
|||||||
bool close_connection = false;
|
bool close_connection = false;
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
char buffer[256];
|
tf_ssb_connection_close(connection, "rpc recv zero");
|
||||||
const char* request_name = "<unknown>";
|
|
||||||
_tf_ssb_connection_get_request_callback(connection, -request_number, NULL, NULL, &request_name);
|
|
||||||
snprintf(buffer, sizeof(buffer), "rpc recv zero (req=%d, name=%s)", request_number, request_name);
|
|
||||||
tf_ssb_connection_close(connection, buffer);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (flags & k_ssb_rpc_flag_json)
|
else if (flags & k_ssb_rpc_flag_json)
|
||||||
@ -3326,7 +3322,7 @@ static void _tf_ssb_update_seeds_after_work(tf_ssb_t* ssb, int status, void* use
|
|||||||
for (int i = 0; i < seeds->seeds_count; i++)
|
for (int i = 0; i < seeds->seeds_count; i++)
|
||||||
{
|
{
|
||||||
tf_ssb_broadcast_t broadcast = { .origin = k_tf_ssb_broadcast_origin_peer_exchange };
|
tf_ssb_broadcast_t broadcast = { .origin = k_tf_ssb_broadcast_origin_peer_exchange };
|
||||||
if (_tf_ssb_parse_connect_string(ssb, seeds->seeds[i], &broadcast))
|
if (_tf_ssb_parse_connect_string(seeds->seeds[i], &broadcast))
|
||||||
{
|
{
|
||||||
_tf_ssb_add_broadcast(ssb, &broadcast, k_seed_expire_seconds);
|
_tf_ssb_add_broadcast(ssb, &broadcast, k_seed_expire_seconds);
|
||||||
}
|
}
|
||||||
@ -3435,7 +3431,7 @@ bool tf_ssb_whoami(tf_ssb_t* ssb, char* out_id, size_t out_id_size)
|
|||||||
return tf_ssb_id_bin_to_str(out_id, out_id_size, ssb->pub);
|
return tf_ssb_id_bin_to_str(out_id, out_id_size, ssb->pub);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _tf_ssb_parse_connect_string(tf_ssb_t* ssb, const char* in_broadcast, tf_ssb_broadcast_t* out_broadcast)
|
static bool _tf_ssb_parse_connect_string(const char* in_broadcast, tf_ssb_broadcast_t* out_broadcast)
|
||||||
{
|
{
|
||||||
char public_key_str[54] = { 0 };
|
char public_key_str[54] = { 0 };
|
||||||
char secret_key_str[45] = { 0 };
|
char secret_key_str[45] = { 0 };
|
||||||
@ -3454,7 +3450,7 @@ static bool _tf_ssb_parse_connect_string(tf_ssb_t* ssb, const char* in_broadcast
|
|||||||
return tf_ssb_id_str_to_bin(out_broadcast->pub, public_key_str) &&
|
return tf_ssb_id_str_to_bin(out_broadcast->pub, public_key_str) &&
|
||||||
tf_base64_decode(secret_key_str, strlen(secret_key_str), out_broadcast->invite, sizeof(out_broadcast->invite));
|
tf_base64_decode(secret_key_str, strlen(secret_key_str), out_broadcast->invite, sizeof(out_broadcast->invite));
|
||||||
}
|
}
|
||||||
else if (ssb->verbose && strncmp(in_broadcast, "ws:", 3) == 0)
|
else if (strncmp(in_broadcast, "ws:", 3) == 0)
|
||||||
{
|
{
|
||||||
tf_printf("Unsupported broadcast: %s\n", in_broadcast);
|
tf_printf("Unsupported broadcast: %s\n", in_broadcast);
|
||||||
}
|
}
|
||||||
@ -3464,7 +3460,7 @@ static bool _tf_ssb_parse_connect_string(tf_ssb_t* ssb, const char* in_broadcast
|
|||||||
void tf_ssb_connect_str(tf_ssb_t* ssb, const char* address, int connect_flags, tf_ssb_connect_callback_t* callback, void* user_data)
|
void tf_ssb_connect_str(tf_ssb_t* ssb, const char* address, int connect_flags, tf_ssb_connect_callback_t* callback, void* user_data)
|
||||||
{
|
{
|
||||||
tf_ssb_broadcast_t broadcast = { 0 };
|
tf_ssb_broadcast_t broadcast = { 0 };
|
||||||
if (_tf_ssb_parse_connect_string(ssb, address, &broadcast))
|
if (_tf_ssb_parse_connect_string(address, &broadcast))
|
||||||
{
|
{
|
||||||
if (memcmp(broadcast.invite, (uint8_t[crypto_sign_ed25519_SEEDBYTES]) { 0 }, crypto_sign_ed25519_SEEDBYTES) == 0)
|
if (memcmp(broadcast.invite, (uint8_t[crypto_sign_ed25519_SEEDBYTES]) { 0 }, crypto_sign_ed25519_SEEDBYTES) == 0)
|
||||||
{
|
{
|
||||||
@ -3560,7 +3556,7 @@ static void _tf_ssb_add_broadcast(tf_ssb_t* ssb, const tf_ssb_broadcast_t* broad
|
|||||||
void tf_ssb_add_broadcast(tf_ssb_t* ssb, const char* connection, tf_ssb_broadcast_origin_t origin, int64_t expires_seconds)
|
void tf_ssb_add_broadcast(tf_ssb_t* ssb, const char* connection, tf_ssb_broadcast_origin_t origin, int64_t expires_seconds)
|
||||||
{
|
{
|
||||||
tf_ssb_broadcast_t broadcast = { .origin = origin };
|
tf_ssb_broadcast_t broadcast = { .origin = origin };
|
||||||
if (_tf_ssb_parse_connect_string(ssb, connection, &broadcast))
|
if (_tf_ssb_parse_connect_string(connection, &broadcast))
|
||||||
{
|
{
|
||||||
_tf_ssb_add_broadcast(ssb, &broadcast, expires_seconds);
|
_tf_ssb_add_broadcast(ssb, &broadcast, expires_seconds);
|
||||||
}
|
}
|
||||||
@ -3583,7 +3579,7 @@ static void _tf_ssb_on_broadcast_listener_recv(uv_udp_t* handle, ssize_t nread,
|
|||||||
while (entry)
|
while (entry)
|
||||||
{
|
{
|
||||||
tf_ssb_broadcast_t broadcast = { .origin = k_tf_ssb_broadcast_origin_discovery };
|
tf_ssb_broadcast_t broadcast = { .origin = k_tf_ssb_broadcast_origin_discovery };
|
||||||
if (_tf_ssb_parse_connect_string(ssb, entry, &broadcast))
|
if (_tf_ssb_parse_connect_string(entry, &broadcast))
|
||||||
{
|
{
|
||||||
_tf_ssb_add_broadcast(ssb, &broadcast, k_udp_discovery_expires_seconds);
|
_tf_ssb_add_broadcast(ssb, &broadcast, k_udp_discovery_expires_seconds);
|
||||||
}
|
}
|
||||||
|
13
src/ssb.db.c
13
src/ssb.db.c
@ -2182,7 +2182,7 @@ const char* tf_ssb_db_get_profile_name(sqlite3* db, const char* id)
|
|||||||
static void _tf_ssb_db_invite_cleanup(sqlite3* db)
|
static void _tf_ssb_db_invite_cleanup(sqlite3* db)
|
||||||
{
|
{
|
||||||
sqlite3_stmt* statement;
|
sqlite3_stmt* statement;
|
||||||
if (sqlite3_prepare(db, "DELETE FROM invites WHERE use_count = 0 OR (expires > 0 AND expires < ?)", -1, &statement, NULL) == SQLITE_OK)
|
if (sqlite3_prepare(db, "DELETE FROM invites WHERE use_count = 0 OR expires < ?", -1, &statement, NULL) == SQLITE_OK)
|
||||||
{
|
{
|
||||||
if (sqlite3_bind_int64(statement, 1, (int64_t)time(NULL)) == SQLITE_OK)
|
if (sqlite3_bind_int64(statement, 1, (int64_t)time(NULL)) == SQLITE_OK)
|
||||||
{
|
{
|
||||||
@ -2190,13 +2190,7 @@ static void _tf_ssb_db_invite_cleanup(sqlite3* db)
|
|||||||
{
|
{
|
||||||
if (sqlite3_changes(db))
|
if (sqlite3_changes(db))
|
||||||
{
|
{
|
||||||
char buffer[2] = { 0 };
|
tf_printf("Cleaned up %d used/expired invites.\n", sqlite3_changes(db));
|
||||||
size_t buffer_size = sizeof(buffer);
|
|
||||||
bool verbose = uv_os_getenv("TF_SSB_VERBOSE", buffer, &buffer_size) == 0 && strcmp(buffer, "1") == 0;
|
|
||||||
if (verbose)
|
|
||||||
{
|
|
||||||
tf_printf("Cleaned up %d used/expired invites.\n", sqlite3_changes(db));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2237,8 +2231,7 @@ bool tf_ssb_db_generate_invite(sqlite3* db, const char* id, const char* host, in
|
|||||||
if (sqlite3_prepare(db, "INSERT INTO invites (invite_public_key, account, use_count, expires) VALUES (?, ?, ?, ?)", -1, &statement, NULL) == SQLITE_OK)
|
if (sqlite3_prepare(db, "INSERT INTO invites (invite_public_key, account, use_count, expires) VALUES (?, ?, ?, ?)", -1, &statement, NULL) == SQLITE_OK)
|
||||||
{
|
{
|
||||||
if (sqlite3_bind_text(statement, 1, public, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, id, -1, NULL) == SQLITE_OK &&
|
if (sqlite3_bind_text(statement, 1, public, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, id, -1, NULL) == SQLITE_OK &&
|
||||||
sqlite3_bind_int(statement, 3, use_count) == SQLITE_OK &&
|
sqlite3_bind_int(statement, 3, use_count) == SQLITE_OK && sqlite3_bind_int64(statement, 4, (int64_t)time(NULL) + expires_seconds) == SQLITE_OK)
|
||||||
sqlite3_bind_int64(statement, 4, (expires_seconds > 0 ? (int64_t)time(NULL) : 0) + expires_seconds) == SQLITE_OK)
|
|
||||||
{
|
{
|
||||||
inserted = sqlite3_step(statement) == SQLITE_DONE;
|
inserted = sqlite3_step(statement) == SQLITE_DONE;
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,6 @@ static void _tf_ssb_rpc_send_peers_exchange(tf_ssb_connection_t* connection);
|
|||||||
static void _tf_ssb_rpc_start_delete_blobs(tf_ssb_t* ssb, int delay_ms);
|
static void _tf_ssb_rpc_start_delete_blobs(tf_ssb_t* ssb, int delay_ms);
|
||||||
static void _tf_ssb_rpc_start_delete_feeds(tf_ssb_t* ssb, int delay_ms);
|
static void _tf_ssb_rpc_start_delete_feeds(tf_ssb_t* ssb, int delay_ms);
|
||||||
static void _tf_ssb_rpc_ebt_replicate_resend_clock(tf_ssb_connection_t* connection, bool skip, void* user_data);
|
static void _tf_ssb_rpc_ebt_replicate_resend_clock(tf_ssb_connection_t* connection, bool skip, void* user_data);
|
||||||
static void _tf_ssb_rpc_connection_blobs_createWants_callback(
|
|
||||||
tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data);
|
|
||||||
|
|
||||||
static void _tf_ssb_rpc_gossip_ping_callback(
|
static void _tf_ssb_rpc_gossip_ping_callback(
|
||||||
tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
|
tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
|
||||||
@ -279,7 +277,6 @@ static void _tf_ssb_rpc_blobs_createWants(
|
|||||||
tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "blobs.createWants");
|
tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "blobs.createWants");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tf_ssb_connection_add_request(connection, -request_number, "blobs.createWants", _tf_ssb_rpc_connection_blobs_createWants_callback, NULL, NULL, NULL);
|
|
||||||
tf_ssb_blob_wants_t* blob_wants = tf_ssb_connection_get_blob_wants_state(connection);
|
tf_ssb_blob_wants_t* blob_wants = tf_ssb_connection_get_blob_wants_state(connection);
|
||||||
tf_ssb_add_blob_want_added_callback(ssb, _tf_ssb_rpc_blob_wants_added_callback, NULL, connection);
|
tf_ssb_add_blob_want_added_callback(ssb, _tf_ssb_rpc_blob_wants_added_callback, NULL, connection);
|
||||||
blob_wants->request_number = request_number;
|
blob_wants->request_number = request_number;
|
||||||
@ -460,7 +457,7 @@ static void _tf_ssb_rpc_send_endpoints(tf_ssb_t* ssb)
|
|||||||
{
|
{
|
||||||
if (tf_ssb_connection_is_endpoint(connections[i]) && tf_ssb_connection_is_connected(connections[i]))
|
if (tf_ssb_connection_is_endpoint(connections[i]) && tf_ssb_connection_is_connected(connections[i]))
|
||||||
{
|
{
|
||||||
int32_t request_number = tf_ssb_connection_get_endpoint_request_number(connections[i]);
|
int32_t request_number = tf_ssb_connection_get_ebt_request_number(connections[i]);
|
||||||
tf_ssb_connection_rpc_send_json(connections[i], k_ssb_rpc_flag_json | k_ssb_rpc_flag_stream, -request_number, NULL, endpoints, NULL, NULL, NULL);
|
tf_ssb_connection_rpc_send_json(connections[i], k_ssb_rpc_flag_json | k_ssb_rpc_flag_stream, -request_number, NULL, endpoints, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,6 @@
|
|||||||
|
|
||||||
#include "sodium/crypto_sign.h"
|
#include "sodium/crypto_sign.h"
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
#include <TargetConditionals.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#endif
|
#endif
|
||||||
|
52
src/task.c
52
src/task.c
@ -40,10 +40,6 @@
|
|||||||
#define WEXITSTATUS(x) (x)
|
#define WEXITSTATUS(x) (x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
|
||||||
#include <TargetConditionals.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(__APPLE__) && !defined(__OpenBSD__)
|
#if !defined(__APPLE__) && !defined(__OpenBSD__)
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#endif
|
#endif
|
||||||
@ -159,7 +155,6 @@ typedef struct _tf_task_t
|
|||||||
int _https_port;
|
int _https_port;
|
||||||
char _db_path[256];
|
char _db_path[256];
|
||||||
char _zip_path[256];
|
char _zip_path[256];
|
||||||
char _root_path[256];
|
|
||||||
unzFile _zip;
|
unzFile _zip;
|
||||||
const char* _args;
|
const char* _args;
|
||||||
|
|
||||||
@ -368,15 +363,7 @@ static const char* _task_loadFile(tf_task_t* task, const char* fileName, size_t*
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const char* actual = fileName;
|
FILE* file = fopen(fileName, "rb");
|
||||||
if (*task->_root_path)
|
|
||||||
{
|
|
||||||
size_t size = strlen(task->_root_path) + strlen(fileName) + 2;
|
|
||||||
char* buffer = alloca(size);
|
|
||||||
snprintf(buffer, size, "%s/%s", task->_root_path, fileName);
|
|
||||||
actual = fileName;
|
|
||||||
}
|
|
||||||
FILE* file = fopen(actual, "rb");
|
|
||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
fseek(file, 0, SEEK_END);
|
fseek(file, 0, SEEK_END);
|
||||||
@ -729,6 +716,7 @@ static JSValue _tf_task_platform(JSContext* context, JSValueConst this_val, int
|
|||||||
#elif defined(__ANDROID__)
|
#elif defined(__ANDROID__)
|
||||||
return JS_NewString(context, "android");
|
return JS_NewString(context, "android");
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
|
#include <TargetConditionals.h>
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
return JS_NewString(context, "iphone");
|
return JS_NewString(context, "iphone");
|
||||||
#else
|
#else
|
||||||
@ -1726,6 +1714,7 @@ void tf_task_activate(tf_task_t* task)
|
|||||||
JS_SetPropertyStr(context, global, "TlsContext", tf_tls_context_register(context));
|
JS_SetPropertyStr(context, global, "TlsContext", tf_tls_context_register(context));
|
||||||
tf_file_register(context);
|
tf_file_register(context);
|
||||||
tf_database_register(context);
|
tf_database_register(context);
|
||||||
|
tf_httpd_register(context);
|
||||||
|
|
||||||
task->_ssb = tf_ssb_create(&task->_loop, task->_context, task->_db_path, task->_network_key);
|
task->_ssb = tf_ssb_create(&task->_loop, task->_context, task->_db_path, task->_network_key);
|
||||||
tf_ssb_set_trace(task->_ssb, task->_trace);
|
tf_ssb_set_trace(task->_ssb, task->_trace);
|
||||||
@ -1742,18 +1731,10 @@ void tf_task_activate(tf_task_t* task)
|
|||||||
}
|
}
|
||||||
|
|
||||||
JS_SetPropertyStr(context, tildefriends, "ssb_port", JS_NewInt32(context, actual_ssb_port));
|
JS_SetPropertyStr(context, tildefriends, "ssb_port", JS_NewInt32(context, actual_ssb_port));
|
||||||
if (task->_http_port)
|
JS_SetPropertyStr(context, tildefriends, "http_port", JS_NewInt32(context, task->_http_port));
|
||||||
{
|
JS_SetPropertyStr(context, tildefriends, "https_port", JS_NewInt32(context, task->_https_port));
|
||||||
JS_SetPropertyStr(context, tildefriends, "http_port", JS_NewInt32(context, task->_http_port));
|
|
||||||
}
|
|
||||||
if (task->_https_port)
|
|
||||||
{
|
|
||||||
JS_SetPropertyStr(context, tildefriends, "https_port", JS_NewInt32(context, task->_https_port));
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_SetPropertyStr(context, global, "getStats", JS_NewCFunction(context, _tf_task_getStats, "getStats", 0));
|
JS_SetPropertyStr(context, global, "getStats", JS_NewCFunction(context, _tf_task_getStats, "getStats", 0));
|
||||||
|
|
||||||
tf_httpd_register(context);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2034,34 +2015,11 @@ void tf_task_set_zip_path(tf_task_t* task, const char* zip_path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tf_task_set_root_path(tf_task_t* task, const char* path)
|
|
||||||
{
|
|
||||||
snprintf(task->_root_path, sizeof(task->_root_path), "%s", path ? path : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* tf_task_get_zip_path(tf_task_t* task)
|
const char* tf_task_get_zip_path(tf_task_t* task)
|
||||||
{
|
{
|
||||||
return task->_zip ? task->_zip_path : NULL;
|
return task->_zip ? task->_zip_path : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* tf_task_get_root_path(tf_task_t* task)
|
|
||||||
{
|
|
||||||
return *task->_root_path ? task->_root_path : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* tf_task_get_path_with_root(tf_task_t* task, const char* path)
|
|
||||||
{
|
|
||||||
if (!*task->_root_path)
|
|
||||||
{
|
|
||||||
return tf_strdup(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size = strlen(task->_root_path) + 1 + strlen(path) + 1;
|
|
||||||
char* result = tf_malloc(size);
|
|
||||||
snprintf(result, size, "%s/%s", task->_root_path, path);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tf_task_set_args(tf_task_t* task, const char* args)
|
void tf_task_set_args(tf_task_t* task, const char* args)
|
||||||
{
|
{
|
||||||
task->_args = args;
|
task->_args = args;
|
||||||
|
24
src/task.h
24
src/task.h
@ -112,34 +112,12 @@ void tf_task_set_db_path(tf_task_t* task, const char* path);
|
|||||||
void tf_task_set_zip_path(tf_task_t* task, const char* path);
|
void tf_task_set_zip_path(tf_task_t* task, const char* path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Set the path to the root of the project directory for data.
|
** Get the path to the zipp file being used for static data.
|
||||||
** @param task The task.
|
|
||||||
** @param path The file path or NULL.
|
|
||||||
*/
|
|
||||||
void tf_task_set_root_path(tf_task_t* task, const char* path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Get the path to the zip file being used for static data.
|
|
||||||
** @param task The task.
|
** @param task The task.
|
||||||
** @return The zip file path or NULL.
|
** @return The zip file path or NULL.
|
||||||
*/
|
*/
|
||||||
const char* tf_task_get_zip_path(tf_task_t* task);
|
const char* tf_task_get_zip_path(tf_task_t* task);
|
||||||
|
|
||||||
/**
|
|
||||||
** Get the path to use for reading loose files.
|
|
||||||
** @param task The task.
|
|
||||||
** @return The path or NULL.
|
|
||||||
*/
|
|
||||||
const char* tf_task_get_root_path(tf_task_t* task);
|
|
||||||
|
|
||||||
/**
|
|
||||||
** Get the path to use for reading a given loose file.
|
|
||||||
** @param task The task.
|
|
||||||
** @param path The path to the file.
|
|
||||||
** @return The path or NULL. Free with tf_free().
|
|
||||||
*/
|
|
||||||
const char* tf_task_get_path_with_root(tf_task_t* task, const char* path);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Set arbitrary named arguments that will be made available to the task.
|
** Set arbitrary named arguments that will be made available to the task.
|
||||||
** @param task The task.
|
** @param task The task.
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
#define VERSION_NUMBER "0.0.28-wip"
|
#define VERSION_NUMBER "0.0.27"
|
||||||
#define VERSION_NAME "This program kills fascists."
|
#define VERSION_NAME "This program kills fascists."
|
||||||
|
136
tools/ssl-android
Executable file
136
tools/ssl-android
Executable file
@ -0,0 +1,136 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ -z $ANDROID_NDK_ROOT ]; then
|
||||||
|
ANDROID_NDK_ROOT=~/Android/Sdk/ndk/26.1.10909125
|
||||||
|
fi
|
||||||
|
|
||||||
|
API_LEVEL=24
|
||||||
|
|
||||||
|
BUILD_DIR=out/openssl_android_build
|
||||||
|
|
||||||
|
BUILD_TARGETS="x86_64 x86 arm64-v8a armeabi-v7a"
|
||||||
|
|
||||||
|
WORK_DIR=out/openssl-android
|
||||||
|
rm -rf $WORK_DIR
|
||||||
|
cp -arf deps/openssl_src/ $WORK_DIR
|
||||||
|
|
||||||
|
export ANDROID_NDK_ROOT
|
||||||
|
echo ANDROID_NDK_ROOT=$ANDROID_NDK_ROOT
|
||||||
|
|
||||||
|
build_the_thing() {
|
||||||
|
TOOLCHAIN=$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64
|
||||||
|
export PATH=$TOOLCHAIN/$TRIBLE/bin:$TOOLCHAIN/bin:$PATH
|
||||||
|
echo $PATH
|
||||||
|
export GLOBAL_OPTIONS="
|
||||||
|
no-apps
|
||||||
|
no-asm
|
||||||
|
no-async
|
||||||
|
no-autoerrinit
|
||||||
|
no-autoload-config
|
||||||
|
no-cmp
|
||||||
|
no-cms
|
||||||
|
no-comp
|
||||||
|
no-deprecated
|
||||||
|
no-dgram
|
||||||
|
no-docs
|
||||||
|
no-dsa
|
||||||
|
no-dso
|
||||||
|
no-dtls
|
||||||
|
no-dtls1
|
||||||
|
no-dtls1-method
|
||||||
|
no-dynamic-engine
|
||||||
|
no-ec2m
|
||||||
|
no-egd
|
||||||
|
no-engine
|
||||||
|
no-err
|
||||||
|
no-filenames
|
||||||
|
no-gost
|
||||||
|
no-http
|
||||||
|
no-idea
|
||||||
|
no-legacy
|
||||||
|
no-md2
|
||||||
|
no-md4
|
||||||
|
no-module
|
||||||
|
no-multiblock
|
||||||
|
no-nextprotoneg
|
||||||
|
no-ocsp
|
||||||
|
no-psk
|
||||||
|
no-shared
|
||||||
|
no-sock
|
||||||
|
no-srp
|
||||||
|
no-ssl
|
||||||
|
no-ssl3
|
||||||
|
no-ssl-trace
|
||||||
|
no-stdio
|
||||||
|
no-tests
|
||||||
|
no-thread-pool
|
||||||
|
no-threads
|
||||||
|
no-tls1
|
||||||
|
no-tls1-method
|
||||||
|
no-trace
|
||||||
|
no-ui-console
|
||||||
|
no-uplink
|
||||||
|
no-whirlpool
|
||||||
|
no-weak-ssl-ciphers
|
||||||
|
no-zlib
|
||||||
|
-Oz
|
||||||
|
-DOPENSSL_SMALL_FOOTPRINT
|
||||||
|
-ffunction-sections
|
||||||
|
-fdata-sections"
|
||||||
|
pwd
|
||||||
|
echo "./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS" && \
|
||||||
|
./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS && \
|
||||||
|
make -s clean && \
|
||||||
|
make -s build_generated && \
|
||||||
|
make -s libcrypto.a libssl.a || exit 128
|
||||||
|
}
|
||||||
|
|
||||||
|
for build_target in $BUILD_TARGETS
|
||||||
|
do
|
||||||
|
echo "Building $build_target"
|
||||||
|
pwd
|
||||||
|
pushd $WORK_DIR || exit 128
|
||||||
|
|
||||||
|
case $build_target in
|
||||||
|
armeabi-v7a)
|
||||||
|
TRIBLE="arm-linux-androideabi"
|
||||||
|
OPTIONS="--target=armv7a-linux-androideabi -ffunction-sections -fdata-sections -Wl,--fix-cortex-a8 -fPIC -D__ANDROID_API__=$API_LEVEL -Wno-macro-redefined"
|
||||||
|
DESTDIR="/tmp/$BUILD_DIR/armeabi-v7a"
|
||||||
|
SSL_TARGET="android-arm"
|
||||||
|
CC=clang
|
||||||
|
;;
|
||||||
|
x86)
|
||||||
|
TRIBLE="i686-linux-android"
|
||||||
|
OPTIONS="-fPIC -ffunction-sections -fdata-sections -D__ANDROID_API__=${API_LEVEL} -Wno-macro-redefined"
|
||||||
|
DESTDIR="/tmp/$BUILD_DIR/x86"
|
||||||
|
SSL_TARGET="android-x86"
|
||||||
|
CC=clang
|
||||||
|
;;
|
||||||
|
x86_64)
|
||||||
|
TRIBLE="x86_64-linux-android"
|
||||||
|
OPTIONS="--static -static -ffunction-sections -fdata-sections -D__ANDROID_API__=${API_LEVEL} -Wno-macro-redefined"
|
||||||
|
DESTDIR="/tmp/$BUILD_DIR/x86_64"
|
||||||
|
SSL_TARGET="android-x86_64"
|
||||||
|
CC=clang
|
||||||
|
;;
|
||||||
|
arm64-v8a)
|
||||||
|
TRIBLE="aarch64-linux-android"
|
||||||
|
OPTIONS="--static -static -ffunction-sections -fdata-sections -fPIC -D__ANDROID_API__=${API_LEVEL} -Wno-macro-redefined"
|
||||||
|
DESTDIR="/tmp/$BUILD_DIR/arm64-v8a"
|
||||||
|
SSL_TARGET="android-arm64"
|
||||||
|
CC=clang
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
rm -rf $DESTDIR
|
||||||
|
build_the_thing
|
||||||
|
popd
|
||||||
|
echo WORK_DIR=$WORK_DIR
|
||||||
|
rm -rf deps/openssl/android/$build_target/
|
||||||
|
mkdir -p deps/openssl/android/$build_target/usr/local/include/
|
||||||
|
mkdir -p deps/openssl/android/$build_target/usr/local/lib/
|
||||||
|
cp -R $WORK_DIR/include/* deps/openssl/android/$build_target/usr/local/include/
|
||||||
|
cp $WORK_DIR/*.a deps/openssl/android/$build_target/usr/local/lib/
|
||||||
|
done
|
||||||
|
|
||||||
|
echo Success
|
57
tools/ssl-ios
Executable file
57
tools/ssl-ios
Executable file
@ -0,0 +1,57 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
API_LEVEL=28
|
||||||
|
|
||||||
|
BUILD_DIR=out/openssl_ios_build
|
||||||
|
|
||||||
|
BUILD_TARGETS="ios64-xcrun iossimulator-xcrun"
|
||||||
|
|
||||||
|
WORK_DIR=out/openssl-ios
|
||||||
|
rm -rf $WORK_DIR
|
||||||
|
cp -af deps/openssl_src/ $WORK_DIR
|
||||||
|
|
||||||
|
build_the_thing() {
|
||||||
|
export PATH=$TOOLCHAIN/$TRIBLE/bin:$TOOLCHAIN/bin:$PATH
|
||||||
|
echo $PATH
|
||||||
|
echo "./Configure $SSL_TARGET $OPTIONS" && \
|
||||||
|
./Configure $SSL_TARGET $OPTIONS no-tests && \
|
||||||
|
make clean && \
|
||||||
|
make build_generated && \
|
||||||
|
make libcrypto.a libssl.a || exit 128
|
||||||
|
}
|
||||||
|
|
||||||
|
for build_target in $BUILD_TARGETS
|
||||||
|
do
|
||||||
|
echo "Building $build_target"
|
||||||
|
pwd
|
||||||
|
pushd $WORK_DIR || exit 128
|
||||||
|
|
||||||
|
case $build_target in
|
||||||
|
ios64-xcrun)
|
||||||
|
TRIBLE="arm64-darwin-ios"
|
||||||
|
OPTIONS="--static -static -Os -ffunction-sections -fdata-sections -fPIC -Wno-macro-redefined -miphoneos-version-min=9.0"
|
||||||
|
DESTDIR="/tmp/$BUILD_DIR/arm64-ios"
|
||||||
|
SSL_TARGET="ios64-xcrun"
|
||||||
|
CC=clang
|
||||||
|
;;
|
||||||
|
iossimulator-xcrun)
|
||||||
|
TRIBLE="x86_64-darwin-ios"
|
||||||
|
OPTIONS="--static -static -Os -ffunction-sections -fdata-sections -fPIC -Wno-macro-redefined"
|
||||||
|
DESTDIR="/tmp/$BUILD_DIR/x86_64-iossim"
|
||||||
|
SSL_TARGET="iossimulator-xcrun"
|
||||||
|
CC=clang
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
rm -rf $DESTDIR
|
||||||
|
build_the_thing
|
||||||
|
popd
|
||||||
|
echo WORK_DIR=$WORK_DIR
|
||||||
|
rm -rf deps/openssl/ios/$build_target/
|
||||||
|
mkdir -p deps/openssl/ios/$build_target/usr/local/include/
|
||||||
|
mkdir -p deps/openssl/ios/$build_target/usr/local/lib/
|
||||||
|
cp -R $WORK_DIR/include/* deps/openssl/ios/$build_target/usr/local/include/
|
||||||
|
cp $WORK_DIR/*.a deps/openssl/ios/$build_target/usr/local/lib/
|
||||||
|
done
|
||||||
|
|
||||||
|
echo Success
|
135
tools/ssl-local
135
tools/ssl-local
@ -1,15 +1,13 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
if [[ -z $BUILD_PLATFORM ]]; then
|
BUILD_PLATFORM=$(uname -s)
|
||||||
BUILD_PLATFORM=$(uname -s)
|
|
||||||
fi
|
|
||||||
if [[ -z $BUILD_TARGET ]]; then
|
if [[ -z $BUILD_TARGET ]]; then
|
||||||
BUILD_TARGET=$(uname -m)
|
BUILD_TARGET=$(uname -m)
|
||||||
WORK_DIR=out/openssl-local
|
WORK_DIR=out/openssl-local
|
||||||
else
|
else
|
||||||
WORK_DIR=out/openssl-$BUILD_PLATFORM-$BUILD_TARGET
|
WORK_DIR=out/openssl-$BUILD_TARGET
|
||||||
if [[ -z $SSL_TARGET ]]; then
|
if [[ -z $SSL_TARGET ]]; then
|
||||||
SSL_TARGET=linux-$BUILD_PLATFORM-$BUILD_TARGET
|
SSL_TARGET=linux-$BUILD_TARGET
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -22,66 +20,63 @@ pwd
|
|||||||
pushd $WORK_DIR || exit 128
|
pushd $WORK_DIR || exit 128
|
||||||
rm -rf $DESTDIR
|
rm -rf $DESTDIR
|
||||||
echo $PATH
|
echo $PATH
|
||||||
export GLOBAL_OPTIONS=" \
|
export GLOBAL_OPTIONS="
|
||||||
no-apps \
|
no-apps
|
||||||
no-asm \
|
no-asm
|
||||||
no-async \
|
no-async
|
||||||
no-autoerrinit \
|
no-autoerrinit
|
||||||
no-autoload-config \
|
no-autoload-config
|
||||||
no-cmp \
|
no-cmp
|
||||||
no-cms \
|
no-cms
|
||||||
no-comp \
|
no-comp
|
||||||
no-deprecated \
|
no-deprecated
|
||||||
no-dgram \
|
no-dgram
|
||||||
no-docs \
|
no-docs
|
||||||
no-dsa \
|
no-dsa
|
||||||
no-dso \
|
no-dso
|
||||||
no-dtls \
|
no-dtls
|
||||||
no-dtls1 \
|
no-dtls1
|
||||||
no-dtls1-method \
|
no-dtls1-method
|
||||||
no-dynamic-engine \
|
no-dynamic-engine
|
||||||
no-ec2m \
|
no-ec2m
|
||||||
no-egd \
|
no-egd
|
||||||
no-engine \
|
no-engine
|
||||||
no-err \
|
no-err
|
||||||
no-filenames \
|
no-filenames
|
||||||
no-gost \
|
no-gost
|
||||||
no-http \
|
no-http
|
||||||
no-idea \
|
no-idea
|
||||||
no-legacy \
|
no-legacy
|
||||||
no-md2 \
|
no-md2
|
||||||
no-md4 \
|
no-md4
|
||||||
no-module \
|
no-module
|
||||||
no-multiblock \
|
no-multiblock
|
||||||
no-nextprotoneg \
|
no-nextprotoneg
|
||||||
no-ocsp \
|
no-ocsp
|
||||||
no-psk \
|
no-psk
|
||||||
no-shared \
|
no-shared
|
||||||
no-sock \
|
no-sock
|
||||||
no-srp \
|
no-srp
|
||||||
no-ssl \
|
no-ssl
|
||||||
no-ssl3 \
|
no-ssl3
|
||||||
no-ssl-trace \
|
no-ssl-trace
|
||||||
no-stdio \
|
no-stdio
|
||||||
no-tests \
|
no-tests
|
||||||
no-thread-pool \
|
no-thread-pool
|
||||||
no-threads \
|
no-threads
|
||||||
no-tls1 \
|
no-tls1
|
||||||
no-tls1-method \
|
no-tls1-method
|
||||||
no-trace \
|
no-trace
|
||||||
no-ui-console \
|
no-ui-console
|
||||||
no-uplink \
|
no-uplink
|
||||||
no-weak-ssl-ciphers \
|
no-whirlpool
|
||||||
no-whirlpool \
|
no-weak-ssl-ciphers
|
||||||
no-zlib \
|
no-zlib
|
||||||
-Os \
|
-Os
|
||||||
-DOPENSSL_SMALL_FOOTPRINT \
|
-DOPENSSL_SMALL_FOOTPRINT
|
||||||
-Wno-error \
|
-Wno-error
|
||||||
-ffunction-sections \
|
-ffunction-sections
|
||||||
-fdata-sections \
|
-fdata-sections"
|
||||||
--static \
|
|
||||||
-static \
|
|
||||||
"
|
|
||||||
pwd
|
pwd
|
||||||
echo "./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS" && \
|
echo "./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS" && \
|
||||||
./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS && \
|
./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS && \
|
||||||
@ -90,10 +85,10 @@ make -s build_generated && \
|
|||||||
make -s libcrypto.a libssl.a || exit 128
|
make -s libcrypto.a libssl.a || exit 128
|
||||||
popd
|
popd
|
||||||
echo WORK_DIR=$WORK_DIR
|
echo WORK_DIR=$WORK_DIR
|
||||||
rm -rf out/openssl/$BUILD_PLATFORM/$BUILD_TARGET/
|
rm -rf deps/openssl/$BUILD_PLATFORM/$BUILD_TARGET/
|
||||||
mkdir -p out/openssl/$BUILD_PLATFORM/$BUILD_TARGET/usr/local/include/
|
mkdir -p deps/openssl/$BUILD_PLATFORM/$BUILD_TARGET/usr/local/include/
|
||||||
mkdir -p out/openssl/$BUILD_PLATFORM/$BUILD_TARGET/usr/local/lib/
|
mkdir -p deps/openssl/$BUILD_PLATFORM/$BUILD_TARGET/usr/local/lib/
|
||||||
cp -R $WORK_DIR/include/* out/openssl/$BUILD_PLATFORM/$BUILD_TARGET/usr/local/include/
|
cp -R $WORK_DIR/include/* deps/openssl/$BUILD_PLATFORM/$BUILD_TARGET/usr/local/include/
|
||||||
cp $WORK_DIR/*.a out/openssl/$BUILD_PLATFORM/$BUILD_TARGET/usr/local/lib/
|
cp $WORK_DIR/*.a deps/openssl/$BUILD_PLATFORM/$BUILD_TARGET/usr/local/lib/
|
||||||
|
|
||||||
echo Success
|
echo Success
|
||||||
|
94
tools/ssl-mingw64
Executable file
94
tools/ssl-mingw64
Executable file
@ -0,0 +1,94 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
API_LEVEL=24
|
||||||
|
|
||||||
|
BUILD_DIR=out/openssl_mingw64_build
|
||||||
|
|
||||||
|
BUILD_TARGETS="mingw64"
|
||||||
|
|
||||||
|
WORK_DIR=out/openssl-mingw64
|
||||||
|
rm -rf $WORK_DIR
|
||||||
|
cp -arf deps/openssl_src/ $WORK_DIR
|
||||||
|
|
||||||
|
build_the_thing() {
|
||||||
|
export GLOBAL_OPTIONS="
|
||||||
|
no-apps
|
||||||
|
no-asm
|
||||||
|
no-async
|
||||||
|
no-autoerrinit
|
||||||
|
no-cmp
|
||||||
|
no-cms
|
||||||
|
no-comp
|
||||||
|
no-deprecated
|
||||||
|
no-dgram
|
||||||
|
no-docs
|
||||||
|
no-dsa
|
||||||
|
no-dso
|
||||||
|
no-dtls
|
||||||
|
no-dynamic-engine
|
||||||
|
no-ec2m
|
||||||
|
no-egd
|
||||||
|
no-engine
|
||||||
|
no-err
|
||||||
|
no-filenames
|
||||||
|
no-gost
|
||||||
|
no-http
|
||||||
|
no-idea
|
||||||
|
no-legacy
|
||||||
|
no-md2
|
||||||
|
no-md4
|
||||||
|
no-module
|
||||||
|
no-multiblock
|
||||||
|
no-nextprotoneg
|
||||||
|
no-ocsp
|
||||||
|
no-psk
|
||||||
|
no-shared
|
||||||
|
no-sock
|
||||||
|
no-srp
|
||||||
|
no-ssl-trace
|
||||||
|
no-ssl3
|
||||||
|
no-stdio
|
||||||
|
no-tests
|
||||||
|
no-thread-pool
|
||||||
|
no-threads
|
||||||
|
no-trace
|
||||||
|
no-ui-console
|
||||||
|
no-uplink
|
||||||
|
no-weak-ssl-ciphers
|
||||||
|
no-zlib
|
||||||
|
-Os
|
||||||
|
-ffunction-sections
|
||||||
|
-fdata-sections
|
||||||
|
-DOPENSSL_SMALL_FOOTPRINT"
|
||||||
|
echo "./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS" && \
|
||||||
|
./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS && \
|
||||||
|
make -s clean && \
|
||||||
|
make -s build_generated && \
|
||||||
|
make -s libcrypto.a libssl.a || exit 128
|
||||||
|
}
|
||||||
|
|
||||||
|
for build_target in $BUILD_TARGETS
|
||||||
|
do
|
||||||
|
echo "Building $build_target"
|
||||||
|
pushd $WORK_DIR || exit 128
|
||||||
|
|
||||||
|
case $build_target in
|
||||||
|
mingw64)
|
||||||
|
OPTIONS="--cross-compile-prefix=x86_64-w64-mingw32-"
|
||||||
|
DESTDIR="/tmp/$BUILD_DIR/mingw64"
|
||||||
|
SSL_TARGET="mingw64"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
rm -rf $DESTDIR
|
||||||
|
build_the_thing
|
||||||
|
popd
|
||||||
|
echo WORK_DIR=$WORK_DIR
|
||||||
|
rm -rf deps/openssl/$build_target/
|
||||||
|
mkdir -p deps/openssl/$build_target/usr/local/include/
|
||||||
|
mkdir -p deps/openssl/$build_target/usr/local/lib/
|
||||||
|
cp -R $WORK_DIR/include/* deps/openssl/$build_target/usr/local/include/
|
||||||
|
cp $WORK_DIR/*.a deps/openssl/$build_target/usr/local/lib/
|
||||||
|
done
|
||||||
|
|
||||||
|
echo Success
|
Loading…
x
Reference in New Issue
Block a user