Compare commits
66 Commits
what-if-dh
...
v0.0.22
Author | SHA1 | Date | |
---|---|---|---|
3c499c834b | |||
17d6cc7d46 | |||
646bd7dc38 | |||
56e483782d | |||
e1b9066b26 | |||
7114ce2516 | |||
9240c6570a | |||
f80a44ccd7 | |||
e6f5eb244e | |||
ab62e83110 | |||
aeefb9e536 | |||
ee0efa536a | |||
2523130fdc | |||
c024777184 | |||
5951d7cd2d | |||
011670c70b | |||
6cebd6c769 | |||
546ae5cbf1 | |||
f543cc642e | |||
8ac3c5ea22 | |||
63918f0680 | |||
bfb3d8b8a2 | |||
e38ff99607 | |||
b0e3d922c8 | |||
a15bb8e994 | |||
6f487100cd | |||
0693a2315f | |||
f360e886ff | |||
6ea08cc5dc | |||
347c706d6f | |||
5f5e6616c7 | |||
657bcadc7e | |||
107666cc60 | |||
b37669184a | |||
163a01f224 | |||
3d58094199 | |||
463951a4f1 | |||
34804d5162 | |||
3895c33915 | |||
17f4eb1a56 | |||
0abdffdea6 | |||
d32999f178 | |||
f621feb843 | |||
8d277f029d | |||
1788a02338 | |||
ba0800d16c | |||
4008c7d8f6 | |||
610a2e2afc | |||
6f3715d1eb | |||
b78ecaa814 | |||
e6f5399d53 | |||
0e5806cadd | |||
68c9d4afa7 | |||
f0ea38fe49 | |||
b0332f923e | |||
8a76c25394 | |||
fd96126e3e | |||
ff3fbedc18 | |||
8791419f8e | |||
5447b247a0 | |||
aabbb10564 | |||
3ccd6c9a3e | |||
c290240de7 | |||
8e799b174b | |||
a9c3a93989 | |||
3ef8698f42 |
.gitea/workflows
.gitmodulesDoxyfileGNUmakefileapps
core
default.nixdeps
metadata/en-US
changelogs
images
src
android
http.chttpd.js.cmain.cssb.cssb.db.cssb.db.hssb.hssb.import.cssb.js.cssb.rpc.cssb.tests.cssb.tests.htask.ctask.htests.cutil.js.cversion.htools
@ -10,6 +10,6 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- run: sudo apt update && sudo apt install -y doxygen mingw-w64
|
||||
- run: sudo apt update && sudo apt install -y doxygen graphviz mingw-w64
|
||||
- run: make all -j`nproc` docs
|
||||
- run: docker build .
|
||||
|
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -22,3 +22,7 @@
|
||||
[submodule "deps/openssl_src"]
|
||||
path = deps/openssl_src
|
||||
url = https://github.com/openssl/openssl.git
|
||||
shallow = true
|
||||
[submodule "deps/c-ares"]
|
||||
path = deps/c-ares
|
||||
url = https://github.com/c-ares/c-ares.git
|
||||
|
174
GNUmakefile
174
GNUmakefile
@ -3,12 +3,11 @@
|
||||
MAKEFLAGS += --warn-undefined-variables
|
||||
MAKEFLAGS += --no-builtin-rules
|
||||
|
||||
VERSION_CODE := 24
|
||||
VERSION_NUMBER := 0.0.21
|
||||
VERSION_NAME := What are we even doing here?
|
||||
VERSION_CODE := 26
|
||||
VERSION_NUMBER := 0.0.22
|
||||
VERSION_NAME := Get born soon.
|
||||
|
||||
SQLITE_URL := https://www.sqlite.org/2024/sqlite-amalgamation-3460000.zip
|
||||
LIBUV_URL := https://dist.libuv.org/dist/v1.48.0/libuv-v1.48.0.tar.gz
|
||||
SQLITE_URL := https://www.sqlite.org/2024/sqlite-amalgamation-3460100.zip
|
||||
BUNDLETOOL_URL := https://github.com/google/bundletool/releases/download/1.17.0/bundletool-all-1.17.0.jar
|
||||
|
||||
PROJECT = tildefriends
|
||||
@ -21,6 +20,9 @@ BUNDLETOOL = out/bundletool.jar
|
||||
|
||||
HAVE_WIN := 0
|
||||
|
||||
export SOURCE_DATE_EPOCH=1
|
||||
export TZ=UTC
|
||||
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
BUILD_TYPES := macosdebug macosrelease iosdebug iosrelease iossimdebug iossimrelease
|
||||
else ifeq ($(UNAME_S),Linux)
|
||||
@ -52,26 +54,22 @@ CFLAGS += \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-Wno-unused-parameter \
|
||||
-Wno-unknown-warning-option \
|
||||
-MMD \
|
||||
-MP \
|
||||
-ffunction-sections \
|
||||
-fdata-sections \
|
||||
-fno-exceptions \
|
||||
-g \
|
||||
-flto
|
||||
-g
|
||||
LDFLAGS += \
|
||||
-flto=auto \
|
||||
-Wno-attributes
|
||||
-Wno-attributes \
|
||||
-flto=auto
|
||||
|
||||
ANDROID_MIN_SDK_VERSION := 24
|
||||
ANDROID_TARGET_SDK_VERSION := 34
|
||||
ANDROID_BUILD_TOOLS := $(ANDROID_SDK)/build-tools/34.0.0
|
||||
ANDROID_PLATFORM := $(ANDROID_SDK)/platforms/android-$(ANDROID_TARGET_SDK_VERSION)
|
||||
ifneq "$(wildcard $(ANDROID_SDK)/ndk/27.0.12077973/.)" ""
|
||||
ANDROID_NDK ?= $(ANDROID_SDK)/ndk/27.0.12077973
|
||||
else
|
||||
ANDROID_NDK ?= $(ANDROID_SDK)/ndk/26.2.11394342
|
||||
endif
|
||||
ANDROID_NDK ?= $(ANDROID_SDK)/ndk/26.3.11579264
|
||||
|
||||
ANDROID_ARMV7A_TARGETS := \
|
||||
out/androiddebug-armv7a/tildefriends \
|
||||
@ -161,6 +159,7 @@ NONANDROID_RELEASE_TARGETS := $(filter-out $(ANDROID_ARM64_TARGETS),$(RELEASE_TA
|
||||
NONANDROID_TARGETS := $(filter-out $(ANDROID_TARGETS),$(ALL_TARGETS))
|
||||
NONMACOS_TARGETS := $(filter-out $(MACOS_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS),$(ALL_TARGETS))
|
||||
DEADSTRIP_TARGETS := $(filter-out $(ANDROID_TARGETS),$(NONMACOS_TARGETS))
|
||||
$(NONMACOS_TARGETS): LDFLAGS += -static-libgcc
|
||||
|
||||
$(NONANDROID_TARGETS): CFLAGS += -fno-omit-frame-pointer
|
||||
$(filter-out $(WINDOWS_TARGETS),$(ALL_TARGETS)): LDFLAGS += -rdynamic
|
||||
@ -170,10 +169,13 @@ $(ANDROID_TARGETS): CFLAGS += \
|
||||
-fdebug-compilation-dir . \
|
||||
-fomit-frame-pointer \
|
||||
-fno-asynchronous-unwind-tables \
|
||||
-funwind-tables
|
||||
-funwind-tables \
|
||||
-Wno-unknown-warning-option
|
||||
$(ANDROID_TARGETS): LDFLAGS += --sysroot $(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC
|
||||
$(DEBUG_TARGETS): CFLAGS += -DDEBUG -Og
|
||||
$(RELEASE_TARGETS): CFLAGS += -DNDEBUG
|
||||
$(RELEASE_TARGETS): CFLAGS += \
|
||||
-DNDEBUG \
|
||||
-flto
|
||||
$(NONANDROID_RELEASE_TARGETS): CFLAGS += -O3
|
||||
$(ANDROID_RELEASE_TARGETS): CFLAGS += -Oz
|
||||
$(WINDOWS_TARGETS): CC = x86_64-w64-mingw32-gcc-win32
|
||||
@ -249,6 +251,8 @@ APP_SOURCES_ios := $(wildcard src/*.m)
|
||||
APP_OBJS := $(call get_objs,APP_SOURCES)
|
||||
$(APP_OBJS): CFLAGS += \
|
||||
-Ideps/base64c/include \
|
||||
-Ideps/c-ares/include \
|
||||
-Ideps/c-ares_config \
|
||||
-Ideps/crypt_blowfish \
|
||||
-Ideps/libbacktrace \
|
||||
-Ideps/libsodium \
|
||||
@ -267,6 +271,105 @@ $(filter-out $(BUILD_DIR)/android% $(BUILD_DIR)/macos% $(BUILD_DIR)/ios%,$(APP_O
|
||||
-fanalyzer
|
||||
endif
|
||||
|
||||
ARES_SOURCES := \
|
||||
deps/c-ares/src/lib/ares_platform.c \
|
||||
deps/c-ares/src/lib/record/ares_dns_mapping.c \
|
||||
deps/c-ares/src/lib/record/ares_dns_parse.c \
|
||||
deps/c-ares/src/lib/record/ares_dns_write.c \
|
||||
deps/c-ares/src/lib/record/ares_dns_name.c \
|
||||
deps/c-ares/src/lib/record/ares_dns_record.c \
|
||||
deps/c-ares/src/lib/record/ares_dns_multistring.c \
|
||||
deps/c-ares/src/lib/ares_destroy.c \
|
||||
deps/c-ares/src/lib/ares_data.c \
|
||||
deps/c-ares/src/lib/ares_sysconfig.c \
|
||||
deps/c-ares/src/lib/ares_cancel.c \
|
||||
deps/c-ares/src/lib/ares_metrics.c \
|
||||
deps/c-ares/src/lib/ares_getnameinfo.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_txt_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_naptr_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_create_query.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_mx_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_srv_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_ptr_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_caa_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_aaaa_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_expand_name.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_uri_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_a_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_expand_string.c \
|
||||
deps/c-ares/src/lib/legacy/ares_fds.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_ns_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_parse_soa_reply.c \
|
||||
deps/c-ares/src/lib/legacy/ares_getsock.c \
|
||||
deps/c-ares/src/lib/windows_port.c \
|
||||
deps/c-ares/src/lib/ares_qcache.c \
|
||||
deps/c-ares/src/lib/ares_update_servers.c \
|
||||
deps/c-ares/src/lib/ares_process.c \
|
||||
deps/c-ares/src/lib/ares_getenv.c \
|
||||
deps/c-ares/src/lib/ares_gethostbyname.c \
|
||||
deps/c-ares/src/lib/ares_send.c \
|
||||
deps/c-ares/src/lib/dsa/ares__slist.c \
|
||||
deps/c-ares/src/lib/dsa/ares__htable.c \
|
||||
deps/c-ares/src/lib/dsa/ares__llist.c \
|
||||
deps/c-ares/src/lib/dsa/ares__htable_szvp.c \
|
||||
deps/c-ares/src/lib/dsa/ares__htable_asvp.c \
|
||||
deps/c-ares/src/lib/dsa/ares__htable_vpvp.c \
|
||||
deps/c-ares/src/lib/dsa/ares__htable_strvp.c \
|
||||
deps/c-ares/src/lib/dsa/ares__array.c \
|
||||
deps/c-ares/src/lib/ares__socket.c \
|
||||
deps/c-ares/src/lib/event/ares_event_poll.c \
|
||||
deps/c-ares/src/lib/event/ares_event_thread.c \
|
||||
deps/c-ares/src/lib/event/ares_event_select.c \
|
||||
deps/c-ares/src/lib/event/ares_event_kqueue.c \
|
||||
deps/c-ares/src/lib/event/ares_event_configchg.c \
|
||||
deps/c-ares/src/lib/event/ares_event_epoll.c \
|
||||
deps/c-ares/src/lib/event/ares_event_wake_pipe.c \
|
||||
deps/c-ares/src/lib/event/ares_event_win32.c \
|
||||
deps/c-ares/src/lib/ares_search.c \
|
||||
deps/c-ares/src/lib/ares__parse_into_addrinfo.c \
|
||||
deps/c-ares/src/lib/ares__hosts_file.c \
|
||||
deps/c-ares/src/lib/ares_getaddrinfo.c \
|
||||
deps/c-ares/src/lib/ares__addrinfo2hostent.c \
|
||||
deps/c-ares/src/lib/ares_freeaddrinfo.c \
|
||||
deps/c-ares/src/lib/ares_strerror.c \
|
||||
deps/c-ares/src/lib/ares_version.c \
|
||||
deps/c-ares/src/lib/ares_gethostbyaddr.c \
|
||||
deps/c-ares/src/lib/ares__addrinfo_localhost.c \
|
||||
deps/c-ares/src/lib/ares_free_hostent.c \
|
||||
deps/c-ares/src/lib/ares__close_sockets.c \
|
||||
deps/c-ares/src/lib/ares_free_string.c \
|
||||
deps/c-ares/src/lib/ares_init.c \
|
||||
deps/c-ares/src/lib/ares_options.c \
|
||||
deps/c-ares/src/lib/str/ares_strcasecmp.c \
|
||||
deps/c-ares/src/lib/str/ares__buf.c \
|
||||
deps/c-ares/src/lib/str/ares_strsplit.c \
|
||||
deps/c-ares/src/lib/str/ares_str.c \
|
||||
deps/c-ares/src/lib/ares_sysconfig_mac.c \
|
||||
deps/c-ares/src/lib/ares__sortaddrinfo.c \
|
||||
deps/c-ares/src/lib/ares_sysconfig_files.c \
|
||||
deps/c-ares/src/lib/util/ares__iface_ips.c \
|
||||
deps/c-ares/src/lib/util/ares__timeval.c \
|
||||
deps/c-ares/src/lib/util/ares_math.c \
|
||||
deps/c-ares/src/lib/util/ares_rand.c \
|
||||
deps/c-ares/src/lib/util/ares__threads.c \
|
||||
deps/c-ares/src/lib/ares_query.c \
|
||||
deps/c-ares/src/lib/ares_cookie.c \
|
||||
deps/c-ares/src/lib/inet_net_pton.c \
|
||||
deps/c-ares/src/lib/inet_ntop.c \
|
||||
deps/c-ares/src/lib/ares_library_init.c \
|
||||
deps/c-ares/src/lib/ares_android.c \
|
||||
deps/c-ares/src/lib/ares_sysconfig_win.c \
|
||||
deps/c-ares/src/lib/ares_timeout.c
|
||||
ARES_OBJS := $(call get_objs,ARES_SOURCES)
|
||||
$(ARES_OBJS): CFLAGS += \
|
||||
-Ideps/c-ares/include \
|
||||
-Ideps/c-ares/src/lib \
|
||||
-Ideps/c-ares_config/ \
|
||||
-D_GNU_SOURCE \
|
||||
-Wno-unused-function \
|
||||
-Wno-deprecated-declarations \
|
||||
-Wno-unused-result
|
||||
|
||||
BLOWFISH_SOURCES := \
|
||||
deps/crypt_blowfish/crypt_blowfish.c \
|
||||
deps/crypt_blowfish/crypt_gensalt.c \
|
||||
@ -398,6 +501,8 @@ $(UV_OBJS): CFLAGS += \
|
||||
-Wno-unused-but-set-variable \
|
||||
-Wno-unused-result \
|
||||
-Wno-unused-variable
|
||||
$(UV_OBJS): CFLAGS += -fno-lto
|
||||
$(filter out/win%,$(UV_OBJS)): CFLAGS += -Wno-cast-function-type
|
||||
ifeq ($(UNAME_S),Linux)
|
||||
$(UV_OBJS): CFLAGS += \
|
||||
-D_GNU_SOURCE
|
||||
@ -473,6 +578,7 @@ ifneq ($(UNAME_S),OpenBSD)
|
||||
$(filter-out $(BUILD_DIR)/win%,$(SODIUM_OBJS)): CFLAGS += \
|
||||
-DHAVE_ALLOCA_H
|
||||
endif
|
||||
$(SODIUM_OBJS): CFLAGS := $(filter-out -flto,$(CFLAGS))
|
||||
|
||||
SQLITE_SOURCES := deps/sqlite/sqlite3.c
|
||||
SQLITE_OBJS := $(call get_objs,SQLITE_SOURCES)
|
||||
@ -632,6 +738,7 @@ all: $(BUILD_TYPES)
|
||||
|
||||
ALL_APP_OBJS := \
|
||||
$(APP_OBJS) \
|
||||
$(ARES_OBJS) \
|
||||
$(BLOWFISH_OBJS) \
|
||||
$(LIBBACKTRACE_OBJS) \
|
||||
$(MINIUNZIP_OBJS) \
|
||||
@ -675,6 +782,15 @@ src/version.h : $(firstword $(MAKEFILE_LIST))
|
||||
@echo "#define VERSION_NUMBER \"$(VERSION_NUMBER)\"" > $@
|
||||
@echo "#define VERSION_NAME \"$(VERSION_NAME)\"" >> $@
|
||||
|
||||
src/android/AndroidManifest.xml : $(firstword $(MAKEFILE_LIST))
|
||||
@echo "[android_version] $@"
|
||||
@sed -i \
|
||||
-e 's/versionCode=".*"/versionCode="$(VERSION_CODE)"/' \
|
||||
-e 's/versionName=".*"/versionName="$(VERSION_NUMBER)"/' \
|
||||
-e 's/android:minSdkVersion="[[:digit:]]*"/android:minSdkVersion="$(ANDROID_MIN_SDK_VERSION)"/' \
|
||||
-e 's/android:targetSdkVersion="[[:digit:]]*"/android:targetSdkVersion="$(ANDROID_TARGET_SDK_VERSION)"/' \
|
||||
$@
|
||||
|
||||
# Android support.
|
||||
out/res/layout_activity_main.xml.flat: src/android/res/layout/activity_main.xml
|
||||
@mkdir -p $(dir $@)
|
||||
@ -690,8 +806,6 @@ out/apk/res.apk out/gen/com/unprompted/tildefriends/R.java: out/res/layout_activ
|
||||
@echo [aapt2 link] res.apk
|
||||
@mkdir -p out/apk/
|
||||
@$(ANDROID_BUILD_TOOLS)/aapt2 link -I $(ANDROID_PLATFORM)/android.jar out/res/layout_activity_main.xml.flat out/res/drawable_icon.xml.flat \
|
||||
--version-code $(VERSION_CODE) \
|
||||
--version-name $(VERSION_NUMBER) \
|
||||
--min-sdk-version $(ANDROID_MIN_SDK_VERSION) \
|
||||
--target-sdk-version $(ANDROID_TARGET_SDK_VERSION) \
|
||||
--manifest src/android/AndroidManifest.xml \
|
||||
@ -702,8 +816,6 @@ out/apk/res.fdroid.apk out/gen_fdroid/com/unprompted/tildefriends/R.java: out/re
|
||||
@echo [aapt2 link] res.fdroid.apk
|
||||
@mkdir -p out/apk/
|
||||
@$(ANDROID_BUILD_TOOLS)/aapt2 link -I $(ANDROID_PLATFORM)/android.jar out/res/layout_activity_main.xml.flat out/res/drawable_icon.xml.flat \
|
||||
--version-code $(VERSION_CODE) \
|
||||
--version-name $(VERSION_NUMBER) \
|
||||
--min-sdk-version $(ANDROID_MIN_SDK_VERSION) \
|
||||
--target-sdk-version $(ANDROID_TARGET_SDK_VERSION) \
|
||||
--rename-manifest-package com.unprompted.tildefriends.fdroid \
|
||||
@ -730,7 +842,7 @@ PACKAGE_DIRS := \
|
||||
deps/prettier/ \
|
||||
deps/lit/
|
||||
|
||||
RAW_FILES := $(filter-out apps/blog% apps/issues% apps/welcome% apps/journal% %.map, $(shell find $(PACKAGE_DIRS) -type f))
|
||||
RAW_FILES := $(sort $(filter-out apps/blog% apps/issues% apps/welcome% apps/journal% %.map, $(shell find $(PACKAGE_DIRS) -type f)))
|
||||
|
||||
out/apk/TildeFriends-arm-debug.unsigned.apk: BUILD_TYPE := debug
|
||||
out/apk/TildeFriends-arm-release.unsigned.apk: BUILD_TYPE := release
|
||||
@ -753,8 +865,6 @@ out/TildeFriends.aab: out/apk/classes.dex $(filter-out %debug%, $(ANDROID_TARGET
|
||||
@mkdir -p out/aab/staging
|
||||
@$(ANDROID_BUILD_TOOLS)/aapt2 link --proto-format -o out/aab/temporary.apk \
|
||||
-I $(ANDROID_PLATFORM)/android.jar \
|
||||
--version-code $(VERSION_CODE) \
|
||||
--version-name $(VERSION_NUMBER) \
|
||||
--min-sdk-version $(ANDROID_MIN_SDK_VERSION) \
|
||||
--target-sdk-version $(ANDROID_TARGET_SDK_VERSION) \
|
||||
--manifest src/android/AndroidManifest.xml \
|
||||
@ -825,6 +935,7 @@ out/apk/TildeFriends-x86-%.unsigned.apk:
|
||||
@$(ANDROID_BUILD_TOOLS)/zipalign -f 4 $@.zip $@
|
||||
|
||||
out/apk/TildeFriends-%.fdroid.unsigned.apk:
|
||||
@rm -rf out/apk-fdroid-$(BUILD_TYPE) out/apk-fdroid-$(BUILD_TYPE)-raw
|
||||
@mkdir -p $(dir $@) out/apk-fdroid-$(BUILD_TYPE)/lib/x86_64/ out/apk-fdroid-$(BUILD_TYPE)/lib/x86/ out/apk-fdroid-$(BUILD_TYPE)/lib/arm64-v8a/ out/apk-fdroid-$(BUILD_TYPE)/lib/armeabi-v7a/
|
||||
@echo "[aapt] $@"
|
||||
@cp out/android$(BUILD_TYPE)-x86_64/tildefriends out/apk-fdroid-$(BUILD_TYPE)/lib/x86_64/libtildefriends.so
|
||||
@ -837,8 +948,12 @@ out/apk/TildeFriends-%.fdroid.unsigned.apk:
|
||||
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-fdroid-$(BUILD_TYPE)/lib/armeabi-v7a/libtildefriends.so
|
||||
@cp out/apk/res.fdroid.apk $@.zip
|
||||
@cp out/apk/classes.dex out/apk-fdroid-$(BUILD_TYPE)/classes.dex
|
||||
@cd out/apk-fdroid-$(BUILD_TYPE) && zip -u ../../$@.zip -q -9 -r . && cd ../../
|
||||
@zip -u $@.zip -q -9 $(RAW_FILES)
|
||||
@touch -d @0 out/apk-fdroid-$(BUILD_TYPE)/classes.dex out/apk-fdroid-$(BUILD_TYPE)/lib/*/libtildefriends.so
|
||||
@chmod 755 out/apk-fdroid-$(BUILD_TYPE)/classes.dex out/apk-fdroid-$(BUILD_TYPE)/lib/*/libtildefriends.so
|
||||
@cd out/apk-fdroid-$(BUILD_TYPE) && zip -X -u ../../$@.zip -q classes.dex lib/*/libtildefriends.so && cd ../../
|
||||
@mkdir out/apk-fdroid-$(BUILD_TYPE)-raw
|
||||
@for i in $(RAW_FILES); do mkdir -p $$(dirname out/apk-fdroid-$(BUILD_TYPE)-raw/$$i) && cp $$i out/apk-fdroid-$(BUILD_TYPE)-raw/$$i && touch -d @0 out/apk-fdroid-$(BUILD_TYPE)-raw/$$i && chmod 644 out/apk-fdroid-$(BUILD_TYPE)-raw/$$i; done
|
||||
@cd out/apk-fdroid-$(BUILD_TYPE)-raw && zip -X -u ../../$@.zip -q $(RAW_FILES) && cd ../../
|
||||
@$(ANDROID_BUILD_TOOLS)/zipalign -f 4 $@.zip $@
|
||||
|
||||
out/%.apk: out/apk/%.unsigned.apk
|
||||
@ -921,10 +1036,6 @@ apklog:
|
||||
.PHONY: apklog
|
||||
|
||||
fetchdeps:
|
||||
@echo "[fetch] libuv"
|
||||
@test -f out/deps/libuv.tar.gz && test "$$(cat out/deps/libuv.txt 2>/dev/null)" = $(LIBUV_URL) || (mkdir -p out/deps/ && curl -q $(LIBUV_URL) -o out/deps/libuv.tar.gz)
|
||||
@test -d deps/libuv/ && test "$$(cat out/deps/libuv.txt 2>/dev/null)" = $(LIBUV_URL) || (rm -rf deps/libuv/ && mkdir -p deps/libuv/ && tar -C deps/libuv/ -m --strip=1 -xf out/deps/libuv.tar.gz)
|
||||
@echo -n $(LIBUV_URL) > out/deps/libuv.txt
|
||||
@echo "[fetch] sqlite"
|
||||
@test -f out/deps/sqlite.zip && test "$$(cat out/deps/sqlite.txt 2>/dev/null)" = $(SQLITE_URL) || (mkdir -p out/deps/ && curl -q $(SQLITE_URL) -o out/deps/sqlite.zip)
|
||||
@test -d deps/sqlite/ && test "$$(cat out/deps/sqlite.txt 2>/dev/null)" = $(SQLITE_URL) || (mkdir -p deps/sqlite/ && unzip -qDjo -d deps/sqlite/ out/deps/sqlite.zip)
|
||||
@ -959,7 +1070,7 @@ clean:
|
||||
rm -rf $(BUILD_DIR)
|
||||
.PHONY: clean
|
||||
|
||||
dist: release-apk iosrelease-ipa aab $(if $(HAVE_WIN), out/winrelease/tildefriends.standalone.exe)
|
||||
dist: release-apk iosrelease-ipa aab $(if $(HAVE_WIN), out/winrelease/tildefriends.standalone.exe) out/TildeFriends-release.fdroid.apk
|
||||
@echo [archive] dist/tildefriends-$(VERSION_NUMBER).tar.xz
|
||||
@rm -rf out/tildefriends-$(VERSION_NUMBER)
|
||||
@mkdir -p dist/ out/tildefriends-$(VERSION_NUMBER)
|
||||
@ -991,6 +1102,7 @@ dist: release-apk iosrelease-ipa aab $(if $(HAVE_WIN), out/winrelease/tildefrien
|
||||
@test $(HAVE_WIN) && echo "[cp] tildefriends-$(VERSION_NUMBER).exe"
|
||||
@test $(HAVE_WIN) && cp out/winrelease/tildefriends.standalone.exe dist/tildefriends-$(VERSION_NUMBER).exe
|
||||
@cp out/TildeFriends.aab dist/TildeFriends-$(VERSION_NUMBER).aab
|
||||
@cp out/TildeFriends-release.fdroid.apk dist/TildeFriends-$(VERSION_NUMBER).fdroid.apk
|
||||
.PHONY: dist
|
||||
|
||||
dist-test: dist
|
||||
@ -1013,4 +1125,4 @@ docs:
|
||||
.PHONY: docs
|
||||
|
||||
fdroid: out/apk/TildeFriends-release.fdroid.unsigned.apk
|
||||
.PHONE: fdroid
|
||||
.PHONY: fdroid
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"type": "tildefriends-app",
|
||||
"emoji": "🎛",
|
||||
"previous": "&vrpS/vE7n588iYv1p8HafDxHB+YDHTrtUbJiu9nGA9I=.sha256"
|
||||
"previous": "&R49FywYF8CXPhoSEydLbSCgvCddeyTiBwGuDU/gqY+M=.sha256"
|
||||
}
|
||||
|
@ -27,23 +27,27 @@ function global_settings_set(key, value) {
|
||||
});
|
||||
}
|
||||
|
||||
function title_case(name) {
|
||||
return name.split('_').map(x => x.charAt(0).toUpperCase() + x.substring(1)).join(' ');
|
||||
}
|
||||
|
||||
window.addEventListener('load', function () {
|
||||
const permission_template = (permission) => html` <code>${permission}</code>`;
|
||||
function input_template(key, description) {
|
||||
if (description.type === 'boolean') {
|
||||
return html`
|
||||
<li class="w3-row">
|
||||
<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold">${key}</label>
|
||||
<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold">${title_case(key)}</label>
|
||||
<div class="w3-quarter w3-padding">${description.description}</div>
|
||||
<input class="w3-quarter w3-check" type="checkbox" ?checked=${description.value} id=${'gs_' + key}></input>
|
||||
<button class="w3-quarter w3-button w3-theme-action" @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.checked)}>Set</button>
|
||||
<div class="w3-quarter w3-padding w3-center"><input class="w3-check" type="checkbox" ?checked=${description.value} id=${'gs_' + key}></input></div>
|
||||
<button class="w3-quarter w3-button w3-theme-action" @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.firstChild.checked)}>Set</button>
|
||||
</li>
|
||||
`;
|
||||
} else if (description.type === 'textarea') {
|
||||
return html`
|
||||
<li class="w3-row">
|
||||
<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold"
|
||||
>${key}</label
|
||||
>${title_case(key)}</label
|
||||
>
|
||||
<div class="w3-rest w3-padding">${description.description}</div>
|
||||
<textarea
|
||||
@ -68,7 +72,7 @@ ${description.value}</textarea
|
||||
} else {
|
||||
return html`
|
||||
<li class="w3-row">
|
||||
<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold">${key}</label>
|
||||
<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold">${title_case(key)}</label>
|
||||
<div class="w3-quarter w3-padding">${description.description}</div>
|
||||
<input class="w3-input w3-quarter" type="text" value="${description.value}" id=${'gs_' + key}></input>
|
||||
<button class="w3-button w3-quarter w3-theme-action" @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.value)}>Set</button>
|
||||
|
44
apps/blog/lit-all.min.js
vendored
44
apps/blog/lit-all.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
44
apps/issues/lit-all.min.js
vendored
44
apps/issues/lit-all.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
44
apps/journal/lit-all.min.js
vendored
44
apps/journal/lit-all.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
44
apps/sneaker/lit-all.min.js
vendored
44
apps/sneaker/lit-all.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,5 +1,5 @@
|
||||
{
|
||||
"type": "tildefriends-app",
|
||||
"emoji": "🐌",
|
||||
"previous": "&2xK//SIpjFb0+uT5I7MSAGJ3d1FKuI/rlzhcCQd3NME=.sha256"
|
||||
"previous": "&xsmsLytB3VvoHphiFHZGGEvrCfTEVGXrGwobGTIYFPQ=.sha256"
|
||||
}
|
||||
|
44
apps/ssb/lit-all.min.js
vendored
44
apps/ssb/lit-all.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -188,6 +188,10 @@ class TfProfileElement extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
copy_id() {
|
||||
navigator.clipboard.writeText(this.id);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (
|
||||
this.id == this.whoami &&
|
||||
@ -287,6 +291,14 @@ class TfProfileElement extends LitElement {
|
||||
let description = this.editing?.description ?? profile.description;
|
||||
return html`<div style="border: 2px solid black; background-color: rgba(255, 255, 255, 0.2); padding: 16px">
|
||||
<tf-user id=${this.id} .users=${this.users}></tf-user> (${tfutils.human_readable_size(this.size)})
|
||||
<div class="w3-row">
|
||||
<div class="w3-col s1 w3-container w3-right">
|
||||
<button class="w3-button w3-theme-d1 w3-ripple" @click=${this.copy_id}>Copy</button>
|
||||
</div>
|
||||
<div class="w3-rest w3-container">
|
||||
<input type="text" class="w3-theme-d1" style="width: 100%; vertical-align: middle" readonly value=${this.id}></input>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: row; gap: 1em">
|
||||
${edit_profile}
|
||||
<div style="flex: 1 0 50%">
|
||||
|
@ -17,6 +17,12 @@ class TfTabConnectionsElement extends LitElement {
|
||||
|
||||
static styles = styles;
|
||||
|
||||
static k_broadcast_emojis = {
|
||||
discovery: '🏓',
|
||||
room: '🚪',
|
||||
peer_exchange: '🕸',
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
let self = this;
|
||||
@ -92,6 +98,7 @@ class TfTabConnectionsElement extends LitElement {
|
||||
Connect
|
||||
</button>
|
||||
<div class="w3-bar-item">
|
||||
${TfTabConnectionsElement.k_broadcast_emojis[connection.origin]}
|
||||
<tf-user id=${connection.pubkey} .users=${this.users}></tf-user>
|
||||
${this.render_connection_summary(connection)}
|
||||
</div>
|
||||
|
44
apps/wiki/lit-all.min.js
vendored
44
apps/wiki/lit-all.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
26
core/core.js
26
core/core.js
@ -23,13 +23,18 @@ const k_global_settings = {
|
||||
room: {
|
||||
type: 'boolean',
|
||||
default_value: true,
|
||||
description: 'Whether this instance should behave as a room.',
|
||||
description: 'Enable peers to tunnel through this instance as a room.',
|
||||
},
|
||||
room_name: {
|
||||
type: 'string',
|
||||
default_value: 'tilde friends tunnel',
|
||||
description: 'Name of the room.',
|
||||
},
|
||||
replicator: {
|
||||
type: 'boolean',
|
||||
default_value: true,
|
||||
description: 'Enable message and blob replication.',
|
||||
},
|
||||
code_of_conduct: {
|
||||
type: 'textarea',
|
||||
default_value: undefined,
|
||||
@ -64,6 +69,21 @@ const k_global_settings = {
|
||||
: undefined,
|
||||
description: 'Blobs older than this will be automatically deleted.',
|
||||
},
|
||||
seeds_host: {
|
||||
type: 'string',
|
||||
default_value: 'seeds.tildefriends.net',
|
||||
description: 'Hostname for seed connections.',
|
||||
},
|
||||
peer_exchange: {
|
||||
type: 'boolean',
|
||||
default_value: false,
|
||||
description: 'Enable discovery of, sharing of, and connecting to internet peer strangers, including announcing this instance.',
|
||||
},
|
||||
account_registration: {
|
||||
type: 'boolean',
|
||||
default_value: true,
|
||||
description: 'Allow registration of new accounts.',
|
||||
},
|
||||
};
|
||||
|
||||
let gGlobalSettings = {
|
||||
@ -500,8 +520,9 @@ async function getProcessBlob(blobId, key, options) {
|
||||
imports.core.globalSettingsGet = function (key) {
|
||||
return gGlobalSettings[key];
|
||||
};
|
||||
imports.core.globalSettingsSet = function (key, value) {
|
||||
imports.core.globalSettingsSet = async function (key, value) {
|
||||
print('Setting', key, value);
|
||||
await loadSettings();
|
||||
gGlobalSettings[key] = value;
|
||||
setGlobalSettings(gGlobalSettings);
|
||||
print('Done.');
|
||||
@ -1331,7 +1352,6 @@ function storePermission(user, packageOwner, packageName, permission, allow) {
|
||||
|
||||
export {
|
||||
gGlobalSettings as globalSettings,
|
||||
setGlobalSettings,
|
||||
invoke,
|
||||
getSessionProcessBlob,
|
||||
};
|
||||
|
@ -21,14 +21,14 @@
|
||||
}:
|
||||
pkgs.stdenv.mkDerivation rec {
|
||||
pname = "tildefriends";
|
||||
version = "0.0.21";
|
||||
version = "0.0.22";
|
||||
|
||||
src = pkgs.fetchFromGitea {
|
||||
domain = "dev.tildefriends.net";
|
||||
owner = "cory";
|
||||
repo = "tildefriends";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-cBj9Hz0qT0Tqm7ivM8HPG9TNwC9iv0lTcE8XCNba8F4=";
|
||||
hash = "sha256-0x4LJXtMUxBsWEOoWAaQlStTfvqUf4Qs/5vJZ2EvBpY=";
|
||||
fetchSubmodules = true;
|
||||
};
|
||||
|
||||
|
1
deps/c-ares
vendored
Submodule
1
deps/c-ares
vendored
Submodule
Submodule deps/c-ares added at caffa5ffb3
177
deps/c-ares_config/ares_build.h
vendored
Normal file
177
deps/c-ares_config/ares_build.h
vendored
Normal file
@ -0,0 +1,177 @@
|
||||
#ifndef __CARES_BUILD_H
|
||||
#define __CARES_BUILD_H
|
||||
/*
|
||||
* Copyright (C) The c-ares project and its contributors
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define CARES_STATICLIB
|
||||
|
||||
#ifdef CARES_HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
|
||||
#ifdef CARES_HAVE_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#ifdef CARES_HAVE_SYS_SELECT_H
|
||||
# include <sys/select.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
#undef HAVE_REGISTERWAITFORSINGLEOBJECT
|
||||
#define CARES_HAVE_WINSOCK2_H
|
||||
#define CARES_HAVE_WINDOWS_H
|
||||
#define CARES_HAVE_WS2TCPIP_H
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
#define CARES_TYPEOF_ARES_SOCKLEN_T int
|
||||
#define CARES_TYPEOF_ARES_SSIZE_T ssize_t
|
||||
#else
|
||||
#define CARES_TYPEOF_ARES_SOCKLEN_T socklen_t
|
||||
#define CARES_TYPEOF_ARES_SSIZE_T ssize_t
|
||||
#endif
|
||||
|
||||
#if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(_WIN32) && !defined(__OpenBSD__) && !defined(__HAIKU__)
|
||||
#define GETSERVBYNAME_R_ARGS 6
|
||||
#define GETSERVBYPORT_R_ARGS 6
|
||||
#define HAVE_GETSERVBYNAME_R 1
|
||||
#define HAVE_GETSERVBYPORT_R 1
|
||||
#endif
|
||||
|
||||
#if !defined(__APPLE__) && !defined(_WIN32) && !defined(__OpenBSD__) && !defined(__HAIKU__)
|
||||
#define HAVE_PIPE2 1
|
||||
#endif
|
||||
|
||||
#if defined(__OpenBSD__) || defined(__HAIKU__)
|
||||
#define GETSERVBYNAME_R_ARGS 4
|
||||
#define GETSERVBYPORT_R_ARGS 4
|
||||
#endif
|
||||
|
||||
#if !defined(__APPLE__) && !defined(_WIN32) && !defined(__OpenBSD__) && !defined(__HAIKU__)
|
||||
#define HAVE_MALLOC_H 1
|
||||
#define HAVE_EPOLL 1
|
||||
#define HAVE_SYS_EPOLL_H 1
|
||||
#define HAVE_SYS_RANDOM_H 1
|
||||
#endif
|
||||
|
||||
#if !defined(__WIN32)
|
||||
#undef AC_APPLE_UNIVERSAL_BUILD
|
||||
#undef ETC_INET
|
||||
#define GETHOSTNAME_TYPE_ARG2 size_t
|
||||
#define GETNAMEINFO_QUAL_ARG1
|
||||
#define GETNAMEINFO_TYPE_ARG1 struct sockaddr *
|
||||
#define GETNAMEINFO_TYPE_ARG2 socklen_t
|
||||
#define GETNAMEINFO_TYPE_ARG46 socklen_t
|
||||
#define GETNAMEINFO_TYPE_ARG7 int
|
||||
#define HAVE_AF_INET6 1
|
||||
#define HAVE_ARPA_INET_H 1
|
||||
#define HAVE_ARPA_NAMESER_COMPAT_H 1
|
||||
#define HAVE_ARPA_NAMESER_H 1
|
||||
#define HAVE_ASSERT_H 1
|
||||
#define HAVE_CLOCK_GETTIME_MONOTONIC 1
|
||||
#define HAVE_CONNECT 1
|
||||
#define HAVE_DLFCN_H 1
|
||||
#define HAVE_ERRNO_H 1
|
||||
#define HAVE_POLL_H 1
|
||||
#define HAVE_POLL 1
|
||||
#define HAVE_PIPE 1
|
||||
#define HAVE_FCNTL 1
|
||||
#define HAVE_FCNTL_H 1
|
||||
#define HAVE_FCNTL_O_NONBLOCK 1
|
||||
#define HAVE_FREEADDRINFO 1
|
||||
#define HAVE_GETADDRINFO 1
|
||||
#define HAVE_GETENV 1
|
||||
#define HAVE_GETHOSTNAME 1
|
||||
#define HAVE_GETNAMEINFO 1
|
||||
#if !defined(__HAIKU__)
|
||||
#define HAVE_GETRANDOM 1
|
||||
#endif
|
||||
#define HAVE_GETTIMEOFDAY 1
|
||||
#define HAVE_IF_INDEXTONAME 1
|
||||
#define HAVE_IF_NAMETOINDEX 1
|
||||
#define HAVE_INET_NTOP 1
|
||||
#define HAVE_INET_PTON 1
|
||||
#define HAVE_INTTYPES_H 1
|
||||
#define HAVE_IOCTL 1
|
||||
#define HAVE_IOCTL_FIONBIO 1
|
||||
#define HAVE_IOCTL_SIOCGIFADDR 1
|
||||
#define HAVE_LIMITS_H 1
|
||||
#define HAVE_LONGLONG 1
|
||||
#define HAVE_MEMORY_H 1
|
||||
#define HAVE_MSG_NOSIGNAL 1
|
||||
#define HAVE_NETDB_H 1
|
||||
#define HAVE_NETINET_IN_H 1
|
||||
#define HAVE_NETINET_TCP_H 1
|
||||
#define HAVE_NET_IF_H 1
|
||||
#define HAVE_PF_INET6 1
|
||||
#define HAVE_RECV 1
|
||||
#define HAVE_RECVFROM 1
|
||||
#define HAVE_SEND 1
|
||||
#define HAVE_SETSOCKOPT 1
|
||||
#define HAVE_SIGNAL_H 1
|
||||
#define HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 1
|
||||
#define HAVE_SOCKET 1
|
||||
#define HAVE_STDBOOL_H 1
|
||||
#define HAVE_STDINT_H 1
|
||||
#define HAVE_STDLIB_H 1
|
||||
#define HAVE_STRCASECMP 1
|
||||
#define HAVE_STRDUP 1
|
||||
#define HAVE_STRINGS_H 1
|
||||
#define HAVE_STRING_H 1
|
||||
#define HAVE_STRNCASECMP 1
|
||||
#define HAVE_STRUCT_ADDRINFO 1
|
||||
#define HAVE_STRUCT_IN6_ADDR 1
|
||||
#define HAVE_STRUCT_SOCKADDR_IN6 1
|
||||
#define HAVE_STRUCT_SOCKADDR_STORAGE 1
|
||||
#define HAVE_STRUCT_TIMEVAL 1
|
||||
#define HAVE_SYS_IOCTL_H 1
|
||||
#define HAVE_SYS_PARAM_H 1
|
||||
#define HAVE_SYS_SELECT_H 1
|
||||
#define HAVE_SYS_SOCKET_H 1
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
#define HAVE_SYS_TIME_H 1
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
#define HAVE_SYS_UIO_H 1
|
||||
#define HAVE_TIME_H 1
|
||||
#define HAVE_IFADDRS_H 1
|
||||
#define HAVE_UNISTD_H 1
|
||||
#define HAVE_WRITEV 1
|
||||
#if defined(__ANDROID__) || defined(__APPLE__) || defined(__OpenBSD__)
|
||||
#define HAVE_ARC4RANDOM_BUF 1
|
||||
#else
|
||||
#undef HAVE_ARC4RANDOM_BUF
|
||||
#endif
|
||||
#define HAVE_GETIFADDRS 1
|
||||
#define HAVE_STAT 1
|
||||
#define CARES_RANDOM_FILE "/dev/urandom"
|
||||
#define RECVFROM_QUAL_ARG5
|
||||
#define RECVFROM_TYPE_ARG1 int
|
||||
#define RECVFROM_TYPE_ARG2 void *
|
||||
#define RECVFROM_TYPE_ARG2_IS_VOID 0
|
||||
#define RECVFROM_TYPE_ARG3 size_t
|
||||
#define RECVFROM_TYPE_ARG4 int
|
||||
#define RECVFROM_TYPE_ARG5 struct sockaddr *
|
||||
#define RECVFROM_TYPE_ARG5_IS_VOID 0
|
||||
#define RECVFROM_TYPE_ARG6 socklen_t *
|
||||
#define RECVFROM_TYPE_ARG6_IS_VOID 0
|
||||
#define RECVFROM_TYPE_RETV ssize_t
|
||||
#define RECV_TYPE_ARG1 int
|
||||
#define RECV_TYPE_ARG2 void *
|
||||
#define RECV_TYPE_ARG3 size_t
|
||||
#define RECV_TYPE_ARG4 int
|
||||
#define RECV_TYPE_RETV ssize_t
|
||||
#define SEND_TYPE_ARG1 int
|
||||
#define SEND_TYPE_ARG2 const void *
|
||||
#define SEND_TYPE_ARG3 size_t
|
||||
#define SEND_TYPE_ARG4 int
|
||||
#define SEND_TYPE_RETV ssize_t
|
||||
#undef USE_BLOCKING_SOCKETS
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#define HAVE_PTHREAD_H 1
|
||||
#define CARES_THREADS 1
|
||||
#endif
|
||||
|
||||
#endif /* __CARES_BUILD_H */
|
2
deps/codemirror/cm6.js
vendored
2
deps/codemirror/cm6.js
vendored
File diff suppressed because one or more lines are too long
268
deps/codemirror_src/package-lock.json
generated
vendored
268
deps/codemirror_src/package-lock.json
generated
vendored
@ -19,9 +19,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/autocomplete": {
|
||||
"version": "6.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.17.0.tgz",
|
||||
"integrity": "sha512-fdfj6e6ZxZf8yrkMHUSJJir7OJkHkZKaOZGzLWIYp2PZ3jd+d+UjG8zVPqJF6d3bKxkhvXTPan/UZ1t7Bqm0gA==",
|
||||
"version": "6.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.0.tgz",
|
||||
"integrity": "sha512-5DbOvBbY4qW5l57cjDsmmpDh3/TeK1vXfTHa+BUMrRzdWdcxKZ4U4V7vQaTtOpApNU4kLS4FQ6cINtLg245LXA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
@ -39,6 +40,7 @@
|
||||
"version": "6.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.6.0.tgz",
|
||||
"integrity": "sha512-qnY+b7j1UNcTS31Eenuc/5YJB6gQOzkUoNmJQc0rznwqSRpeaWWpjkWy2C/MPTcePpsKJEM26hXrOXl1+nceXg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.4.0",
|
||||
@ -50,6 +52,7 @@
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.2.1.tgz",
|
||||
"integrity": "sha512-/UNWDNV5Viwi/1lpr/dIXJNWiwDxpw13I4pTUAsNxZdg6E0mI2kTQb0P2iHczg1Tu+H4EBgJR+hYhKiHKko7qg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.0.0",
|
||||
@ -62,6 +65,7 @@
|
||||
"version": "6.4.9",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.9.tgz",
|
||||
"integrity": "sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/lang-css": "^6.0.0",
|
||||
@ -78,6 +82,7 @@
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.2.tgz",
|
||||
"integrity": "sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.6.0",
|
||||
@ -92,6 +97,7 @@
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.1.tgz",
|
||||
"integrity": "sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@lezer/json": "^1.0.0"
|
||||
@ -101,6 +107,7 @@
|
||||
"version": "6.10.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.2.tgz",
|
||||
"integrity": "sha512-kgbTYTo0Au6dCSc/TFy7fK3fpJmgHDv1sG1KNQKJXVi+xBTEeBPY/M30YXiU6mMXeH+YIDLsbrT4ZwNRdtF+SA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.23.0",
|
||||
@ -114,6 +121,7 @@
|
||||
"version": "6.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.1.tgz",
|
||||
"integrity": "sha512-IZ0Y7S4/bpaunwggW2jYqwLuHj0QtESf5xcROewY6+lDNwZ/NzvR4t+vpYgg9m7V8UXLPYqG+lu3DF470E5Oxg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0",
|
||||
@ -124,6 +132,7 @@
|
||||
"version": "6.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz",
|
||||
"integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0",
|
||||
@ -133,12 +142,14 @@
|
||||
"node_modules/@codemirror/state": {
|
||||
"version": "6.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz",
|
||||
"integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A=="
|
||||
"integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@codemirror/theme-one-dark": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz",
|
||||
"integrity": "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
@ -147,9 +158,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/view": {
|
||||
"version": "6.29.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.29.1.tgz",
|
||||
"integrity": "sha512-7r+DlO/QFwPqKp73uq5mmrS4TuLPUVotbNOKYzN3OLP5ScrOVXcm4g13/48b6ZXGhdmzMinzFYqH0vo+qihIkQ==",
|
||||
"version": "6.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.33.0.tgz",
|
||||
"integrity": "sha512-AroaR3BvnjRW8fiZBalAaK+ZzB5usGgI014YKElYZvQdNH5ZIidHlO+cyf/2rWzyBFRkvG6VhiXeAEbC53P2YQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.4.0",
|
||||
"style-mod": "^4.1.0",
|
||||
@ -161,6 +173,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
|
||||
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/set-array": "^1.2.1",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||
@ -175,6 +188,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
@ -184,6 +198,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
|
||||
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
@ -193,6 +208,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
|
||||
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/gen-mapping": "^0.3.5",
|
||||
"@jridgewell/trace-mapping": "^0.3.25"
|
||||
@ -202,13 +218,15 @@
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
||||
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.25",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
|
||||
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.1.0",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
@ -217,12 +235,14 @@
|
||||
"node_modules/@lezer/common": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz",
|
||||
"integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ=="
|
||||
"integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@lezer/css": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.8.tgz",
|
||||
"integrity": "sha512-7JhxupKuMBaWQKjQoLtzhGj83DdnZY9MckEOG5+/iLKNK2ZJqKc6hf6uc0HjwCX7Qlok44jBNqZhHKDhEhZYLA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
@ -230,9 +250,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/highlight": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz",
|
||||
"integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==",
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz",
|
||||
"integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
@ -241,6 +262,7 @@
|
||||
"version": "1.3.10",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.10.tgz",
|
||||
"integrity": "sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
@ -251,6 +273,7 @@
|
||||
"version": "1.4.17",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.17.tgz",
|
||||
"integrity": "sha512-bYW4ctpyGK+JMumDApeUzuIezX01H76R1foD6LcRX224FWfyYit/HYxiPGDjXXe/wQWASjCvVGoukTH68+0HIA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.1.3",
|
||||
@ -261,6 +284,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.2.tgz",
|
||||
"integrity": "sha512-xHT2P4S5eeCYECyKNPhr4cbEL9tc8w83SPwRC373o9uEdrvGKTZoJVAGxpOsZckMlEh9W23Pc72ew918RWQOBQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
@ -271,6 +295,7 @@
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz",
|
||||
"integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
@ -279,6 +304,7 @@
|
||||
"version": "15.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz",
|
||||
"integrity": "sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@rollup/pluginutils": "^5.0.1",
|
||||
"@types/resolve": "1.20.2",
|
||||
@ -304,6 +330,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz",
|
||||
"integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"serialize-javascript": "^6.0.1",
|
||||
"smob": "^1.0.0",
|
||||
@ -325,6 +352,7 @@
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz",
|
||||
"integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
@ -343,192 +371,208 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.1.tgz",
|
||||
"integrity": "sha512-XzqSg714++M+FXhHfXpS1tDnNZNpgxxuGZWlRG/jSj+VEPmZ0yg6jV4E0AL3uyBKxO8mO3xtOsP5mQ+XLfrlww==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.0.tgz",
|
||||
"integrity": "sha512-WTWD8PfoSAJ+qL87lE7votj3syLavxunWhzCnx3XFxFiI/BA/r3X7MUM8dVrH8rb2r4AiO8jJsr3ZjdaftmnfA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.1.tgz",
|
||||
"integrity": "sha512-thFUbkHteM20BGShD6P08aungq4irbIZKUNbG70LN8RkO7YztcGPiKTTGZS7Kw+x5h8hOXs0i4OaHwFxlpQN6A==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.0.tgz",
|
||||
"integrity": "sha512-a1sR2zSK1B4eYkiZu17ZUZhmUQcKjk2/j9Me2IDjk1GHW7LB5Z35LEzj9iJch6gtUfsnvZs1ZNyDW2oZSThrkA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.1.tgz",
|
||||
"integrity": "sha512-8o6eqeFZzVLia2hKPUZk4jdE3zW7LCcZr+MD18tXkgBBid3lssGVAYuox8x6YHoEPDdDa9ixTaStcmx88lio5Q==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.0.tgz",
|
||||
"integrity": "sha512-zOnKWLgDld/svhKO5PD9ozmL6roy5OQ5T4ThvdYZLpiOhEGY+dp2NwUmxK0Ld91LrbjrvtNAE0ERBwjqhZTRAA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.1.tgz",
|
||||
"integrity": "sha512-4T42heKsnbjkn7ovYiAdDVRRWZLU9Kmhdt6HafZxFcUdpjlBlxj4wDrt1yFWLk7G4+E+8p2C9tcmSu0KA6auGA==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.0.tgz",
|
||||
"integrity": "sha512-7doS8br0xAkg48SKE2QNtMSFPFUlRdw9+votl27MvT46vo44ATBmdZdGysOevNELmZlfd+NEa0UYOA8f01WSrg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.1.tgz",
|
||||
"integrity": "sha512-MXg1xp+e5GhZ3Vit1gGEyoC+dyQUBy2JgVQ+3hUrD9wZMkUw/ywgkpK7oZgnB6kPpGrxJ41clkPPnsknuD6M2Q==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.0.tgz",
|
||||
"integrity": "sha512-pWJsfQjNWNGsoCq53KjMtwdJDmh/6NubwQcz52aEwLEuvx08bzcy6tOUuawAOncPnxz/3siRtd8hiQ32G1y8VA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.1.tgz",
|
||||
"integrity": "sha512-DZNLwIY4ftPSRVkJEaxYkq7u2zel7aah57HESuNkUnz+3bZHxwkCUkrfS2IWC1sxK6F2QNIR0Qr/YXw7nkF3Pw==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.0.tgz",
|
||||
"integrity": "sha512-efRIANsz3UHZrnZXuEvxS9LoCOWMGD1rweciD6uJQIx2myN3a8Im1FafZBzh7zk1RJ6oKcR16dU3UPldaKd83w==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.1.tgz",
|
||||
"integrity": "sha512-C7evongnjyxdngSDRRSQv5GvyfISizgtk9RM+z2biV5kY6S/NF/wta7K+DanmktC5DkuaJQgoKGf7KUDmA7RUw==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.0.tgz",
|
||||
"integrity": "sha512-ZrPhydkTVhyeGTW94WJ8pnl1uroqVHM3j3hjdquwAcWnmivjAwOYjTEAuEDeJvGX7xv3Z9GAvrBkEzCgHq9U1w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.1.tgz",
|
||||
"integrity": "sha512-89tFWqxfxLLHkAthAcrTs9etAoBFRduNfWdl2xUs/yLV+7XDrJ5yuXMHptNqf1Zw0UCA3cAutkAiAokYCkaPtw==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.0.tgz",
|
||||
"integrity": "sha512-cfaupqd+UEFeURmqNP2eEvXqgbSox/LHOyN9/d2pSdV8xTrjdg3NgOFJCtc1vQ/jEke1qD0IejbBfxleBPHnPw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.1.tgz",
|
||||
"integrity": "sha512-PromGeV50sq+YfaisG8W3fd+Cl6mnOOiNv2qKKqKCpiiEke2KiKVyDqG/Mb9GWKbYMHj5a01fq/qlUR28PFhCQ==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.0.tgz",
|
||||
"integrity": "sha512-ZKPan1/RvAhrUylwBXC9t7B2hXdpb/ufeu22pG2psV7RN8roOfGurEghw1ySmX/CmDDHNTDDjY3lo9hRlgtaHg==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.1.tgz",
|
||||
"integrity": "sha512-/1BmHYh+iz0cNCP0oHCuF8CSiNj0JOGf0jRlSo3L/FAyZyG2rGBuKpkZVH9YF+x58r1jgWxvm1aRg3DHrLDt6A==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.0.tgz",
|
||||
"integrity": "sha512-H1eRaCwd5E8eS8leiS+o/NqMdljkcb1d6r2h4fKSsCXQilLKArq6WS7XBLDu80Yz+nMqHVFDquwcVrQmGr28rg==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.1.tgz",
|
||||
"integrity": "sha512-0cYP5rGkQWRZKy9/HtsWVStLXzCF3cCBTRI+qRL8Z+wkYlqN7zrSYm6FuY5Kd5ysS5aH0q5lVgb/WbG4jqXN1Q==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.0.tgz",
|
||||
"integrity": "sha512-zJ4hA+3b5tu8u7L58CCSI0A9N1vkfwPhWd/puGXwtZlsB5bTkwDNW/+JCU84+3QYmKpLi+XvHdmrlwUwDA6kqw==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.1.tgz",
|
||||
"integrity": "sha512-XUXeI9eM8rMP8aGvii/aOOiMvTs7xlCosq9xCjcqI9+5hBxtjDpD+7Abm1ZhVIFE1J2h2VIg0t2DX/gjespC2Q==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.0.tgz",
|
||||
"integrity": "sha512-e2hrvElFIh6kW/UNBQK/kzqMNY5mO+67YtEh9OA65RM5IJXYTWiXjX6fjIiPaqOkBthYF1EqgiZ6OXKcQsM0hg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.1.tgz",
|
||||
"integrity": "sha512-V7cBw/cKXMfEVhpSvVZhC+iGifD6U1zJ4tbibjjN+Xi3blSXaj/rJynAkCFFQfoG6VZrAiP7uGVzL440Q6Me2Q==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.0.tgz",
|
||||
"integrity": "sha512-1vvmgDdUSebVGXWX2lIcgRebqfQSff0hMEkLJyakQ9JQUbLDkEaMsPTLOmyccyC6IJ/l3FZuJbmrBw/u0A0uCQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.1.tgz",
|
||||
"integrity": "sha512-88brja2vldW/76jWATlBqHEoGjJLRnP0WOEKAUbMcXaAZnemNhlAHSyj4jIwMoP2T750LE9lblvD4e2jXleZsA==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.0.tgz",
|
||||
"integrity": "sha512-s5oFkZ/hFcrlAyBTONFY1TWndfyre1wOMwU+6KCpm/iatybvrRgmZVM+vCFwxmC5ZhdlgfE0N4XorsDpi7/4XQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.1.tgz",
|
||||
"integrity": "sha512-LdxxcqRVSXi6k6JUrTah1rHuaupoeuiv38du8Mt4r4IPer3kwlTo+RuvfE8KzZ/tL6BhaPlzJ3835i6CxrFIRQ==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.0.tgz",
|
||||
"integrity": "sha512-G9+TEqRnAA6nbpqyUqgTiopmnfgnMkR3kMukFBDsiyy23LZvUCpiUwjTRx6ezYCjJODXrh52rBR9oXvm+Fp5wg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.1.tgz",
|
||||
"integrity": "sha512-2bIrL28PcK3YCqD9anGxDxamxdiJAxA+l7fWIwM5o8UqNy1t3d1NdAweO2XhA0KTDJ5aH1FsuiT5+7VhtHliXg==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.0.tgz",
|
||||
"integrity": "sha512-2jsCDZwtQvRhejHLfZ1JY6w6kEuEtfF9nzYsZxzSlNVKDX+DpsDJ+Rbjkm74nvg2rdx0gwBS+IMdvwJuq3S9pQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
@ -537,18 +581,21 @@
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
|
||||
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
|
||||
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/resolve": {
|
||||
"version": "1.20.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
|
||||
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="
|
||||
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.12.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
|
||||
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@ -560,12 +607,14 @@
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/builtin-modules": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
|
||||
"integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
@ -577,6 +626,7 @@
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz",
|
||||
"integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/commands": "^6.0.0",
|
||||
@ -591,17 +641,20 @@
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/crelt": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
|
||||
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="
|
||||
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/deepmerge": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@ -609,13 +662,15 @@
|
||||
"node_modules/estree-walker": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
@ -628,6 +683,7 @@
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
@ -636,6 +692,7 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
@ -647,6 +704,7 @@
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz",
|
||||
"integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"builtin-modules": "^3.3.0"
|
||||
},
|
||||
@ -658,9 +716,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/is-core-module": {
|
||||
"version": "2.15.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz",
|
||||
"integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==",
|
||||
"version": "2.15.1",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
|
||||
"integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"hasown": "^2.0.2"
|
||||
},
|
||||
@ -674,17 +733,20 @@
|
||||
"node_modules/is-module": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
|
||||
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g=="
|
||||
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
@ -697,6 +759,7 @@
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
@ -705,6 +768,7 @@
|
||||
"version": "1.22.8",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
|
||||
"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-core-module": "^2.13.0",
|
||||
"path-parse": "^1.0.7",
|
||||
@ -718,9 +782,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.19.1.tgz",
|
||||
"integrity": "sha512-K5vziVlg7hTpYfFBI+91zHBEMo6jafYXpkMlqZjg7/zhIG9iHqazBf4xz9AVdjS9BruRn280ROqLI7G3OFRIlw==",
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.0.tgz",
|
||||
"integrity": "sha512-vo+S/lfA2lMS7rZ2Qoubi6I5hwZwzXeUIctILZLbHI+laNtvhhOIon2S1JksA5UEDQ7l3vberd0fxK44lTYjbQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.5"
|
||||
},
|
||||
@ -732,22 +797,22 @@
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.19.1",
|
||||
"@rollup/rollup-android-arm64": "4.19.1",
|
||||
"@rollup/rollup-darwin-arm64": "4.19.1",
|
||||
"@rollup/rollup-darwin-x64": "4.19.1",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.19.1",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.19.1",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.19.1",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.19.1",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.19.1",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.19.1",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.19.1",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.19.1",
|
||||
"@rollup/rollup-linux-x64-musl": "4.19.1",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.19.1",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.19.1",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.19.1",
|
||||
"@rollup/rollup-android-arm-eabi": "4.21.0",
|
||||
"@rollup/rollup-android-arm64": "4.21.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.21.0",
|
||||
"@rollup/rollup-darwin-x64": "4.21.0",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.21.0",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.21.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.21.0",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.21.0",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.21.0",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.21.0",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.21.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.21.0",
|
||||
"@rollup/rollup-linux-x64-musl": "4.21.0",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.21.0",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.21.0",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.21.0",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
@ -769,13 +834,15 @@
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
]
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/serialize-javascript": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
|
||||
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
@ -784,13 +851,15 @@
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz",
|
||||
"integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@ -800,6 +869,7 @@
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"source-map": "^0.6.0"
|
||||
@ -808,12 +878,14 @@
|
||||
"node_modules/style-mod": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz",
|
||||
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw=="
|
||||
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/supports-preserve-symlinks-flag": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
@ -822,10 +894,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.31.3",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.31.3.tgz",
|
||||
"integrity": "sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==",
|
||||
"version": "5.31.6",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.31.6.tgz",
|
||||
"integrity": "sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@jridgewell/source-map": "^0.3.3",
|
||||
"acorn": "^8.8.2",
|
||||
@ -842,7 +915,8 @@
|
||||
"node_modules/w3c-keyname": {
|
||||
"version": "2.2.8",
|
||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
|
||||
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="
|
||||
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2
deps/libbacktrace
vendored
2
deps/libbacktrace
vendored
Submodule deps/libbacktrace updated: 7e2b7da3d6...86885d1404
2
deps/libsodium
vendored
2
deps/libsodium
vendored
Submodule deps/libsodium updated: 9511c982fb...0217d07326
44
deps/lit/lit-all.min.js
vendored
44
deps/lit/lit-all.min.js
vendored
File diff suppressed because one or more lines are too long
2
deps/lit/lit-all.min.js.map
vendored
2
deps/lit/lit-all.min.js.map
vendored
File diff suppressed because one or more lines are too long
40
deps/sqlite/shell.c
vendored
40
deps/sqlite/shell.c
vendored
@ -604,11 +604,6 @@ zSkipValidUtf8(const char *z, int nAccept, long ccm);
|
||||
# define CIO_WIN_WC_XLATE 0 /* Not exposing translation routines at all */
|
||||
#endif
|
||||
|
||||
#if CIO_WIN_WC_XLATE
|
||||
/* Character used to represent a known-incomplete UTF-8 char group (<28>) */
|
||||
static WCHAR cBadGroup = 0xfffd;
|
||||
#endif
|
||||
|
||||
#if CIO_WIN_WC_XLATE
|
||||
static HANDLE handleOfFile(FILE *pf){
|
||||
int fileDesc = _fileno(pf);
|
||||
@ -12547,7 +12542,7 @@ static int expertFilter(
|
||||
pCsr->pData = 0;
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = idxPrintfPrepareStmt(pExpert->db, &pCsr->pData, &pVtab->base.zErrMsg,
|
||||
"SELECT * FROM main.%Q WHERE sample()", pVtab->pTab->zName
|
||||
"SELECT * FROM main.%Q WHERE sqlite_expert_sample()", pVtab->pTab->zName
|
||||
);
|
||||
}
|
||||
|
||||
@ -13421,7 +13416,7 @@ struct IdxRemCtx {
|
||||
};
|
||||
|
||||
/*
|
||||
** Implementation of scalar function rem().
|
||||
** Implementation of scalar function sqlite_expert_rem().
|
||||
*/
|
||||
static void idxRemFunc(
|
||||
sqlite3_context *pCtx,
|
||||
@ -13434,7 +13429,7 @@ static void idxRemFunc(
|
||||
assert( argc==2 );
|
||||
|
||||
iSlot = sqlite3_value_int(argv[0]);
|
||||
assert( iSlot<=p->nSlot );
|
||||
assert( iSlot<p->nSlot );
|
||||
pSlot = &p->aSlot[iSlot];
|
||||
|
||||
switch( pSlot->eType ){
|
||||
@ -13545,7 +13540,8 @@ static int idxPopulateOneStat1(
|
||||
const char *zName = (const char*)sqlite3_column_text(pIndexXInfo, 0);
|
||||
const char *zColl = (const char*)sqlite3_column_text(pIndexXInfo, 1);
|
||||
zCols = idxAppendText(&rc, zCols,
|
||||
"%sx.%Q IS rem(%d, x.%Q) COLLATE %s", zComma, zName, nCol, zName, zColl
|
||||
"%sx.%Q IS sqlite_expert_rem(%d, x.%Q) COLLATE %s",
|
||||
zComma, zName, nCol, zName, zColl
|
||||
);
|
||||
zOrder = idxAppendText(&rc, zOrder, "%s%d", zComma, ++nCol);
|
||||
}
|
||||
@ -13678,13 +13674,13 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3 *dbrem = (p->iSample==100 ? p->db : p->dbv);
|
||||
rc = sqlite3_create_function(
|
||||
dbrem, "rem", 2, SQLITE_UTF8, (void*)pCtx, idxRemFunc, 0, 0
|
||||
rc = sqlite3_create_function(dbrem, "sqlite_expert_rem",
|
||||
2, SQLITE_UTF8, (void*)pCtx, idxRemFunc, 0, 0
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(
|
||||
p->db, "sample", 0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0
|
||||
rc = sqlite3_create_function(p->db, "sqlite_expert_sample",
|
||||
0, SQLITE_UTF8, (void*)&samplectx, idxSampleFunc, 0, 0
|
||||
);
|
||||
}
|
||||
|
||||
@ -13736,6 +13732,9 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
|
||||
rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_schema", 0, 0, 0);
|
||||
}
|
||||
|
||||
sqlite3_create_function(p->db, "sqlite_expert_rem", 2, SQLITE_UTF8, 0,0,0,0);
|
||||
sqlite3_create_function(p->db, "sqlite_expert_sample", 0,SQLITE_UTF8,0,0,0,0);
|
||||
|
||||
sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
|
||||
return rc;
|
||||
}
|
||||
@ -16836,8 +16835,8 @@ static int recoverError(
|
||||
va_start(ap, zFmt);
|
||||
if( zFmt ){
|
||||
z = sqlite3_vmprintf(zFmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
va_end(ap);
|
||||
sqlite3_free(p->zErrMsg);
|
||||
p->zErrMsg = z;
|
||||
p->errCode = errCode;
|
||||
@ -27085,7 +27084,6 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
import_cleanup(&sCtx);
|
||||
shell_out_of_memory();
|
||||
}
|
||||
nByte = strlen(zSql);
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
zSql = 0;
|
||||
@ -27104,16 +27102,21 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
sqlite3_finalize(pStmt);
|
||||
pStmt = 0;
|
||||
if( nCol==0 ) return 0; /* no columns, no error */
|
||||
zSql = sqlite3_malloc64( nByte*2 + 20 + nCol*2 );
|
||||
|
||||
nByte = 64 /* space for "INSERT INTO", "VALUES(", ")\0" */
|
||||
+ (zSchema ? strlen(zSchema)*2 + 2: 0) /* Quoted schema name */
|
||||
+ strlen(zTable)*2 + 2 /* Quoted table name */
|
||||
+ nCol*2; /* Space for ",?" for each column */
|
||||
zSql = sqlite3_malloc64( nByte );
|
||||
if( zSql==0 ){
|
||||
import_cleanup(&sCtx);
|
||||
shell_out_of_memory();
|
||||
}
|
||||
if( zSchema ){
|
||||
sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?",
|
||||
sqlite3_snprintf(nByte, zSql, "INSERT INTO \"%w\".\"%w\" VALUES(?",
|
||||
zSchema, zTable);
|
||||
}else{
|
||||
sqlite3_snprintf(nByte+20, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
|
||||
sqlite3_snprintf(nByte, zSql, "INSERT INTO \"%w\" VALUES(?", zTable);
|
||||
}
|
||||
j = strlen30(zSql);
|
||||
for(i=1; i<nCol; i++){
|
||||
@ -27122,6 +27125,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}
|
||||
zSql[j++] = ')';
|
||||
zSql[j] = 0;
|
||||
assert( j<nByte );
|
||||
if( eVerbose>=2 ){
|
||||
oputf("Insert using: %s\n", zSql);
|
||||
}
|
||||
|
154
deps/sqlite/sqlite3.c
vendored
154
deps/sqlite/sqlite3.c
vendored
@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
** This file is an amalgamation of many separate C source files from SQLite
|
||||
** version 3.46.0. By combining all the individual C code files into this
|
||||
** version 3.46.1. By combining all the individual C code files into this
|
||||
** single large file, the entire code can be compiled as a single translation
|
||||
** unit. This allows many compilers to do optimizations that would not be
|
||||
** possible if the files were compiled separately. Performance improvements
|
||||
@ -18,7 +18,7 @@
|
||||
** separate file. This file contains only code for the core SQLite library.
|
||||
**
|
||||
** The content in this amalgamation comes from Fossil check-in
|
||||
** 96c92aba00c8375bc32fafcdf12429c58bd8.
|
||||
** c9c2ab54ba1f5f46360f1b4f35d849cd3f08.
|
||||
*/
|
||||
#define SQLITE_CORE 1
|
||||
#define SQLITE_AMALGAMATION 1
|
||||
@ -459,9 +459,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.46.0"
|
||||
#define SQLITE_VERSION_NUMBER 3046000
|
||||
#define SQLITE_SOURCE_ID "2024-05-23 13:25:27 96c92aba00c8375bc32fafcdf12429c58bd8aabfcadab6683e35bbb9cdebf19e"
|
||||
#define SQLITE_VERSION "3.46.1"
|
||||
#define SQLITE_VERSION_NUMBER 3046001
|
||||
#define SQLITE_SOURCE_ID "2024-08-13 09:16:08 c9c2ab54ba1f5f46360f1b4f35d849cd3f080e6fc2b6c60e91b16c63f69a1e33"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@ -19361,7 +19361,7 @@ struct SrcList {
|
||||
#define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */
|
||||
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
|
||||
#define WHERE_RIGHT_JOIN 0x1000 /* Processing a RIGHT JOIN */
|
||||
/* 0x2000 not currently used */
|
||||
#define WHERE_KEEP_ALL_JOINS 0x2000 /* Do not do the omit-noop-join opt */
|
||||
#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
|
||||
/* 0x8000 not currently used */
|
||||
|
||||
@ -90173,7 +90173,8 @@ SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff
|
||||
assert( iVar>0 );
|
||||
if( v ){
|
||||
Mem *pMem = &v->aVar[iVar-1];
|
||||
assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
|
||||
assert( (v->db->flags & SQLITE_EnableQPSG)==0
|
||||
|| (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 );
|
||||
if( 0==(pMem->flags & MEM_Null) ){
|
||||
sqlite3_value *pRet = sqlite3ValueNew(v->db);
|
||||
if( pRet ){
|
||||
@ -90193,7 +90194,8 @@ SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe *v, int iVar, u8 aff
|
||||
*/
|
||||
SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe *v, int iVar){
|
||||
assert( iVar>0 );
|
||||
assert( (v->db->flags & SQLITE_EnableQPSG)==0 );
|
||||
assert( (v->db->flags & SQLITE_EnableQPSG)==0
|
||||
|| (v->db->mDbFlags & DBFLAG_InternalFunc)!=0 );
|
||||
if( iVar>=32 ){
|
||||
v->expmask |= 0x80000000;
|
||||
}else{
|
||||
@ -106950,7 +106952,7 @@ static void extendFJMatch(
|
||||
static SQLITE_NOINLINE int isValidSchemaTableName(
|
||||
const char *zTab, /* Name as it appears in the SQL */
|
||||
Table *pTab, /* The schema table we are trying to match */
|
||||
Schema *pSchema /* non-NULL if a database qualifier is present */
|
||||
const char *zDb /* non-NULL if a database qualifier is present */
|
||||
){
|
||||
const char *zLegacy;
|
||||
assert( pTab!=0 );
|
||||
@ -106961,7 +106963,7 @@ static SQLITE_NOINLINE int isValidSchemaTableName(
|
||||
if( sqlite3StrICmp(zTab+7, &PREFERRED_TEMP_SCHEMA_TABLE[7])==0 ){
|
||||
return 1;
|
||||
}
|
||||
if( pSchema==0 ) return 0;
|
||||
if( zDb==0 ) return 0;
|
||||
if( sqlite3StrICmp(zTab+7, &LEGACY_SCHEMA_TABLE[7])==0 ) return 1;
|
||||
if( sqlite3StrICmp(zTab+7, &PREFERRED_SCHEMA_TABLE[7])==0 ) return 1;
|
||||
}else{
|
||||
@ -107144,7 +107146,7 @@ static int lookupName(
|
||||
}
|
||||
}else if( sqlite3StrICmp(zTab, pTab->zName)!=0 ){
|
||||
if( pTab->tnum!=1 ) continue;
|
||||
if( !isValidSchemaTableName(zTab, pTab, pSchema) ) continue;
|
||||
if( !isValidSchemaTableName(zTab, pTab, zDb) ) continue;
|
||||
}
|
||||
assert( ExprUseYTab(pExpr) );
|
||||
if( IN_RENAME_OBJECT && pItem->zAlias ){
|
||||
@ -108876,6 +108878,9 @@ SQLITE_PRIVATE int sqlite3ResolveExprNames(
|
||||
** Resolve all names for all expression in an expression list. This is
|
||||
** just like sqlite3ResolveExprNames() except that it works for an expression
|
||||
** list rather than a single expression.
|
||||
**
|
||||
** The return value is SQLITE_OK (0) for success or SQLITE_ERROR (1) for a
|
||||
** failure.
|
||||
*/
|
||||
SQLITE_PRIVATE int sqlite3ResolveExprListNames(
|
||||
NameContext *pNC, /* Namespace to resolve expressions in. */
|
||||
@ -108884,7 +108889,7 @@ SQLITE_PRIVATE int sqlite3ResolveExprListNames(
|
||||
int i;
|
||||
int savedHasAgg = 0;
|
||||
Walker w;
|
||||
if( pList==0 ) return WRC_Continue;
|
||||
if( pList==0 ) return SQLITE_OK;
|
||||
w.pParse = pNC->pParse;
|
||||
w.xExprCallback = resolveExprStep;
|
||||
w.xSelectCallback = resolveSelectStep;
|
||||
@ -108898,7 +108903,7 @@ SQLITE_PRIVATE int sqlite3ResolveExprListNames(
|
||||
#if SQLITE_MAX_EXPR_DEPTH>0
|
||||
w.pParse->nHeight += pExpr->nHeight;
|
||||
if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){
|
||||
return WRC_Abort;
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
#endif
|
||||
sqlite3WalkExprNN(&w, pExpr);
|
||||
@ -108915,10 +108920,10 @@ SQLITE_PRIVATE int sqlite3ResolveExprListNames(
|
||||
(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
|
||||
pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin|NC_OrderAgg);
|
||||
}
|
||||
if( w.pParse->nErr>0 ) return WRC_Abort;
|
||||
if( w.pParse->nErr>0 ) return SQLITE_ERROR;
|
||||
}
|
||||
pNC->ncFlags |= savedHasAgg;
|
||||
return WRC_Continue;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -117457,7 +117462,7 @@ static int renameResolveTrigger(Parse *pParse){
|
||||
/* ALWAYS() because if the table of the trigger does not exist, the
|
||||
** error would have been hit before this point */
|
||||
if( ALWAYS(pParse->pTriggerTab) ){
|
||||
rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab);
|
||||
rc = sqlite3ViewGetColumnNames(pParse, pParse->pTriggerTab)!=0;
|
||||
}
|
||||
|
||||
/* Resolve symbols in WHEN clause */
|
||||
@ -124426,8 +124431,9 @@ create_view_fail:
|
||||
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
|
||||
/*
|
||||
** The Table structure pTable is really a VIEW. Fill in the names of
|
||||
** the columns of the view in the pTable structure. Return the number
|
||||
** of errors. If an error is seen leave an error message in pParse->zErrMsg.
|
||||
** the columns of the view in the pTable structure. Return non-zero if
|
||||
** there are errors. If an error is seen an error message is left
|
||||
** in pParse->zErrMsg.
|
||||
*/
|
||||
static SQLITE_NOINLINE int viewGetColumnNames(Parse *pParse, Table *pTable){
|
||||
Table *pSelTab; /* A fake table from which we get the result set */
|
||||
@ -124550,7 +124556,7 @@ static SQLITE_NOINLINE int viewGetColumnNames(Parse *pParse, Table *pTable){
|
||||
sqlite3DeleteColumnNames(db, pTable);
|
||||
}
|
||||
#endif /* SQLITE_OMIT_VIEW */
|
||||
return nErr;
|
||||
return nErr + pParse->nErr;
|
||||
}
|
||||
SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
|
||||
assert( pTable!=0 );
|
||||
@ -130848,6 +130854,8 @@ static void groupConcatValue(sqlite3_context *context){
|
||||
sqlite3_result_error_toobig(context);
|
||||
}else if( pAccum->accError==SQLITE_NOMEM ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else if( pGCC->nAccum>0 && pAccum->nChar==0 ){
|
||||
sqlite3_result_text(context, "", 1, SQLITE_STATIC);
|
||||
}else{
|
||||
const char *zText = sqlite3_str_value(pAccum);
|
||||
sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT);
|
||||
@ -133602,6 +133610,7 @@ SQLITE_PRIVATE Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList
|
||||
pRet->pSrc->nSrc = 1;
|
||||
pRet->pPrior = pLeft->pPrior;
|
||||
pRet->op = pLeft->op;
|
||||
if( pRet->pPrior ) pRet->selFlags |= SF_Values;
|
||||
pLeft->pPrior = 0;
|
||||
pLeft->op = TK_SELECT;
|
||||
assert( pLeft->pNext==0 );
|
||||
@ -166067,7 +166076,9 @@ static int whereLoopAddBtree(
|
||||
" according to whereIsCoveringIndex()\n", pProbe->zName));
|
||||
}
|
||||
}
|
||||
}else if( m==0 ){
|
||||
}else if( m==0
|
||||
&& (HasRowid(pTab) || pWInfo->pSelect!=0 || sqlite3FaultSim(700))
|
||||
){
|
||||
WHERETRACE(0x200,
|
||||
("-> %s a covering index according to bitmasks\n",
|
||||
pProbe->zName, m==0 ? "is" : "is not"));
|
||||
@ -167956,6 +167967,10 @@ static void showAllWhereLoops(WhereInfo *pWInfo, WhereClause *pWC){
|
||||
** the right-most table of a subquery that was flattened into the
|
||||
** main query and that subquery was the right-hand operand of an
|
||||
** inner join that held an ON or USING clause.
|
||||
** 6) The ORDER BY clause has 63 or fewer terms
|
||||
** 7) The omit-noop-join optimization is enabled.
|
||||
**
|
||||
** Items (1), (6), and (7) are checked by the caller.
|
||||
**
|
||||
** For example, given:
|
||||
**
|
||||
@ -168369,6 +168384,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
|
||||
if( pOrderBy && pOrderBy->nExpr>=BMS ){
|
||||
pOrderBy = 0;
|
||||
wctrlFlags &= ~WHERE_WANT_DISTINCT;
|
||||
wctrlFlags |= WHERE_KEEP_ALL_JOINS; /* Disable omit-noop-join opt */
|
||||
}
|
||||
|
||||
/* The number of tables in the FROM clause is limited by the number of
|
||||
@ -168669,10 +168685,10 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
|
||||
** in-line sqlite3WhereCodeOneLoopStart() for performance reasons.
|
||||
*/
|
||||
notReady = ~(Bitmask)0;
|
||||
if( pWInfo->nLevel>=2
|
||||
&& pResultSet!=0 /* these two combine to guarantee */
|
||||
&& 0==(wctrlFlags & WHERE_AGG_DISTINCT) /* condition (1) above */
|
||||
&& OptimizationEnabled(db, SQLITE_OmitNoopJoin)
|
||||
if( pWInfo->nLevel>=2 /* Must be a join, or this opt8n is pointless */
|
||||
&& pResultSet!=0 /* Condition (1) */
|
||||
&& 0==(wctrlFlags & (WHERE_AGG_DISTINCT|WHERE_KEEP_ALL_JOINS)) /* (1),(6) */
|
||||
&& OptimizationEnabled(db, SQLITE_OmitNoopJoin) /* (7) */
|
||||
){
|
||||
notReady = whereOmitNoopJoin(pWInfo, notReady);
|
||||
nTabList = pWInfo->nLevel;
|
||||
@ -168992,26 +169008,6 @@ whereBeginError:
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Return true if cursor iCur is opened by instruction k of the
|
||||
** bytecode. Used inside of assert() only.
|
||||
*/
|
||||
static int cursorIsOpen(Vdbe *v, int iCur, int k){
|
||||
while( k>=0 ){
|
||||
VdbeOp *pOp = sqlite3VdbeGetOp(v,k--);
|
||||
if( pOp->p1!=iCur ) continue;
|
||||
if( pOp->opcode==OP_Close ) return 0;
|
||||
if( pOp->opcode==OP_OpenRead ) return 1;
|
||||
if( pOp->opcode==OP_OpenWrite ) return 1;
|
||||
if( pOp->opcode==OP_OpenDup ) return 1;
|
||||
if( pOp->opcode==OP_OpenAutoindex ) return 1;
|
||||
if( pOp->opcode==OP_OpenEphemeral ) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
||||
/*
|
||||
** Generate the end of the WHERE loop. See comments on
|
||||
** sqlite3WhereBegin() for additional information.
|
||||
@ -169311,16 +169307,10 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
|
||||
** reference. Verify that this is harmless - that the
|
||||
** table being referenced really is open.
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
|
||||
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
|
||||
|| cursorIsOpen(v,pOp->p1,k)
|
||||
|| pOp->opcode==OP_Offset
|
||||
);
|
||||
#else
|
||||
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
|
||||
|| cursorIsOpen(v,pOp->p1,k)
|
||||
);
|
||||
#endif
|
||||
if( pLoop->wsFlags & WHERE_IDX_ONLY ){
|
||||
sqlite3ErrorMsg(pParse, "internal query planner error");
|
||||
pParse->rc = SQLITE_INTERNAL;
|
||||
}
|
||||
}
|
||||
}else if( pOp->opcode==OP_Rowid ){
|
||||
pOp->p1 = pLevel->iIdxCur;
|
||||
@ -172591,9 +172581,9 @@ static void updateDeleteLimitError(
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( (p->selFlags & SF_MultiValue)==0 &&
|
||||
(mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 &&
|
||||
cnt>mxSelect
|
||||
if( (p->selFlags & (SF_MultiValue|SF_Values))==0
|
||||
&& (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0
|
||||
&& cnt>mxSelect
|
||||
){
|
||||
sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
|
||||
}
|
||||
@ -237004,7 +236994,11 @@ static int sqlite3Fts5ExprNew(
|
||||
}
|
||||
|
||||
sqlite3_free(sParse.apPhrase);
|
||||
*pzErr = sParse.zErr;
|
||||
if( 0==*pzErr ){
|
||||
*pzErr = sParse.zErr;
|
||||
}else{
|
||||
sqlite3_free(sParse.zErr);
|
||||
}
|
||||
return sParse.rc;
|
||||
}
|
||||
|
||||
@ -239132,6 +239126,7 @@ static Fts5ExprNode *sqlite3Fts5ParseImplicitAnd(
|
||||
assert( pRight->eType==FTS5_STRING
|
||||
|| pRight->eType==FTS5_TERM
|
||||
|| pRight->eType==FTS5_EOF
|
||||
|| (pRight->eType==FTS5_AND && pParse->bPhraseToAnd)
|
||||
);
|
||||
|
||||
if( pLeft->eType==FTS5_AND ){
|
||||
@ -251299,6 +251294,7 @@ static int fts5UpdateMethod(
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
rc = fts5SpecialDelete(pTab, apVal);
|
||||
bUpdateOrDelete = 1;
|
||||
}
|
||||
}else{
|
||||
rc = fts5SpecialInsert(pTab, z, apVal[2 + pConfig->nCol + 1]);
|
||||
@ -252473,14 +252469,16 @@ static int sqlite3Fts5GetTokenizer(
|
||||
if( pMod==0 ){
|
||||
assert( nArg>0 );
|
||||
rc = SQLITE_ERROR;
|
||||
*pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
|
||||
if( pzErr ) *pzErr = sqlite3_mprintf("no such tokenizer: %s", azArg[0]);
|
||||
}else{
|
||||
rc = pMod->x.xCreate(
|
||||
pMod->pUserData, (azArg?&azArg[1]:0), (nArg?nArg-1:0), &pConfig->pTok
|
||||
);
|
||||
pConfig->pTokApi = &pMod->x;
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( pzErr ) *pzErr = sqlite3_mprintf("error in tokenizer constructor");
|
||||
if( pzErr && rc!=SQLITE_NOMEM ){
|
||||
*pzErr = sqlite3_mprintf("error in tokenizer constructor");
|
||||
}
|
||||
}else{
|
||||
pConfig->ePattern = sqlite3Fts5TokenizerPattern(
|
||||
pMod->x.xCreate, pConfig->pTok
|
||||
@ -252539,7 +252537,7 @@ static void fts5SourceIdFunc(
|
||||
){
|
||||
assert( nArg==0 );
|
||||
UNUSED_PARAM2(nArg, apUnused);
|
||||
sqlite3_result_text(pCtx, "fts5: 2024-05-23 13:25:27 96c92aba00c8375bc32fafcdf12429c58bd8aabfcadab6683e35bbb9cdebf19e", -1, SQLITE_TRANSIENT);
|
||||
sqlite3_result_text(pCtx, "fts5: 2024-08-13 09:16:08 c9c2ab54ba1f5f46360f1b4f35d849cd3f080e6fc2b6c60e91b16c63f69a1e33", -1, SQLITE_TRANSIENT);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -252574,17 +252572,23 @@ static int fts5IntegrityMethod(
|
||||
|
||||
assert( pzErr!=0 && *pzErr==0 );
|
||||
UNUSED_PARAM(isQuick);
|
||||
assert( pTab->p.pConfig->pzErrmsg==0 );
|
||||
pTab->p.pConfig->pzErrmsg = pzErr;
|
||||
rc = sqlite3Fts5StorageIntegrity(pTab->pStorage, 0);
|
||||
if( (rc&0xff)==SQLITE_CORRUPT ){
|
||||
*pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s",
|
||||
zSchema, zTabname);
|
||||
rc = (*pzErr) ? SQLITE_OK : SQLITE_NOMEM;
|
||||
}else if( rc!=SQLITE_OK ){
|
||||
*pzErr = sqlite3_mprintf("unable to validate the inverted index for"
|
||||
" FTS5 table %s.%s: %s",
|
||||
zSchema, zTabname, sqlite3_errstr(rc));
|
||||
if( *pzErr==0 && rc!=SQLITE_OK ){
|
||||
if( (rc&0xff)==SQLITE_CORRUPT ){
|
||||
*pzErr = sqlite3_mprintf("malformed inverted index for FTS5 table %s.%s",
|
||||
zSchema, zTabname);
|
||||
rc = (*pzErr) ? SQLITE_OK : SQLITE_NOMEM;
|
||||
}else{
|
||||
*pzErr = sqlite3_mprintf("unable to validate the inverted index for"
|
||||
" FTS5 table %s.%s: %s",
|
||||
zSchema, zTabname, sqlite3_errstr(rc));
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
|
||||
pTab->p.pConfig->pzErrmsg = 0;
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -254018,7 +254022,7 @@ static int fts5AsciiCreate(
|
||||
int i;
|
||||
memset(p, 0, sizeof(AsciiTokenizer));
|
||||
memcpy(p->aTokenChar, aAsciiTokenChar, sizeof(aAsciiTokenChar));
|
||||
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
|
||||
for(i=0; rc==SQLITE_OK && i<nArg-1; i+=2){
|
||||
const char *zArg = azArg[i+1];
|
||||
if( 0==sqlite3_stricmp(azArg[i], "tokenchars") ){
|
||||
fts5AsciiAddExceptions(p, zArg, 1);
|
||||
@ -254029,6 +254033,7 @@ static int fts5AsciiCreate(
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK && i<nArg ) rc = SQLITE_ERROR;
|
||||
if( rc!=SQLITE_OK ){
|
||||
fts5AsciiDelete((Fts5Tokenizer*)p);
|
||||
p = 0;
|
||||
@ -254320,17 +254325,16 @@ static int fts5UnicodeCreate(
|
||||
}
|
||||
|
||||
/* Search for a "categories" argument */
|
||||
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
|
||||
for(i=0; rc==SQLITE_OK && i<nArg-1; i+=2){
|
||||
if( 0==sqlite3_stricmp(azArg[i], "categories") ){
|
||||
zCat = azArg[i+1];
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = unicodeSetCategories(p, zCat);
|
||||
}
|
||||
|
||||
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
|
||||
for(i=0; rc==SQLITE_OK && i<nArg-1; i+=2){
|
||||
const char *zArg = azArg[i+1];
|
||||
if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
|
||||
if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){
|
||||
@ -254355,6 +254359,7 @@ static int fts5UnicodeCreate(
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
if( i<nArg && rc==SQLITE_OK ) rc = SQLITE_ERROR;
|
||||
|
||||
}else{
|
||||
rc = SQLITE_NOMEM;
|
||||
@ -255237,7 +255242,7 @@ static int fts5TriCreate(
|
||||
int i;
|
||||
pNew->bFold = 1;
|
||||
pNew->iFoldParam = 0;
|
||||
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
|
||||
for(i=0; rc==SQLITE_OK && i<nArg-1; i+=2){
|
||||
const char *zArg = azArg[i+1];
|
||||
if( 0==sqlite3_stricmp(azArg[i], "case_sensitive") ){
|
||||
if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
|
||||
@ -255255,6 +255260,7 @@ static int fts5TriCreate(
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
if( i<nArg && rc==SQLITE_OK ) rc = SQLITE_ERROR;
|
||||
|
||||
if( pNew->iFoldParam!=0 && pNew->bFold==0 ){
|
||||
rc = SQLITE_ERROR;
|
||||
|
6
deps/sqlite/sqlite3.h
vendored
6
deps/sqlite/sqlite3.h
vendored
@ -146,9 +146,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.46.0"
|
||||
#define SQLITE_VERSION_NUMBER 3046000
|
||||
#define SQLITE_SOURCE_ID "2024-05-23 13:25:27 96c92aba00c8375bc32fafcdf12429c58bd8aabfcadab6683e35bbb9cdebf19e"
|
||||
#define SQLITE_VERSION "3.46.1"
|
||||
#define SQLITE_VERSION_NUMBER 3046001
|
||||
#define SQLITE_SOURCE_ID "2024-08-13 09:16:08 c9c2ab54ba1f5f46360f1b4f35d849cd3f080e6fc2b6c60e91b16c63f69a1e33"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
|
12
metadata/en-US/changelogs/26.txt
Normal file
12
metadata/en-US/changelogs/26.txt
Normal file
@ -0,0 +1,12 @@
|
||||
* Took an initial whack at encouraging internet-based discovery of open peers.
|
||||
* Added settings to control whether replication, room, peer exchange, and account registration are allowed.
|
||||
* Implemented prompt() on Android.
|
||||
* Fixed some incorrect cross-thread use of the main JS context.
|
||||
* Fixed yet another incorrect use of the DB from the main thread, from an RPC that isn't ever hit. Hmm.
|
||||
* Minor admin layout fixes.
|
||||
* Added c-ares for TXT record lookups.
|
||||
* Latest libsodium-stable.
|
||||
* Latest libbacktrace.
|
||||
* Latest CodeMirror.
|
||||
* Updated to Lit 3.2.0.
|
||||
* Updated sqlite to 3.46.1.
|
BIN
metadata/en-US/images/icon.png
Normal file
BIN
metadata/en-US/images/icon.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 18 KiB |
Binary file not shown.
After ![]() (image error) Size: 298 KiB |
Binary file not shown.
After ![]() (image error) Size: 275 KiB |
Binary file not shown.
After ![]() (image error) Size: 186 KiB |
@ -1,11 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.unprompted.tildefriends">
|
||||
package="com.unprompted.tildefriends"
|
||||
android:versionCode="26"
|
||||
android:versionName="0.0.22">
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<application
|
||||
android:label="Tilde Friends"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:debuggable="false">
|
||||
android:usesCleartextTraffic="true">
|
||||
<meta-data android:name="android.max_aspect" android:value="2.1"/>
|
||||
<activity
|
||||
android:name=".TildeFriendsActivity"
|
||||
|
@ -7,6 +7,7 @@ import android.content.ComponentName;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
@ -15,6 +16,7 @@ import android.os.Parcel;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.RemoteException;
|
||||
import android.os.StrictMode;
|
||||
import android.text.InputType;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
@ -32,6 +34,7 @@ import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebResourceRequest;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import java.io.BufferedReader;
|
||||
@ -66,7 +69,7 @@ public class TildeFriendsActivity extends Activity {
|
||||
Log.w("tildefriends", "system.loadLibrary() completed.");
|
||||
}
|
||||
|
||||
public static native int tf_server_main(String files_dir, String apk_path, String out_port_file_path);
|
||||
public static native int tf_server_main(String files_dir, String apk_path, String out_port_file_path, ConnectivityManager connectivity_manager);
|
||||
public static native int tf_sandbox_main(int pipe_fd);
|
||||
|
||||
@Override
|
||||
@ -148,7 +151,11 @@ public class TildeFriendsActivity extends Activity {
|
||||
@Override
|
||||
public void run() {
|
||||
Log.w("tildefriends", "Calling tf_server_main.");
|
||||
int result = tf_server_main(getFilesDir().toString(), getPackageResourcePath().toString(), port_file_path);
|
||||
int result = tf_server_main(
|
||||
getFilesDir().toString(),
|
||||
getPackageResourcePath().toString(),
|
||||
port_file_path,
|
||||
(ConnectivityManager)getApplicationContext().getSystemService(CONNECTIVITY_SERVICE));
|
||||
Log.w("tildefriends", "tf_server_main returned " + result + ".");
|
||||
}
|
||||
});
|
||||
@ -192,7 +199,24 @@ public class TildeFriendsActivity extends Activity {
|
||||
|
||||
web_view.setWebChromeClient(new WebChromeClient() {
|
||||
@Override
|
||||
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
|
||||
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
|
||||
new AlertDialog.Builder(view.getContext())
|
||||
.setTitle("Tilde Friends")
|
||||
.setMessage(message)
|
||||
.setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
result.confirm();
|
||||
}
|
||||
})
|
||||
.create()
|
||||
.show();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
|
||||
new AlertDialog.Builder(view.getContext())
|
||||
.setTitle("Tilde Friends")
|
||||
.setMessage(message)
|
||||
@ -216,15 +240,27 @@ public class TildeFriendsActivity extends Activity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
|
||||
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
|
||||
EditText input = new EditText(view.getContext());
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||
input.setText(defaultValue);
|
||||
|
||||
new AlertDialog.Builder(view.getContext())
|
||||
.setTitle("Tilde Friends")
|
||||
.setMessage(message)
|
||||
.setNeutralButton(android.R.string.ok, new DialogInterface.OnClickListener()
|
||||
.setView(input)
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
result.confirm();
|
||||
result.confirm(input.getText().toString());
|
||||
}
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener()
|
||||
{
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
result.cancel();
|
||||
}
|
||||
})
|
||||
.create()
|
||||
|
@ -1071,7 +1071,7 @@ void* tf_http_get_user_data(tf_http_t* http)
|
||||
|
||||
const char* tf_http_get_cookie(const char* cookie_header, const char* name)
|
||||
{
|
||||
if (!cookie_header)
|
||||
if (!cookie_header || !name)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ const int64_t k_refresh_interval = 1ULL * 7 * 24 * 60 * 60 * 1000;
|
||||
|
||||
static JSValue _authenticate_jwt(tf_ssb_t* ssb, JSContext* context, const char* jwt);
|
||||
static JSValue _httpd_websocket_upgrade(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv);
|
||||
static const char* _make_session_jwt(tf_ssb_t* ssb, const char* name);
|
||||
static const char* _make_session_jwt(JSContext* context, tf_ssb_t* ssb, const char* name);
|
||||
static const char* _make_set_session_cookie_header(tf_http_request_t* request, const char* session_cookie);
|
||||
|
||||
static JSClassID _httpd_class_id;
|
||||
@ -334,7 +334,7 @@ static JSValue _httpd_websocket_upgrade(JSContext* context, JSValueConst this_va
|
||||
tf_free((void*)session);
|
||||
JSValue name = !JS_IsUndefined(jwt) ? JS_GetPropertyStr(context, jwt, "name") : JS_UNDEFINED;
|
||||
const char* name_string = !JS_IsUndefined(name) ? JS_ToCString(context, name) : NULL;
|
||||
const char* session_token = _make_session_jwt(ssb, name_string);
|
||||
const char* session_token = _make_session_jwt(tf_ssb_get_context(ssb), ssb, name_string);
|
||||
const char* cookie = _make_set_session_cookie_header(request, session_token);
|
||||
tf_free((void*)session_token);
|
||||
JS_FreeCString(context, name_string);
|
||||
@ -1305,7 +1305,7 @@ static bool _is_name_valid(const char* name)
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char* _make_session_jwt(tf_ssb_t* ssb, const char* name)
|
||||
static const char* _make_session_jwt(JSContext* context, tf_ssb_t* ssb, const char* name)
|
||||
{
|
||||
if (!name || !*name)
|
||||
{
|
||||
@ -1319,7 +1319,6 @@ static const char* _make_session_jwt(tf_ssb_t* ssb, const char* name)
|
||||
char header_base64[256];
|
||||
sodium_bin2base64(header_base64, sizeof(header_base64), (uint8_t*)header_json, strlen(header_json), sodium_base64_VARIANT_URLSAFE_NO_PADDING);
|
||||
|
||||
JSContext* context = tf_ssb_get_context(ssb);
|
||||
JSValue payload = JS_NewObject(context);
|
||||
JS_SetPropertyStr(context, payload, "name", JS_NewString(context, name));
|
||||
JS_SetPropertyStr(context, payload, "exp", JS_NewInt64(context, now.tv_sec * 1000 + now.tv_nsec / 1000000LL + k_refresh_interval));
|
||||
@ -1484,27 +1483,39 @@ static void _httpd_endpoint_login_work(tf_ssb_t* ssb, void* user_data)
|
||||
|
||||
if (form_register && strcmp(form_register, "1") == 0)
|
||||
{
|
||||
if (!have_account && _is_name_valid(account_name) && password && confirm && strcmp(password, confirm) == 0 &&
|
||||
tf_ssb_db_register_account(ssb, account_name, password))
|
||||
bool registered = false;
|
||||
if (!have_account && _is_name_valid(account_name) && password && confirm && strcmp(password, confirm) == 0)
|
||||
{
|
||||
tf_free((void*)send_session);
|
||||
send_session = _make_session_jwt(ssb, account_name);
|
||||
may_become_first_admin = true;
|
||||
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
|
||||
registered = tf_ssb_db_register_account(tf_ssb_get_loop(ssb), db, context, account_name, password);
|
||||
tf_ssb_release_db_writer(ssb, db);
|
||||
if (registered)
|
||||
{
|
||||
tf_free((void*)send_session);
|
||||
send_session = _make_session_jwt(context, ssb, account_name);
|
||||
may_become_first_admin = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!registered)
|
||||
{
|
||||
login_error = "Error registering account.";
|
||||
}
|
||||
}
|
||||
else if (change && strcmp(change, "1") == 0)
|
||||
{
|
||||
if (have_account && _is_name_valid(account_name) && new_password && confirm && strcmp(new_password, confirm) == 0 && _verify_password(password, account_passwd) &&
|
||||
tf_ssb_db_set_account_password(ssb, account_name, new_password))
|
||||
bool set = false;
|
||||
if (have_account && _is_name_valid(account_name) && new_password && confirm && strcmp(new_password, confirm) == 0 && _verify_password(password, account_passwd))
|
||||
{
|
||||
tf_free((void*)send_session);
|
||||
send_session = _make_session_jwt(ssb, account_name);
|
||||
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
|
||||
set = tf_ssb_db_set_account_password(tf_ssb_get_loop(ssb), db, context, account_name, new_password);
|
||||
tf_ssb_release_db_writer(ssb, db);
|
||||
if (set)
|
||||
{
|
||||
tf_free((void*)send_session);
|
||||
send_session = _make_session_jwt(context, ssb, account_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!set)
|
||||
{
|
||||
login_error = "Error changing password.";
|
||||
}
|
||||
@ -1514,7 +1525,7 @@ static void _httpd_endpoint_login_work(tf_ssb_t* ssb, void* user_data)
|
||||
if (have_account && *account_passwd && _verify_password(password, account_passwd))
|
||||
{
|
||||
tf_free((void*)send_session);
|
||||
send_session = _make_session_jwt(ssb, account_name);
|
||||
send_session = _make_session_jwt(context, ssb, account_name);
|
||||
may_become_first_admin = true;
|
||||
}
|
||||
else
|
||||
@ -1526,7 +1537,7 @@ static void _httpd_endpoint_login_work(tf_ssb_t* ssb, void* user_data)
|
||||
else
|
||||
{
|
||||
tf_free((void*)send_session);
|
||||
send_session = _make_session_jwt(ssb, "guest");
|
||||
send_session = _make_session_jwt(context, ssb, "guest");
|
||||
}
|
||||
tf_free(post_form_data);
|
||||
}
|
||||
|
13
src/main.c
13
src/main.c
@ -9,6 +9,7 @@
|
||||
#include "tests.h"
|
||||
#include "util.js.h"
|
||||
|
||||
#include "ares.h"
|
||||
#include "backtrace.h"
|
||||
#include "sqlite3.h"
|
||||
#include "unzip.h"
|
||||
@ -750,7 +751,7 @@ static void _tf_service_stop()
|
||||
(*s_jni_env)->CallStaticVoidMethod(s_jni_env, c, stop_sandbox);
|
||||
}
|
||||
|
||||
static jint _tf_server_main(JNIEnv* env, jobject this_object, jstring files_dir, jstring apk_path, jstring out_port_file_path)
|
||||
static jint _tf_server_main(JNIEnv* env, jobject this_object, jstring files_dir, jstring apk_path, jstring out_port_file_path, jobject connectivity_manager)
|
||||
{
|
||||
s_jni_env = env;
|
||||
|
||||
@ -758,6 +759,9 @@ static jint _tf_server_main(JNIEnv* env, jobject this_object, jstring files_dir,
|
||||
_startup(0, (char*[]) { NULL });
|
||||
tf_printf("That was startup.\n");
|
||||
|
||||
ares_library_init_android(connectivity_manager);
|
||||
ares_library_init(0);
|
||||
|
||||
const char* files = (*env)->GetStringUTFChars(env, files_dir, NULL);
|
||||
const char* apk = (*env)->GetStringUTFChars(env, apk_path, NULL);
|
||||
const char* out_port_file = (*env)->GetStringUTFChars(env, out_port_file_path, NULL);
|
||||
@ -794,6 +798,7 @@ static jint _tf_server_main(JNIEnv* env, jobject this_object, jstring files_dir,
|
||||
(*env)->ReleaseStringUTFChars(env, apk_path, apk);
|
||||
(*env)->ReleaseStringUTFChars(env, out_port_file_path, out_port_file);
|
||||
|
||||
ares_library_cleanup();
|
||||
tf_mem_shutdown();
|
||||
tf_printf("tf_server_main finished with %d.", result);
|
||||
|
||||
@ -846,7 +851,7 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
|
||||
tf_printf("Registering method.\n");
|
||||
static const JNINativeMethod methods[] = {
|
||||
{ "tf_server_main", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", _tf_server_main },
|
||||
{ "tf_server_main", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/net/ConnectivityManager;)I", _tf_server_main },
|
||||
{ "tf_sandbox_main", "(I)I", _tf_sandbox_main },
|
||||
};
|
||||
int result = (*env)->RegisterNatives(env, c, methods, (int)_countof(methods));
|
||||
@ -855,6 +860,8 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
return result;
|
||||
}
|
||||
|
||||
ares_library_init_jvm(vm);
|
||||
|
||||
tf_printf("Done.\n");
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
@ -889,6 +896,7 @@ void tf_run_thread_start(const char* zip_path)
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
_startup(argc, argv);
|
||||
ares_library_init(0);
|
||||
|
||||
int result = 0;
|
||||
if (argc >= 2)
|
||||
@ -909,6 +917,7 @@ int main(int argc, char* argv[])
|
||||
result = _tf_command_run(argv[0], argc, argv);
|
||||
}
|
||||
done:
|
||||
ares_library_cleanup();
|
||||
tf_mem_shutdown();
|
||||
return result;
|
||||
}
|
||||
|
162
src/ssb.c
162
src/ssb.c
@ -8,6 +8,7 @@
|
||||
#include "trace.h"
|
||||
#include "util.js.h"
|
||||
|
||||
#include "ares.h"
|
||||
#include "quickjs.h"
|
||||
#include "sodium/crypto_auth.h"
|
||||
#include "sodium/crypto_box.h"
|
||||
@ -20,6 +21,10 @@
|
||||
#include "sqlite3.h"
|
||||
#include "uv.h"
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <arpa/nameser.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
@ -72,6 +77,9 @@ enum
|
||||
k_tf_ssb_rpc_message_body_length_max = 1 * 1024 * 1024,
|
||||
k_debug_close_message_count = 256,
|
||||
k_debug_close_connection_count = 32,
|
||||
k_seed_expire_seconds = 10 * 60,
|
||||
k_seed_check_interval_seconds = 5 * 60,
|
||||
k_udp_discovery_expires_seconds = 10,
|
||||
};
|
||||
|
||||
typedef struct _tf_ssb_broadcast_t tf_ssb_broadcast_t;
|
||||
@ -111,7 +119,9 @@ typedef struct _tf_ssb_broadcast_t
|
||||
tf_ssb_broadcast_t* next;
|
||||
time_t ctime;
|
||||
time_t mtime;
|
||||
time_t expires_at;
|
||||
char host[256];
|
||||
tf_ssb_broadcast_origin_t origin;
|
||||
struct sockaddr_in addr;
|
||||
tf_ssb_connection_t* tunnel_connection;
|
||||
uint8_t pub[crypto_sign_PUBLICKEYBYTES];
|
||||
@ -255,7 +265,11 @@ typedef struct _tf_ssb_t
|
||||
|
||||
uv_thread_t thread_self;
|
||||
bool is_room;
|
||||
bool is_replicator;
|
||||
bool is_peer_exchange;
|
||||
char* room_name;
|
||||
char seeds_host[256];
|
||||
time_t last_seed_check;
|
||||
|
||||
tf_ssb_timer_t** timers;
|
||||
int timers_count;
|
||||
@ -351,6 +365,7 @@ static JSClassID _connection_class_id;
|
||||
static int s_connection_index;
|
||||
static int s_tunnel_index;
|
||||
|
||||
static void _tf_ssb_add_broadcast(tf_ssb_t* ssb, const tf_ssb_broadcast_t* broadcast, int expires_seconds);
|
||||
static void _tf_ssb_connection_client_send_hello(tf_ssb_connection_t* connection);
|
||||
static void _tf_ssb_connection_close(tf_ssb_connection_t* connection, const char* reason);
|
||||
static void _tf_ssb_connection_destroy(tf_ssb_connection_t* connection, const char* reason);
|
||||
@ -358,6 +373,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_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 bool _tf_ssb_parse_broadcast(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_update_settings(tf_ssb_t* ssb);
|
||||
static void _tf_ssb_write(tf_ssb_connection_t* connection, void* data, size_t size);
|
||||
@ -2182,6 +2198,7 @@ tf_ssb_t* tf_ssb_create(uv_loop_t* loop, JSContext* context, const char* db_path
|
||||
{
|
||||
tf_ssb_t* ssb = tf_malloc(sizeof(tf_ssb_t));
|
||||
memset(ssb, 0, sizeof(*ssb));
|
||||
ssb->is_replicator = true;
|
||||
|
||||
const char* actual_key = network_key ? network_key : k_ssb_network_string;
|
||||
if (sodium_hex2bin(ssb->network_key, sizeof(ssb->network_key), actual_key, strlen(actual_key), ": ", NULL, NULL))
|
||||
@ -2385,6 +2402,14 @@ tf_trace_t* tf_ssb_get_trace(tf_ssb_t* ssb)
|
||||
|
||||
JSContext* tf_ssb_get_context(tf_ssb_t* ssb)
|
||||
{
|
||||
if (ssb->thread_self && uv_thread_self() != ssb->thread_self)
|
||||
{
|
||||
const char* bt = tf_util_backtrace_string();
|
||||
tf_printf("Acquiring JS context from non-main thread:\n%s\n", bt);
|
||||
tf_free((void*)bt);
|
||||
abort();
|
||||
}
|
||||
|
||||
return ssb->context;
|
||||
}
|
||||
|
||||
@ -2892,6 +2917,60 @@ static void _tf_ssb_send_broadcast(tf_ssb_t* ssb, struct sockaddr_in* address, s
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct _seeds_t
|
||||
{
|
||||
char** seeds;
|
||||
int seeds_count;
|
||||
} seeds_t;
|
||||
|
||||
static void _tf_ssb_update_seed_callback(void* arg, ares_status_t status, size_t timeouts, const ares_dns_record_t* record)
|
||||
{
|
||||
seeds_t* seeds = arg;
|
||||
for (int i = 0; i < (int)ares_dns_record_rr_cnt(record, ARES_SECTION_ANSWER); i++)
|
||||
{
|
||||
const ares_dns_rr_t* rr = ares_dns_record_rr_get_const(record, ARES_SECTION_ANSWER, i);
|
||||
size_t len = 0;
|
||||
const unsigned char* str = ares_dns_rr_get_bin(rr, ARES_RR_TXT_DATA, &len);
|
||||
seeds->seeds = tf_resize_vec(seeds->seeds, sizeof(char*) * (seeds->seeds_count + 1));
|
||||
seeds->seeds[seeds->seeds_count++] = tf_strdup((const char*)str);
|
||||
}
|
||||
}
|
||||
|
||||
static void _tf_ssb_update_seeds_work(tf_ssb_t* ssb, void* user_data)
|
||||
{
|
||||
if (ares_library_init(0) == ARES_SUCCESS)
|
||||
{
|
||||
ares_channel channel;
|
||||
struct ares_options options = { .evsys = ARES_EVSYS_DEFAULT };
|
||||
int result = ares_init_options(&channel, &options, ARES_OPT_EVENT_THREAD);
|
||||
if (result == ARES_SUCCESS)
|
||||
{
|
||||
if (ares_query_dnsrec(channel, ssb->seeds_host, ARES_CLASS_IN, ARES_REC_TYPE_TXT, _tf_ssb_update_seed_callback, user_data, NULL) == ARES_SUCCESS)
|
||||
{
|
||||
ares_queue_wait_empty(channel, -1);
|
||||
}
|
||||
ares_destroy(channel);
|
||||
}
|
||||
ares_library_cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
static void _tf_ssb_update_seeds_after_work(tf_ssb_t* ssb, int status, void* user_data)
|
||||
{
|
||||
seeds_t* seeds = user_data;
|
||||
for (int i = 0; i < seeds->seeds_count; i++)
|
||||
{
|
||||
tf_ssb_broadcast_t broadcast = { .origin = k_tf_ssb_broadcast_origin_peer_exchange };
|
||||
if (_tf_ssb_parse_broadcast(seeds->seeds[i], &broadcast))
|
||||
{
|
||||
_tf_ssb_add_broadcast(ssb, &broadcast, k_seed_expire_seconds);
|
||||
}
|
||||
tf_free(seeds->seeds[i]);
|
||||
}
|
||||
tf_free(seeds->seeds);
|
||||
tf_free(seeds);
|
||||
}
|
||||
|
||||
static void _tf_ssb_broadcast_timer(uv_timer_t* timer)
|
||||
{
|
||||
tf_ssb_t* ssb = timer->data;
|
||||
@ -2908,6 +2987,15 @@ static void _tf_ssb_broadcast_timer(uv_timer_t* timer)
|
||||
}
|
||||
uv_free_interface_addresses(info, count);
|
||||
}
|
||||
|
||||
time_t now = time(NULL);
|
||||
if (ssb->is_peer_exchange && *ssb->seeds_host && now - ssb->last_seed_check > k_seed_check_interval_seconds)
|
||||
{
|
||||
seeds_t* seeds = tf_malloc(sizeof(seeds_t));
|
||||
*seeds = (seeds_t) { 0 };
|
||||
ssb->last_seed_check = now;
|
||||
tf_ssb_run_work(ssb, _tf_ssb_update_seeds_work, _tf_ssb_update_seeds_after_work, seeds);
|
||||
}
|
||||
}
|
||||
|
||||
int tf_ssb_server_open(tf_ssb_t* ssb, int port)
|
||||
@ -2951,6 +3039,21 @@ int tf_ssb_server_open(tf_ssb_t* ssb, int port)
|
||||
return status == 0 ? assigned_port : 0;
|
||||
}
|
||||
|
||||
int tf_ssb_server_get_port(tf_ssb_t* ssb)
|
||||
{
|
||||
int port = 0;
|
||||
if (ssb && ssb->server.data)
|
||||
{
|
||||
struct sockaddr_storage name = { 0 };
|
||||
int size = (int)sizeof(name);
|
||||
if (uv_tcp_getsockname(&ssb->server, (struct sockaddr*)&name, &size) == 0)
|
||||
{
|
||||
port = ntohs(((struct sockaddr_in*)&name)->sin_port);
|
||||
}
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
void tf_ssb_server_close(tf_ssb_t* ssb)
|
||||
{
|
||||
if (ssb->server.data && !uv_is_closing((uv_handle_t*)&ssb->server))
|
||||
@ -3020,7 +3123,7 @@ static void _tf_ssb_notify_broadcasts_changed(tf_ssb_t* ssb)
|
||||
}
|
||||
}
|
||||
|
||||
static void _tf_ssb_add_broadcast(tf_ssb_t* ssb, const tf_ssb_broadcast_t* broadcast)
|
||||
static void _tf_ssb_add_broadcast(tf_ssb_t* ssb, const tf_ssb_broadcast_t* broadcast, int expires_seconds)
|
||||
{
|
||||
if (memcmp(broadcast->pub, ssb->pub, sizeof(ssb->pub)) == 0)
|
||||
{
|
||||
@ -3034,6 +3137,7 @@ static void _tf_ssb_add_broadcast(tf_ssb_t* ssb, const tf_ssb_broadcast_t* broad
|
||||
if (node->tunnel_connection == broadcast->tunnel_connection && memcmp(node->pub, broadcast->pub, sizeof(node->pub)) == 0)
|
||||
{
|
||||
node->mtime = time(NULL);
|
||||
node->expires_at = node->mtime + expires_seconds;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -3046,6 +3150,7 @@ static void _tf_ssb_add_broadcast(tf_ssb_t* ssb, const tf_ssb_broadcast_t* broad
|
||||
node->addr.sin_addr.s_addr == broadcast->addr.sin_addr.s_addr && memcmp(node->pub, broadcast->pub, sizeof(node->pub)) == 0)
|
||||
{
|
||||
node->mtime = time(NULL);
|
||||
node->expires_at = node->mtime + expires_seconds;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -3062,12 +3167,22 @@ static void _tf_ssb_add_broadcast(tf_ssb_t* ssb, const tf_ssb_broadcast_t* broad
|
||||
node->next = ssb->broadcasts;
|
||||
node->ctime = time(NULL);
|
||||
node->mtime = node->ctime;
|
||||
node->expires_at = node->mtime + expires_seconds;
|
||||
ssb->broadcasts = node;
|
||||
ssb->broadcasts_count++;
|
||||
|
||||
_tf_ssb_notify_broadcasts_changed(ssb);
|
||||
}
|
||||
|
||||
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 };
|
||||
if (_tf_ssb_parse_broadcast(connection, &broadcast))
|
||||
{
|
||||
_tf_ssb_add_broadcast(ssb, &broadcast, expires_seconds);
|
||||
}
|
||||
}
|
||||
|
||||
static void _tf_ssb_on_broadcast_listener_recv(uv_udp_t* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags)
|
||||
{
|
||||
if (nread <= 0)
|
||||
@ -3084,18 +3199,19 @@ static void _tf_ssb_on_broadcast_listener_recv(uv_udp_t* handle, ssize_t nread,
|
||||
char* entry = strtok_r(buf->base, k_delim, &state);
|
||||
while (entry)
|
||||
{
|
||||
tf_ssb_broadcast_t broadcast = { 0 };
|
||||
tf_ssb_broadcast_t broadcast = { .origin = k_tf_ssb_broadcast_origin_discovery };
|
||||
if (_tf_ssb_parse_broadcast(entry, &broadcast))
|
||||
{
|
||||
_tf_ssb_add_broadcast(ssb, &broadcast);
|
||||
_tf_ssb_add_broadcast(ssb, &broadcast, k_udp_discovery_expires_seconds);
|
||||
}
|
||||
entry = strtok_r(NULL, k_delim, &state);
|
||||
}
|
||||
tf_free(buf->base);
|
||||
}
|
||||
|
||||
void tf_ssb_visit_broadcasts(
|
||||
tf_ssb_t* ssb, void (*callback)(const char* host, const struct sockaddr_in* addr, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data), void* user_data)
|
||||
void tf_ssb_visit_broadcasts(tf_ssb_t* ssb,
|
||||
void (*callback)(const char* host, const struct sockaddr_in* addr, tf_ssb_broadcast_origin_t origin, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data),
|
||||
void* user_data)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
tf_ssb_broadcast_t* next = NULL;
|
||||
@ -3105,7 +3221,7 @@ void tf_ssb_visit_broadcasts(
|
||||
if (node->mtime - now < 60)
|
||||
{
|
||||
tf_trace_begin(ssb->trace, "broadcast");
|
||||
callback(node->host, &node->addr, node->tunnel_connection, node->pub, user_data);
|
||||
callback(node->host, &node->addr, node->origin, node->tunnel_connection, node->pub, user_data);
|
||||
tf_trace_end(ssb->trace);
|
||||
}
|
||||
}
|
||||
@ -3118,7 +3234,7 @@ static void _tf_ssb_broadcast_cleanup_timer(uv_timer_t* timer)
|
||||
time_t now = time(NULL);
|
||||
for (tf_ssb_broadcast_t** it = &ssb->broadcasts; *it;)
|
||||
{
|
||||
if (!(*it)->tunnel_connection && (*it)->mtime < now - 10)
|
||||
if (!(*it)->tunnel_connection && now > (*it)->expires_at)
|
||||
{
|
||||
tf_ssb_broadcast_t* node = *it;
|
||||
*it = node->next;
|
||||
@ -3531,10 +3647,11 @@ void tf_ssb_notify_blob_want_added(tf_ssb_t* ssb, const char* id)
|
||||
void tf_ssb_connection_add_room_attendant(tf_ssb_connection_t* connection, const char* id)
|
||||
{
|
||||
tf_ssb_broadcast_t broadcast = {
|
||||
.origin = k_tf_ssb_broadcast_origin_room,
|
||||
.tunnel_connection = connection,
|
||||
};
|
||||
tf_ssb_id_str_to_bin(broadcast.pub, id);
|
||||
_tf_ssb_add_broadcast(connection->ssb, &broadcast);
|
||||
_tf_ssb_add_broadcast(connection->ssb, &broadcast, 0);
|
||||
}
|
||||
|
||||
void tf_ssb_connection_remove_room_attendant(tf_ssb_connection_t* connection, const char* id)
|
||||
@ -3915,6 +4032,26 @@ const char* tf_ssb_get_room_name(tf_ssb_t* ssb)
|
||||
return ssb->room_name;
|
||||
}
|
||||
|
||||
bool tf_ssb_is_replicator(tf_ssb_t* ssb)
|
||||
{
|
||||
return ssb->is_replicator;
|
||||
}
|
||||
|
||||
void tf_ssb_set_is_replicator(tf_ssb_t* ssb, bool is_replicator)
|
||||
{
|
||||
ssb->is_replicator = is_replicator;
|
||||
}
|
||||
|
||||
bool tf_ssb_is_peer_exchange(tf_ssb_t* ssb)
|
||||
{
|
||||
return ssb->is_peer_exchange;
|
||||
}
|
||||
|
||||
void tf_ssb_set_is_peer_exchange(tf_ssb_t* ssb, bool is_peer_exchange)
|
||||
{
|
||||
ssb->is_peer_exchange = is_peer_exchange;
|
||||
}
|
||||
|
||||
void tf_ssb_set_room_name(tf_ssb_t* ssb, const char* room_name)
|
||||
{
|
||||
tf_free(ssb->room_name);
|
||||
@ -3924,6 +4061,9 @@ void tf_ssb_set_room_name(tf_ssb_t* ssb, const char* room_name)
|
||||
typedef struct _update_settings_t
|
||||
{
|
||||
bool is_room;
|
||||
bool is_replicator;
|
||||
bool is_peer_exchange;
|
||||
char seeds_host[256];
|
||||
char room_name[1024];
|
||||
} update_settings_t;
|
||||
|
||||
@ -3980,7 +4120,10 @@ static void _tf_ssb_update_settings_work(tf_ssb_t* ssb, void* user_data)
|
||||
{
|
||||
update_settings_t* update = user_data;
|
||||
update->is_room = _get_global_setting_bool(ssb, "room", true);
|
||||
update->is_replicator = _get_global_setting_bool(ssb, "replicator", true);
|
||||
update->is_peer_exchange = _get_global_setting_bool(ssb, "peer_exchange", true);
|
||||
_get_global_setting_string(ssb, "room_name", update->room_name, sizeof(update->room_name));
|
||||
_get_global_setting_string(ssb, "seeds_host", update->seeds_host, sizeof(update->seeds_host));
|
||||
}
|
||||
|
||||
static void _tf_ssb_update_settings_after_work(tf_ssb_t* ssb, int result, void* user_data)
|
||||
@ -3988,6 +4131,9 @@ static void _tf_ssb_update_settings_after_work(tf_ssb_t* ssb, int result, void*
|
||||
update_settings_t* update = user_data;
|
||||
tf_ssb_set_is_room(ssb, update->is_room);
|
||||
tf_ssb_set_room_name(ssb, update->room_name);
|
||||
tf_ssb_set_is_peer_exchange(ssb, update->is_peer_exchange);
|
||||
tf_ssb_set_is_replicator(ssb, update->is_replicator);
|
||||
snprintf(ssb->seeds_host, sizeof(ssb->seeds_host), "%s", update->seeds_host);
|
||||
_tf_ssb_start_update_settings(ssb);
|
||||
tf_free(update);
|
||||
}
|
||||
|
92
src/ssb.db.c
92
src/ssb.db.c
@ -1644,14 +1644,13 @@ bool tf_ssb_db_get_account_password_hash(tf_ssb_t* ssb, const char* name, char*
|
||||
return result;
|
||||
}
|
||||
|
||||
bool tf_ssb_db_set_account_password(tf_ssb_t* ssb, const char* name, const char* password)
|
||||
bool tf_ssb_db_set_account_password(uv_loop_t* loop, sqlite3* db, JSContext* context, const char* name, const char* password)
|
||||
{
|
||||
JSContext* context = tf_ssb_get_context(ssb);
|
||||
bool result = false;
|
||||
static const int k_salt_length = 12;
|
||||
|
||||
char buffer[16];
|
||||
size_t bytes = uv_random(tf_ssb_get_loop(ssb), &(uv_random_t) { 0 }, buffer, sizeof(buffer), 0, NULL) == 0 ? sizeof(buffer) : 0;
|
||||
size_t bytes = uv_random(loop, &(uv_random_t) { 0 }, buffer, sizeof(buffer), 0, NULL) == 0 ? sizeof(buffer) : 0;
|
||||
char output[7 + 22 + 1];
|
||||
char* salt = crypt_gensalt_rn("$2b$", k_salt_length, buffer, bytes, output, sizeof(output));
|
||||
char hash_output[7 + 22 + 31 + 1];
|
||||
@ -1663,7 +1662,6 @@ bool tf_ssb_db_set_account_password(tf_ssb_t* ssb, const char* name, const char*
|
||||
size_t user_length = 0;
|
||||
const char* user_string = JS_ToCStringLen(context, &user_length, user_json);
|
||||
|
||||
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
|
||||
sqlite3_stmt* statement = NULL;
|
||||
if (sqlite3_prepare(db, "INSERT OR REPLACE INTO properties (id, key, value) VALUES ('auth', 'user:' || ?, ?)", -1, &statement, NULL) == SQLITE_OK)
|
||||
{
|
||||
@ -1673,7 +1671,6 @@ bool tf_ssb_db_set_account_password(tf_ssb_t* ssb, const char* name, const char*
|
||||
}
|
||||
sqlite3_finalize(statement);
|
||||
}
|
||||
tf_ssb_release_db_writer(ssb, db);
|
||||
|
||||
JS_FreeCString(context, user_string);
|
||||
JS_FreeValue(context, user_json);
|
||||
@ -1681,47 +1678,70 @@ bool tf_ssb_db_set_account_password(tf_ssb_t* ssb, const char* name, const char*
|
||||
return result;
|
||||
}
|
||||
|
||||
bool tf_ssb_db_register_account(tf_ssb_t* ssb, const char* name, const char* password)
|
||||
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 result = false;
|
||||
JSContext* context = tf_ssb_get_context(ssb);
|
||||
JSValue users_array = JS_UNDEFINED;
|
||||
|
||||
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
|
||||
sqlite3_stmt* statement = NULL;
|
||||
if (sqlite3_prepare(db, "SELECT value FROM properties WHERE id = 'auth' AND key = 'users'", -1, &statement, NULL) == SQLITE_OK)
|
||||
bool registration_allowed = _tf_ssb_db_get_global_setting_bool(db, "account_registration", true);
|
||||
if (registration_allowed)
|
||||
{
|
||||
if (sqlite3_step(statement) == SQLITE_ROW)
|
||||
sqlite3_stmt* statement = NULL;
|
||||
if (sqlite3_prepare(db, "SELECT value FROM properties WHERE id = 'auth' AND key = 'users'", -1, &statement, NULL) == SQLITE_OK)
|
||||
{
|
||||
users_array = JS_ParseJSON(context, (const char*)sqlite3_column_text(statement, 0), sqlite3_column_bytes(statement, 0), NULL);
|
||||
if (sqlite3_step(statement) == SQLITE_ROW)
|
||||
{
|
||||
users_array = JS_ParseJSON(context, (const char*)sqlite3_column_text(statement, 0), sqlite3_column_bytes(statement, 0), NULL);
|
||||
}
|
||||
sqlite3_finalize(statement);
|
||||
}
|
||||
sqlite3_finalize(statement);
|
||||
}
|
||||
if (JS_IsUndefined(users_array))
|
||||
{
|
||||
users_array = JS_NewArray(context);
|
||||
}
|
||||
int length = tf_util_get_length(context, users_array);
|
||||
JS_SetPropertyUint32(context, users_array, length, JS_NewString(context, name));
|
||||
|
||||
JSValue json = JS_JSONStringify(context, users_array, JS_NULL, JS_NULL);
|
||||
JS_FreeValue(context, users_array);
|
||||
size_t value_length = 0;
|
||||
const char* value = JS_ToCStringLen(context, &value_length, json);
|
||||
if (sqlite3_prepare(db, "INSERT OR REPLACE INTO properties (id, key, value) VALUES ('auth', 'users', ?)", -1, &statement, NULL) == SQLITE_OK)
|
||||
{
|
||||
if (sqlite3_bind_text(statement, 1, value, value_length, NULL) == SQLITE_OK)
|
||||
if (JS_IsUndefined(users_array))
|
||||
{
|
||||
tf_printf("added user to properties\n");
|
||||
result = sqlite3_step(statement) == SQLITE_DONE;
|
||||
users_array = JS_NewArray(context);
|
||||
}
|
||||
sqlite3_finalize(statement);
|
||||
}
|
||||
JS_FreeCString(context, value);
|
||||
JS_FreeValue(context, json);
|
||||
tf_ssb_release_db_writer(ssb, db);
|
||||
int length = tf_util_get_length(context, users_array);
|
||||
JS_SetPropertyUint32(context, users_array, length, JS_NewString(context, name));
|
||||
|
||||
result = result && tf_ssb_db_set_account_password(ssb, name, password);
|
||||
JSValue json = JS_JSONStringify(context, users_array, JS_NULL, JS_NULL);
|
||||
JS_FreeValue(context, users_array);
|
||||
size_t value_length = 0;
|
||||
const char* value = JS_ToCStringLen(context, &value_length, json);
|
||||
if (sqlite3_prepare(db, "INSERT OR REPLACE INTO properties (id, key, value) VALUES ('auth', 'users', ?)", -1, &statement, NULL) == SQLITE_OK)
|
||||
{
|
||||
if (sqlite3_bind_text(statement, 1, value, value_length, NULL) == SQLITE_OK)
|
||||
{
|
||||
tf_printf("added user to properties\n");
|
||||
result = sqlite3_step(statement) == SQLITE_DONE;
|
||||
}
|
||||
sqlite3_finalize(statement);
|
||||
}
|
||||
JS_FreeCString(context, value);
|
||||
JS_FreeValue(context, json);
|
||||
}
|
||||
|
||||
result = result && tf_ssb_db_set_account_password(loop, db, context, name, password);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
12
src/ssb.db.h
12
src/ssb.db.h
@ -360,21 +360,25 @@ bool tf_ssb_db_get_account_password_hash(tf_ssb_t* ssb, const char* name, char*
|
||||
|
||||
/**
|
||||
** Insert or update a user's hashed password in the database.
|
||||
** @param ssb The SSB instance.
|
||||
** @param loop The event loop.
|
||||
** @param db A DB writer.
|
||||
** @param context A JS context.
|
||||
** @param name The username.
|
||||
** @param password The raw password.
|
||||
** @return true if the hash of the password was successfully stored.
|
||||
*/
|
||||
bool tf_ssb_db_set_account_password(tf_ssb_t* ssb, const char* name, const char* password);
|
||||
bool tf_ssb_db_set_account_password(uv_loop_t* loop, sqlite3* db, JSContext* context, const char* name, const char* password);
|
||||
|
||||
/**
|
||||
** Add a user account to the database.
|
||||
** @param ssb The SSB instance.
|
||||
** @param loop The event loop.
|
||||
** @param db A DB writer.
|
||||
** @param context A JS context.
|
||||
** @param name The username to add.
|
||||
** @param password The user's raw password.
|
||||
** @return true If the user was added successfully.
|
||||
*/
|
||||
bool tf_ssb_db_register_account(tf_ssb_t* ssb, 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);
|
||||
|
||||
/**
|
||||
** Get an entry from the properties table.
|
||||
|
61
src/ssb.h
61
src/ssb.h
@ -28,6 +28,8 @@ enum
|
||||
k_ssb_rpc_flag_new_request = 0x10,
|
||||
|
||||
k_ssb_blob_bytes_max = 5 * 1024 * 1024,
|
||||
|
||||
k_ssb_peer_exchange_expires_seconds = 60 * 60,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -41,6 +43,16 @@ typedef enum _tf_ssb_change_t
|
||||
k_tf_ssb_change_update,
|
||||
} tf_ssb_change_t;
|
||||
|
||||
/**
|
||||
** The origin of a broadcast entry.
|
||||
*/
|
||||
typedef enum _tf_ssb_broadcast_origin_t
|
||||
{
|
||||
k_tf_ssb_broadcast_origin_discovery,
|
||||
k_tf_ssb_broadcast_origin_room,
|
||||
k_tf_ssb_broadcast_origin_peer_exchange,
|
||||
} tf_ssb_broadcast_origin_t;
|
||||
|
||||
/**
|
||||
** Flags describing the structure of a message.
|
||||
*/
|
||||
@ -299,8 +311,18 @@ bool tf_ssb_whoami(tf_ssb_t* ssb, char* out_id, size_t out_id_size);
|
||||
** @param callback The callback.
|
||||
** @param user_data User data for the callback.
|
||||
*/
|
||||
void tf_ssb_visit_broadcasts(
|
||||
tf_ssb_t* ssb, void (*callback)(const char* host, const struct sockaddr_in* addr, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data), void* user_data);
|
||||
void tf_ssb_visit_broadcasts(tf_ssb_t* ssb,
|
||||
void (*callback)(const char* host, const struct sockaddr_in* addr, tf_ssb_broadcast_origin_t origin, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data),
|
||||
void* user_data);
|
||||
|
||||
/**
|
||||
** Add a broadcast entry.
|
||||
** @param ssb The SSB instance.
|
||||
** @param connection The connection string to add.
|
||||
** @param origin The origin of the broadcast entry.
|
||||
** @param expires_seconds How long the broadcast entry should last.
|
||||
*/
|
||||
void tf_ssb_add_broadcast(tf_ssb_t* ssb, const char* connection, tf_ssb_broadcast_origin_t origin, int64_t expires_seconds);
|
||||
|
||||
/**
|
||||
** Get the identities of all active connections.
|
||||
@ -342,6 +364,13 @@ void tf_ssb_connect_str(tf_ssb_t* ssb, const char* address);
|
||||
*/
|
||||
int tf_ssb_server_open(tf_ssb_t* ssb, int port);
|
||||
|
||||
/**
|
||||
** Determine the port that a server is listening on.
|
||||
** @param ssb The SSB instance.
|
||||
** @return The port number, or 0 if not bound.
|
||||
*/
|
||||
int tf_ssb_server_get_port(tf_ssb_t* ssb);
|
||||
|
||||
/**
|
||||
** Stop listening for SHS connections.
|
||||
** @param ssb The SSB instance.
|
||||
@ -964,6 +993,34 @@ bool tf_ssb_is_room(tf_ssb_t* ssb);
|
||||
*/
|
||||
void tf_ssb_set_is_room(tf_ssb_t* ssb, bool is_room);
|
||||
|
||||
/**
|
||||
** Get whether the running server supports replication of messages and blobs.
|
||||
** @param ssb The SSB instance.
|
||||
** @return True if the server is a replicator.
|
||||
*/
|
||||
bool tf_ssb_is_replicator(tf_ssb_t* ssb);
|
||||
|
||||
/**
|
||||
** Set whether the running server supports replication of messages and blobs.
|
||||
** @param ssb The SSB instance.
|
||||
** @param is_replicator Whether to support replication.
|
||||
*/
|
||||
void tf_ssb_set_is_replicator(tf_ssb_t* ssb, bool is_replicator);
|
||||
|
||||
/**
|
||||
** Get whether the running server participates in peer exchange.
|
||||
** @param ssb The SSB instance.
|
||||
** @return True if the server participates in peer exchange.
|
||||
*/
|
||||
bool tf_ssb_is_peer_exchange(tf_ssb_t* ssb);
|
||||
|
||||
/**
|
||||
** Set whether the running server participates in peer exchange.
|
||||
** @param ssb The SSB instance.
|
||||
** @param is_peer_exchange Whether to participate in peer exchange.
|
||||
*/
|
||||
void tf_ssb_set_is_peer_exchange(tf_ssb_t* ssb, bool is_peer_exchange);
|
||||
|
||||
/**
|
||||
** Get the name of the room hosted by the running server.
|
||||
** @param ssb The SSB instance.
|
||||
|
@ -231,7 +231,11 @@ static void _tf_ssb_import_app_json(tf_ssb_t* ssb, uv_loop_t* loop, JSContext* c
|
||||
|
||||
void tf_ssb_import(tf_ssb_t* ssb, const char* user, const char* path)
|
||||
{
|
||||
if (strlen(path) > strlen(".json") && strcasecmp(path + strlen(path) - strlen(".json"), ".json") == 0)
|
||||
if (!path)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (strlen(path) > strlen(".json") && strcasecmp(path + strlen(path) - strlen(".json"), ".json") == 0)
|
||||
{
|
||||
_tf_ssb_import_app_json(ssb, tf_ssb_get_loop(ssb), tf_ssb_get_context(ssb), user, path);
|
||||
}
|
||||
|
15
src/ssb.js.c
15
src/ssb.js.c
@ -1450,12 +1450,25 @@ typedef struct _broadcasts_t
|
||||
int length;
|
||||
} broadcasts_t;
|
||||
|
||||
static void _tf_ssb_broadcasts_visit(const char* host, const struct sockaddr_in* addr, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data)
|
||||
static void _tf_ssb_broadcasts_visit(
|
||||
const char* host, const struct sockaddr_in* addr, tf_ssb_broadcast_origin_t origin, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data)
|
||||
{
|
||||
broadcasts_t* broadcasts = user_data;
|
||||
JSValue entry = JS_NewObject(broadcasts->context);
|
||||
char pubkey[k_id_base64_len];
|
||||
tf_ssb_id_bin_to_str(pubkey, sizeof(pubkey), pub);
|
||||
switch (origin)
|
||||
{
|
||||
case k_tf_ssb_broadcast_origin_discovery:
|
||||
JS_SetPropertyStr(broadcasts->context, entry, "origin", JS_NewString(broadcasts->context, "discovery"));
|
||||
break;
|
||||
case k_tf_ssb_broadcast_origin_room:
|
||||
JS_SetPropertyStr(broadcasts->context, entry, "origin", JS_NewString(broadcasts->context, "room"));
|
||||
break;
|
||||
case k_tf_ssb_broadcast_origin_peer_exchange:
|
||||
JS_SetPropertyStr(broadcasts->context, entry, "origin", JS_NewString(broadcasts->context, "peer_exchange"));
|
||||
break;
|
||||
}
|
||||
if (tunnel)
|
||||
{
|
||||
JS_SetPropertyStr(broadcasts->context, entry, "tunnel", JS_DupValue(broadcasts->context, tf_ssb_connection_get_object(tunnel)));
|
||||
|
238
src/ssb.rpc.c
238
src/ssb.rpc.c
@ -19,6 +19,7 @@
|
||||
#endif
|
||||
|
||||
static void _tf_ssb_connection_send_history_stream(tf_ssb_connection_t* connection, int32_t request_number, const char* author, int64_t sequence, bool keys, bool live);
|
||||
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 int64_t _get_global_setting_int64(tf_ssb_t* ssb, const char* name, int64_t default_value)
|
||||
@ -107,6 +108,12 @@ static void _tf_ssb_rpc_blobs_get(tf_ssb_connection_t* connection, uint8_t flags
|
||||
{
|
||||
return;
|
||||
}
|
||||
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
|
||||
if (!tf_ssb_is_replicator(ssb))
|
||||
{
|
||||
tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "blobs.get");
|
||||
return;
|
||||
}
|
||||
|
||||
tf_ssb_connection_add_request(connection, -request_number, "blobs.get", _tf_ssb_rpc_blobs_get_callback, NULL, NULL, NULL);
|
||||
JSContext* context = tf_ssb_connection_get_context(connection);
|
||||
@ -141,18 +148,51 @@ static void _tf_ssb_rpc_blobs_get(tf_ssb_connection_t* connection, uint8_t flags
|
||||
JS_FreeValue(context, ids);
|
||||
}
|
||||
|
||||
typedef struct _blobs_has_work_t
|
||||
{
|
||||
int64_t request_number;
|
||||
char id[k_id_base64_len];
|
||||
bool found;
|
||||
} blobs_has_work_t;
|
||||
|
||||
static void _tf_ssb_rpc_blobs_has_work(tf_ssb_connection_t* connection, void* user_data)
|
||||
{
|
||||
blobs_has_work_t* work = user_data;
|
||||
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
|
||||
work->found = tf_ssb_db_blob_has(ssb, work->id);
|
||||
}
|
||||
|
||||
static void _tf_ssb_rpc_blobs_has_after_work(tf_ssb_connection_t* connection, int status, void* user_data)
|
||||
{
|
||||
blobs_has_work_t* work = user_data;
|
||||
tf_ssb_connection_rpc_send(connection, k_ssb_rpc_flag_json | k_ssb_rpc_flag_end_error | k_ssb_rpc_flag_stream, -work->request_number, NULL,
|
||||
(const uint8_t*)(work->found ? "true" : "false"), strlen(work->found ? "true" : "false"), NULL, NULL, NULL);
|
||||
tf_free(work);
|
||||
}
|
||||
|
||||
static void _tf_ssb_rpc_blobs_has(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_t* ssb = tf_ssb_connection_get_ssb(connection);
|
||||
if (!tf_ssb_is_replicator(ssb))
|
||||
{
|
||||
tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "blobs.has");
|
||||
return;
|
||||
}
|
||||
JSContext* context = tf_ssb_connection_get_context(connection);
|
||||
JSValue ids = JS_GetPropertyStr(context, args, "args");
|
||||
JSValue id = JS_GetPropertyUint32(context, ids, 0);
|
||||
const char* id_str = JS_ToCString(context, id);
|
||||
bool has = tf_ssb_db_blob_has(ssb, id_str);
|
||||
|
||||
blobs_has_work_t* work = tf_malloc(sizeof(blobs_has_work_t));
|
||||
*work = (blobs_has_work_t) {
|
||||
.request_number = request_number,
|
||||
};
|
||||
snprintf(work->id, sizeof(work->id), "%s", id_str);
|
||||
tf_ssb_connection_run_work(connection, _tf_ssb_rpc_blobs_has_work, _tf_ssb_rpc_blobs_has_after_work, work);
|
||||
|
||||
JS_FreeCString(context, id_str);
|
||||
JS_FreeValue(context, id);
|
||||
JS_FreeValue(context, ids);
|
||||
tf_ssb_connection_rpc_send(connection, k_ssb_rpc_flag_json, -request_number, NULL, (const uint8_t*)(has ? "true" : "false"), strlen(has ? "true" : "false"), NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static void _tf_ssb_rpc_blob_wants_added_callback(tf_ssb_t* ssb, const char* id, void* user_data)
|
||||
@ -242,8 +282,13 @@ static void _tf_ssb_rpc_request_more_blobs(tf_ssb_connection_t* connection)
|
||||
static void _tf_ssb_rpc_blobs_createWants(
|
||||
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_blob_wants_t* blob_wants = tf_ssb_connection_get_blob_wants_state(connection);
|
||||
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
|
||||
if (!tf_ssb_is_replicator(ssb))
|
||||
{
|
||||
tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "blobs.createWants");
|
||||
return;
|
||||
}
|
||||
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);
|
||||
blob_wants->request_number = request_number;
|
||||
_tf_ssb_rpc_request_more_blobs(connection);
|
||||
@ -560,6 +605,7 @@ static void _tf_ssb_rpc_connection_blobs_createWants_callback(
|
||||
if (!JS_IsUndefined(name))
|
||||
{
|
||||
/* { name: "Error" } */
|
||||
tf_ssb_connection_remove_request(connection, -request_number);
|
||||
JS_FreeValue(context, name);
|
||||
return;
|
||||
}
|
||||
@ -855,6 +901,11 @@ static void _tf_ssb_rpc_createHistoryStream(
|
||||
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_t* ssb = tf_ssb_connection_get_ssb(connection);
|
||||
if (!tf_ssb_is_replicator(ssb))
|
||||
{
|
||||
tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "createHistoryStream");
|
||||
return;
|
||||
}
|
||||
JSContext* context = tf_ssb_get_context(ssb);
|
||||
JSValue arg_array = JS_GetPropertyStr(context, args, "args");
|
||||
JSValue arg = JS_GetPropertyUint32(context, arg_array, 0);
|
||||
@ -1086,6 +1137,7 @@ static void _tf_ssb_rpc_ebt_replicate(tf_ssb_connection_t* connection, uint8_t f
|
||||
if (_is_error(context, args))
|
||||
{
|
||||
/* TODO: Send createHistoryStream. */
|
||||
tf_ssb_connection_remove_request(connection, -request_number);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1157,6 +1209,12 @@ static void _tf_ssb_rpc_ebt_replicate_server(
|
||||
{
|
||||
return;
|
||||
}
|
||||
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
|
||||
if (!tf_ssb_is_replicator(ssb))
|
||||
{
|
||||
tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "ebt.replicate");
|
||||
return;
|
||||
}
|
||||
_tf_ssb_rpc_ebt_replicate(connection, flags, request_number, args, message, size, user_data);
|
||||
tf_ssb_connection_add_request(connection, -request_number, "ebt.replicate", _tf_ssb_rpc_ebt_replicate, NULL, NULL, NULL);
|
||||
}
|
||||
@ -1166,21 +1224,24 @@ static void _tf_ssb_rpc_connections_changed_callback(tf_ssb_t* ssb, tf_ssb_chang
|
||||
JSContext* context = tf_ssb_get_context(ssb);
|
||||
if (change == k_tf_ssb_change_connect)
|
||||
{
|
||||
JSValue message = JS_NewObject(context);
|
||||
JSValue name = JS_NewArray(context);
|
||||
JS_SetPropertyUint32(context, name, 0, JS_NewString(context, "blobs"));
|
||||
JS_SetPropertyUint32(context, name, 1, JS_NewString(context, "createWants"));
|
||||
JS_SetPropertyStr(context, message, "name", name);
|
||||
JS_SetPropertyStr(context, message, "type", JS_NewString(context, "source"));
|
||||
JS_SetPropertyStr(context, message, "args", JS_NewArray(context));
|
||||
tf_ssb_connection_rpc_send_json(connection, k_ssb_rpc_flag_stream | k_ssb_rpc_flag_new_request, tf_ssb_connection_next_request_number(connection), "blobs.createWants",
|
||||
message, _tf_ssb_rpc_connection_blobs_createWants_callback, NULL, NULL);
|
||||
JS_FreeValue(context, message);
|
||||
if (tf_ssb_is_replicator(ssb))
|
||||
{
|
||||
JSValue message = JS_NewObject(context);
|
||||
JSValue name = JS_NewArray(context);
|
||||
JS_SetPropertyUint32(context, name, 0, JS_NewString(context, "blobs"));
|
||||
JS_SetPropertyUint32(context, name, 1, JS_NewString(context, "createWants"));
|
||||
JS_SetPropertyStr(context, message, "name", name);
|
||||
JS_SetPropertyStr(context, message, "type", JS_NewString(context, "source"));
|
||||
JS_SetPropertyStr(context, message, "args", JS_NewArray(context));
|
||||
tf_ssb_connection_rpc_send_json(connection, k_ssb_rpc_flag_stream | k_ssb_rpc_flag_new_request, tf_ssb_connection_next_request_number(connection), "blobs.createWants",
|
||||
message, _tf_ssb_rpc_connection_blobs_createWants_callback, NULL, NULL);
|
||||
JS_FreeValue(context, message);
|
||||
}
|
||||
|
||||
if (tf_ssb_connection_is_client(connection))
|
||||
{
|
||||
message = JS_NewObject(context);
|
||||
name = JS_NewArray(context);
|
||||
JSValue message = JS_NewObject(context);
|
||||
JSValue name = JS_NewArray(context);
|
||||
JS_SetPropertyUint32(context, name, 0, JS_NewString(context, "tunnel"));
|
||||
JS_SetPropertyUint32(context, name, 1, JS_NewString(context, "isRoom"));
|
||||
JS_SetPropertyStr(context, message, "name", name);
|
||||
@ -1189,7 +1250,15 @@ static void _tf_ssb_rpc_connections_changed_callback(tf_ssb_t* ssb, tf_ssb_chang
|
||||
_tf_ssb_rpc_connection_tunnel_isRoom_callback, NULL, NULL);
|
||||
JS_FreeValue(context, message);
|
||||
|
||||
_tf_ssb_rpc_send_ebt_replicate(connection);
|
||||
if (tf_ssb_is_peer_exchange(ssb))
|
||||
{
|
||||
_tf_ssb_rpc_send_peers_exchange(connection);
|
||||
}
|
||||
|
||||
if (tf_ssb_is_replicator(ssb))
|
||||
{
|
||||
_tf_ssb_rpc_send_ebt_replicate(connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (change == k_tf_ssb_change_remove)
|
||||
@ -1303,6 +1372,142 @@ void tf_ssb_rpc_start_periodic(tf_ssb_t* ssb)
|
||||
_tf_ssb_rpc_start_delete_blobs(ssb, 30 * 1000);
|
||||
}
|
||||
|
||||
typedef struct _peers_exchange_t
|
||||
{
|
||||
tf_ssb_t* ssb;
|
||||
JSValue peers;
|
||||
} peers_exchange_t;
|
||||
|
||||
static void _tf_ssb_get_peers_exhange_callback(
|
||||
const char* host, const struct sockaddr_in* addr, tf_ssb_broadcast_origin_t origin, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data)
|
||||
{
|
||||
peers_exchange_t* data = user_data;
|
||||
if (origin == k_tf_ssb_broadcast_origin_peer_exchange)
|
||||
{
|
||||
char fullid[256] = { 0 };
|
||||
tf_base64_encode(pub, k_id_bin_len, fullid, sizeof(fullid));
|
||||
char* dot = strchr(fullid, '.');
|
||||
if (dot)
|
||||
{
|
||||
*dot = '\0';
|
||||
}
|
||||
|
||||
char connection[1024] = { 0 };
|
||||
snprintf(connection, sizeof(connection), "net:%s:%d~shs:%s", host, ntohs(addr->sin_port), fullid);
|
||||
|
||||
JSContext* context = tf_ssb_get_context(data->ssb);
|
||||
JS_SetPropertyStr(context, data->peers, connection, JS_NewInt32(context, 0));
|
||||
}
|
||||
}
|
||||
|
||||
static JSValue _tf_ssb_get_peers_exchange(tf_ssb_t* ssb)
|
||||
{
|
||||
JSContext* context = tf_ssb_get_context(ssb);
|
||||
JSValue peers = JS_NewObject(context);
|
||||
tf_ssb_visit_broadcasts(ssb, _tf_ssb_get_peers_exhange_callback, &(peers_exchange_t) { .ssb = ssb, .peers = peers });
|
||||
return peers;
|
||||
}
|
||||
|
||||
static void _tf_ssb_rpc_peers_exchange_internal(
|
||||
tf_ssb_connection_t* connection, uint8_t flags, int32_t request_number, JSValue args, const uint8_t* message, size_t size, void* user_data)
|
||||
{
|
||||
JSContext* context = tf_ssb_connection_get_context(connection);
|
||||
if (_is_error(context, args))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* The peer that participated in the exchange is now a peer exchange entry, too. */
|
||||
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
|
||||
if (*tf_ssb_connection_get_host(connection))
|
||||
{
|
||||
char fullid[k_id_base64_len] = { 0 };
|
||||
tf_ssb_connection_get_id(connection, fullid, sizeof(fullid));
|
||||
char* dot = strchr(fullid, '.');
|
||||
if (dot)
|
||||
{
|
||||
*dot = '\0';
|
||||
}
|
||||
|
||||
int port = tf_ssb_connection_get_port(connection);
|
||||
JSValue port_value = JS_GetPropertyStr(context, args, "port");
|
||||
JS_ToInt32(context, &port, port_value);
|
||||
JS_FreeValue(context, port_value);
|
||||
|
||||
char connection_string[1024] = { 0 };
|
||||
snprintf(connection_string, sizeof(connection_string), "net:%s:%d~shs:%s", tf_ssb_connection_get_host(connection), port, fullid + 1);
|
||||
tf_ssb_add_broadcast(ssb, connection_string, k_tf_ssb_broadcast_origin_peer_exchange, k_ssb_peer_exchange_expires_seconds);
|
||||
}
|
||||
|
||||
JSValue in_peers = JS_GetPropertyStr(context, args, "peers");
|
||||
|
||||
JSPropertyEnum* ptab = NULL;
|
||||
uint32_t plen = 0;
|
||||
if (JS_GetOwnPropertyNames(context, &ptab, &plen, in_peers, JS_GPN_STRING_MASK) == 0)
|
||||
{
|
||||
for (uint32_t i = 0; i < plen; ++i)
|
||||
{
|
||||
JSValue key = JS_AtomToString(context, ptab[i].atom);
|
||||
JSPropertyDescriptor desc;
|
||||
JSValue key_value = JS_NULL;
|
||||
if (JS_GetOwnProperty(context, &desc, args, ptab[i].atom) == 1)
|
||||
{
|
||||
key_value = desc.value;
|
||||
JS_FreeValue(context, desc.setter);
|
||||
JS_FreeValue(context, desc.getter);
|
||||
}
|
||||
const char* connection = JS_ToCString(context, key);
|
||||
int64_t timestamp = 0;
|
||||
JS_ToInt64(context, ×tamp, key_value);
|
||||
/* ADD BROADCAST connection: timestamp */
|
||||
JS_FreeCString(context, connection);
|
||||
JS_FreeValue(context, key);
|
||||
JS_FreeValue(context, key_value);
|
||||
}
|
||||
for (uint32_t i = 0; i < plen; ++i)
|
||||
{
|
||||
JS_FreeAtom(context, ptab[i].atom);
|
||||
}
|
||||
js_free(context, ptab);
|
||||
}
|
||||
JS_FreeValue(context, in_peers);
|
||||
}
|
||||
|
||||
static void _tf_ssb_rpc_send_peers_exchange(tf_ssb_connection_t* connection)
|
||||
{
|
||||
int32_t request_number = tf_ssb_connection_next_request_number(connection);
|
||||
JSContext* context = tf_ssb_connection_get_context(connection);
|
||||
JSValue message = JS_NewObject(context);
|
||||
JSValue name = JS_NewArray(context);
|
||||
JS_SetPropertyUint32(context, name, 0, JS_NewString(context, "peers"));
|
||||
JS_SetPropertyUint32(context, name, 1, JS_NewString(context, "exchange"));
|
||||
JS_SetPropertyStr(context, message, "name", name);
|
||||
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
|
||||
JS_SetPropertyStr(context, message, "port", JS_NewInt32(context, tf_ssb_server_get_port(ssb)));
|
||||
JS_SetPropertyStr(context, message, "peers", _tf_ssb_get_peers_exchange(ssb));
|
||||
tf_ssb_connection_rpc_send_json(connection, k_ssb_rpc_flag_new_request, request_number, "peers.exchange", message, _tf_ssb_rpc_peers_exchange_internal, NULL, NULL);
|
||||
JS_FreeValue(context, message);
|
||||
}
|
||||
|
||||
static void _tf_ssb_rpc_peers_exchange(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_t* ssb = tf_ssb_connection_get_ssb(connection);
|
||||
if (!tf_ssb_is_peer_exchange(ssb))
|
||||
{
|
||||
tf_ssb_connection_rpc_send_error_method_not_allowed(connection, flags, -request_number, "peers.exchange");
|
||||
return;
|
||||
}
|
||||
|
||||
_tf_ssb_rpc_peers_exchange_internal(connection, flags, request_number, args, message, size, user_data);
|
||||
|
||||
JSContext* context = tf_ssb_connection_get_context(connection);
|
||||
JSValue out_message = JS_NewObject(context);
|
||||
JS_SetPropertyStr(context, out_message, "port", JS_NewInt32(context, tf_ssb_server_get_port(ssb)));
|
||||
JS_SetPropertyStr(context, out_message, "peers", _tf_ssb_get_peers_exchange(ssb));
|
||||
tf_ssb_connection_rpc_send_json(connection, flags, -request_number, NULL, out_message, NULL, NULL, NULL);
|
||||
JS_FreeValue(context, out_message);
|
||||
}
|
||||
|
||||
void tf_ssb_rpc_register(tf_ssb_t* ssb)
|
||||
{
|
||||
tf_ssb_add_connections_changed_callback(ssb, _tf_ssb_rpc_connections_changed_callback, NULL, NULL);
|
||||
@ -1316,4 +1521,5 @@ void tf_ssb_rpc_register(tf_ssb_t* ssb)
|
||||
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "room", "attendants", NULL }, _tf_ssb_rpc_room_attendants, NULL, NULL); /* SOURCE */
|
||||
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "createHistoryStream", NULL }, _tf_ssb_rpc_createHistoryStream, NULL, NULL); /* SOURCE */
|
||||
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "ebt", "replicate", NULL }, _tf_ssb_rpc_ebt_replicate_server, NULL, NULL); /* DUPLEX */
|
||||
tf_ssb_add_rpc_callback(ssb, (const char*[]) { "peers", "exchange", NULL }, _tf_ssb_rpc_peers_exchange, NULL, NULL); /* ASYNC */
|
||||
}
|
||||
|
115
src/ssb.tests.c
115
src/ssb.tests.c
@ -250,22 +250,51 @@ void tf_ssb_test_ssb(const tf_test_options_t* options)
|
||||
tf_printf("Waiting for connection.\n");
|
||||
while (test.connection_count0 != 1 || test.connection_count1 != 1)
|
||||
{
|
||||
tf_ssb_set_main_thread(ssb0, true);
|
||||
tf_ssb_set_main_thread(ssb1, true);
|
||||
uv_run(&loop, UV_RUN_ONCE);
|
||||
tf_ssb_set_main_thread(ssb0, false);
|
||||
tf_ssb_set_main_thread(ssb1, false);
|
||||
}
|
||||
tf_ssb_server_close(ssb0);
|
||||
|
||||
tf_printf("Waiting for messages.\n");
|
||||
while (_ssb_test_count_messages(ssb1) < 3)
|
||||
{
|
||||
tf_ssb_set_main_thread(ssb0, true);
|
||||
tf_ssb_set_main_thread(ssb1, true);
|
||||
uv_run(&loop, UV_RUN_ONCE);
|
||||
tf_ssb_set_main_thread(ssb0, false);
|
||||
tf_ssb_set_main_thread(ssb1, false);
|
||||
}
|
||||
|
||||
tf_printf("Waiting for blob.\n");
|
||||
while (!tf_ssb_db_blob_get(ssb1, blob_id, NULL, NULL))
|
||||
{
|
||||
tf_ssb_set_main_thread(ssb0, true);
|
||||
tf_ssb_set_main_thread(ssb1, true);
|
||||
uv_run(&loop, UV_RUN_ONCE);
|
||||
tf_ssb_set_main_thread(ssb0, false);
|
||||
tf_ssb_set_main_thread(ssb1, false);
|
||||
}
|
||||
|
||||
JSContext* context = tf_ssb_get_context(ssb1);
|
||||
JSValue message = JS_NewObject(context);
|
||||
JSValue name = JS_NewArray(context);
|
||||
JS_SetPropertyUint32(context, name, 0, JS_NewString(context, "blobs"));
|
||||
JS_SetPropertyUint32(context, name, 1, JS_NewString(context, "has"));
|
||||
JS_SetPropertyStr(context, message, "name", name);
|
||||
JSValue args = JS_NewArray(context);
|
||||
JS_SetPropertyUint32(context, args, 0, JS_NewString(context, blob_id));
|
||||
JS_SetPropertyStr(context, message, "args", args);
|
||||
JS_SetPropertyStr(context, message, "type", JS_NewString(context, "async"));
|
||||
|
||||
tf_ssb_connection_t* connections[4] = { 0 };
|
||||
tf_ssb_get_connections(ssb1, connections, 4);
|
||||
int64_t request_number = tf_ssb_connection_next_request_number(connections[0]);
|
||||
tf_ssb_connection_rpc_send_json(connections[0], k_ssb_rpc_flag_stream | k_ssb_rpc_flag_new_request, request_number, "blobs.has", message, NULL, NULL, NULL);
|
||||
JS_FreeValue(context, message);
|
||||
|
||||
uint8_t* b1;
|
||||
size_t s1 = 0;
|
||||
b = tf_ssb_db_blob_get(ssb1, blob_id, &b1, &s1);
|
||||
@ -293,14 +322,22 @@ void tf_ssb_test_ssb(const tf_test_options_t* options)
|
||||
|
||||
while (count0 == 0)
|
||||
{
|
||||
tf_ssb_set_main_thread(ssb0, true);
|
||||
tf_ssb_set_main_thread(ssb1, true);
|
||||
uv_run(&loop, UV_RUN_ONCE);
|
||||
tf_ssb_set_main_thread(ssb0, false);
|
||||
tf_ssb_set_main_thread(ssb1, false);
|
||||
}
|
||||
tf_ssb_remove_message_added_callback(ssb0, _message_added, &count0);
|
||||
|
||||
tf_printf("Waiting for message from other.\n");
|
||||
while (count1 == 0)
|
||||
{
|
||||
tf_ssb_set_main_thread(ssb0, true);
|
||||
tf_ssb_set_main_thread(ssb1, true);
|
||||
uv_run(&loop, UV_RUN_ONCE);
|
||||
tf_ssb_set_main_thread(ssb0, false);
|
||||
tf_ssb_set_main_thread(ssb1, false);
|
||||
}
|
||||
tf_ssb_remove_message_added_callback(ssb1, _message_added, &count1);
|
||||
tf_printf("done\n");
|
||||
@ -311,7 +348,11 @@ void tf_ssb_test_ssb(const tf_test_options_t* options)
|
||||
uv_close((uv_handle_t*)&idle1, NULL);
|
||||
|
||||
tf_printf("final run\n");
|
||||
tf_ssb_set_main_thread(ssb0, true);
|
||||
tf_ssb_set_main_thread(ssb1, true);
|
||||
uv_run(&loop, UV_RUN_DEFAULT);
|
||||
tf_ssb_set_main_thread(ssb0, false);
|
||||
tf_ssb_set_main_thread(ssb1, false);
|
||||
tf_printf("done\n");
|
||||
|
||||
tf_printf("destroy 0\n");
|
||||
@ -323,7 +364,7 @@ void tf_ssb_test_ssb(const tf_test_options_t* options)
|
||||
uv_loop_close(&loop);
|
||||
}
|
||||
|
||||
static void _broadcasts_visit(const char* host, const struct sockaddr_in* addr, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data)
|
||||
static void _broadcasts_visit(const char* host, const struct sockaddr_in* addr, tf_ssb_broadcast_origin_t origin, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data)
|
||||
{
|
||||
int* count = user_data;
|
||||
(*count)++;
|
||||
@ -747,7 +788,8 @@ static void _break_in_a_bit(tf_ssb_t* ssb, tf_ssb_connection_t* connection, cons
|
||||
uv_timer_start(&data->timer, _close_callback, 3000, 0);
|
||||
}
|
||||
|
||||
static void _ssb_test_room_broadcasts_visit(const char* host, const struct sockaddr_in* addr, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data)
|
||||
static void _ssb_test_room_broadcasts_visit(
|
||||
const char* host, const struct sockaddr_in* addr, tf_ssb_broadcast_origin_t origin, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data)
|
||||
{
|
||||
tf_ssb_t* ssb = user_data;
|
||||
char id[k_id_base64_len] = { 0 };
|
||||
@ -869,4 +911,73 @@ void tf_ssb_test_encrypt(const tf_test_options_t* options)
|
||||
printf("returned %d\n", WEXITSTATUS(result));
|
||||
assert(WEXITSTATUS(result) == 0);
|
||||
}
|
||||
|
||||
static void _count_broadcasts_callback(
|
||||
const char* host, const struct sockaddr_in* addr, tf_ssb_broadcast_origin_t origin, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data)
|
||||
{
|
||||
int* count = user_data;
|
||||
(*count)++;
|
||||
}
|
||||
|
||||
static int _count_broadcasts(tf_ssb_t* ssb)
|
||||
{
|
||||
int count = 0;
|
||||
tf_ssb_visit_broadcasts(ssb, _count_broadcasts_callback, &count);
|
||||
return count;
|
||||
}
|
||||
|
||||
void tf_ssb_test_peer_exchange(const tf_test_options_t* options)
|
||||
{
|
||||
uv_loop_t loop = { 0 };
|
||||
uv_loop_init(&loop);
|
||||
|
||||
unlink("out/test_db0.sqlite");
|
||||
tf_ssb_t* ssb0 = tf_ssb_create(&loop, NULL, "file:out/test_db0.sqlite", NULL);
|
||||
tf_ssb_set_is_room(ssb0, false);
|
||||
tf_ssb_set_is_replicator(ssb0, false);
|
||||
tf_ssb_set_is_peer_exchange(ssb0, true);
|
||||
tf_ssb_register(tf_ssb_get_context(ssb0), ssb0);
|
||||
tf_ssb_server_open(ssb0, 12347);
|
||||
|
||||
unlink("out/test_db1.sqlite");
|
||||
tf_ssb_t* ssb1 = tf_ssb_create(&loop, NULL, "file:out/test_db1.sqlite", NULL);
|
||||
tf_ssb_set_is_room(ssb1, false);
|
||||
tf_ssb_set_is_replicator(ssb1, false);
|
||||
tf_ssb_set_is_peer_exchange(ssb1, true);
|
||||
tf_ssb_register(tf_ssb_get_context(ssb1), ssb1);
|
||||
tf_ssb_server_open(ssb1, 12348);
|
||||
|
||||
unlink("out/test_db2.sqlite");
|
||||
tf_ssb_t* ssb2 = tf_ssb_create(&loop, NULL, "file:out/test_db2.sqlite", NULL);
|
||||
tf_ssb_set_is_room(ssb2, false);
|
||||
tf_ssb_set_is_replicator(ssb2, false);
|
||||
tf_ssb_set_is_peer_exchange(ssb2, true);
|
||||
tf_ssb_register(tf_ssb_get_context(ssb2), ssb2);
|
||||
tf_ssb_server_open(ssb2, 12349);
|
||||
|
||||
char id0[k_id_base64_len] = { 0 };
|
||||
tf_ssb_whoami(ssb0, id0, sizeof(id0));
|
||||
uint8_t id0bin[k_id_bin_len];
|
||||
tf_ssb_id_str_to_bin(id0bin, id0);
|
||||
tf_ssb_connect(ssb1, "127.0.0.1", 12347, id0bin);
|
||||
tf_ssb_connect(ssb2, "127.0.0.1", 12347, id0bin);
|
||||
|
||||
while (_count_broadcasts(ssb0) != 2 || _count_broadcasts(ssb1) != 1 || _count_broadcasts(ssb2) != 1)
|
||||
{
|
||||
uv_run(&loop, UV_RUN_ONCE);
|
||||
}
|
||||
|
||||
tf_ssb_send_close(ssb0);
|
||||
tf_ssb_send_close(ssb1);
|
||||
tf_ssb_send_close(ssb2);
|
||||
|
||||
tf_ssb_destroy(ssb0);
|
||||
tf_ssb_destroy(ssb1);
|
||||
tf_ssb_destroy(ssb2);
|
||||
|
||||
uv_run(&loop, UV_RUN_DEFAULT);
|
||||
|
||||
uv_loop_close(&loop);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -53,4 +53,10 @@ void tf_ssb_test_go_ssb_room(const tf_test_options_t* options);
|
||||
*/
|
||||
void tf_ssb_test_encrypt(const tf_test_options_t* options);
|
||||
|
||||
/**
|
||||
** Test peer exchange.
|
||||
** @param options The test options.
|
||||
*/
|
||||
void tf_ssb_test_peer_exchange(const tf_test_options_t* options);
|
||||
|
||||
/** @} */
|
||||
|
38
src/task.c
38
src/task.c
@ -140,8 +140,7 @@ typedef struct _tf_task_t
|
||||
float idle_percent;
|
||||
float thread_percent;
|
||||
|
||||
uv_idle_t idle;
|
||||
uv_prepare_t prepare;
|
||||
uv_async_t run_jobs_async;
|
||||
uv_signal_t sig_term;
|
||||
uv_signal_t sig_int;
|
||||
|
||||
@ -208,7 +207,6 @@ static void _tf_task_sendPromiseExportMessage(tf_task_t* from, tf_taskstub_t* to
|
||||
static JSValue _tf_task_executeSource(tf_task_t* task, const char* source, const char* name);
|
||||
static tf_taskstub_t* _tf_task_get_stub(tf_task_t* task, taskid_t id);
|
||||
static void _tf_task_release_export(tf_taskstub_t* stub, exportid_t exportId);
|
||||
static void _tf_task_run_jobs_prepare(uv_prepare_t* prepare);
|
||||
static void _timeout_unlink(tf_task_t* task, timeout_t* timeout);
|
||||
static void _timeout_closed(uv_handle_t* handle);
|
||||
|
||||
@ -1521,25 +1519,20 @@ static bool _tf_task_run_jobs(tf_task_t* task)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _tf_task_run_jobs_idle(uv_idle_t* idle)
|
||||
static void _tf_task_run_jobs_async(uv_async_t* async)
|
||||
{
|
||||
tf_task_t* task = idle->data;
|
||||
if (!_tf_task_run_jobs(task))
|
||||
tf_task_t* task = async->data;
|
||||
if (_tf_task_run_jobs(task))
|
||||
{
|
||||
/* No more jobs. Don't try again as actively. */
|
||||
uv_idle_stop(&task->idle);
|
||||
uv_prepare_start(&task->prepare, _tf_task_run_jobs_prepare);
|
||||
uv_async_send(async);
|
||||
}
|
||||
}
|
||||
|
||||
static void _tf_task_run_jobs_prepare(uv_prepare_t* prepare)
|
||||
void tf_task_check_jobs(tf_task_t* task)
|
||||
{
|
||||
tf_task_t* task = prepare->data;
|
||||
if (_tf_task_run_jobs(task))
|
||||
if (JS_IsJobPending(task->_runtime))
|
||||
{
|
||||
/* More jobs. We can run again immediately. */
|
||||
uv_idle_start(&task->idle, _tf_task_run_jobs_idle);
|
||||
uv_prepare_stop(&task->prepare);
|
||||
uv_async_send(&task->run_jobs_async);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1636,13 +1629,9 @@ tf_task_t* tf_task_create()
|
||||
uv_timer_init(&task->_loop, &task->gc_timer);
|
||||
uv_timer_start(&task->gc_timer, _tf_task_gc_timer, 1000, 1000);
|
||||
uv_unref((uv_handle_t*)&task->gc_timer);
|
||||
task->idle.data = task;
|
||||
uv_idle_init(&task->_loop, &task->idle);
|
||||
uv_unref((uv_handle_t*)&task->idle);
|
||||
task->prepare.data = task;
|
||||
uv_prepare_init(&task->_loop, &task->prepare);
|
||||
uv_unref((uv_handle_t*)&task->prepare);
|
||||
uv_idle_start(&task->idle, _tf_task_run_jobs_idle);
|
||||
task->run_jobs_async.data = task;
|
||||
uv_async_init(&task->_loop, &task->run_jobs_async, _tf_task_run_jobs_async);
|
||||
uv_unref((uv_handle_t*)&task->run_jobs_async);
|
||||
task->sig_term.data = task;
|
||||
uv_signal_init(&task->_loop, &task->sig_term);
|
||||
uv_signal_start(&task->sig_term, _tf_task_signal_shutdown, SIGTERM);
|
||||
@ -1910,14 +1899,13 @@ void tf_task_destroy(tf_task_t* task)
|
||||
{
|
||||
uv_close((uv_handle_t*)&task->gc_timer, _tf_task_on_handle_close);
|
||||
}
|
||||
uv_close((uv_handle_t*)&task->idle, _tf_task_on_handle_close);
|
||||
uv_close((uv_handle_t*)&task->prepare, _tf_task_on_handle_close);
|
||||
uv_close((uv_handle_t*)&task->run_jobs_async, _tf_task_on_handle_close);
|
||||
uv_signal_stop(&task->sig_term);
|
||||
uv_close((uv_handle_t*)&task->sig_term, _tf_task_on_handle_close);
|
||||
uv_signal_stop(&task->sig_int);
|
||||
uv_close((uv_handle_t*)&task->sig_int, _tf_task_on_handle_close);
|
||||
|
||||
while (task->trace_timer.data || task->gc_timer.data || task->idle.data || task->prepare.data || task->sig_term.data || task->sig_int.data)
|
||||
while (task->trace_timer.data || task->gc_timer.data || task->run_jobs_async.data || task->sig_term.data || task->sig_int.data)
|
||||
{
|
||||
uv_run(&task->_loop, UV_RUN_ONCE);
|
||||
}
|
||||
|
@ -364,4 +364,11 @@ tf_android_start_service_t* tf_task_get_android_start_service();
|
||||
*/
|
||||
tf_android_stop_service_t* tf_task_get_android_stop_service();
|
||||
|
||||
/**
|
||||
** Check for JS jobs that need to be run. Generally to be called post-JS_Call
|
||||
** in tf_util_report_error.
|
||||
** @param task The task.
|
||||
*/
|
||||
void tf_task_check_jobs(tf_task_t* task);
|
||||
|
||||
/** @} */
|
||||
|
@ -915,6 +915,7 @@ void tf_tests(const tf_test_options_t* options)
|
||||
_tf_test_run(options, "auto", _test_auto, false);
|
||||
_tf_test_run(options, "go-ssb-room", tf_ssb_test_go_ssb_room, true);
|
||||
_tf_test_run(options, "encrypt", tf_ssb_test_encrypt, false);
|
||||
_tf_test_run(options, "peer_exchange", tf_ssb_test_peer_exchange, false);
|
||||
tf_printf("Tests completed.\n");
|
||||
#endif
|
||||
}
|
||||
|
@ -211,6 +211,7 @@ static JSValue _util_print(JSContext* context, JSValueConst this_val, int argc,
|
||||
bool tf_util_report_error(JSContext* context, JSValue value)
|
||||
{
|
||||
bool is_error = false;
|
||||
tf_task_t* task = tf_task_get(context);
|
||||
if (JS_IsError(context, value))
|
||||
{
|
||||
const char* string = JS_ToCString(context, value);
|
||||
@ -226,13 +227,11 @@ bool tf_util_report_error(JSContext* context, JSValue value)
|
||||
}
|
||||
JS_FreeValue(context, stack);
|
||||
|
||||
tf_task_t* task = tf_task_get(context);
|
||||
tf_task_send_error_to_parent(task, value);
|
||||
is_error = true;
|
||||
}
|
||||
else if (JS_IsException(value))
|
||||
{
|
||||
tf_task_t* task = tf_task_get(context);
|
||||
if (!tf_task_send_error_to_parent(task, value))
|
||||
{
|
||||
JSValue exception = JS_GetException(context);
|
||||
@ -241,6 +240,7 @@ bool tf_util_report_error(JSContext* context, JSValue value)
|
||||
}
|
||||
is_error = true;
|
||||
}
|
||||
tf_task_check_jobs(task);
|
||||
return is_error;
|
||||
}
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
#define VERSION_NUMBER "0.0.21"
|
||||
#define VERSION_NAME "What are we even doing here?"
|
||||
#define VERSION_NUMBER "0.0.22"
|
||||
#define VERSION_NAME "Get born soon."
|
||||
|
@ -80,9 +80,9 @@ build_the_thing() {
|
||||
pwd
|
||||
echo "./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS" && \
|
||||
./Configure $SSL_TARGET $OPTIONS $GLOBAL_OPTIONS && \
|
||||
make clean && \
|
||||
make build_generated && \
|
||||
make libcrypto.a libssl.a || exit 128
|
||||
make -s clean && \
|
||||
make -s build_generated && \
|
||||
make -s libcrypto.a libssl.a || exit 128
|
||||
}
|
||||
|
||||
for build_target in $BUILD_TARGETS
|
||||
|
@ -1,4 +1,4 @@
|
||||
VERSION=3.1.4
|
||||
VERSION=3.2.0
|
||||
wget https://cdn.jsdelivr.net/gh/lit/dist@$VERSION/all/lit-all.min.js -O deps/lit/lit-all.min.js
|
||||
wget https://cdn.jsdelivr.net/gh/lit/dist@$VERSION/all/lit-all.min.js.map -O deps/lit/lit-all.min.js.map
|
||||
cp -fv deps/lit/* apps/blog/
|
||||
|
Reference in New Issue
Block a user