Compare commits
19 Commits
v0.0.26
...
9c8b922069
Author | SHA1 | Date | |
---|---|---|---|
9c8b922069 | |||
d4b421421d | |||
58e9646fa6 | |||
500f172561 | |||
68f6c90ea4 | |||
41e91f2922 | |||
999117cfeb | |||
6185df512f | |||
0cbf66c007 | |||
cd378b721d | |||
547d38d1ef | |||
dca56af5b9 | |||
224442772e | |||
003951fdf7 | |||
d51b3da1b4 | |||
69f4af84db | |||
771759b252 | |||
20c7a71db6 | |||
8475ee0985 |
@ -24,15 +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'
|
||||||
- run: sudo apt update && sudo apt install -y doxygen graphviz mingw-w64 libgpgme11
|
- run: sudo apt update && sudo apt install -y doxygen graphviz mingw-w64 libgpgme11 gcc-aarch64-linux-gnu
|
||||||
- run: ANDROID_SDK=$HOME/.android/sdk make -j`nproc` all docs
|
- run: ANDROID_SDK=$HOME/.android/sdk make -j`nproc` all docs
|
||||||
- run: docker build .
|
- run: docker build .
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
path: out/TildeFriends-release.fdroid.apk
|
path: |
|
||||||
- uses: actions/upload-artifact@v3
|
out/TildeFriends-release.fdroid.apk
|
||||||
with:
|
out/winrelease/tildefriends.exe
|
||||||
path: out/winrelease/tildefriends.exe
|
out/tildefriends-x86_64.AppImage
|
||||||
- uses: actions/upload-artifact@v3
|
out/release/tildefriends.standalone
|
||||||
with:
|
out/armrelease/tildefriends.standalone
|
||||||
path: out/tildefriends-x86_64.AppImage
|
|
||||||
|
74
GNUmakefile
74
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 := 31
|
VERSION_CODE := 32
|
||||||
VERSION_NUMBER := 0.0.26
|
VERSION_NUMBER := 0.0.27-wip
|
||||||
VERSION_NAME := This program kills fascists.
|
VERSION_NAME := This program kills fascists.
|
||||||
|
|
||||||
SQLITE_URL := https://www.sqlite.org/2024/sqlite-amalgamation-3470200.zip
|
SQLITE_URL := https://www.sqlite.org/2024/sqlite-amalgamation-3470200.zip
|
||||||
@ -34,6 +34,7 @@ ANDROID_SDK ?= ~/Android/Sdk
|
|||||||
BUNDLETOOL = out/bundletool.jar
|
BUNDLETOOL = out/bundletool.jar
|
||||||
|
|
||||||
HAVE_WIN := 0
|
HAVE_WIN := 0
|
||||||
|
HAVE_CROSS_AARCH64 := 0
|
||||||
|
|
||||||
export SOURCE_DATE_EPOCH=1
|
export SOURCE_DATE_EPOCH=1
|
||||||
export TZ=UTC
|
export TZ=UTC
|
||||||
@ -45,6 +46,9 @@ BUILD_TYPES := debug release
|
|||||||
HAVE_ANDROID = $(if $(shell which $(ANDROID_SDK)/platform-tools/adb),1,0)
|
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,0)
|
HAVE_LINUX_IOS = $(if $(shell which deps/ios_toolchain/target/bin deps/ios_toolchain/target/bin/arm-apple-darwin11-clang),1,0)
|
||||||
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,0)
|
||||||
|
ifneq ($(UNAME_M),aarch64)
|
||||||
|
HAVE_CROSS_AARCH64 = $(if $(shell which aarch64-linux-gnu-gcc),1,0)
|
||||||
|
endif
|
||||||
else ifeq ($(UNAME_S),Haiku)
|
else ifeq ($(UNAME_S),Haiku)
|
||||||
BUILD_TYPES := debug release
|
BUILD_TYPES := debug release
|
||||||
CFLAGS += -Dstatic_assert=_Static_assert
|
CFLAGS += -Dstatic_assert=_Static_assert
|
||||||
@ -125,6 +129,13 @@ ifeq ($(HAVE_WIN),1)
|
|||||||
BUILD_TYPES += windebug winrelease
|
BUILD_TYPES += windebug winrelease
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
AARCH64_TARGETS := \
|
||||||
|
out/armdebug/tildefriends \
|
||||||
|
out/armrelease/tildefriends
|
||||||
|
ifeq ($(HAVE_CROSS_AARCH64),1)
|
||||||
|
BUILD_TYPES += armdebug armrelease
|
||||||
|
endif
|
||||||
|
|
||||||
LINUX_TARGETS := \
|
LINUX_TARGETS := \
|
||||||
out/debug/tildefriends \
|
out/debug/tildefriends \
|
||||||
out/release/tildefriends
|
out/release/tildefriends
|
||||||
@ -149,6 +160,9 @@ all: $(IOS_APPS) \
|
|||||||
out/tildefriends-iossimdebug.app/tildefriends \
|
out/tildefriends-iossimdebug.app/tildefriends \
|
||||||
out/tildefriends-iossimrelease.app/tildefriends
|
out/tildefriends-iossimrelease.app/tildefriends
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(HAVE_CROSS_AARCH64),1)
|
||||||
|
all: out/armrelease/tildefriends.standalone
|
||||||
|
endif
|
||||||
|
|
||||||
DEBUG_TARGETS := \
|
DEBUG_TARGETS := \
|
||||||
out/debug/tildefriends \
|
out/debug/tildefriends \
|
||||||
@ -159,7 +173,8 @@ DEBUG_TARGETS := \
|
|||||||
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
|
||||||
RELEASE_TARGETS := \
|
RELEASE_TARGETS := \
|
||||||
out/release/tildefriends \
|
out/release/tildefriends \
|
||||||
out/winrelease/tildefriends.exe \
|
out/winrelease/tildefriends.exe \
|
||||||
@ -169,7 +184,8 @@ RELEASE_TARGETS := \
|
|||||||
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
|
||||||
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))
|
||||||
@ -192,11 +208,12 @@ $(ANDROID_TARGETS): CFLAGS += \
|
|||||||
-Wno-unknown-warning-option
|
-Wno-unknown-warning-option
|
||||||
$(ANDROID_TARGETS): LDFLAGS += --sysroot $(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC
|
$(ANDROID_TARGETS): LDFLAGS += --sysroot $(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC
|
||||||
$(DEBUG_TARGETS): CFLAGS += -DDEBUG -Og
|
$(DEBUG_TARGETS): CFLAGS += -DDEBUG -Og
|
||||||
|
$(DEBUG_TARGETS): LDFLAGS += -Og
|
||||||
$(RELEASE_TARGETS): CFLAGS += \
|
$(RELEASE_TARGETS): CFLAGS += \
|
||||||
-DNDEBUG \
|
-DNDEBUG \
|
||||||
-flto
|
-flto \
|
||||||
$(NONANDROID_RELEASE_TARGETS): CFLAGS += -O3
|
-Oz
|
||||||
$(ANDROID_RELEASE_TARGETS): CFLAGS += -Oz
|
$(RELEASE_TARGETS): LDFLAGS += -Oz
|
||||||
$(WINDOWS_TARGETS): CC = x86_64-w64-mingw32-gcc-win32
|
$(WINDOWS_TARGETS): CC = x86_64-w64-mingw32-gcc-win32
|
||||||
$(WINDOWS_TARGETS): AS = $(CC)
|
$(WINDOWS_TARGETS): AS = $(CC)
|
||||||
$(WINDOWS_TARGETS): CFLAGS += \
|
$(WINDOWS_TARGETS): CFLAGS += \
|
||||||
@ -208,6 +225,10 @@ $(WINDOWS_TARGETS): LDFLAGS += \
|
|||||||
-static \
|
-static \
|
||||||
-lm \
|
-lm \
|
||||||
-Ldeps/openssl/mingw64/usr/local/lib
|
-Ldeps/openssl/mingw64/usr/local/lib
|
||||||
|
$(AARCH64_TARGETS): CC = aarch64-linux-gnu-gcc
|
||||||
|
$(AARCH64_TARGETS): AS = $(CC)
|
||||||
|
$(AARCH64_TARGETS): CFLAGS += -Ideps/openssl/Linux/aarch64/usr/local/include
|
||||||
|
$(AARCH64_TARGETS): LDFLAGS += -Ldeps/openssl/Linux/aarch64/usr/local/lib
|
||||||
ifeq ($(UNAME_S),Darwin)
|
ifeq ($(UNAME_S),Darwin)
|
||||||
$(MACOS_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)
|
||||||
@ -242,10 +263,12 @@ $(IOS_TARGETS): CFLAGS += -miphoneos-version-min=9.0 -Ideps/openssl/ios/ios64-xc
|
|||||||
$(IOS_TARGETS): LDFLAGS += -miphoneos-version-min=9.0 -Ldeps/openssl/ios/ios64-xcrun/usr/local/lib
|
$(IOS_TARGETS): LDFLAGS += -miphoneos-version-min=9.0 -Ldeps/openssl/ios/ios64-xcrun/usr/local/lib
|
||||||
$(IOSSIM_TARGETS): CFLAGS += -Ideps/openssl/ios/iossimulator-xcrun/usr/local/include
|
$(IOSSIM_TARGETS): CFLAGS += -Ideps/openssl/ios/iossimulator-xcrun/usr/local/include
|
||||||
$(IOSSIM_TARGETS): LDFLAGS += -Ldeps/openssl/ios/iossimulator-xcrun/usr/local/lib
|
$(IOSSIM_TARGETS): LDFLAGS += -Ldeps/openssl/ios/iossimulator-xcrun/usr/local/lib
|
||||||
|
$(LINUX_TARGETS) $(MACOS_TARGETS): CFLAGS += -Ideps/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/include
|
||||||
|
$(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)
|
||||||
all: appimage
|
all: appimage out/release/tildefriends.standalone
|
||||||
endif
|
endif
|
||||||
ifneq ($(UNAME_S),Haiku)
|
ifneq ($(UNAME_S),Haiku)
|
||||||
out/debug/tildefriends: CFLAGS += -fsanitize=address -fsanitize=undefined -fno-common
|
out/debug/tildefriends: CFLAGS += -fsanitize=address -fsanitize=undefined -fno-common
|
||||||
@ -260,7 +283,7 @@ 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,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_unix))))) \
|
$(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 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 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))))) \
|
||||||
@ -725,7 +748,7 @@ $(MINIUNZIP_OBJS): CFLAGS += \
|
|||||||
LDFLAGS += \
|
LDFLAGS += \
|
||||||
-pthread \
|
-pthread \
|
||||||
-lm
|
-lm
|
||||||
$(LINUX_TARGETS) $(MACOS_TARGETS) $(IOS_TARGETS) $(IOSSIM_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)
|
||||||
@ -765,6 +788,8 @@ $(IOS_TARGETS) $(IOSSIM_TARGETS): LDFLAGS += \
|
|||||||
##
|
##
|
||||||
debug: ## Build a debug executable for the current platform.
|
debug: ## Build a debug executable for the current platform.
|
||||||
release: ## Build a release executable for the current platform.
|
release: ## Build a release executable for the current platform.
|
||||||
|
armdebug: ## Cross-compile aarch64 debug on Linux.
|
||||||
|
armrelease: ## Cross-compile aarch64 release on Linux.
|
||||||
all: $(BUILD_TYPES) ## Build all targets that appear possible to build on this machine.
|
all: $(BUILD_TYPES) ## Build all targets that appear possible to build on this machine.
|
||||||
unix: debug release ## Build all UNIX targets.
|
unix: debug release ## Build all UNIX targets.
|
||||||
win: windebug winrelease ## Build all Windows targets.
|
win: windebug winrelease ## Build all Windows targets.
|
||||||
@ -1106,6 +1131,27 @@ $(ANDROID_DEPS):
|
|||||||
+@ANDROID_NDK_ROOT=$(ANDROID_NDK) tools/ssl-android
|
+@ANDROID_NDK_ROOT=$(ANDROID_NDK) tools/ssl-android
|
||||||
$(filter $(BUILD_DIR)/android%,$(APP_OBJS)): | $(ANDROID_DEPS)
|
$(filter $(BUILD_DIR)/android%,$(APP_OBJS)): | $(ANDROID_DEPS)
|
||||||
|
|
||||||
|
ifeq ($(UNAME_S),Linux)
|
||||||
|
LOCAL_DEPS := deps/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/lib/libssl.a
|
||||||
|
$(LOCAL_DEPS):
|
||||||
|
+@tools/ssl-local
|
||||||
|
$(filter $(BUILD_DIR)/debug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/release/%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
||||||
|
|
||||||
|
ifeq ($(HAVE_CROSS_AARCH64),1)
|
||||||
|
LOCAL_DEPS := deps/openssl/$(UNAME_S)/aarch64/usr/local/lib/libssl.a
|
||||||
|
$(LOCAL_DEPS):
|
||||||
|
+@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)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(UNAME_S),Darwin)
|
||||||
|
LOCAL_DEPS := deps/openssl/$(UNAME_S)/$(UNAME_M)/usr/local/lib/libssl.a
|
||||||
|
$(LOCAL_DEPS):
|
||||||
|
+@tools/ssl-local
|
||||||
|
$(filter $(BUILD_DIR)/macosdebug/%,$(APP_OBJS)) $(filter $(BUILD_DIR)/macosrelease/%,$(APP_OBJS)): | $(LOCAL_DEPS)
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(HAVE_WIN),1)
|
ifeq ($(HAVE_WIN),1)
|
||||||
WINDOWS_DEPS := deps/openssl/mingw64/usr/local/lib/libssl.a
|
WINDOWS_DEPS := deps/openssl/mingw64/usr/local/lib/libssl.a
|
||||||
$(WINDOWS_DEPS):
|
$(WINDOWS_DEPS):
|
||||||
@ -1198,7 +1244,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 iosrelease-ipa aab $(if $(HAVE_WIN), out/winrelease/tildefriends.standalone.exe) out/TildeFriends-release.fdroid.apk appimage tarball
|
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
|
||||||
@ -1216,6 +1262,10 @@ dist: release-apk iosrelease-ipa aab $(if $(HAVE_WIN), out/winrelease/tildefrien
|
|||||||
@cp out/TildeFriends-release.fdroid.apk dist/TildeFriends-$(VERSION_NUMBER).fdroid.apk
|
@cp out/TildeFriends-release.fdroid.apk dist/TildeFriends-$(VERSION_NUMBER).fdroid.apk
|
||||||
@echo "[cp] TildeFriends-x86_64-$(VERSION_NUMBER).AppImage"
|
@echo "[cp] TildeFriends-x86_64-$(VERSION_NUMBER).AppImage"
|
||||||
@cp out/tildefriends-x86_64.AppImage dist/TildeFriends-x86_64-$(VERSION_NUMBER).AppImage
|
@cp out/tildefriends-x86_64.AppImage dist/TildeFriends-x86_64-$(VERSION_NUMBER).AppImage
|
||||||
|
@echo "[cp] tildefriends-linux-$(UNAME_M)-$(VERSION_NUMBER)"
|
||||||
|
@cp out/release/tildefriends.standalone dist/tildefriends-linux-$(UNAME_M)-$(VERSION_NUMBER)
|
||||||
|
@test $(HAVE_CROSS_AARCH64) && echo "[cp] tildefriends-linux-aarch64-$(VERSION_NUMBER)"
|
||||||
|
@test $(HAVE_CROSS_AARCH64) && cp out/armrelease/tildefriends.standalone dist/tildefriends-linux-aarch64-$(VERSION_NUMBER)
|
||||||
.PHONY: dist
|
.PHONY: dist
|
||||||
|
|
||||||
dist-test: dist ## Exercise some built distributable files, making sure they work as intended.
|
dist-test: dist ## Exercise some built distributable files, making sure they work as intended.
|
||||||
@ -1258,7 +1308,7 @@ help: ## Display this help message.
|
|||||||
/^##/ { sub(/^## ?/, ""); print $$0 } \
|
/^##/ { sub(/^## ?/, ""); print $$0 } \
|
||||||
/^[[:alnum:]-]+:.*##/ { \
|
/^[[:alnum:]-]+:.*##/ { \
|
||||||
sub(/:.*##\s?/, ":"); \
|
sub(/:.*##\s?/, ":"); \
|
||||||
printf " %s%-20s%s %s%s%s\n", G, $$1, R, O, $$2, R \
|
printf " %s%-21s%s %s%s%s\n", G, $$1, R, O, $$2, R \
|
||||||
} \
|
} \
|
||||||
' < $(filter-out %.d,$(MAKEFILE_LIST))
|
' < $(filter-out %.d,$(MAKEFILE_LIST))
|
||||||
@echo "" # Blank line.
|
@echo "" # Blank line.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"type": "tildefriends-app",
|
"type": "tildefriends-app",
|
||||||
"emoji": "🐌",
|
"emoji": "🦀",
|
||||||
"previous": "&q/1uGp0jMvsYGW7Gj8E33kf6UFo/uNYDXg3zo1sVKQg=.sha256"
|
"previous": "&QuEaXfdWGAl42dkJBoHocZbtKRT3zT25BNgCo88CSfE=.sha256"
|
||||||
}
|
}
|
||||||
|
@ -112,26 +112,24 @@ class TfElement extends LitElement {
|
|||||||
|
|
||||||
keydown(event) {
|
keydown(event) {
|
||||||
if (event.altKey && event.key == 'ArrowUp') {
|
if (event.altKey && event.key == 'ArrowUp') {
|
||||||
this.next_channel(1);
|
this.next_channel(-1);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
} else if (event.altKey && event.key == 'ArrowDown') {
|
} else if (event.altKey && event.key == 'ArrowDown') {
|
||||||
this.next_channel(-1);
|
this.next_channel(1);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
next_channel(delta) {
|
next_channel(delta) {
|
||||||
let channel_names = ['', '@'].concat(this.channels);
|
let channel_names = ['', '@', '🔐', ...this.channels.map((x) => '#' + x)];
|
||||||
let index = channel_names.indexOf(this.hash.substring(1));
|
let index = channel_names.indexOf(this.hash.substring(1));
|
||||||
if (index != -1) {
|
index = index != -1 ? index + delta : 0;
|
||||||
index += delta;
|
tfrpc.rpc.setHash(
|
||||||
this.set_hash(
|
'#' +
|
||||||
'#' +
|
encodeURIComponent(
|
||||||
encodeURIComponent(
|
channel_names[(index + channel_names.length) % channel_names.length]
|
||||||
channel_names[(index + channel_names.length) % channel_names.length]
|
)
|
||||||
)
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set_hash(hash) {
|
set_hash(hash) {
|
||||||
@ -150,6 +148,7 @@ class TfElement extends LitElement {
|
|||||||
async fetch_about(ids, users) {
|
async fetch_about(ids, users) {
|
||||||
const k_cache_version = 1;
|
const k_cache_version = 1;
|
||||||
let cache = await tfrpc.rpc.databaseGet('about');
|
let cache = await tfrpc.rpc.databaseGet('about');
|
||||||
|
let original_cache = cache;
|
||||||
cache = cache ? JSON.parse(cache) : {};
|
cache = cache ? JSON.parse(cache) : {};
|
||||||
if (cache.version !== k_cache_version) {
|
if (cache.version !== k_cache_version) {
|
||||||
cache = {
|
cache = {
|
||||||
@ -215,7 +214,13 @@ class TfElement extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
cache.last_row_id = max_row_id;
|
cache.last_row_id = max_row_id;
|
||||||
await tfrpc.rpc.databaseSet('about', JSON.stringify(cache));
|
let new_cache = JSON.stringify(cache);
|
||||||
|
if (new_cache !== original_cache) {
|
||||||
|
let start_time = new Date();
|
||||||
|
tfrpc.rpc.databaseSet('about', new_cache).then(function () {
|
||||||
|
console.log('saving about took', (new Date() - start_time) / 1000);
|
||||||
|
});
|
||||||
|
}
|
||||||
users = users || {};
|
users = users || {};
|
||||||
for (let id of Object.keys(cache.about)) {
|
for (let id of Object.keys(cache.about)) {
|
||||||
users[id] = Object.assign(users[id] || {}, cache.about[id]);
|
users[id] = Object.assign(users[id] || {}, cache.about[id]);
|
||||||
@ -538,16 +543,15 @@ class TfElement extends LitElement {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
let contents = !this.loaded
|
let contents =
|
||||||
? this.loading
|
!this.loaded || this.loading
|
||||||
? html`<div
|
? html`<div
|
||||||
class="w3-panel w3-theme-l5 w3-card-4 w3-padding-large w3-round-xlarge"
|
class="w3-display-middle w3-panel w3-theme-l5 w3-card-4 w3-padding-large w3-round-xlarge w3-xlarge"
|
||||||
>
|
>
|
||||||
Loading...
|
<span class="w3-spin" style="display: inline-block">🦀</span>
|
||||||
</div>
|
Loading...
|
||||||
${this.render_tab()}`
|
</div>`
|
||||||
: html`<div>Select or create an identity.</div>`
|
: this.render_tab();
|
||||||
: this.render_tab();
|
|
||||||
return html`
|
return html`
|
||||||
<div
|
<div
|
||||||
style="width: 100vw; min-height: 100vh; height: 100%"
|
style="width: 100vw; min-height: 100vh; height: 100%"
|
||||||
|
@ -15,6 +15,7 @@ class TfComposeElement extends LitElement {
|
|||||||
drafts: {type: Object},
|
drafts: {type: Object},
|
||||||
author: {type: String},
|
author: {type: String},
|
||||||
channel: {type: String},
|
channel: {type: String},
|
||||||
|
new_thread: {type: Boolean},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ class TfComposeElement extends LitElement {
|
|||||||
this.apps = undefined;
|
this.apps = undefined;
|
||||||
this.drafts = {};
|
this.drafts = {};
|
||||||
this.author = undefined;
|
this.author = undefined;
|
||||||
|
this.new_thread = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
process_text(text) {
|
process_text(text) {
|
||||||
@ -200,9 +202,23 @@ class TfComposeElement extends LitElement {
|
|||||||
channel: this.channel,
|
channel: this.channel,
|
||||||
};
|
};
|
||||||
if (this.root || this.branch) {
|
if (this.root || this.branch) {
|
||||||
message.root = this.root;
|
message.root = this.new_thread ? (this.branch ?? this.root) : this.root;
|
||||||
message.branch = this.branch;
|
message.branch = this.branch;
|
||||||
}
|
}
|
||||||
|
let reply = Object.fromEntries(
|
||||||
|
(
|
||||||
|
await tfrpc.rpc.query(
|
||||||
|
`
|
||||||
|
SELECT messages.id, messages.author FROM messages
|
||||||
|
JOIN json_each(?) AS refs ON messages.id = refs.value
|
||||||
|
`,
|
||||||
|
[JSON.stringify([this.root, this.branch])]
|
||||||
|
)
|
||||||
|
).map((row) => [row.id, row.author])
|
||||||
|
);
|
||||||
|
if (Object.keys(reply).length) {
|
||||||
|
message.reply = reply;
|
||||||
|
}
|
||||||
if (Object.values(draft.mentions || {}).length) {
|
if (Object.values(draft.mentions || {}).length) {
|
||||||
message.mentions = Object.values(draft.mentions);
|
message.mentions = Object.values(draft.mentions);
|
||||||
}
|
}
|
||||||
@ -469,6 +485,20 @@ class TfComposeElement extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render_new_thread() {
|
||||||
|
let self = this;
|
||||||
|
if (
|
||||||
|
this.root !== undefined &&
|
||||||
|
this.branch !== undefined &&
|
||||||
|
this.root != this.branch
|
||||||
|
) {
|
||||||
|
return html`
|
||||||
|
<input type="checkbox" class="w3-check w3-theme-d1" id="new_thread" @change=${() => (self.new_thread = !self.new_thread)} ?checked=${self.new_thread}></input>
|
||||||
|
<label for="new_thread">New Thread</label>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get_draft() {
|
get_draft() {
|
||||||
return this.drafts[this.branch || ''] || {};
|
return this.drafts[this.branch || ''] || {};
|
||||||
}
|
}
|
||||||
@ -563,6 +593,7 @@ class TfComposeElement extends LitElement {
|
|||||||
self.render_mention(x)
|
self.render_mention(x)
|
||||||
)}
|
)}
|
||||||
${this.render_attach_app()} ${this.render_content_warning()}
|
${this.render_attach_app()} ${this.render_content_warning()}
|
||||||
|
${this.render_new_thread()}
|
||||||
<button class="w3-button w3-theme-d1" id="submit" @click=${this.submit}>
|
<button class="w3-button w3-theme-d1" id="submit" @click=${this.submit}>
|
||||||
Submit
|
Submit
|
||||||
</button>
|
</button>
|
||||||
|
@ -51,15 +51,21 @@ class TfTabNewsFeedElement extends LitElement {
|
|||||||
if (this.hash == '#@') {
|
if (this.hash == '#@') {
|
||||||
result = await tfrpc.rpc.query(
|
result = await tfrpc.rpc.query(
|
||||||
`
|
`
|
||||||
|
WITH mentions AS (SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||||
|
FROM messages_fts(?1)
|
||||||
|
JOIN messages ON messages.rowid = messages_fts.rowid
|
||||||
|
JOIN json_each(?2) AS following ON messages.author = following.value
|
||||||
|
WHERE
|
||||||
|
messages.author != ?1 AND
|
||||||
|
messages.timestamp >= ?3 AND
|
||||||
|
messages.timestamp < ?4
|
||||||
|
ORDER BY timestamp DESC limit 20)
|
||||||
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
SELECT messages.rowid, messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
|
||||||
FROM messages_fts(?1)
|
FROM mentions
|
||||||
JOIN messages ON messages.rowid = messages_fts.rowid
|
JOIN messages_refs ON mentions.id = messages_refs.ref
|
||||||
JOIN json_each(?2) AS following ON messages.author = following.value
|
JOIN messages ON messages_refs.message = messages.id
|
||||||
WHERE
|
UNION
|
||||||
messages.author != ?1 AND
|
SELECT * FROM mentions
|
||||||
messages.timestamp >= ?3 AND
|
|
||||||
messages.timestamp < ?4
|
|
||||||
ORDER BY timestamp DESC limit 20
|
|
||||||
`,
|
`,
|
||||||
[
|
[
|
||||||
'"' + this.whoami.replace('"', '""') + '"',
|
'"' + this.whoami.replace('"', '""') + '"',
|
||||||
|
@ -176,7 +176,7 @@ class TfTabNewsElement extends LitElement {
|
|||||||
return html`
|
return html`
|
||||||
<div
|
<div
|
||||||
class="w3-sidebar w3-bar-block w3-theme-d1 w3-collapse w3-animate-left"
|
class="w3-sidebar w3-bar-block w3-theme-d1 w3-collapse w3-animate-left"
|
||||||
style="width: 2in; left: 0; z-index: 5"
|
style="width: 2in; left: 0; z-index: 5; box-sizing: border-box"
|
||||||
id="sidebar"
|
id="sidebar"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -216,6 +216,18 @@ class TfTabNewsElement extends LitElement {
|
|||||||
style=${this.hash == '#🔐' ? 'font-weight: bold' : undefined}
|
style=${this.hash == '#🔐' ? 'font-weight: bold' : undefined}
|
||||||
>🔐private ${this.unread_status('🔐')}</a
|
>🔐private ${this.unread_status('🔐')}</a
|
||||||
>
|
>
|
||||||
|
${Object.keys(this.drafts)
|
||||||
|
.sort()
|
||||||
|
.map(
|
||||||
|
(x) => html`
|
||||||
|
<a
|
||||||
|
href=${'#' + encodeURIComponent(x)}
|
||||||
|
class="w3-bar-item w3-button"
|
||||||
|
style="text-wrap: nowrap; text-overflow: ellipsis"
|
||||||
|
>📝 ${this.drafts[x]?.text ?? x}</a
|
||||||
|
>
|
||||||
|
`
|
||||||
|
)}
|
||||||
${this.channels.map(
|
${this.channels.map(
|
||||||
(x) => html`
|
(x) => html`
|
||||||
<a
|
<a
|
||||||
|
@ -21,14 +21,14 @@
|
|||||||
}:
|
}:
|
||||||
pkgs.stdenv.mkDerivation rec {
|
pkgs.stdenv.mkDerivation rec {
|
||||||
pname = "tildefriends";
|
pname = "tildefriends";
|
||||||
version = "0.0.25";
|
version = "0.0.26";
|
||||||
|
|
||||||
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-Rfk+CUhi+Ss0z70CCgmtVM/w4nCL1GX/MsD4sPYIa5s=";
|
hash = "sha256-XJ7M++risfsRn9GkS1zjTQpqqV5S09uyimeVzU9hGGg=";
|
||||||
fetchSubmodules = true;
|
fetchSubmodules = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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="31"
|
android:versionCode="32"
|
||||||
android:versionName="0.0.26">
|
android:versionName="0.0.27-wip">
|
||||||
<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
|
||||||
|
148
src/main.c
148
src/main.c
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
@ -41,7 +42,102 @@
|
|||||||
|
|
||||||
struct backtrace_state* g_backtrace_state;
|
struct backtrace_state* g_backtrace_state;
|
||||||
|
|
||||||
const char* k_db_path_default = "db.sqlite";
|
#if !defined(TARGET_OS_IPHONE)
|
||||||
|
static const char* _get_db_path()
|
||||||
|
{
|
||||||
|
const char* k_db_path_default = "db.sqlite";
|
||||||
|
#if defined(__linux__)
|
||||||
|
if (stat(k_db_path_default, &(struct stat) { 0 }) == 0)
|
||||||
|
{
|
||||||
|
return tf_strdup(k_db_path_default);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char buffer[32];
|
||||||
|
|
||||||
|
char* data_home = NULL;
|
||||||
|
size_t size = sizeof(buffer);
|
||||||
|
int r = uv_os_getenv("XDG_DATA_HOME", buffer, &size);
|
||||||
|
if (r == 0 || r == UV_ENOBUFS)
|
||||||
|
{
|
||||||
|
size++;
|
||||||
|
data_home = alloca(size);
|
||||||
|
if (uv_os_getenv("XDG_DATA_HOME", data_home, &size) != 0)
|
||||||
|
{
|
||||||
|
data_home = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data_home)
|
||||||
|
{
|
||||||
|
size = sizeof(buffer);
|
||||||
|
r = uv_os_getenv("HOME", buffer, &size);
|
||||||
|
if (r == 0 || r == UV_ENOBUFS)
|
||||||
|
{
|
||||||
|
size++;
|
||||||
|
char* home = alloca(size);
|
||||||
|
r = uv_os_getenv("HOME", home, &size);
|
||||||
|
if (r == 0)
|
||||||
|
{
|
||||||
|
size = snprintf(NULL, 0, "%s/.local/share", home) + 1;
|
||||||
|
data_home = alloca(size);
|
||||||
|
snprintf(data_home, size, "%s/.local/share", home);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_home)
|
||||||
|
{
|
||||||
|
size = snprintf(NULL, 0, "%s/tildefriends/db.sqlite", data_home) + 1;
|
||||||
|
char* path = alloca(size);
|
||||||
|
snprintf(path, size, "%s/tildefriends/db.sqlite", data_home);
|
||||||
|
return tf_strdup(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return tf_strdup(k_db_path_default);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _create_directories_for_file(const char* path, int mode)
|
||||||
|
{
|
||||||
|
if (stat(path, &(struct stat) { 0 }) == 0)
|
||||||
|
{
|
||||||
|
/* It already exists. OK. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t length = strlen(path) + 1;
|
||||||
|
char* copy = alloca(length);
|
||||||
|
memcpy(copy, path, length);
|
||||||
|
#if defined(_WIN32)
|
||||||
|
for (char* c = copy; *c; c++)
|
||||||
|
{
|
||||||
|
if (*c == '\\')
|
||||||
|
{
|
||||||
|
*c = '/';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
char* slash = copy;
|
||||||
|
while (slash)
|
||||||
|
{
|
||||||
|
slash = strchr(slash + 1, '/');
|
||||||
|
if (slash)
|
||||||
|
{
|
||||||
|
*slash = '\0';
|
||||||
|
#if defined(_WIN32)
|
||||||
|
if (mkdir(copy) == 0)
|
||||||
|
#else
|
||||||
|
if (mkdir(copy, mode) == 0)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
tf_printf("Created directory %s.\n", copy);
|
||||||
|
}
|
||||||
|
*slash = '/';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !TARGET_OS_IPHONE && !defined(__ANDROID__)
|
#if !TARGET_OS_IPHONE && !defined(__ANDROID__)
|
||||||
static int _tf_command_export(const char* file, int argc, char* argv[]);
|
static int _tf_command_export(const char* file, int argc, char* argv[]);
|
||||||
@ -131,7 +227,8 @@ static int _tf_command_test(const char* file, int argc, char* argv[])
|
|||||||
static int _tf_command_import(const char* file, int argc, char* argv[])
|
static int _tf_command_import(const char* file, int argc, char* argv[])
|
||||||
{
|
{
|
||||||
const char* user = "import";
|
const char* user = "import";
|
||||||
const char* db_path = k_db_path_default;
|
const char* default_db_path = _get_db_path();
|
||||||
|
const char* db_path = default_db_path;
|
||||||
bool show_usage = false;
|
bool show_usage = false;
|
||||||
|
|
||||||
while (!show_usage)
|
while (!show_usage)
|
||||||
@ -169,11 +266,13 @@ static int _tf_command_import(const char* file, int argc, char* argv[])
|
|||||||
tf_printf("\n%s import [options] [paths...]\n\n", file);
|
tf_printf("\n%s import [options] [paths...]\n\n", file);
|
||||||
tf_printf("options:\n");
|
tf_printf("options:\n");
|
||||||
tf_printf(" -u, --user user User into whose account apps will be imported (default: \"import\").\n");
|
tf_printf(" -u, --user user User into whose account apps will be imported (default: \"import\").\n");
|
||||||
tf_printf(" -d, --db-path db_path SQLite database path (default: %s).\n", k_db_path_default);
|
tf_printf(" -d, --db-path db_path SQLite database path (default: %s).\n", default_db_path);
|
||||||
tf_printf(" -h, --help Show this usage information.\n");
|
tf_printf(" -h, --help Show this usage information.\n");
|
||||||
|
tf_free((void*)default_db_path);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_create_directories_for_file(db_path, 0700);
|
||||||
tf_ssb_t* ssb = tf_ssb_create(NULL, NULL, db_path, NULL);
|
tf_ssb_t* ssb = tf_ssb_create(NULL, NULL, db_path, NULL);
|
||||||
if (optind < argc)
|
if (optind < argc)
|
||||||
{
|
{
|
||||||
@ -189,13 +288,15 @@ static int _tf_command_import(const char* file, int argc, char* argv[])
|
|||||||
tf_ssb_import(ssb, user, "apps");
|
tf_ssb_import(ssb, user, "apps");
|
||||||
}
|
}
|
||||||
tf_ssb_destroy(ssb);
|
tf_ssb_destroy(ssb);
|
||||||
|
tf_free((void*)default_db_path);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _tf_command_export(const char* file, int argc, char* argv[])
|
static int _tf_command_export(const char* file, int argc, char* argv[])
|
||||||
{
|
{
|
||||||
const char* user = "core";
|
const char* user = "core";
|
||||||
const char* db_path = k_db_path_default;
|
const char* default_db_path = _get_db_path();
|
||||||
|
const char* db_path = default_db_path;
|
||||||
bool show_usage = false;
|
bool show_usage = false;
|
||||||
|
|
||||||
while (!show_usage)
|
while (!show_usage)
|
||||||
@ -233,10 +334,11 @@ static int _tf_command_export(const char* file, int argc, char* argv[])
|
|||||||
tf_printf("\n%s export [options] [paths...]\n\n", file);
|
tf_printf("\n%s export [options] [paths...]\n\n", file);
|
||||||
tf_printf("options:\n");
|
tf_printf("options:\n");
|
||||||
tf_printf(" -u, --user user User from whose account apps will be exported (default: \"core\").\n");
|
tf_printf(" -u, --user user User from whose account apps will be exported (default: \"core\").\n");
|
||||||
tf_printf(" -d, --db-path db_path SQLite database path (default: %s).\n", k_db_path_default);
|
tf_printf(" -d, --db-path db_path SQLite database path (default: %s).\n", default_db_path);
|
||||||
tf_printf(" -h, --help Show this usage information.\n");
|
tf_printf(" -h, --help Show this usage information.\n");
|
||||||
tf_printf("\n");
|
tf_printf("\n");
|
||||||
tf_printf("paths Paths of apps to export (example: /~core/ssb /~user/app).\n");
|
tf_printf("paths Paths of apps to export (example: /~core/ssb /~user/app).\n");
|
||||||
|
tf_free((void*)default_db_path);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,6 +373,7 @@ static int _tf_command_export(const char* file, int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
tf_ssb_destroy(ssb);
|
tf_ssb_destroy(ssb);
|
||||||
|
tf_free((void*)default_db_path);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,7 +401,8 @@ static int _tf_command_publish(const char* file, int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
const char* user = NULL;
|
const char* user = NULL;
|
||||||
const char* identity = NULL;
|
const char* identity = NULL;
|
||||||
const char* db_path = k_db_path_default;
|
const char* default_db_path = _get_db_path();
|
||||||
|
const char* db_path = default_db_path;
|
||||||
const char* content = NULL;
|
const char* content = NULL;
|
||||||
bool show_usage = false;
|
bool show_usage = false;
|
||||||
|
|
||||||
@ -346,14 +450,16 @@ static int _tf_command_publish(const char* file, int argc, char* argv[])
|
|||||||
tf_printf("options:\n");
|
tf_printf("options:\n");
|
||||||
tf_printf(" -u, --user user User owning identity with which to publish.\n");
|
tf_printf(" -u, --user user User owning identity with which to publish.\n");
|
||||||
tf_printf(" -i, --id identity Identity with which to publish message.\n");
|
tf_printf(" -i, --id identity Identity with which to publish message.\n");
|
||||||
tf_printf(" -d, --db-path db_path SQLite database path (default: %s).\n", k_db_path_default);
|
tf_printf(" -d, --db-path db_path SQLite database path (default: %s).\n", default_db_path);
|
||||||
tf_printf(" -c, --content json JSON content of message to publish.\n");
|
tf_printf(" -c, --content json JSON content of message to publish.\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);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = EXIT_FAILURE;
|
int result = EXIT_FAILURE;
|
||||||
tf_printf("Posting %s as account %s belonging to %s...\n", content, identity, user);
|
tf_printf("Posting %s as account %s belonging to %s...\n", content, identity, user);
|
||||||
|
_create_directories_for_file(db_path, 0700);
|
||||||
tf_ssb_t* ssb = tf_ssb_create(NULL, NULL, db_path, NULL);
|
tf_ssb_t* ssb = tf_ssb_create(NULL, NULL, db_path, NULL);
|
||||||
uint8_t private_key[512] = { 0 };
|
uint8_t private_key[512] = { 0 };
|
||||||
if (tf_ssb_db_identity_get_private_key(ssb, user, identity, private_key, sizeof(private_key)))
|
if (tf_ssb_db_identity_get_private_key(ssb, user, identity, private_key, sizeof(private_key)))
|
||||||
@ -386,12 +492,14 @@ static int _tf_command_publish(const char* file, int argc, char* argv[])
|
|||||||
tf_printf("Did not find private key for identity %s belonging to %s.\n", identity, user);
|
tf_printf("Did not find private key for identity %s belonging to %s.\n", identity, user);
|
||||||
}
|
}
|
||||||
tf_ssb_destroy(ssb);
|
tf_ssb_destroy(ssb);
|
||||||
|
tf_free((void*)default_db_path);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _tf_command_store_blob(const char* file, int argc, char* argv[])
|
static int _tf_command_store_blob(const char* file, int argc, char* argv[])
|
||||||
{
|
{
|
||||||
const char* db_path = k_db_path_default;
|
const char* default_db_path = _get_db_path();
|
||||||
|
const char* db_path = default_db_path;
|
||||||
const char* file_path = NULL;
|
const char* file_path = NULL;
|
||||||
bool show_usage = false;
|
bool show_usage = false;
|
||||||
|
|
||||||
@ -429,9 +537,10 @@ static int _tf_command_store_blob(const char* file, int argc, char* argv[])
|
|||||||
{
|
{
|
||||||
tf_printf("\n%s store_blob [options]\n\n", file);
|
tf_printf("\n%s store_blob [options]\n\n", file);
|
||||||
tf_printf("options:\n");
|
tf_printf("options:\n");
|
||||||
tf_printf(" -d, --db-path db_path SQLite database path (default: %s).\n", k_db_path_default);
|
tf_printf(" -d, --db-path db_path SQLite database path (default: %s).\n", default_db_path);
|
||||||
tf_printf(" -f, --file file_path Path to file to add to the blob store.\n");
|
tf_printf(" -f, --file file_path Path to file to add to the blob store.\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);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,6 +550,7 @@ static int _tf_command_store_blob(const char* file, int argc, char* argv[])
|
|||||||
if (!blob_file)
|
if (!blob_file)
|
||||||
{
|
{
|
||||||
tf_printf("Failed to open %s: %s.\n", file_path, strerror(errno));
|
tf_printf("Failed to open %s: %s.\n", file_path, strerror(errno));
|
||||||
|
tf_free((void*)default_db_path);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,11 +574,13 @@ static int _tf_command_store_blob(const char* file, int argc, char* argv[])
|
|||||||
tf_printf("Failed to read %s: %s.\n", file_path, strerror(errno));
|
tf_printf("Failed to read %s: %s.\n", file_path, strerror(errno));
|
||||||
fclose(blob_file);
|
fclose(blob_file);
|
||||||
tf_free(data);
|
tf_free(data);
|
||||||
|
tf_free((void*)default_db_path);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
fclose(blob_file);
|
fclose(blob_file);
|
||||||
|
|
||||||
char id[256];
|
char id[256];
|
||||||
|
_create_directories_for_file(db_path, 0700);
|
||||||
tf_ssb_t* ssb = tf_ssb_create(NULL, NULL, db_path, NULL);
|
tf_ssb_t* ssb = tf_ssb_create(NULL, NULL, db_path, NULL);
|
||||||
if (tf_ssb_db_blob_store(ssb, (const uint8_t*)data, size, id, sizeof(id), NULL))
|
if (tf_ssb_db_blob_store(ssb, (const uint8_t*)data, size, id, sizeof(id), NULL))
|
||||||
{
|
{
|
||||||
@ -476,13 +588,15 @@ static int _tf_command_store_blob(const char* file, int argc, char* argv[])
|
|||||||
}
|
}
|
||||||
tf_ssb_destroy(ssb);
|
tf_ssb_destroy(ssb);
|
||||||
tf_free(data);
|
tf_free(data);
|
||||||
|
tf_free((void*)default_db_path);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _tf_command_verify(const char* file, int argc, char* argv[])
|
static int _tf_command_verify(const char* file, int argc, char* argv[])
|
||||||
{
|
{
|
||||||
const char* identity = NULL;
|
const char* identity = NULL;
|
||||||
const char* db_path = k_db_path_default;
|
const char* default_db_path = _get_db_path();
|
||||||
|
const char* db_path = default_db_path;
|
||||||
bool show_usage = false;
|
bool show_usage = false;
|
||||||
|
|
||||||
while (!show_usage)
|
while (!show_usage)
|
||||||
@ -520,8 +634,9 @@ static int _tf_command_verify(const char* file, int argc, char* argv[])
|
|||||||
tf_printf("\n%s import [options] [paths...]\n\n", file);
|
tf_printf("\n%s import [options] [paths...]\n\n", file);
|
||||||
tf_printf("options:\n");
|
tf_printf("options:\n");
|
||||||
tf_printf(" -i, --identity identity Identity to verify.\n");
|
tf_printf(" -i, --identity identity Identity to verify.\n");
|
||||||
tf_printf(" -d, --db-path db_path SQLite database path (default: %s).\n", k_db_path_default);
|
tf_printf(" -d, --db-path db_path SQLite database path (default: %s).\n", default_db_path);
|
||||||
tf_printf(" -h, --help Show this usage information.\n");
|
tf_printf(" -h, --help Show this usage information.\n");
|
||||||
|
tf_free((void*)default_db_path);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,6 +644,7 @@ static int _tf_command_verify(const char* file, int argc, char* argv[])
|
|||||||
tf_ssb_t* ssb = tf_ssb_create(NULL, NULL, db_path, NULL);
|
tf_ssb_t* ssb = tf_ssb_create(NULL, NULL, db_path, NULL);
|
||||||
bool verified = tf_ssb_db_verify(ssb, identity);
|
bool verified = tf_ssb_db_verify(ssb, identity);
|
||||||
tf_ssb_destroy(ssb);
|
tf_ssb_destroy(ssb);
|
||||||
|
tf_free((void*)default_db_path);
|
||||||
return verified ? EXIT_SUCCESS : EXIT_FAILURE;
|
return verified ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -673,13 +789,14 @@ static void _shed_privileges()
|
|||||||
|
|
||||||
static int _tf_command_run(const char* file, int argc, char* argv[])
|
static int _tf_command_run(const char* file, int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
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",
|
.script = "core/core.js",
|
||||||
.http_port = 12345,
|
.http_port = 12345,
|
||||||
.https_port = 12346,
|
.https_port = 12346,
|
||||||
.ssb_port = 8008,
|
.ssb_port = 8008,
|
||||||
.db_path = k_db_path_default,
|
.db_path = default_db_path,
|
||||||
};
|
};
|
||||||
bool show_usage = false;
|
bool show_usage = false;
|
||||||
|
|
||||||
@ -764,7 +881,7 @@ static int _tf_command_run(const char* file, int argc, char* argv[])
|
|||||||
tf_printf(" -b, --ssb-port port Port on which to run SSB (default: 8008, 0 disables).\n");
|
tf_printf(" -b, --ssb-port port Port on which to run SSB (default: 8008, 0 disables).\n");
|
||||||
tf_printf(" -p, --http-port port Port on which to run Tilde Friends web server (default: 12345).\n");
|
tf_printf(" -p, --http-port port Port on which to run Tilde Friends web server (default: 12345).\n");
|
||||||
tf_printf(" -q, --https-port port Port on which to run secure Tilde Friends web server (default: 12346).\n");
|
tf_printf(" -q, --https-port port Port on which to run secure Tilde Friends web server (default: 12346).\n");
|
||||||
tf_printf(" -d, --db-path path SQLite database path (default: %s).\n", k_db_path_default);
|
tf_printf(" -d, --db-path path SQLite database path (default: %s).\n", default_db_path);
|
||||||
tf_printf(" -k, --ssb-network-key key SSB network key to use.\n");
|
tf_printf(" -k, --ssb-network-key key SSB network key to use.\n");
|
||||||
tf_printf(" -n, --count count Number of instances to run.\n");
|
tf_printf(" -n, --count count Number of instances to run.\n");
|
||||||
tf_printf(" -a, --args args Arguments of the format key=value,foo=bar,verbose=true.\n");
|
tf_printf(" -a, --args args Arguments of the format key=value,foo=bar,verbose=true.\n");
|
||||||
@ -772,6 +889,7 @@ static int _tf_command_run(const char* file, int argc, char* argv[])
|
|||||||
tf_printf(" -z, --zip path Zip archive from which to load files.\n");
|
tf_printf(" -z, --zip path Zip archive from which to load files.\n");
|
||||||
tf_printf(" -v, --verbose Log raw messages.\n");
|
tf_printf(" -v, --verbose Log raw messages.\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);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -780,6 +898,7 @@ static int _tf_command_run(const char* file, int argc, char* argv[])
|
|||||||
setpgid(0, 0);
|
setpgid(0, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
_create_directories_for_file(args.db_path, 0700);
|
||||||
if (args.count == 1)
|
if (args.count == 1)
|
||||||
{
|
{
|
||||||
result = _tf_run_task(&args, 0);
|
result = _tf_run_task(&args, 0);
|
||||||
@ -807,6 +926,7 @@ static int _tf_command_run(const char* file, int argc, char* argv[])
|
|||||||
tf_free(data);
|
tf_free(data);
|
||||||
tf_free(threads);
|
tf_free(threads);
|
||||||
}
|
}
|
||||||
|
tf_free((void*)default_db_path);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1088,7 +1208,7 @@ void tf_run_thread_start(const char* zip_path)
|
|||||||
.http_port = 12345,
|
.http_port = 12345,
|
||||||
.https_port = 12346,
|
.https_port = 12346,
|
||||||
.ssb_port = 8008,
|
.ssb_port = 8008,
|
||||||
.db_path = k_db_path_default,
|
.db_path = "db.sqlite",
|
||||||
.one_proc = true,
|
.one_proc = true,
|
||||||
.zip = zip_path,
|
.zip = zip_path,
|
||||||
};
|
};
|
||||||
|
64
src/ssb.c
64
src/ssb.c
@ -4222,63 +4222,19 @@ typedef struct _update_settings_t
|
|||||||
char room_name[1024];
|
char room_name[1024];
|
||||||
} update_settings_t;
|
} update_settings_t;
|
||||||
|
|
||||||
static bool _get_global_setting_string(tf_ssb_t* ssb, const char* name, char* out_value, size_t size)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
|
||||||
sqlite3_stmt* statement;
|
|
||||||
if (sqlite3_prepare(db, "SELECT json_extract(value, '$.' || ?) FROM properties WHERE id = 'core' AND key = 'settings'", -1, &statement, NULL) == SQLITE_OK)
|
|
||||||
{
|
|
||||||
if (sqlite3_bind_text(statement, 1, name, -1, NULL) == SQLITE_OK)
|
|
||||||
{
|
|
||||||
if (sqlite3_step(statement) == SQLITE_ROW)
|
|
||||||
{
|
|
||||||
snprintf(out_value, size, "%s", sqlite3_column_text(statement, 0));
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sqlite3_finalize(statement);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
|
|
||||||
}
|
|
||||||
tf_ssb_release_db_reader(ssb, db);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _get_global_setting_bool(tf_ssb_t* ssb, const char* name, bool default_value)
|
|
||||||
{
|
|
||||||
bool result = default_value;
|
|
||||||
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
|
||||||
sqlite3_stmt* statement;
|
|
||||||
if (sqlite3_prepare(db, "SELECT json_extract(value, '$.' || ?) FROM properties WHERE id = 'core' AND key = 'settings'", -1, &statement, NULL) == SQLITE_OK)
|
|
||||||
{
|
|
||||||
if (sqlite3_bind_text(statement, 1, name, -1, NULL) == SQLITE_OK)
|
|
||||||
{
|
|
||||||
if (sqlite3_step(statement) == SQLITE_ROW)
|
|
||||||
{
|
|
||||||
result = sqlite3_column_int(statement, 0) != 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sqlite3_finalize(statement);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
|
|
||||||
}
|
|
||||||
tf_ssb_release_db_reader(ssb, db);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _tf_ssb_update_settings_work(tf_ssb_t* ssb, void* user_data)
|
static void _tf_ssb_update_settings_work(tf_ssb_t* ssb, void* user_data)
|
||||||
{
|
{
|
||||||
update_settings_t* update = user_data;
|
update_settings_t* update = user_data;
|
||||||
update->is_room = _get_global_setting_bool(ssb, "room", true);
|
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
||||||
update->is_replicator = _get_global_setting_bool(ssb, "replicator", true);
|
update->is_room = true;
|
||||||
update->is_peer_exchange = _get_global_setting_bool(ssb, "peer_exchange", true);
|
update->is_replicator = true;
|
||||||
_get_global_setting_string(ssb, "room_name", update->room_name, sizeof(update->room_name));
|
update->is_peer_exchange = true;
|
||||||
_get_global_setting_string(ssb, "seeds_host", update->seeds_host, sizeof(update->seeds_host));
|
tf_ssb_db_get_global_setting_bool(db, "room", &update->is_room);
|
||||||
|
tf_ssb_db_get_global_setting_bool(db, "replicator", &update->is_replicator);
|
||||||
|
tf_ssb_db_get_global_setting_bool(db, "peer_exchange", &update->is_peer_exchange);
|
||||||
|
tf_ssb_db_get_global_setting_string(db, "room_name", update->room_name, sizeof(update->room_name));
|
||||||
|
tf_ssb_db_get_global_setting_string(db, "seeds_host", update->seeds_host, sizeof(update->seeds_host));
|
||||||
|
tf_ssb_release_db_reader(ssb, db);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _tf_ssb_update_settings_after_work(tf_ssb_t* ssb, int result, void* user_data)
|
static void _tf_ssb_update_settings_after_work(tf_ssb_t* ssb, int result, void* user_data)
|
||||||
|
94
src/ssb.db.c
94
src/ssb.db.c
@ -1681,34 +1681,13 @@ bool tf_ssb_db_set_account_password(uv_loop_t* loop, sqlite3* db, JSContext* con
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _tf_ssb_db_get_global_setting_bool(sqlite3* db, const char* name, bool default_value)
|
|
||||||
{
|
|
||||||
bool result = default_value;
|
|
||||||
sqlite3_stmt* statement;
|
|
||||||
if (sqlite3_prepare(db, "SELECT json_extract(value, '$.' || ?) FROM properties WHERE id = 'core' AND key = 'settings'", -1, &statement, NULL) == SQLITE_OK)
|
|
||||||
{
|
|
||||||
if (sqlite3_bind_text(statement, 1, name, -1, NULL) == SQLITE_OK)
|
|
||||||
{
|
|
||||||
if (sqlite3_step(statement) == SQLITE_ROW && sqlite3_column_type(statement, 0) != SQLITE_NULL)
|
|
||||||
{
|
|
||||||
result = sqlite3_column_int(statement, 0) != 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sqlite3_finalize(statement);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tf_ssb_db_register_account(uv_loop_t* loop, sqlite3* db, JSContext* context, const char* name, const char* password)
|
bool tf_ssb_db_register_account(uv_loop_t* loop, sqlite3* db, JSContext* context, const char* name, const char* password)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
JSValue users_array = JS_UNDEFINED;
|
JSValue users_array = JS_UNDEFINED;
|
||||||
|
|
||||||
bool registration_allowed = _tf_ssb_db_get_global_setting_bool(db, "account_registration", true);
|
bool registration_allowed = true;
|
||||||
|
tf_ssb_db_get_global_setting_bool(db, "account_registration", ®istration_allowed);
|
||||||
if (registration_allowed)
|
if (registration_allowed)
|
||||||
{
|
{
|
||||||
sqlite3_stmt* statement = NULL;
|
sqlite3_stmt* statement = NULL;
|
||||||
@ -2030,3 +2009,72 @@ bool tf_ssb_db_user_has_permission(tf_ssb_t* ssb, sqlite3* db, const char* id, c
|
|||||||
}
|
}
|
||||||
return has_permission;
|
return has_permission;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tf_ssb_db_get_global_setting_bool(sqlite3* db, const char* name, bool* out_value)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
sqlite3_stmt* statement;
|
||||||
|
if (sqlite3_prepare(db, "SELECT json_extract(value, '$.' || ?) FROM properties WHERE id = 'core' AND key = 'settings'", -1, &statement, NULL) == SQLITE_OK)
|
||||||
|
{
|
||||||
|
if (sqlite3_bind_text(statement, 1, name, -1, NULL) == SQLITE_OK)
|
||||||
|
{
|
||||||
|
if (sqlite3_step(statement) == SQLITE_ROW)
|
||||||
|
{
|
||||||
|
*out_value = sqlite3_column_int(statement, 0) != 0;
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqlite3_finalize(statement);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tf_ssb_db_get_global_setting_int64(sqlite3* db, const char* name, int64_t* out_value)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
sqlite3_stmt* statement;
|
||||||
|
if (sqlite3_prepare(db, "SELECT json_extract(value, '$.' || ?) FROM properties WHERE id = 'core' AND key = 'settings'", -1, &statement, NULL) == SQLITE_OK)
|
||||||
|
{
|
||||||
|
if (sqlite3_bind_text(statement, 1, name, -1, NULL) == SQLITE_OK)
|
||||||
|
{
|
||||||
|
if (sqlite3_step(statement) == SQLITE_ROW && sqlite3_column_type(statement, 0) != SQLITE_NULL)
|
||||||
|
{
|
||||||
|
*out_value = sqlite3_column_int64(statement, 0);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqlite3_finalize(statement);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tf_ssb_db_get_global_setting_string(sqlite3* db, const char* name, char* out_value, size_t size)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
sqlite3_stmt* statement;
|
||||||
|
if (sqlite3_prepare(db, "SELECT json_extract(value, '$.' || ?) FROM properties WHERE id = 'core' AND key = 'settings'", -1, &statement, NULL) == SQLITE_OK)
|
||||||
|
{
|
||||||
|
if (sqlite3_bind_text(statement, 1, name, -1, NULL) == SQLITE_OK)
|
||||||
|
{
|
||||||
|
if (sqlite3_step(statement) == SQLITE_ROW)
|
||||||
|
{
|
||||||
|
snprintf(out_value, size, "%s", sqlite3_column_text(statement, 0));
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqlite3_finalize(statement);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
28
src/ssb.db.h
28
src/ssb.db.h
@ -455,6 +455,34 @@ bool tf_ssb_db_verify(tf_ssb_t* ssb, const char* id);
|
|||||||
*/
|
*/
|
||||||
bool tf_ssb_db_user_has_permission(tf_ssb_t* ssb, sqlite3* db, const char* id, const char* permission);
|
bool tf_ssb_db_user_has_permission(tf_ssb_t* ssb, sqlite3* db, const char* id, const char* permission);
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Get a boolean global setting value.
|
||||||
|
** @param db The database.
|
||||||
|
** @param name The setting name.
|
||||||
|
** @param out_value Populated with the value.
|
||||||
|
** @return true if the setting was found.
|
||||||
|
*/
|
||||||
|
bool tf_ssb_db_get_global_setting_bool(sqlite3* db, const char* name, bool* out_value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Get an int64_t global setting value.
|
||||||
|
** @param db The database.
|
||||||
|
** @param name The setting name.
|
||||||
|
** @param out_value Populated with the value.
|
||||||
|
** @return true if the setting was found.
|
||||||
|
*/
|
||||||
|
bool tf_ssb_db_get_global_setting_int64(sqlite3* db, const char* name, int64_t* out_value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Get a string global setting value.
|
||||||
|
** @param db The database.
|
||||||
|
** @param name The setting name.
|
||||||
|
** @param out_value Populated with the value.
|
||||||
|
** @param size The size of the out_value buffer.
|
||||||
|
** @return true if the setting was found.
|
||||||
|
*/
|
||||||
|
bool tf_ssb_db_get_global_setting_string(sqlite3* db, const char* name, char* out_value, size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** An SQLite authorizer callback. See https://www.sqlite.org/c3ref/set_authorizer.html for use.
|
** An SQLite authorizer callback. See https://www.sqlite.org/c3ref/set_authorizer.html for use.
|
||||||
** @param user_data User data registered with the authorizer.
|
** @param user_data User data registered with the authorizer.
|
||||||
|
@ -20,30 +20,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 int64_t _get_global_setting_int64(tf_ssb_t* ssb, const char* name, int64_t default_value)
|
|
||||||
{
|
|
||||||
int64_t result = default_value;
|
|
||||||
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
|
||||||
sqlite3_stmt* statement;
|
|
||||||
if (sqlite3_prepare(db, "SELECT json_extract(value, '$.' || ?) FROM properties WHERE id = 'core' AND key = 'settings'", -1, &statement, NULL) == SQLITE_OK)
|
|
||||||
{
|
|
||||||
if (sqlite3_bind_text(statement, 1, name, -1, NULL) == SQLITE_OK)
|
|
||||||
{
|
|
||||||
if (sqlite3_step(statement) == SQLITE_ROW && sqlite3_column_type(statement, 0) != SQLITE_NULL)
|
|
||||||
{
|
|
||||||
result = sqlite3_column_int64(statement, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sqlite3_finalize(statement);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
|
|
||||||
}
|
|
||||||
tf_ssb_release_db_reader(ssb, db);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool _get_global_setting_bool(tf_ssb_t* ssb, const char* name, bool default_value)
|
static bool _get_global_setting_bool(tf_ssb_t* ssb, const char* name, bool default_value)
|
||||||
{
|
{
|
||||||
bool result = default_value;
|
bool result = default_value;
|
||||||
@ -243,7 +219,10 @@ static void _tf_ssb_request_blob_wants_work(tf_ssb_connection_t* connection, voi
|
|||||||
blob_wants_work_t* work = user_data;
|
blob_wants_work_t* work = user_data;
|
||||||
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_t* ssb = tf_ssb_connection_get_ssb(connection);
|
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
|
||||||
int64_t age = _get_global_setting_int64(ssb, "blob_fetch_age_seconds", -1);
|
int64_t age = -1;
|
||||||
|
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
||||||
|
tf_ssb_db_get_global_setting_int64(db, "blob_fetch_age_seconds", &age);
|
||||||
|
tf_ssb_release_db_reader(ssb, db);
|
||||||
int64_t timestamp = -1;
|
int64_t timestamp = -1;
|
||||||
if (age == 0)
|
if (age == 0)
|
||||||
{
|
{
|
||||||
@ -256,7 +235,7 @@ static void _tf_ssb_request_blob_wants_work(tf_ssb_connection_t* connection, voi
|
|||||||
timestamp = now - age * 1000ULL;
|
timestamp = now - age * 1000ULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
db = tf_ssb_acquire_db_reader(ssb);
|
||||||
sqlite3_stmt* statement;
|
sqlite3_stmt* statement;
|
||||||
if (sqlite3_prepare(db, "SELECT id FROM blob_wants_view WHERE id > ? AND timestamp > ? ORDER BY id LIMIT ?", -1, &statement, NULL) == SQLITE_OK)
|
if (sqlite3_prepare(db, "SELECT id FROM blob_wants_view WHERE id > ? AND timestamp > ? ORDER BY id LIMIT ?", -1, &statement, NULL) == SQLITE_OK)
|
||||||
{
|
{
|
||||||
@ -1003,7 +982,10 @@ static void _tf_ssb_rpc_ebt_replicate_send_clock_work(tf_ssb_connection_t* conne
|
|||||||
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
|
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
|
||||||
JSValue full_clock = JS_NewObject(context);
|
JSValue full_clock = JS_NewObject(context);
|
||||||
|
|
||||||
int64_t depth = _get_global_setting_int64(ssb, "replication_hops", 2);
|
int64_t depth = 2;
|
||||||
|
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
||||||
|
tf_ssb_db_get_global_setting_int64(db, "replication_hops", &depth);
|
||||||
|
tf_ssb_release_db_reader(ssb, db);
|
||||||
|
|
||||||
/* Ask for every identity we know is being followed from local accounts. */
|
/* Ask for every identity we know is being followed from local accounts. */
|
||||||
const char** visible = tf_ssb_db_get_all_visible_identities(ssb, depth);
|
const char** visible = tf_ssb_db_get_all_visible_identities(ssb, depth);
|
||||||
@ -1400,14 +1382,17 @@ typedef struct _delete_t
|
|||||||
static void _tf_ssb_rpc_delete_blobs_work(tf_ssb_t* ssb, void* user_data)
|
static void _tf_ssb_rpc_delete_blobs_work(tf_ssb_t* ssb, void* user_data)
|
||||||
{
|
{
|
||||||
delete_t* delete = user_data;
|
delete_t* delete = user_data;
|
||||||
int64_t age = _get_global_setting_int64(ssb, "blob_expire_age_seconds", -1);
|
int64_t age = -1;
|
||||||
|
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
||||||
|
tf_ssb_db_get_global_setting_int64(db, "blob_expire_age_seconds", &age);
|
||||||
|
tf_ssb_release_db_reader(ssb, db);
|
||||||
if (age <= 0)
|
if (age <= 0)
|
||||||
{
|
{
|
||||||
_tf_ssb_rpc_checkpoint(ssb);
|
_tf_ssb_rpc_checkpoint(ssb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int64_t start_ns = uv_hrtime();
|
int64_t start_ns = uv_hrtime();
|
||||||
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
|
db = tf_ssb_acquire_db_writer(ssb);
|
||||||
sqlite3_stmt* statement;
|
sqlite3_stmt* statement;
|
||||||
int64_t now = (int64_t)time(NULL) * 1000ULL;
|
int64_t now = (int64_t)time(NULL) * 1000ULL;
|
||||||
int64_t timestamp = now - age * 1000ULL;
|
int64_t timestamp = now - age * 1000ULL;
|
||||||
@ -1474,7 +1459,10 @@ static void _tf_ssb_rpc_delete_feeds_work(tf_ssb_t* ssb, void* user_data)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int64_t start_ns = uv_hrtime();
|
int64_t start_ns = uv_hrtime();
|
||||||
int replication_hops = (int)_get_global_setting_int64(ssb, "replication_hops", 2);
|
int64_t replication_hops = 2;
|
||||||
|
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
||||||
|
tf_ssb_db_get_global_setting_int64(db, "replication_hops", &replication_hops);
|
||||||
|
tf_ssb_release_db_reader(ssb, db);
|
||||||
const char** identities = tf_ssb_db_get_all_visible_identities(ssb, replication_hops);
|
const char** identities = tf_ssb_db_get_all_visible_identities(ssb, replication_hops);
|
||||||
|
|
||||||
JSMallocFunctions funcs = { 0 };
|
JSMallocFunctions funcs = { 0 };
|
||||||
@ -1493,7 +1481,7 @@ static void _tf_ssb_rpc_delete_feeds_work(tf_ssb_t* ssb, void* user_data)
|
|||||||
JS_FreeValue(context, json);
|
JS_FreeValue(context, json);
|
||||||
JS_FreeValue(context, array);
|
JS_FreeValue(context, array);
|
||||||
|
|
||||||
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
|
db = tf_ssb_acquire_db_writer(ssb);
|
||||||
sqlite3_stmt* statement;
|
sqlite3_stmt* statement;
|
||||||
if (sqlite3_prepare(db,
|
if (sqlite3_prepare(db,
|
||||||
"DELETE FROM messages WHERE author IN ("
|
"DELETE FROM messages WHERE author IN ("
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
#define VERSION_NUMBER "0.0.26"
|
#define VERSION_NUMBER "0.0.27-wip"
|
||||||
#define VERSION_NAME "This program kills fascists."
|
#define VERSION_NAME "This program kills fascists."
|
||||||
|
@ -73,8 +73,10 @@ build_the_thing() {
|
|||||||
no-whirlpool
|
no-whirlpool
|
||||||
no-weak-ssl-ciphers
|
no-weak-ssl-ciphers
|
||||||
no-zlib
|
no-zlib
|
||||||
-Os
|
-Oz
|
||||||
-DOPENSSL_SMALL_FOOTPRINT
|
-DOPENSSL_SMALL_FOOTPRINT
|
||||||
|
-ffunction-sections
|
||||||
|
-fdata-sections
|
||||||
-flto"
|
-flto"
|
||||||
pwd
|
pwd
|
||||||
echo "./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS" && \
|
echo "./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS" && \
|
||||||
|
@ -29,14 +29,14 @@ do
|
|||||||
case $build_target in
|
case $build_target in
|
||||||
ios64-xcrun)
|
ios64-xcrun)
|
||||||
TRIBLE="arm64-darwin-ios"
|
TRIBLE="arm64-darwin-ios"
|
||||||
OPTIONS="--static -static -ffunction-sections -fdata-sections -fPIC -Wno-macro-redefined -miphoneos-version-min=9.0"
|
OPTIONS="--static -static -Oz -ffunction-sections -fdata-sections -fPIC -Wno-macro-redefined -miphoneos-version-min=9.0"
|
||||||
DESTDIR="/tmp/$BUILD_DIR/arm64-ios"
|
DESTDIR="/tmp/$BUILD_DIR/arm64-ios"
|
||||||
SSL_TARGET="ios64-xcrun"
|
SSL_TARGET="ios64-xcrun"
|
||||||
CC=clang
|
CC=clang
|
||||||
;;
|
;;
|
||||||
iossimulator-xcrun)
|
iossimulator-xcrun)
|
||||||
TRIBLE="x86_64-darwin-ios"
|
TRIBLE="x86_64-darwin-ios"
|
||||||
OPTIONS="--static -static -ffunction-sections -fdata-sections -fPIC -Wno-macro-redefined"
|
OPTIONS="--static -static -Oz -ffunction-sections -fdata-sections -fPIC -Wno-macro-redefined"
|
||||||
DESTDIR="/tmp/$BUILD_DIR/x86_64-iossim"
|
DESTDIR="/tmp/$BUILD_DIR/x86_64-iossim"
|
||||||
SSL_TARGET="iossimulator-xcrun"
|
SSL_TARGET="iossimulator-xcrun"
|
||||||
CC=clang
|
CC=clang
|
||||||
|
91
tools/ssl-local
Executable file
91
tools/ssl-local
Executable file
@ -0,0 +1,91 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BUILD_PLATFORM=$(uname -s)
|
||||||
|
if [[ -z $BUILD_TARGET ]]; then
|
||||||
|
BUILD_TARGET=$(uname -m)
|
||||||
|
WORK_DIR=out/openssl-local
|
||||||
|
else
|
||||||
|
WORK_DIR=out/openssl-$BUILD_TARGET
|
||||||
|
SSL_TARGET=linux-$BUILD_TARGET
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf $WORK_DIR
|
||||||
|
cp -aRf deps/openssl_src/ $WORK_DIR
|
||||||
|
|
||||||
|
echo "Building"
|
||||||
|
pwd
|
||||||
|
pushd $WORK_DIR || exit 128
|
||||||
|
rm -rf $DESTDIR
|
||||||
|
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
|
||||||
|
-flto"
|
||||||
|
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
|
||||||
|
popd
|
||||||
|
echo WORK_DIR=$WORK_DIR
|
||||||
|
rm -rf deps/openssl/$BUILD_PLATFORM/$BUILD_TARGET/
|
||||||
|
mkdir -p deps/openssl/$BUILD_PLATFORM/$BUILD_TARGET/usr/local/include/
|
||||||
|
mkdir -p deps/openssl/$BUILD_PLATFORM/$BUILD_TARGET/usr/local/lib/
|
||||||
|
cp -R $WORK_DIR/include/* deps/openssl/$BUILD_PLATFORM/$BUILD_TARGET/usr/local/include/
|
||||||
|
cp $WORK_DIR/*.a deps/openssl/$BUILD_PLATFORM/$BUILD_TARGET/usr/local/lib/
|
||||||
|
|
||||||
|
echo Success
|
@ -56,7 +56,7 @@ build_the_thing() {
|
|||||||
no-uplink
|
no-uplink
|
||||||
no-weak-ssl-ciphers
|
no-weak-ssl-ciphers
|
||||||
no-zlib
|
no-zlib
|
||||||
-Os
|
-Oz
|
||||||
-ffunction-sections
|
-ffunction-sections
|
||||||
-fdata-sections
|
-fdata-sections
|
||||||
-flto
|
-flto
|
||||||
|
Reference in New Issue
Block a user