forked from cory/tildefriends
		
	Compare commits
	
		
			10 Commits
		
	
	
		
			4485234980
			...
			user_setti
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 58dbf42a3a | |||
| a1f221879b | |||
| 2a928dcafc | |||
| 5474c5a101 | |||
| 4b7261fa20 | |||
| 4992ff3a2d | |||
| 88ee0aa6f0 | |||
| 392206c19e | |||
| f9e95e5733 | |||
| 1444c945de | 
							
								
								
									
										21
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							| @@ -1,21 +0,0 @@ | |||||||
| [submodule "deps/zlib"] |  | ||||||
| 	path = deps/zlib |  | ||||||
| 	url = https://github.com/madler/zlib.git |  | ||||||
| [submodule "deps/libsodium"] |  | ||||||
| 	path = deps/libsodium |  | ||||||
| 	url = https://github.com/jedisct1/libsodium.git |  | ||||||
| [submodule "deps/quickjs"] |  | ||||||
| 	path = deps/quickjs |  | ||||||
| 	url = https://github.com/bellard/quickjs.git |  | ||||||
| [submodule "deps/crypt_blowfish"] |  | ||||||
| 	path = deps/crypt_blowfish |  | ||||||
| 	url = https://github.com/openwall/crypt_blowfish.git |  | ||||||
| [submodule "deps/libbacktrace"] |  | ||||||
| 	path = deps/libbacktrace |  | ||||||
| 	url = https://github.com/ianlancetaylor/libbacktrace.git |  | ||||||
| [submodule "deps/libuv"] |  | ||||||
| 	path = deps/libuv |  | ||||||
| 	url = https://github.com/libuv/libuv.git |  | ||||||
| [submodule "deps/picohttpparser"] |  | ||||||
| 	path = deps/picohttpparser |  | ||||||
| 	url = https://github.com/h2o/picohttpparser.git |  | ||||||
							
								
								
									
										69
									
								
								GNUmakefile
									
									
									
									
									
								
							
							
						
						
									
										69
									
								
								GNUmakefile
									
									
									
									
									
								
							| @@ -3,11 +3,11 @@ | |||||||
| MAKEFLAGS += --warn-undefined-variables | MAKEFLAGS += --warn-undefined-variables | ||||||
| MAKEFLAGS += --no-builtin-rules | MAKEFLAGS += --no-builtin-rules | ||||||
|  |  | ||||||
| VERSION_CODE := 19 | VERSION_CODE := 17 | ||||||
| VERSION_NUMBER := 0.0.19-wip | VERSION_NUMBER := 0.0.17-wip | ||||||
| VERSION_NAME := Don't let your loyalty become a burden. | VERSION_NAME := Please enjoy responsibly. | ||||||
|  |  | ||||||
| SQLITE_URL := https://www.sqlite.org/2024/sqlite-amalgamation-3450300.zip | SQLITE_URL := https://www.sqlite.org/2024/sqlite-amalgamation-3450200.zip | ||||||
| LIBUV_URL := https://dist.libuv.org/dist/v1.48.0/libuv-v1.48.0.tar.gz | LIBUV_URL := https://dist.libuv.org/dist/v1.48.0/libuv-v1.48.0.tar.gz | ||||||
|  |  | ||||||
| PROJECT = tildefriends | PROJECT = tildefriends | ||||||
| @@ -17,7 +17,17 @@ UNAME_M := $(shell uname -m) | |||||||
|  |  | ||||||
| ANDROID_SDK ?= ~/Android/Sdk | ANDROID_SDK ?= ~/Android/Sdk | ||||||
|  |  | ||||||
| HAVE_WIN := 0 | ifeq ($(UNAME_M),x86_64) | ||||||
|  | ifneq ($(UNAME_S),Haiku) | ||||||
|  | debug: CFLAGS += -fsanitize=address -fsanitize=undefined -fno-common | ||||||
|  | debug: LDFLAGS += -fsanitize=address -fsanitize=undefined | ||||||
|  | endif | ||||||
|  | endif | ||||||
|  |  | ||||||
|  | ifeq ($(UNAME_M),aarch64) | ||||||
|  | debug: CFLAGS += -fsanitize=address -fsanitize=undefined -fno-common | ||||||
|  | debug: LDFLAGS += -fsanitize=address -fsanitize=undefined | ||||||
|  | endif | ||||||
|  |  | ||||||
| ifeq ($(UNAME_S),Darwin) | ifeq ($(UNAME_S),Darwin) | ||||||
| BUILD_TYPES := macosdebug macosrelease iosdebug iosrelease iossimdebug iossimrelease | BUILD_TYPES := macosdebug macosrelease iosdebug iosrelease iossimdebug iossimrelease | ||||||
| @@ -41,6 +51,7 @@ LDFLAGS += \ | |||||||
| 	-lc++abi | 	-lc++abi | ||||||
| HAVE_ANDROID := 0 | HAVE_ANDROID := 0 | ||||||
| HAVE_LINUX_IOS := 0 | HAVE_LINUX_IOS := 0 | ||||||
|  | HAVE_WIN := 0 | ||||||
| else | else | ||||||
| $(error Unexpected host platform $(UNAME_S).) | $(error Unexpected host platform $(UNAME_S).) | ||||||
| endif | endif | ||||||
| @@ -57,11 +68,11 @@ CFLAGS += \ | |||||||
| 	-fno-exceptions \ | 	-fno-exceptions \ | ||||||
| 	-g | 	-g | ||||||
|  |  | ||||||
|  | ANDROID_BUILD_TOOLS := $(ANDROID_SDK)/build-tools/34.0.0 | ||||||
|  | ANDROID_PLATFORM := $(ANDROID_SDK)/platforms/android-34 | ||||||
|  | ANDROID_NDK ?= $(ANDROID_SDK)/ndk/26.2.11394342 | ||||||
| ANDROID_MIN_SDK_VERSION := 24 | ANDROID_MIN_SDK_VERSION := 24 | ||||||
| ANDROID_TARGET_SDK_VERSION := 34 | 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) |  | ||||||
| ANDROID_NDK ?= $(ANDROID_SDK)/ndk/26.2.11394342 |  | ||||||
|  |  | ||||||
| ANDROID_ARMV7A_TARGETS := \ | ANDROID_ARMV7A_TARGETS := \ | ||||||
| 	out/androiddebug-armv7a/tildefriends \ | 	out/androiddebug-armv7a/tildefriends \ | ||||||
| @@ -211,18 +222,6 @@ $(IOS_TARGETS): LDFLAGS += -Ldeps/openssl/ios/ios64-xcrun/usr/local/lib | |||||||
| $(IOSSIM_TARGETS): CFLAGS += -Ideps/openssl/ios/iossimulator-xcrun/usr/local/include | $(IOSSIM_TARGETS): CFLAGS += -Ideps/openssl/ios/iossimulator-xcrun/usr/local/include | ||||||
| $(IOSSIM_TARGETS): LDFLAGS += -Ldeps/openssl/ios/iossimulator-xcrun/usr/local/lib | $(IOSSIM_TARGETS): LDFLAGS += -Ldeps/openssl/ios/iossimulator-xcrun/usr/local/lib | ||||||
|  |  | ||||||
| ifeq ($(UNAME_M),x86_64) |  | ||||||
| ifneq ($(UNAME_S),Haiku) |  | ||||||
| out/debug/tildefriends: CFLAGS += -fsanitize=address -fsanitize=undefined -fno-common |  | ||||||
| out/debug/tildefriends: LDFLAGS += -fsanitize=address -fsanitize=undefined |  | ||||||
| endif |  | ||||||
| endif |  | ||||||
|  |  | ||||||
| ifeq ($(UNAME_M),aarch64) |  | ||||||
| out/debug/tildefriends: CFLAGS += -fsanitize=address -fsanitize=undefined -fno-common |  | ||||||
| out/debug/tildefriends: LDFLAGS += -fsanitize=address -fsanitize=undefined |  | ||||||
| endif |  | ||||||
|  |  | ||||||
| get_objs = \ | get_objs = \ | ||||||
| 	$(foreach build_type,$(BUILD_TYPES),$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)))))) \ | 	$(foreach build_type,$(BUILD_TYPES),$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)))))) \ | ||||||
| 	$(foreach build_type,debug release,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_unix))))) \ | 	$(foreach build_type,debug release,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_unix))))) \ | ||||||
| @@ -579,7 +578,7 @@ $(MINIUNZIP_OBJS): CFLAGS += \ | |||||||
| LDFLAGS += \ | LDFLAGS += \ | ||||||
| 	-pthread \ | 	-pthread \ | ||||||
| 	-lm | 	-lm | ||||||
| $(LINUX_TARGETS) $(MACOS_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS): LDFLAGS += \ | debug release $(MACOS_TARGETS) $(IOS_TARGETS) $(IOSSIM_TARGETS): LDFLAGS += \ | ||||||
| 	-lssl \ | 	-lssl \ | ||||||
| 	-lcrypto | 	-lcrypto | ||||||
| ifneq ($(UNAME_S),Haiku) | ifneq ($(UNAME_S),Haiku) | ||||||
| @@ -693,7 +692,7 @@ CLASS_FILES := $(foreach src,$(JAVA_FILES),out/classes/com/unprompted/tildefrien | |||||||
|  |  | ||||||
| $(CLASS_FILES) &: $(JAVA_FILES) | $(CLASS_FILES) &: $(JAVA_FILES) | ||||||
| 	@echo "[javac] $(CLASS_FILES)" | 	@echo "[javac] $(CLASS_FILES)" | ||||||
| 	@javac --release 8 -encoding UTF-8 -Xlint:deprecation -XDuseUnsharedTable=true -classpath $(ANDROID_PLATFORM)/android.jar:$(ANDROID_BUILD_TOOLS)/core-lambda-stubs.jar -d out/classes $(JAVA_FILES) | 	@javac --release 8 -Xlint:deprecation -classpath $(ANDROID_PLATFORM)/android.jar -d out/classes $(JAVA_FILES) | ||||||
|  |  | ||||||
| out/apk/classes.dex: $(CLASS_FILES) | out/apk/classes.dex: $(CLASS_FILES) | ||||||
| 	@mkdir -p $(dir $@) | 	@mkdir -p $(dir $@) | ||||||
| @@ -729,7 +728,7 @@ out/apk/TildeFriends-arm-%.unsigned.apk: | |||||||
| 	@cp out/apk/res.apk $@.zip | 	@cp out/apk/res.apk $@.zip | ||||||
| 	@cp out/apk/classes.dex out/apk-arm-$(BUILD_TYPE)/ | 	@cp out/apk/classes.dex out/apk-arm-$(BUILD_TYPE)/ | ||||||
| 	@cd out/apk-arm-$(BUILD_TYPE) && zip -u ../../$@.zip -q -9 -r . && cd ../../ | 	@cd out/apk-arm-$(BUILD_TYPE) && zip -u ../../$@.zip -q -9 -r . && cd ../../ | ||||||
| 	@zip -u $@.zip -q -9 $(RAW_FILES) | 	@zip -u $@.zip -q $(RAW_FILES) | ||||||
| 	@$(ANDROID_BUILD_TOOLS)/zipalign -f 4 $@.zip $@ | 	@$(ANDROID_BUILD_TOOLS)/zipalign -f 4 $@.zip $@ | ||||||
|  |  | ||||||
| out/apk/TildeFriends-x86-%.unsigned.apk: | out/apk/TildeFriends-x86-%.unsigned.apk: | ||||||
| @@ -742,7 +741,7 @@ out/apk/TildeFriends-x86-%.unsigned.apk: | |||||||
| 	@cp out/apk/res.apk $@.zip | 	@cp out/apk/res.apk $@.zip | ||||||
| 	@cp out/apk/classes.dex out/apk-x86-$(BUILD_TYPE)/ | 	@cp out/apk/classes.dex out/apk-x86-$(BUILD_TYPE)/ | ||||||
| 	@cd out/apk-x86-$(BUILD_TYPE) && zip -u ../../$@.zip -q -9 -r . && cd ../../ | 	@cd out/apk-x86-$(BUILD_TYPE) && zip -u ../../$@.zip -q -9 -r . && cd ../../ | ||||||
| 	@zip -u $@.zip -q -9 $(RAW_FILES) | 	@zip -u $@.zip -q $(RAW_FILES) | ||||||
| 	@$(ANDROID_BUILD_TOOLS)/zipalign -f 4 $@.zip $@ | 	@$(ANDROID_BUILD_TOOLS)/zipalign -f 4 $@.zip $@ | ||||||
|  |  | ||||||
| out/%.apk: out/apk/%.unsigned.apk | out/%.apk: out/apk/%.unsigned.apk | ||||||
| @@ -759,7 +758,7 @@ release-apk: out/TildeFriends-arm-release.zopfli.apk out/TildeFriends-x86-releas | |||||||
|  |  | ||||||
| releaseapkgo: out/TildeFriends-arm-release.apk | releaseapkgo: out/TildeFriends-arm-release.apk | ||||||
| 	@adb install -r $< | 	@adb install -r $< | ||||||
| 	@adb shell am start com.unprompted.tildefriends/.TildeFriendsActivity | 	@adb shell am start com.unprompted.tildefriends/.MainActivity | ||||||
| .PHONY: releaseapkgo | .PHONY: releaseapkgo | ||||||
|  |  | ||||||
| # iOS Support | # iOS Support | ||||||
| @@ -770,10 +769,10 @@ out/%.app/tildefriends.png: src/ios/tildefriends.png | |||||||
| 	@mkdir -p $(dir $@) | 	@mkdir -p $(dir $@) | ||||||
| 	@cp -v $< $@ | 	@cp -v $< $@ | ||||||
|  |  | ||||||
| out/data.zip: $(RAW_FILES) | out/%/data.zip: $(RAW_FILES) | ||||||
| 	@zip -u $@ -q -9 $(RAW_FILES) | 	@zip -u $@ -q -9 $(RAW_FILES) | ||||||
|  |  | ||||||
| out/tildefriends-%.app/tildefriends: out/%/tildefriends out/tildefriends-%.app/Info.plist out/tildefriends-%.app/tildefriends.png out/data.zip | out/tildefriends-%.app/tildefriends: out/%/tildefriends out/tildefriends-%.app/Info.plist out/tildefriends-%.app/tildefriends.png out/tildefriends-%.app/data.zip | ||||||
| 	@mkdir -p $(dir $@) | 	@mkdir -p $(dir $@) | ||||||
| 	@cp -v $< $@ | 	@cp -v $< $@ | ||||||
| ifeq ($(HAVE_LINUX_IOS),1) | ifeq ($(HAVE_LINUX_IOS),1) | ||||||
| @@ -788,16 +787,6 @@ out/tildefriends-%.ipa: out/tildefriends-ios%.app/tildefriends | |||||||
| 	@cd $@.tmp/ && zip -u ../../$@ -q -9 -r ./ | 	@cd $@.tmp/ && zip -u ../../$@ -q -9 -r ./ | ||||||
| 	@rm -rf $@.tmp/ | 	@rm -rf $@.tmp/ | ||||||
|  |  | ||||||
|  |  | ||||||
| out/%/tildefriends.standalone: out/%/tildefriends out/data.zip |  | ||||||
| 	@echo "[standalone] $@" |  | ||||||
| 	@cat $< out/data.zip > $@ |  | ||||||
| 	@chmod +x $@ |  | ||||||
| out/%/tildefriends.standalone.exe: out/%/tildefriends.exe out/data.zip |  | ||||||
| 	@echo "[standalone] $@" |  | ||||||
| 	@cat $< out/data.zip > $@ |  | ||||||
| 	@chmod +x $@ |  | ||||||
|  |  | ||||||
| iossimdebug-app: out/tildefriends-iossimdebug.app/tildefriends | iossimdebug-app: out/tildefriends-iossimdebug.app/tildefriends | ||||||
| iossimrelease-app: out/tildefriends-iossimrelease.app/tildefriends | iossimrelease-app: out/tildefriends-iossimrelease.app/tildefriends | ||||||
| iosdebug-app: out/tildefriends-iosdebug.app/tildefriends | iosdebug-app: out/tildefriends-iosdebug.app/tildefriends | ||||||
| @@ -858,11 +847,11 @@ clean: | |||||||
| 	rm -rf $(BUILD_DIR) | 	rm -rf $(BUILD_DIR) | ||||||
| .PHONY: clean | .PHONY: clean | ||||||
|  |  | ||||||
| dist: release-apk iosrelease-ipa $(if $(HAVE_WIN), out/winrelease/tildefriends.standalone.exe) | dist: release-apk iosrelease-ipa | ||||||
| 	@echo [archive] dist/tildefriends-$(VERSION_NUMBER).tar.xz | 	@echo [archive] dist/tildefriends-$(VERSION_NUMBER).tar.xz | ||||||
| 	@rm -rf out/tildefriends-$(VERSION_NUMBER) | 	@rm -rf out/tildefriends-$(VERSION_NUMBER) | ||||||
| 	@mkdir -p dist/ out/tildefriends-$(VERSION_NUMBER) | 	@mkdir -p dist/ out/tildefriends-$(VERSION_NUMBER) | ||||||
| 	@git ls-files --recurse-submodules | tar -c -T- | tar -x -C out/tildefriends-$(VERSION_NUMBER) | 	@git archive main | tar -x -C out/tildefriends-$(VERSION_NUMBER) | ||||||
| 	@tar \ | 	@tar \ | ||||||
| 		--exclude=apps/welcome* \ | 		--exclude=apps/welcome* \ | ||||||
| 		--exclude=deps/libbacktrace/Isaac.Newton-Opticks.txt \ | 		--exclude=deps/libbacktrace/Isaac.Newton-Opticks.txt \ | ||||||
| @@ -887,8 +876,6 @@ dist: release-apk iosrelease-ipa $(if $(HAVE_WIN), out/winrelease/tildefriends.s | |||||||
| 	@cp out/TildeFriends-arm-release.zopfli.apk dist/TildeFriends-arm-$(VERSION_NUMBER).apk | 	@cp out/TildeFriends-arm-release.zopfli.apk dist/TildeFriends-arm-$(VERSION_NUMBER).apk | ||||||
| 	@echo "[cp] TildeFriends-$(VERSION_NUMBER).ipa" | 	@echo "[cp] TildeFriends-$(VERSION_NUMBER).ipa" | ||||||
| 	@cp out/tildefriends-release.ipa dist/TildeFriends-$(VERSION_NUMBER).ipa | 	@cp out/tildefriends-release.ipa dist/TildeFriends-$(VERSION_NUMBER).ipa | ||||||
| 	@test $(HAVE_WIN) && echo "[cp] tildefriends-$(VERSION_NUMBER).exe" |  | ||||||
| 	@test $(HAVE_WIN) && cp out/winrelease/tildefriends.standalone.exe dist/tildefriends-$(VERSION_NUMBER).exe |  | ||||||
| .PHONY: dist | .PHONY: dist | ||||||
|  |  | ||||||
| dist-test: dist | dist-test: dist | ||||||
|   | |||||||
| @@ -1,5 +1,4 @@ | |||||||
| { | { | ||||||
| 	"type": "tildefriends-app", | 	"type": "tildefriends-app", | ||||||
| 	"emoji": "🎛", | 	"emoji": "🎛" | ||||||
| 	"previous": "&vrpS/vE7n588iYv1p8HafDxHB+YDHTrtUbJiu9nGA9I=.sha256" |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,38 +4,9 @@ | |||||||
| 		<script> | 		<script> | ||||||
| 			const g_data = $data; | 			const g_data = $data; | ||||||
| 		</script> | 		</script> | ||||||
| 		<link rel="stylesheet" href="w3.css" /> |  | ||||||
| 		<!-- prettier-ignore --> |  | ||||||
| 		<style> |  | ||||||
| 			/* 2018 Valiant Poppy */ |  | ||||||
| 			.w3-theme-l5 {color:#000 !important; background-color:#fbf3f3 !important} |  | ||||||
| 			.w3-theme-l4 {color:#000 !important; background-color:#f3d7d6 !important} |  | ||||||
| 			.w3-theme-l3 {color:#000 !important; background-color:#e6afae !important} |  | ||||||
| 			.w3-theme-l2 {color:#fff !important; background-color:#da8785 !important} |  | ||||||
| 			.w3-theme-l1 {color:#fff !important; background-color:#cd5f5d !important} |  | ||||||
| 			.w3-theme-d1 {color:#fff !important; background-color:#a93634 !important} |  | ||||||
| 			.w3-theme-d2 {color:#fff !important; background-color:#96302e !important} |  | ||||||
| 			.w3-theme-d3 {color:#fff !important; background-color:#832a28 !important} |  | ||||||
| 			.w3-theme-d4 {color:#fff !important; background-color:#702423 !important} |  | ||||||
| 			.w3-theme-d5 {color:#fff !important; background-color:#5e1e1d !important} |  | ||||||
|  |  | ||||||
| 			.w3-theme-light {color:#000 !important; background-color:#fbf3f3 !important} |  | ||||||
| 			.w3-theme-dark {color:#fff !important; background-color:#5e1e1d !important} |  | ||||||
| 			.w3-theme-action {color:#fff !important; background-color:#5e1e1d !important} |  | ||||||
|  |  | ||||||
| 			.w3-theme {color:#fff !important; background-color:#bd3d3a !important} |  | ||||||
| 			.w3-text-theme {color:#bd3d3a !important} |  | ||||||
| 			.w3-border-theme {border-color:#bd3d3a !important} |  | ||||||
|  |  | ||||||
| 			.w3-hover-theme:hover {color:#fff !important; background-color:#bd3d3a !important} |  | ||||||
| 			.w3-hover-text-theme:hover {color:#bd3d3a !important} |  | ||||||
| 			.w3-hover-border-theme:hover {border-color:#bd3d3a !important} |  | ||||||
| 		</style> |  | ||||||
| 	</head> | 	</head> | ||||||
| 	<body class="w3-theme-l4"> | 	<body style="color: #fff; width: 100%"> | ||||||
| 		<header class="w3-row w3-padding w3-header w3-theme-l1"> |  | ||||||
| 		<h1>Tilde Friends Administration</h1> | 		<h1>Tilde Friends Administration</h1> | ||||||
| 		</header> |  | ||||||
| 	</body> | 	</body> | ||||||
| 	<script type="module" src="script.js"></script> | 	<script type="module" src="script.js"></script> | ||||||
| </html> | </html> | ||||||
|   | |||||||
| @@ -32,75 +32,59 @@ window.addEventListener('load', function () { | |||||||
| 	function input_template(key, description) { | 	function input_template(key, description) { | ||||||
| 		if (description.type === 'boolean') { | 		if (description.type === 'boolean') { | ||||||
| 			return html` | 			return html` | ||||||
| 				<li class="w3-row"> | 				<div style="margin-top: 1em"> | ||||||
| 					<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold">${key}</label> | 					<label for=${'gs_' + key} style="font-weight: bold">${key}: </label> | ||||||
| 					<div class="w3-quarter w3-padding">${description.description}</div> | 					<div> | ||||||
| 					<input class="w3-quarter w3-check" type="checkbox" ?checked=${description.value} id=${'gs_' + key}></input> | 						<input 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> | 						<button @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.checked)}>Set</button> | ||||||
| 				</li> | 						<div>${description.description}</div> | ||||||
|  | 					</div> | ||||||
|  | 				</div> | ||||||
| 			`; | 			`; | ||||||
| 		} else if (description.type === 'textarea') { | 		} else if (description.type === 'textarea') { | ||||||
| 			return html` | 			return html` | ||||||
| 				<li class="w3-row"> | 				<div style="margin-top: 1em""> | ||||||
| 					<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold" | 					<label for=${'gs_' + key} style="font-weight: bold">${key}: </label> | ||||||
| 						>${key}</label | 					<div style="width: 100%; padding: 0; margin: 0"> | ||||||
| 					> | 						<div style="width: 90%; padding: 0 margin: 0"> | ||||||
| 					<div class="w3-rest w3-padding">${description.description}</div> | 							<textarea style="vertical-align: top; width: 100%" rows=20 cols=80 id=${'gs_' + key}>${description.value}</textarea> | ||||||
| 					<textarea | 						</div> | ||||||
| 						class="w3-input" | 						<button @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.firstElementChild.value)}>Set</button> | ||||||
| 						style="vertical-align: top; resize: vertical" | 						<div>${description.description}</div> | ||||||
| 						id=${'gs_' + key} | 					</div> | ||||||
| 					> | 				</div> | ||||||
| ${description.value}</textarea |  | ||||||
| 					> |  | ||||||
| 					<button |  | ||||||
| 						class="w3-button w3-right w3-quarter w3-theme-action" |  | ||||||
| 						@click=${(e) => |  | ||||||
| 							global_settings_set( |  | ||||||
| 								key, |  | ||||||
| 								e.srcElement.previousElementSibling.value |  | ||||||
| 							)} |  | ||||||
| 					> |  | ||||||
| 						Set |  | ||||||
| 					</button> |  | ||||||
| 				</li> |  | ||||||
| 			`; | 			`; | ||||||
| 		} else { | 		} else { | ||||||
| 			return html` | 			return html` | ||||||
| 				<li class="w3-row"> | 				<div style="margin-top: 1em"> | ||||||
| 					<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold">${key}</label> | 					<label for=${'gs_' + key} style="font-weight: bold">${key}: </label> | ||||||
| 					<div class="w3-quarter w3-padding">${description.description}</div> | 					<div> | ||||||
| 					<input class="w3-input w3-quarter" type="text" value="${description.value}" id=${'gs_' + key}></input> | 						<input 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> | 						<button @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.value)}>Set</button> | ||||||
| 				</li> | 						<div>${description.description}</div> | ||||||
|  | 					</div> | ||||||
|  | 				</div> | ||||||
| 			`; | 			`; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	const user_template = (user, permissions) => html` | 	const user_template = (user, permissions) => html` | ||||||
| 		<li class="w3-card w3-margin"> | 		<li> | ||||||
| 			<button | 			<button @click=${(e) => delete_user(user)}>Delete</button> | ||||||
| 				class="w3-button w3-theme-action" |  | ||||||
| 				@click=${(e) => delete_user(user)} |  | ||||||
| 			> |  | ||||||
| 				Delete |  | ||||||
| 			</button> |  | ||||||
| 			${user}: ${permissions.map((x) => permission_template(x))} | 			${user}: ${permissions.map((x) => permission_template(x))} | ||||||
| 		</li> | 		</li> | ||||||
| 	`; | 	`; | ||||||
| 	const users_template = (users) => | 	const users_template = (users) => | ||||||
| 		html` <header class="w3-container w3-theme-l2"><h2>Users</h2></header> | 		html`<h2>Users</h2> | ||||||
| 			<ul class="w3-ul"> | 			<ul> | ||||||
| 				${Object.entries(users).map((u) => user_template(u[0], u[1]))} | 				${Object.entries(users).map((u) => user_template(u[0], u[1]))} | ||||||
| 			</ul>`; | 			</ul>`; | ||||||
| 	const page_template = (data) => | 	const page_template = (data) => | ||||||
| 		html`<div style="padding: 0; margin: 0; width: 100%; max-width: 100%"> | 		html`<div style="padding: 0; margin: 0; width: 100%; max-width: 100%"> | ||||||
| 			<header class="w3-container w3-theme-l2"><h2>Global Settings</h2></header> | 			<h2>Global Settings</h2> | ||||||
| 			<div class="w3-container"> | 			<div> | ||||||
| 				<ul class="w3-ul"> |  | ||||||
| 				${Object.keys(data.settings) | 				${Object.keys(data.settings) | ||||||
| 					.sort() | 					.sort() | ||||||
| 					.map((x) => html`${input_template(x, data.settings[x])}`)} | 					.map((x) => html`${input_template(x, data.settings[x])}`)} | ||||||
| 				</ul> |  | ||||||
| 			</div> | 			</div> | ||||||
| 			${users_template(data.users)} | 			${users_template(data.users)} | ||||||
| 		</div> `; | 		</div> `; | ||||||
|   | |||||||
| @@ -1,235 +0,0 @@ | |||||||
| /* W3.CSS 4.15 December 2020 by Jan Egil and Borge Refsnes */ |  | ||||||
| html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit} |  | ||||||
| /* Extract from normalize.css by Nicolas Gallagher and Jonathan Neal git.io/normalize */ |  | ||||||
| html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0} |  | ||||||
| article,aside,details,figcaption,figure,footer,header,main,menu,nav,section{display:block}summary{display:list-item} |  | ||||||
| audio,canvas,progress,video{display:inline-block}progress{vertical-align:baseline} |  | ||||||
| audio:not([controls]){display:none;height:0}[hidden],template{display:none} |  | ||||||
| a{background-color:transparent}a:active,a:hover{outline-width:0} |  | ||||||
| abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted} |  | ||||||
| b,strong{font-weight:bolder}dfn{font-style:italic}mark{background:#ff0;color:#000} |  | ||||||
| small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} |  | ||||||
| sub{bottom:-0.25em}sup{top:-0.5em}figure{margin:1em 40px}img{border-style:none} |  | ||||||
| code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}hr{box-sizing:content-box;height:0;overflow:visible} |  | ||||||
| button,input,select,textarea,optgroup{font:inherit;margin:0}optgroup{font-weight:bold} |  | ||||||
| button,input{overflow:visible}button,select{text-transform:none} |  | ||||||
| button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button} |  | ||||||
| button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0} |  | ||||||
| button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText} |  | ||||||
| fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em} |  | ||||||
| legend{color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto} |  | ||||||
| [type=checkbox],[type=radio]{padding:0} |  | ||||||
| [type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto} |  | ||||||
| [type=search]{-webkit-appearance:textfield;outline-offset:-2px} |  | ||||||
| [type=search]::-webkit-search-decoration{-webkit-appearance:none} |  | ||||||
| ::-webkit-file-upload-button{-webkit-appearance:button;font:inherit} |  | ||||||
| /* End extract */ |  | ||||||
| html,body{font-family:Verdana,sans-serif;font-size:15px;line-height:1.5}html{overflow-x:hidden} |  | ||||||
| h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:20px}h5{font-size:18px}h6{font-size:16px} |  | ||||||
| .w3-serif{font-family:serif}.w3-sans-serif{font-family:sans-serif}.w3-cursive{font-family:cursive}.w3-monospace{font-family:monospace} |  | ||||||
| h1,h2,h3,h4,h5,h6{font-family:"Segoe UI",Arial,sans-serif;font-weight:400;margin:10px 0}.w3-wide{letter-spacing:4px} |  | ||||||
| hr{border:0;border-top:1px solid #eee;margin:20px 0} |  | ||||||
| .w3-image{max-width:100%;height:auto}img{vertical-align:middle}a{color:inherit} |  | ||||||
| .w3-table,.w3-table-all{border-collapse:collapse;border-spacing:0;width:100%;display:table}.w3-table-all{border:1px solid #ccc} |  | ||||||
| .w3-bordered tr,.w3-table-all tr{border-bottom:1px solid #ddd}.w3-striped tbody tr:nth-child(even){background-color:#f1f1f1} |  | ||||||
| .w3-table-all tr:nth-child(odd){background-color:#fff}.w3-table-all tr:nth-child(even){background-color:#f1f1f1} |  | ||||||
| .w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center} |  | ||||||
| .w3-table td,.w3-table th,.w3-table-all td,.w3-table-all th{padding:8px 8px;display:table-cell;text-align:left;vertical-align:top} |  | ||||||
| .w3-table th:first-child,.w3-table td:first-child,.w3-table-all th:first-child,.w3-table-all td:first-child{padding-left:16px} |  | ||||||
| .w3-btn,.w3-button{border:none;display:inline-block;padding:8px 16px;vertical-align:middle;overflow:hidden;text-decoration:none;color:inherit;background-color:inherit;text-align:center;cursor:pointer;white-space:nowrap} |  | ||||||
| .w3-btn:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)} |  | ||||||
| .w3-btn,.w3-button{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}    |  | ||||||
| .w3-disabled,.w3-btn:disabled,.w3-button:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none} |  | ||||||
| .w3-btn.w3-disabled:hover,.w3-btn:disabled:hover{box-shadow:none} |  | ||||||
| .w3-badge,.w3-tag{background-color:#000;color:#fff;display:inline-block;padding-left:8px;padding-right:8px;text-align:center}.w3-badge{border-radius:50%} |  | ||||||
| .w3-ul{list-style-type:none;padding:0;margin:0}.w3-ul li{padding:8px 16px;border-bottom:1px solid #ddd}.w3-ul li:last-child{border-bottom:none} |  | ||||||
| .w3-tooltip,.w3-display-container{position:relative}.w3-tooltip .w3-text{display:none}.w3-tooltip:hover .w3-text{display:inline-block} |  | ||||||
| .w3-ripple:active{opacity:0.5}.w3-ripple{transition:opacity 0s} |  | ||||||
| .w3-input{padding:8px;display:block;border:none;border-bottom:1px solid #ccc;width:100%} |  | ||||||
| .w3-select{padding:9px 0;width:100%;border:none;border-bottom:1px solid #ccc} |  | ||||||
| .w3-dropdown-click,.w3-dropdown-hover{position:relative;display:inline-block;cursor:pointer} |  | ||||||
| .w3-dropdown-hover:hover .w3-dropdown-content{display:block} |  | ||||||
| .w3-dropdown-hover:first-child,.w3-dropdown-click:hover{background-color:#ccc;color:#000} |  | ||||||
| .w3-dropdown-hover:hover > .w3-button:first-child,.w3-dropdown-click:hover > .w3-button:first-child{background-color:#ccc;color:#000} |  | ||||||
| .w3-dropdown-content{cursor:auto;color:#000;background-color:#fff;display:none;position:absolute;min-width:160px;margin:0;padding:0;z-index:1} |  | ||||||
| .w3-check,.w3-radio{width:24px;height:24px;position:relative;top:6px} |  | ||||||
| .w3-sidebar{height:100%;width:200px;background-color:#fff;position:fixed!important;z-index:1;overflow:auto} |  | ||||||
| .w3-bar-block .w3-dropdown-hover,.w3-bar-block .w3-dropdown-click{width:100%} |  | ||||||
| .w3-bar-block .w3-dropdown-hover .w3-dropdown-content,.w3-bar-block .w3-dropdown-click .w3-dropdown-content{min-width:100%} |  | ||||||
| .w3-bar-block .w3-dropdown-hover .w3-button,.w3-bar-block .w3-dropdown-click .w3-button{width:100%;text-align:left;padding:8px 16px} |  | ||||||
| .w3-main,#main{transition:margin-left .4s} |  | ||||||
| .w3-modal{z-index:3;display:none;padding-top:100px;position:fixed;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgb(0,0,0);background-color:rgba(0,0,0,0.4)} |  | ||||||
| .w3-modal-content{margin:auto;background-color:#fff;position:relative;padding:0;outline:0;width:600px} |  | ||||||
| .w3-bar{width:100%;overflow:hidden}.w3-center .w3-bar{display:inline-block;width:auto} |  | ||||||
| .w3-bar .w3-bar-item{padding:8px 16px;float:left;width:auto;border:none;display:block;outline:0} |  | ||||||
| .w3-bar .w3-dropdown-hover,.w3-bar .w3-dropdown-click{position:static;float:left} |  | ||||||
| .w3-bar .w3-button{white-space:normal} |  | ||||||
| .w3-bar-block .w3-bar-item{width:100%;display:block;padding:8px 16px;text-align:left;border:none;white-space:normal;float:none;outline:0} |  | ||||||
| .w3-bar-block.w3-center .w3-bar-item{text-align:center}.w3-block{display:block;width:100%} |  | ||||||
| .w3-responsive{display:block;overflow-x:auto} |  | ||||||
| .w3-container:after,.w3-container:before,.w3-panel:after,.w3-panel:before,.w3-row:after,.w3-row:before,.w3-row-padding:after,.w3-row-padding:before, |  | ||||||
| .w3-cell-row:before,.w3-cell-row:after,.w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after{content:"";display:table;clear:both} |  | ||||||
| .w3-col,.w3-half,.w3-third,.w3-twothird,.w3-threequarter,.w3-quarter{float:left;width:100%} |  | ||||||
| .w3-col.s1{width:8.33333%}.w3-col.s2{width:16.66666%}.w3-col.s3{width:24.99999%}.w3-col.s4{width:33.33333%} |  | ||||||
| .w3-col.s5{width:41.66666%}.w3-col.s6{width:49.99999%}.w3-col.s7{width:58.33333%}.w3-col.s8{width:66.66666%} |  | ||||||
| .w3-col.s9{width:74.99999%}.w3-col.s10{width:83.33333%}.w3-col.s11{width:91.66666%}.w3-col.s12{width:99.99999%} |  | ||||||
| @media (min-width:601px){.w3-col.m1{width:8.33333%}.w3-col.m2{width:16.66666%}.w3-col.m3,.w3-quarter{width:24.99999%}.w3-col.m4,.w3-third{width:33.33333%} |  | ||||||
| .w3-col.m5{width:41.66666%}.w3-col.m6,.w3-half{width:49.99999%}.w3-col.m7{width:58.33333%}.w3-col.m8,.w3-twothird{width:66.66666%} |  | ||||||
| .w3-col.m9,.w3-threequarter{width:74.99999%}.w3-col.m10{width:83.33333%}.w3-col.m11{width:91.66666%}.w3-col.m12{width:99.99999%}} |  | ||||||
| @media (min-width:993px){.w3-col.l1{width:8.33333%}.w3-col.l2{width:16.66666%}.w3-col.l3{width:24.99999%}.w3-col.l4{width:33.33333%} |  | ||||||
| .w3-col.l5{width:41.66666%}.w3-col.l6{width:49.99999%}.w3-col.l7{width:58.33333%}.w3-col.l8{width:66.66666%} |  | ||||||
| .w3-col.l9{width:74.99999%}.w3-col.l10{width:83.33333%}.w3-col.l11{width:91.66666%}.w3-col.l12{width:99.99999%}} |  | ||||||
| .w3-rest{overflow:hidden}.w3-stretch{margin-left:-16px;margin-right:-16px} |  | ||||||
| .w3-content,.w3-auto{margin-left:auto;margin-right:auto}.w3-content{max-width:980px}.w3-auto{max-width:1140px} |  | ||||||
| .w3-cell-row{display:table;width:100%}.w3-cell{display:table-cell} |  | ||||||
| .w3-cell-top{vertical-align:top}.w3-cell-middle{vertical-align:middle}.w3-cell-bottom{vertical-align:bottom} |  | ||||||
| .w3-hide{display:none!important}.w3-show-block,.w3-show{display:block!important}.w3-show-inline-block{display:inline-block!important} |  | ||||||
| @media (max-width:1205px){.w3-auto{max-width:95%}} |  | ||||||
| @media (max-width:600px){.w3-modal-content{margin:0 10px;width:auto!important}.w3-modal{padding-top:30px} |  | ||||||
| .w3-dropdown-hover.w3-mobile .w3-dropdown-content,.w3-dropdown-click.w3-mobile .w3-dropdown-content{position:relative}	 |  | ||||||
| .w3-hide-small{display:none!important}.w3-mobile{display:block;width:100%!important}.w3-bar-item.w3-mobile,.w3-dropdown-hover.w3-mobile,.w3-dropdown-click.w3-mobile{text-align:center} |  | ||||||
| .w3-dropdown-hover.w3-mobile,.w3-dropdown-hover.w3-mobile .w3-btn,.w3-dropdown-hover.w3-mobile .w3-button,.w3-dropdown-click.w3-mobile,.w3-dropdown-click.w3-mobile .w3-btn,.w3-dropdown-click.w3-mobile .w3-button{width:100%}} |  | ||||||
| @media (max-width:768px){.w3-modal-content{width:500px}.w3-modal{padding-top:50px}} |  | ||||||
| @media (min-width:993px){.w3-modal-content{width:900px}.w3-hide-large{display:none!important}.w3-sidebar.w3-collapse{display:block!important}} |  | ||||||
| @media (max-width:992px) and (min-width:601px){.w3-hide-medium{display:none!important}} |  | ||||||
| @media (max-width:992px){.w3-sidebar.w3-collapse{display:none}.w3-main{margin-left:0!important;margin-right:0!important}.w3-auto{max-width:100%}} |  | ||||||
| .w3-top,.w3-bottom{position:fixed;width:100%;z-index:1}.w3-top{top:0}.w3-bottom{bottom:0} |  | ||||||
| .w3-overlay{position:fixed;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.5);z-index:2} |  | ||||||
| .w3-display-topleft{position:absolute;left:0;top:0}.w3-display-topright{position:absolute;right:0;top:0} |  | ||||||
| .w3-display-bottomleft{position:absolute;left:0;bottom:0}.w3-display-bottomright{position:absolute;right:0;bottom:0} |  | ||||||
| .w3-display-middle{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%)} |  | ||||||
| .w3-display-left{position:absolute;top:50%;left:0%;transform:translate(0%,-50%);-ms-transform:translate(-0%,-50%)} |  | ||||||
| .w3-display-right{position:absolute;top:50%;right:0%;transform:translate(0%,-50%);-ms-transform:translate(0%,-50%)} |  | ||||||
| .w3-display-topmiddle{position:absolute;left:50%;top:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)} |  | ||||||
| .w3-display-bottommiddle{position:absolute;left:50%;bottom:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)} |  | ||||||
| .w3-display-container:hover .w3-display-hover{display:block}.w3-display-container:hover span.w3-display-hover{display:inline-block}.w3-display-hover{display:none} |  | ||||||
| .w3-display-position{position:absolute} |  | ||||||
| .w3-circle{border-radius:50%} |  | ||||||
| .w3-round-small{border-radius:2px}.w3-round,.w3-round-medium{border-radius:4px}.w3-round-large{border-radius:8px}.w3-round-xlarge{border-radius:16px}.w3-round-xxlarge{border-radius:32px} |  | ||||||
| .w3-row-padding,.w3-row-padding>.w3-half,.w3-row-padding>.w3-third,.w3-row-padding>.w3-twothird,.w3-row-padding>.w3-threequarter,.w3-row-padding>.w3-quarter,.w3-row-padding>.w3-col{padding:0 8px} |  | ||||||
| .w3-container,.w3-panel{padding:0.01em 16px}.w3-panel{margin-top:16px;margin-bottom:16px} |  | ||||||
| .w3-code,.w3-codespan{font-family:Consolas,"courier new";font-size:16px} |  | ||||||
| .w3-code{width:auto;background-color:#fff;padding:8px 12px;border-left:4px solid #4CAF50;word-wrap:break-word} |  | ||||||
| .w3-codespan{color:crimson;background-color:#f1f1f1;padding-left:4px;padding-right:4px;font-size:110%} |  | ||||||
| .w3-card,.w3-card-2{box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12)} |  | ||||||
| .w3-card-4,.w3-hover-shadow:hover{box-shadow:0 4px 10px 0 rgba(0,0,0,0.2),0 4px 20px 0 rgba(0,0,0,0.19)} |  | ||||||
| .w3-spin{animation:w3-spin 2s infinite linear}@keyframes w3-spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}} |  | ||||||
| .w3-animate-fading{animation:fading 10s infinite}@keyframes fading{0%{opacity:0}50%{opacity:1}100%{opacity:0}} |  | ||||||
| .w3-animate-opacity{animation:opac 0.8s}@keyframes opac{from{opacity:0} to{opacity:1}} |  | ||||||
| .w3-animate-top{position:relative;animation:animatetop 0.4s}@keyframes animatetop{from{top:-300px;opacity:0} to{top:0;opacity:1}} |  | ||||||
| .w3-animate-left{position:relative;animation:animateleft 0.4s}@keyframes animateleft{from{left:-300px;opacity:0} to{left:0;opacity:1}} |  | ||||||
| .w3-animate-right{position:relative;animation:animateright 0.4s}@keyframes animateright{from{right:-300px;opacity:0} to{right:0;opacity:1}} |  | ||||||
| .w3-animate-bottom{position:relative;animation:animatebottom 0.4s}@keyframes animatebottom{from{bottom:-300px;opacity:0} to{bottom:0;opacity:1}} |  | ||||||
| .w3-animate-zoom {animation:animatezoom 0.6s}@keyframes animatezoom{from{transform:scale(0)} to{transform:scale(1)}} |  | ||||||
| .w3-animate-input{transition:width 0.4s ease-in-out}.w3-animate-input:focus{width:100%!important} |  | ||||||
| .w3-opacity,.w3-hover-opacity:hover{opacity:0.60}.w3-opacity-off,.w3-hover-opacity-off:hover{opacity:1} |  | ||||||
| .w3-opacity-max{opacity:0.25}.w3-opacity-min{opacity:0.75} |  | ||||||
| .w3-greyscale-max,.w3-grayscale-max,.w3-hover-greyscale:hover,.w3-hover-grayscale:hover{filter:grayscale(100%)} |  | ||||||
| .w3-greyscale,.w3-grayscale{filter:grayscale(75%)}.w3-greyscale-min,.w3-grayscale-min{filter:grayscale(50%)} |  | ||||||
| .w3-sepia{filter:sepia(75%)}.w3-sepia-max,.w3-hover-sepia:hover{filter:sepia(100%)}.w3-sepia-min{filter:sepia(50%)} |  | ||||||
| .w3-tiny{font-size:10px!important}.w3-small{font-size:12px!important}.w3-medium{font-size:15px!important}.w3-large{font-size:18px!important} |  | ||||||
| .w3-xlarge{font-size:24px!important}.w3-xxlarge{font-size:36px!important}.w3-xxxlarge{font-size:48px!important}.w3-jumbo{font-size:64px!important} |  | ||||||
| .w3-left-align{text-align:left!important}.w3-right-align{text-align:right!important}.w3-justify{text-align:justify!important}.w3-center{text-align:center!important} |  | ||||||
| .w3-border-0{border:0!important}.w3-border{border:1px solid #ccc!important} |  | ||||||
| .w3-border-top{border-top:1px solid #ccc!important}.w3-border-bottom{border-bottom:1px solid #ccc!important} |  | ||||||
| .w3-border-left{border-left:1px solid #ccc!important}.w3-border-right{border-right:1px solid #ccc!important} |  | ||||||
| .w3-topbar{border-top:6px solid #ccc!important}.w3-bottombar{border-bottom:6px solid #ccc!important} |  | ||||||
| .w3-leftbar{border-left:6px solid #ccc!important}.w3-rightbar{border-right:6px solid #ccc!important} |  | ||||||
| .w3-section,.w3-code{margin-top:16px!important;margin-bottom:16px!important} |  | ||||||
| .w3-margin{margin:16px!important}.w3-margin-top{margin-top:16px!important}.w3-margin-bottom{margin-bottom:16px!important} |  | ||||||
| .w3-margin-left{margin-left:16px!important}.w3-margin-right{margin-right:16px!important} |  | ||||||
| .w3-padding-small{padding:4px 8px!important}.w3-padding{padding:8px 16px!important}.w3-padding-large{padding:12px 24px!important} |  | ||||||
| .w3-padding-16{padding-top:16px!important;padding-bottom:16px!important}.w3-padding-24{padding-top:24px!important;padding-bottom:24px!important} |  | ||||||
| .w3-padding-32{padding-top:32px!important;padding-bottom:32px!important}.w3-padding-48{padding-top:48px!important;padding-bottom:48px!important} |  | ||||||
| .w3-padding-64{padding-top:64px!important;padding-bottom:64px!important} |  | ||||||
| .w3-padding-top-64{padding-top:64px!important}.w3-padding-top-48{padding-top:48px!important} |  | ||||||
| .w3-padding-top-32{padding-top:32px!important}.w3-padding-top-24{padding-top:24px!important} |  | ||||||
| .w3-left{float:left!important}.w3-right{float:right!important} |  | ||||||
| .w3-button:hover{color:#000!important;background-color:#ccc!important} |  | ||||||
| .w3-transparent,.w3-hover-none:hover{background-color:transparent!important} |  | ||||||
| .w3-hover-none:hover{box-shadow:none!important} |  | ||||||
| /* Colors */ |  | ||||||
| .w3-amber,.w3-hover-amber:hover{color:#000!important;background-color:#ffc107!important} |  | ||||||
| .w3-aqua,.w3-hover-aqua:hover{color:#000!important;background-color:#00ffff!important} |  | ||||||
| .w3-blue,.w3-hover-blue:hover{color:#fff!important;background-color:#2196F3!important} |  | ||||||
| .w3-light-blue,.w3-hover-light-blue:hover{color:#000!important;background-color:#87CEEB!important} |  | ||||||
| .w3-brown,.w3-hover-brown:hover{color:#fff!important;background-color:#795548!important} |  | ||||||
| .w3-cyan,.w3-hover-cyan:hover{color:#000!important;background-color:#00bcd4!important} |  | ||||||
| .w3-blue-grey,.w3-hover-blue-grey:hover,.w3-blue-gray,.w3-hover-blue-gray:hover{color:#fff!important;background-color:#607d8b!important} |  | ||||||
| .w3-green,.w3-hover-green:hover{color:#fff!important;background-color:#4CAF50!important} |  | ||||||
| .w3-light-green,.w3-hover-light-green:hover{color:#000!important;background-color:#8bc34a!important} |  | ||||||
| .w3-indigo,.w3-hover-indigo:hover{color:#fff!important;background-color:#3f51b5!important} |  | ||||||
| .w3-khaki,.w3-hover-khaki:hover{color:#000!important;background-color:#f0e68c!important} |  | ||||||
| .w3-lime,.w3-hover-lime:hover{color:#000!important;background-color:#cddc39!important} |  | ||||||
| .w3-orange,.w3-hover-orange:hover{color:#000!important;background-color:#ff9800!important} |  | ||||||
| .w3-deep-orange,.w3-hover-deep-orange:hover{color:#fff!important;background-color:#ff5722!important} |  | ||||||
| .w3-pink,.w3-hover-pink:hover{color:#fff!important;background-color:#e91e63!important} |  | ||||||
| .w3-purple,.w3-hover-purple:hover{color:#fff!important;background-color:#9c27b0!important} |  | ||||||
| .w3-deep-purple,.w3-hover-deep-purple:hover{color:#fff!important;background-color:#673ab7!important} |  | ||||||
| .w3-red,.w3-hover-red:hover{color:#fff!important;background-color:#f44336!important} |  | ||||||
| .w3-sand,.w3-hover-sand:hover{color:#000!important;background-color:#fdf5e6!important} |  | ||||||
| .w3-teal,.w3-hover-teal:hover{color:#fff!important;background-color:#009688!important} |  | ||||||
| .w3-yellow,.w3-hover-yellow:hover{color:#000!important;background-color:#ffeb3b!important} |  | ||||||
| .w3-white,.w3-hover-white:hover{color:#000!important;background-color:#fff!important} |  | ||||||
| .w3-black,.w3-hover-black:hover{color:#fff!important;background-color:#000!important} |  | ||||||
| .w3-grey,.w3-hover-grey:hover,.w3-gray,.w3-hover-gray:hover{color:#000!important;background-color:#9e9e9e!important} |  | ||||||
| .w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,.w3-hover-light-gray:hover{color:#000!important;background-color:#f1f1f1!important} |  | ||||||
| .w3-dark-grey,.w3-hover-dark-grey:hover,.w3-dark-gray,.w3-hover-dark-gray:hover{color:#fff!important;background-color:#616161!important} |  | ||||||
| .w3-pale-red,.w3-hover-pale-red:hover{color:#000!important;background-color:#ffdddd!important} |  | ||||||
| .w3-pale-green,.w3-hover-pale-green:hover{color:#000!important;background-color:#ddffdd!important} |  | ||||||
| .w3-pale-yellow,.w3-hover-pale-yellow:hover{color:#000!important;background-color:#ffffcc!important} |  | ||||||
| .w3-pale-blue,.w3-hover-pale-blue:hover{color:#000!important;background-color:#ddffff!important} |  | ||||||
| .w3-text-amber,.w3-hover-text-amber:hover{color:#ffc107!important} |  | ||||||
| .w3-text-aqua,.w3-hover-text-aqua:hover{color:#00ffff!important} |  | ||||||
| .w3-text-blue,.w3-hover-text-blue:hover{color:#2196F3!important} |  | ||||||
| .w3-text-light-blue,.w3-hover-text-light-blue:hover{color:#87CEEB!important} |  | ||||||
| .w3-text-brown,.w3-hover-text-brown:hover{color:#795548!important} |  | ||||||
| .w3-text-cyan,.w3-hover-text-cyan:hover{color:#00bcd4!important} |  | ||||||
| .w3-text-blue-grey,.w3-hover-text-blue-grey:hover,.w3-text-blue-gray,.w3-hover-text-blue-gray:hover{color:#607d8b!important} |  | ||||||
| .w3-text-green,.w3-hover-text-green:hover{color:#4CAF50!important} |  | ||||||
| .w3-text-light-green,.w3-hover-text-light-green:hover{color:#8bc34a!important} |  | ||||||
| .w3-text-indigo,.w3-hover-text-indigo:hover{color:#3f51b5!important} |  | ||||||
| .w3-text-khaki,.w3-hover-text-khaki:hover{color:#b4aa50!important} |  | ||||||
| .w3-text-lime,.w3-hover-text-lime:hover{color:#cddc39!important} |  | ||||||
| .w3-text-orange,.w3-hover-text-orange:hover{color:#ff9800!important} |  | ||||||
| .w3-text-deep-orange,.w3-hover-text-deep-orange:hover{color:#ff5722!important} |  | ||||||
| .w3-text-pink,.w3-hover-text-pink:hover{color:#e91e63!important} |  | ||||||
| .w3-text-purple,.w3-hover-text-purple:hover{color:#9c27b0!important} |  | ||||||
| .w3-text-deep-purple,.w3-hover-text-deep-purple:hover{color:#673ab7!important} |  | ||||||
| .w3-text-red,.w3-hover-text-red:hover{color:#f44336!important} |  | ||||||
| .w3-text-sand,.w3-hover-text-sand:hover{color:#fdf5e6!important} |  | ||||||
| .w3-text-teal,.w3-hover-text-teal:hover{color:#009688!important} |  | ||||||
| .w3-text-yellow,.w3-hover-text-yellow:hover{color:#d2be0e!important} |  | ||||||
| .w3-text-white,.w3-hover-text-white:hover{color:#fff!important} |  | ||||||
| .w3-text-black,.w3-hover-text-black:hover{color:#000!important} |  | ||||||
| .w3-text-grey,.w3-hover-text-grey:hover,.w3-text-gray,.w3-hover-text-gray:hover{color:#757575!important} |  | ||||||
| .w3-text-light-grey,.w3-hover-text-light-grey:hover,.w3-text-light-gray,.w3-hover-text-light-gray:hover{color:#f1f1f1!important} |  | ||||||
| .w3-text-dark-grey,.w3-hover-text-dark-grey:hover,.w3-text-dark-gray,.w3-hover-text-dark-gray:hover{color:#3a3a3a!important} |  | ||||||
| .w3-border-amber,.w3-hover-border-amber:hover{border-color:#ffc107!important} |  | ||||||
| .w3-border-aqua,.w3-hover-border-aqua:hover{border-color:#00ffff!important} |  | ||||||
| .w3-border-blue,.w3-hover-border-blue:hover{border-color:#2196F3!important} |  | ||||||
| .w3-border-light-blue,.w3-hover-border-light-blue:hover{border-color:#87CEEB!important} |  | ||||||
| .w3-border-brown,.w3-hover-border-brown:hover{border-color:#795548!important} |  | ||||||
| .w3-border-cyan,.w3-hover-border-cyan:hover{border-color:#00bcd4!important} |  | ||||||
| .w3-border-blue-grey,.w3-hover-border-blue-grey:hover,.w3-border-blue-gray,.w3-hover-border-blue-gray:hover{border-color:#607d8b!important} |  | ||||||
| .w3-border-green,.w3-hover-border-green:hover{border-color:#4CAF50!important} |  | ||||||
| .w3-border-light-green,.w3-hover-border-light-green:hover{border-color:#8bc34a!important} |  | ||||||
| .w3-border-indigo,.w3-hover-border-indigo:hover{border-color:#3f51b5!important} |  | ||||||
| .w3-border-khaki,.w3-hover-border-khaki:hover{border-color:#f0e68c!important} |  | ||||||
| .w3-border-lime,.w3-hover-border-lime:hover{border-color:#cddc39!important} |  | ||||||
| .w3-border-orange,.w3-hover-border-orange:hover{border-color:#ff9800!important} |  | ||||||
| .w3-border-deep-orange,.w3-hover-border-deep-orange:hover{border-color:#ff5722!important} |  | ||||||
| .w3-border-pink,.w3-hover-border-pink:hover{border-color:#e91e63!important} |  | ||||||
| .w3-border-purple,.w3-hover-border-purple:hover{border-color:#9c27b0!important} |  | ||||||
| .w3-border-deep-purple,.w3-hover-border-deep-purple:hover{border-color:#673ab7!important} |  | ||||||
| .w3-border-red,.w3-hover-border-red:hover{border-color:#f44336!important} |  | ||||||
| .w3-border-sand,.w3-hover-border-sand:hover{border-color:#fdf5e6!important} |  | ||||||
| .w3-border-teal,.w3-hover-border-teal:hover{border-color:#009688!important} |  | ||||||
| .w3-border-yellow,.w3-hover-border-yellow:hover{border-color:#ffeb3b!important} |  | ||||||
| .w3-border-white,.w3-hover-border-white:hover{border-color:#fff!important} |  | ||||||
| .w3-border-black,.w3-hover-border-black:hover{border-color:#000!important} |  | ||||||
| .w3-border-grey,.w3-hover-border-grey:hover,.w3-border-gray,.w3-hover-border-gray:hover{border-color:#9e9e9e!important} |  | ||||||
| .w3-border-light-grey,.w3-hover-border-light-grey:hover,.w3-border-light-gray,.w3-hover-border-light-gray:hover{border-color:#f1f1f1!important} |  | ||||||
| .w3-border-dark-grey,.w3-hover-border-dark-grey:hover,.w3-border-dark-gray,.w3-hover-border-dark-gray:hover{border-color:#616161!important} |  | ||||||
| .w3-border-pale-red,.w3-hover-border-pale-red:hover{border-color:#ffe7e7!important}.w3-border-pale-green,.w3-hover-border-pale-green:hover{border-color:#e7ffe7!important} |  | ||||||
| .w3-border-pale-yellow,.w3-hover-border-pale-yellow:hover{border-color:#ffffcc!important}.w3-border-pale-blue,.w3-hover-border-pale-blue:hover{border-color:#e7ffff!important} |  | ||||||
							
								
								
									
										4
									
								
								apps/blog/lit-all.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								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
											
										
									
								
							| @@ -1,5 +0,0 @@ | |||||||
| { |  | ||||||
| 	"type": "tildefriends-app", |  | ||||||
| 	"emoji": "🪪", |  | ||||||
| 	"previous": "&de7q4A59auHP/34bXgeNH05JZoxsGr5TjwXPvehWH30=.sha256" |  | ||||||
| } |  | ||||||
| @@ -1,136 +0,0 @@ | |||||||
| import * as tfrpc from '/tfrpc.js'; |  | ||||||
|  |  | ||||||
| tfrpc.register(async function get_private_key(id) { |  | ||||||
| 	return bip39Words(await ssb.getPrivateKey(id)); |  | ||||||
| }); |  | ||||||
| tfrpc.register(async function create_id(id) { |  | ||||||
| 	return await ssb.createIdentity(); |  | ||||||
| }); |  | ||||||
| tfrpc.register(async function add_id(id) { |  | ||||||
| 	return await ssb.addIdentity(bip39Bytes(id)); |  | ||||||
| }); |  | ||||||
| tfrpc.register(async function delete_id(id) { |  | ||||||
| 	return await ssb.deleteIdentity(id); |  | ||||||
| }); |  | ||||||
| tfrpc.register(async function reload() { |  | ||||||
| 	await main(); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| async function main() { |  | ||||||
| 	let ids = await ssb.getIdentities(); |  | ||||||
| 	await app.setDocument( |  | ||||||
| 		` |  | ||||||
| 		<head> |  | ||||||
| 			<link rel="stylesheet" href="w3.css"></link> |  | ||||||
| 			<style> |  | ||||||
| 				/* "2018 Sargasso Sea" */ |  | ||||||
| 				.w3-theme-l5 {color:#000 !important; background-color:#f3f4f7 !important} |  | ||||||
| 				.w3-theme-l4 {color:#000 !important; background-color:#d7dbe3 !important} |  | ||||||
| 				.w3-theme-l3 {color:#000 !important; background-color:#b0b6c8 !important} |  | ||||||
| 				.w3-theme-l2 {color:#fff !important; background-color:#8892ac !important} |  | ||||||
| 				.w3-theme-l1 {color:#fff !important; background-color:#636f8e !important} |  | ||||||
| 				.w3-theme-d1 {color:#fff !important; background-color:#40485c !important} |  | ||||||
| 				.w3-theme-d2 {color:#fff !important; background-color:#394052 !important} |  | ||||||
| 				.w3-theme-d3 {color:#fff !important; background-color:#323848 !important} |  | ||||||
| 				.w3-theme-d4 {color:#fff !important; background-color:#2b303d !important} |  | ||||||
| 				.w3-theme-d5 {color:#fff !important; background-color:#242833 !important} |  | ||||||
|  |  | ||||||
| 				.w3-theme-light {color:#000 !important; background-color:#f3f4f7 !important} |  | ||||||
| 				.w3-theme-dark {color:#fff !important; background-color:#242833 !important} |  | ||||||
| 				.w3-theme-action {color:#fff !important; background-color:#242833 !important} |  | ||||||
|  |  | ||||||
| 				.w3-theme {color:#fff !important; background-color:#485167 !important} |  | ||||||
| 				.w3-text-theme {color:#485167 !important} |  | ||||||
| 				.w3-border-theme {border-color:#485167 !important} |  | ||||||
|  |  | ||||||
| 				.w3-hover-theme:hover {color:#fff !important; background-color:#485167 !important} |  | ||||||
| 				.w3-hover-text-theme:hover {color:#485167 !important} |  | ||||||
| 				.w3-hover-border-theme:hover {border-color:#485167 !important} |  | ||||||
| 			</style> |  | ||||||
| 		</head> |  | ||||||
| 		<body class="w3-theme-l3"> |  | ||||||
| 		<script>const handler = {};</script> |  | ||||||
| 		<script type="module"> |  | ||||||
| 			import * as tfrpc from '/static/tfrpc.js'; |  | ||||||
| 			handler.export_id = async function export_id(event) { |  | ||||||
| 				let id = event.srcElement.dataset.id; |  | ||||||
| 				let element = document.createElement('textarea'); |  | ||||||
| 				element.value = await tfrpc.rpc.get_private_key(id); |  | ||||||
| 				element.style = 'width: 100%; height: auto; read-only: true; resize: none'; |  | ||||||
| 				element.classList.add('w3-input'); |  | ||||||
| 				element.readOnly = true; |  | ||||||
| 				event.srcElement.parentElement.appendChild(element); |  | ||||||
| 				event.srcElement.onclick = event => handler.hide_id(event, element); |  | ||||||
| 			} |  | ||||||
| 			handler.add_id = async function add_id(event) { |  | ||||||
| 				let id = document.getElementById('add_id').value; |  | ||||||
| 				try { |  | ||||||
| 					let new_id = await tfrpc.rpc.add_id(id); |  | ||||||
| 					alert('Successfully imported: ' + new_id); |  | ||||||
| 					await tfrpc.rpc.reload(); |  | ||||||
| 				} catch (e) { |  | ||||||
| 					alert('Error importing identity: ' + e); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			handler.create_id = async function create_id(event) { |  | ||||||
| 				try { |  | ||||||
| 					let id = await tfrpc.rpc.create_id(); |  | ||||||
| 					alert('Successfully created: ' + id); |  | ||||||
| 					await tfrpc.rpc.reload(); |  | ||||||
| 				} catch (e) { |  | ||||||
| 					alert('Error creating identity: ' + e); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			handler.hide_id = function hide_id(event, element) { |  | ||||||
| 				element.parentNode.removeChild(element); |  | ||||||
| 				event.srcElement.onclick = handler.export_id; |  | ||||||
| 			} |  | ||||||
| 			handler.delete_id = async function delete_id(event) { |  | ||||||
| 				let id = event.srcElement.dataset.id; |  | ||||||
| 				try { |  | ||||||
| 					if (prompt('Are you sure you want to delete "' + id + '"?  It cannot be recovered without the exported phrase.\\n\\nEnter the word "DELETE" to confirm you wish to delete it.') === 'DELETE') { |  | ||||||
| 						if (await tfrpc.rpc.delete_id(id)) { |  | ||||||
| 							alert('Successfully deleted ID: ' + id); |  | ||||||
| 						} |  | ||||||
| 						await tfrpc.rpc.reload(); |  | ||||||
| 					} |  | ||||||
| 				} catch (e) { |  | ||||||
| 					alert('Error deleting ID: ' + e); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		</script> |  | ||||||
| 		<header class="w3-theme w3-padding"><h1>SSB Identity Management</h1></header> |  | ||||||
| 		<div class="w3-card-4 w3-margin"> |  | ||||||
| 			<header class="w3-container w3-theme-l2"><h2>Create a new identity</h2></header> |  | ||||||
| 			<footer class="w3-padding"> |  | ||||||
| 				<button id="create_id" onclick="handler.create_id()" class="w3-button w3-theme">Create Identity</button> |  | ||||||
| 			</footer> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="w3-card-4 w3-margin"> |  | ||||||
| 			<header class="w3-container w3-theme-l2"><h2>Import an SSB Identity from 12 BIP39 English Words</h2></header> |  | ||||||
| 			<textarea id="add_id" style="width: 100%" rows="4" class="w3-input"></textarea> |  | ||||||
| 			<footer class="w3-padding"> |  | ||||||
| 				<button id="add" onclick="handler.add_id(event)" class="w3-button w3-theme">Import Identity</button> |  | ||||||
| 			</footer> |  | ||||||
| 		</div> |  | ||||||
| 		<div class="w3-card-4 w3-margin"> |  | ||||||
| 			<header class="w3-container w3-theme-l2"><h2>Identities</h2></header> |  | ||||||
| 			<ul class="w3-ul">` + |  | ||||||
| 			ids |  | ||||||
| 				.map( |  | ||||||
| 					( |  | ||||||
| 						id |  | ||||||
| 					) => `<li style="overflow: hidden; text-wrap: nowrap; text-overflow: ellipsis"> |  | ||||||
| 				<button onclick="handler.export_id(event)" data-id="${id}" class="w3-button w3-theme">Export Identity</button> |  | ||||||
| 				<button onclick="handler.delete_id(event)" data-id="${id}" class="w3-button w3-theme">Delete Identity</button> |  | ||||||
| 				${id} |  | ||||||
| 			</li>` |  | ||||||
| 				) |  | ||||||
| 				.join('\n') + |  | ||||||
| 			`	</ul> |  | ||||||
| 		</div> |  | ||||||
| 	</body>` |  | ||||||
| 	); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| main(); |  | ||||||
| @@ -1,235 +0,0 @@ | |||||||
| /* W3.CSS 4.15 December 2020 by Jan Egil and Borge Refsnes */ |  | ||||||
| html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit} |  | ||||||
| /* Extract from normalize.css by Nicolas Gallagher and Jonathan Neal git.io/normalize */ |  | ||||||
| html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0} |  | ||||||
| article,aside,details,figcaption,figure,footer,header,main,menu,nav,section{display:block}summary{display:list-item} |  | ||||||
| audio,canvas,progress,video{display:inline-block}progress{vertical-align:baseline} |  | ||||||
| audio:not([controls]){display:none;height:0}[hidden],template{display:none} |  | ||||||
| a{background-color:transparent}a:active,a:hover{outline-width:0} |  | ||||||
| abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted} |  | ||||||
| b,strong{font-weight:bolder}dfn{font-style:italic}mark{background:#ff0;color:#000} |  | ||||||
| small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} |  | ||||||
| sub{bottom:-0.25em}sup{top:-0.5em}figure{margin:1em 40px}img{border-style:none} |  | ||||||
| code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}hr{box-sizing:content-box;height:0;overflow:visible} |  | ||||||
| button,input,select,textarea,optgroup{font:inherit;margin:0}optgroup{font-weight:bold} |  | ||||||
| button,input{overflow:visible}button,select{text-transform:none} |  | ||||||
| button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button} |  | ||||||
| button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0} |  | ||||||
| button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText} |  | ||||||
| fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em} |  | ||||||
| legend{color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto} |  | ||||||
| [type=checkbox],[type=radio]{padding:0} |  | ||||||
| [type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto} |  | ||||||
| [type=search]{-webkit-appearance:textfield;outline-offset:-2px} |  | ||||||
| [type=search]::-webkit-search-decoration{-webkit-appearance:none} |  | ||||||
| ::-webkit-file-upload-button{-webkit-appearance:button;font:inherit} |  | ||||||
| /* End extract */ |  | ||||||
| html,body{font-family:Verdana,sans-serif;font-size:15px;line-height:1.5}html{overflow-x:hidden} |  | ||||||
| h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:20px}h5{font-size:18px}h6{font-size:16px} |  | ||||||
| .w3-serif{font-family:serif}.w3-sans-serif{font-family:sans-serif}.w3-cursive{font-family:cursive}.w3-monospace{font-family:monospace} |  | ||||||
| h1,h2,h3,h4,h5,h6{font-family:"Segoe UI",Arial,sans-serif;font-weight:400;margin:10px 0}.w3-wide{letter-spacing:4px} |  | ||||||
| hr{border:0;border-top:1px solid #eee;margin:20px 0} |  | ||||||
| .w3-image{max-width:100%;height:auto}img{vertical-align:middle}a{color:inherit} |  | ||||||
| .w3-table,.w3-table-all{border-collapse:collapse;border-spacing:0;width:100%;display:table}.w3-table-all{border:1px solid #ccc} |  | ||||||
| .w3-bordered tr,.w3-table-all tr{border-bottom:1px solid #ddd}.w3-striped tbody tr:nth-child(even){background-color:#f1f1f1} |  | ||||||
| .w3-table-all tr:nth-child(odd){background-color:#fff}.w3-table-all tr:nth-child(even){background-color:#f1f1f1} |  | ||||||
| .w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center} |  | ||||||
| .w3-table td,.w3-table th,.w3-table-all td,.w3-table-all th{padding:8px 8px;display:table-cell;text-align:left;vertical-align:top} |  | ||||||
| .w3-table th:first-child,.w3-table td:first-child,.w3-table-all th:first-child,.w3-table-all td:first-child{padding-left:16px} |  | ||||||
| .w3-btn,.w3-button{border:none;display:inline-block;padding:8px 16px;vertical-align:middle;overflow:hidden;text-decoration:none;color:inherit;background-color:inherit;text-align:center;cursor:pointer;white-space:nowrap} |  | ||||||
| .w3-btn:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)} |  | ||||||
| .w3-btn,.w3-button{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}    |  | ||||||
| .w3-disabled,.w3-btn:disabled,.w3-button:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none} |  | ||||||
| .w3-btn.w3-disabled:hover,.w3-btn:disabled:hover{box-shadow:none} |  | ||||||
| .w3-badge,.w3-tag{background-color:#000;color:#fff;display:inline-block;padding-left:8px;padding-right:8px;text-align:center}.w3-badge{border-radius:50%} |  | ||||||
| .w3-ul{list-style-type:none;padding:0;margin:0}.w3-ul li{padding:8px 16px;border-bottom:1px solid #ddd}.w3-ul li:last-child{border-bottom:none} |  | ||||||
| .w3-tooltip,.w3-display-container{position:relative}.w3-tooltip .w3-text{display:none}.w3-tooltip:hover .w3-text{display:inline-block} |  | ||||||
| .w3-ripple:active{opacity:0.5}.w3-ripple{transition:opacity 0s} |  | ||||||
| .w3-input{padding:8px;display:block;border:none;border-bottom:1px solid #ccc;width:100%} |  | ||||||
| .w3-select{padding:9px 0;width:100%;border:none;border-bottom:1px solid #ccc} |  | ||||||
| .w3-dropdown-click,.w3-dropdown-hover{position:relative;display:inline-block;cursor:pointer} |  | ||||||
| .w3-dropdown-hover:hover .w3-dropdown-content{display:block} |  | ||||||
| .w3-dropdown-hover:first-child,.w3-dropdown-click:hover{background-color:#ccc;color:#000} |  | ||||||
| .w3-dropdown-hover:hover > .w3-button:first-child,.w3-dropdown-click:hover > .w3-button:first-child{background-color:#ccc;color:#000} |  | ||||||
| .w3-dropdown-content{cursor:auto;color:#000;background-color:#fff;display:none;position:absolute;min-width:160px;margin:0;padding:0;z-index:1} |  | ||||||
| .w3-check,.w3-radio{width:24px;height:24px;position:relative;top:6px} |  | ||||||
| .w3-sidebar{height:100%;width:200px;background-color:#fff;position:fixed!important;z-index:1;overflow:auto} |  | ||||||
| .w3-bar-block .w3-dropdown-hover,.w3-bar-block .w3-dropdown-click{width:100%} |  | ||||||
| .w3-bar-block .w3-dropdown-hover .w3-dropdown-content,.w3-bar-block .w3-dropdown-click .w3-dropdown-content{min-width:100%} |  | ||||||
| .w3-bar-block .w3-dropdown-hover .w3-button,.w3-bar-block .w3-dropdown-click .w3-button{width:100%;text-align:left;padding:8px 16px} |  | ||||||
| .w3-main,#main{transition:margin-left .4s} |  | ||||||
| .w3-modal{z-index:3;display:none;padding-top:100px;position:fixed;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgb(0,0,0);background-color:rgba(0,0,0,0.4)} |  | ||||||
| .w3-modal-content{margin:auto;background-color:#fff;position:relative;padding:0;outline:0;width:600px} |  | ||||||
| .w3-bar{width:100%;overflow:hidden}.w3-center .w3-bar{display:inline-block;width:auto} |  | ||||||
| .w3-bar .w3-bar-item{padding:8px 16px;float:left;width:auto;border:none;display:block;outline:0} |  | ||||||
| .w3-bar .w3-dropdown-hover,.w3-bar .w3-dropdown-click{position:static;float:left} |  | ||||||
| .w3-bar .w3-button{white-space:normal} |  | ||||||
| .w3-bar-block .w3-bar-item{width:100%;display:block;padding:8px 16px;text-align:left;border:none;white-space:normal;float:none;outline:0} |  | ||||||
| .w3-bar-block.w3-center .w3-bar-item{text-align:center}.w3-block{display:block;width:100%} |  | ||||||
| .w3-responsive{display:block;overflow-x:auto} |  | ||||||
| .w3-container:after,.w3-container:before,.w3-panel:after,.w3-panel:before,.w3-row:after,.w3-row:before,.w3-row-padding:after,.w3-row-padding:before, |  | ||||||
| .w3-cell-row:before,.w3-cell-row:after,.w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after{content:"";display:table;clear:both} |  | ||||||
| .w3-col,.w3-half,.w3-third,.w3-twothird,.w3-threequarter,.w3-quarter{float:left;width:100%} |  | ||||||
| .w3-col.s1{width:8.33333%}.w3-col.s2{width:16.66666%}.w3-col.s3{width:24.99999%}.w3-col.s4{width:33.33333%} |  | ||||||
| .w3-col.s5{width:41.66666%}.w3-col.s6{width:49.99999%}.w3-col.s7{width:58.33333%}.w3-col.s8{width:66.66666%} |  | ||||||
| .w3-col.s9{width:74.99999%}.w3-col.s10{width:83.33333%}.w3-col.s11{width:91.66666%}.w3-col.s12{width:99.99999%} |  | ||||||
| @media (min-width:601px){.w3-col.m1{width:8.33333%}.w3-col.m2{width:16.66666%}.w3-col.m3,.w3-quarter{width:24.99999%}.w3-col.m4,.w3-third{width:33.33333%} |  | ||||||
| .w3-col.m5{width:41.66666%}.w3-col.m6,.w3-half{width:49.99999%}.w3-col.m7{width:58.33333%}.w3-col.m8,.w3-twothird{width:66.66666%} |  | ||||||
| .w3-col.m9,.w3-threequarter{width:74.99999%}.w3-col.m10{width:83.33333%}.w3-col.m11{width:91.66666%}.w3-col.m12{width:99.99999%}} |  | ||||||
| @media (min-width:993px){.w3-col.l1{width:8.33333%}.w3-col.l2{width:16.66666%}.w3-col.l3{width:24.99999%}.w3-col.l4{width:33.33333%} |  | ||||||
| .w3-col.l5{width:41.66666%}.w3-col.l6{width:49.99999%}.w3-col.l7{width:58.33333%}.w3-col.l8{width:66.66666%} |  | ||||||
| .w3-col.l9{width:74.99999%}.w3-col.l10{width:83.33333%}.w3-col.l11{width:91.66666%}.w3-col.l12{width:99.99999%}} |  | ||||||
| .w3-rest{overflow:hidden}.w3-stretch{margin-left:-16px;margin-right:-16px} |  | ||||||
| .w3-content,.w3-auto{margin-left:auto;margin-right:auto}.w3-content{max-width:980px}.w3-auto{max-width:1140px} |  | ||||||
| .w3-cell-row{display:table;width:100%}.w3-cell{display:table-cell} |  | ||||||
| .w3-cell-top{vertical-align:top}.w3-cell-middle{vertical-align:middle}.w3-cell-bottom{vertical-align:bottom} |  | ||||||
| .w3-hide{display:none!important}.w3-show-block,.w3-show{display:block!important}.w3-show-inline-block{display:inline-block!important} |  | ||||||
| @media (max-width:1205px){.w3-auto{max-width:95%}} |  | ||||||
| @media (max-width:600px){.w3-modal-content{margin:0 10px;width:auto!important}.w3-modal{padding-top:30px} |  | ||||||
| .w3-dropdown-hover.w3-mobile .w3-dropdown-content,.w3-dropdown-click.w3-mobile .w3-dropdown-content{position:relative}	 |  | ||||||
| .w3-hide-small{display:none!important}.w3-mobile{display:block;width:100%!important}.w3-bar-item.w3-mobile,.w3-dropdown-hover.w3-mobile,.w3-dropdown-click.w3-mobile{text-align:center} |  | ||||||
| .w3-dropdown-hover.w3-mobile,.w3-dropdown-hover.w3-mobile .w3-btn,.w3-dropdown-hover.w3-mobile .w3-button,.w3-dropdown-click.w3-mobile,.w3-dropdown-click.w3-mobile .w3-btn,.w3-dropdown-click.w3-mobile .w3-button{width:100%}} |  | ||||||
| @media (max-width:768px){.w3-modal-content{width:500px}.w3-modal{padding-top:50px}} |  | ||||||
| @media (min-width:993px){.w3-modal-content{width:900px}.w3-hide-large{display:none!important}.w3-sidebar.w3-collapse{display:block!important}} |  | ||||||
| @media (max-width:992px) and (min-width:601px){.w3-hide-medium{display:none!important}} |  | ||||||
| @media (max-width:992px){.w3-sidebar.w3-collapse{display:none}.w3-main{margin-left:0!important;margin-right:0!important}.w3-auto{max-width:100%}} |  | ||||||
| .w3-top,.w3-bottom{position:fixed;width:100%;z-index:1}.w3-top{top:0}.w3-bottom{bottom:0} |  | ||||||
| .w3-overlay{position:fixed;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.5);z-index:2} |  | ||||||
| .w3-display-topleft{position:absolute;left:0;top:0}.w3-display-topright{position:absolute;right:0;top:0} |  | ||||||
| .w3-display-bottomleft{position:absolute;left:0;bottom:0}.w3-display-bottomright{position:absolute;right:0;bottom:0} |  | ||||||
| .w3-display-middle{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%)} |  | ||||||
| .w3-display-left{position:absolute;top:50%;left:0%;transform:translate(0%,-50%);-ms-transform:translate(-0%,-50%)} |  | ||||||
| .w3-display-right{position:absolute;top:50%;right:0%;transform:translate(0%,-50%);-ms-transform:translate(0%,-50%)} |  | ||||||
| .w3-display-topmiddle{position:absolute;left:50%;top:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)} |  | ||||||
| .w3-display-bottommiddle{position:absolute;left:50%;bottom:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)} |  | ||||||
| .w3-display-container:hover .w3-display-hover{display:block}.w3-display-container:hover span.w3-display-hover{display:inline-block}.w3-display-hover{display:none} |  | ||||||
| .w3-display-position{position:absolute} |  | ||||||
| .w3-circle{border-radius:50%} |  | ||||||
| .w3-round-small{border-radius:2px}.w3-round,.w3-round-medium{border-radius:4px}.w3-round-large{border-radius:8px}.w3-round-xlarge{border-radius:16px}.w3-round-xxlarge{border-radius:32px} |  | ||||||
| .w3-row-padding,.w3-row-padding>.w3-half,.w3-row-padding>.w3-third,.w3-row-padding>.w3-twothird,.w3-row-padding>.w3-threequarter,.w3-row-padding>.w3-quarter,.w3-row-padding>.w3-col{padding:0 8px} |  | ||||||
| .w3-container,.w3-panel{padding:0.01em 16px}.w3-panel{margin-top:16px;margin-bottom:16px} |  | ||||||
| .w3-code,.w3-codespan{font-family:Consolas,"courier new";font-size:16px} |  | ||||||
| .w3-code{width:auto;background-color:#fff;padding:8px 12px;border-left:4px solid #4CAF50;word-wrap:break-word} |  | ||||||
| .w3-codespan{color:crimson;background-color:#f1f1f1;padding-left:4px;padding-right:4px;font-size:110%} |  | ||||||
| .w3-card,.w3-card-2{box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12)} |  | ||||||
| .w3-card-4,.w3-hover-shadow:hover{box-shadow:0 4px 10px 0 rgba(0,0,0,0.2),0 4px 20px 0 rgba(0,0,0,0.19)} |  | ||||||
| .w3-spin{animation:w3-spin 2s infinite linear}@keyframes w3-spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}} |  | ||||||
| .w3-animate-fading{animation:fading 10s infinite}@keyframes fading{0%{opacity:0}50%{opacity:1}100%{opacity:0}} |  | ||||||
| .w3-animate-opacity{animation:opac 0.8s}@keyframes opac{from{opacity:0} to{opacity:1}} |  | ||||||
| .w3-animate-top{position:relative;animation:animatetop 0.4s}@keyframes animatetop{from{top:-300px;opacity:0} to{top:0;opacity:1}} |  | ||||||
| .w3-animate-left{position:relative;animation:animateleft 0.4s}@keyframes animateleft{from{left:-300px;opacity:0} to{left:0;opacity:1}} |  | ||||||
| .w3-animate-right{position:relative;animation:animateright 0.4s}@keyframes animateright{from{right:-300px;opacity:0} to{right:0;opacity:1}} |  | ||||||
| .w3-animate-bottom{position:relative;animation:animatebottom 0.4s}@keyframes animatebottom{from{bottom:-300px;opacity:0} to{bottom:0;opacity:1}} |  | ||||||
| .w3-animate-zoom {animation:animatezoom 0.6s}@keyframes animatezoom{from{transform:scale(0)} to{transform:scale(1)}} |  | ||||||
| .w3-animate-input{transition:width 0.4s ease-in-out}.w3-animate-input:focus{width:100%!important} |  | ||||||
| .w3-opacity,.w3-hover-opacity:hover{opacity:0.60}.w3-opacity-off,.w3-hover-opacity-off:hover{opacity:1} |  | ||||||
| .w3-opacity-max{opacity:0.25}.w3-opacity-min{opacity:0.75} |  | ||||||
| .w3-greyscale-max,.w3-grayscale-max,.w3-hover-greyscale:hover,.w3-hover-grayscale:hover{filter:grayscale(100%)} |  | ||||||
| .w3-greyscale,.w3-grayscale{filter:grayscale(75%)}.w3-greyscale-min,.w3-grayscale-min{filter:grayscale(50%)} |  | ||||||
| .w3-sepia{filter:sepia(75%)}.w3-sepia-max,.w3-hover-sepia:hover{filter:sepia(100%)}.w3-sepia-min{filter:sepia(50%)} |  | ||||||
| .w3-tiny{font-size:10px!important}.w3-small{font-size:12px!important}.w3-medium{font-size:15px!important}.w3-large{font-size:18px!important} |  | ||||||
| .w3-xlarge{font-size:24px!important}.w3-xxlarge{font-size:36px!important}.w3-xxxlarge{font-size:48px!important}.w3-jumbo{font-size:64px!important} |  | ||||||
| .w3-left-align{text-align:left!important}.w3-right-align{text-align:right!important}.w3-justify{text-align:justify!important}.w3-center{text-align:center!important} |  | ||||||
| .w3-border-0{border:0!important}.w3-border{border:1px solid #ccc!important} |  | ||||||
| .w3-border-top{border-top:1px solid #ccc!important}.w3-border-bottom{border-bottom:1px solid #ccc!important} |  | ||||||
| .w3-border-left{border-left:1px solid #ccc!important}.w3-border-right{border-right:1px solid #ccc!important} |  | ||||||
| .w3-topbar{border-top:6px solid #ccc!important}.w3-bottombar{border-bottom:6px solid #ccc!important} |  | ||||||
| .w3-leftbar{border-left:6px solid #ccc!important}.w3-rightbar{border-right:6px solid #ccc!important} |  | ||||||
| .w3-section,.w3-code{margin-top:16px!important;margin-bottom:16px!important} |  | ||||||
| .w3-margin{margin:16px!important}.w3-margin-top{margin-top:16px!important}.w3-margin-bottom{margin-bottom:16px!important} |  | ||||||
| .w3-margin-left{margin-left:16px!important}.w3-margin-right{margin-right:16px!important} |  | ||||||
| .w3-padding-small{padding:4px 8px!important}.w3-padding{padding:8px 16px!important}.w3-padding-large{padding:12px 24px!important} |  | ||||||
| .w3-padding-16{padding-top:16px!important;padding-bottom:16px!important}.w3-padding-24{padding-top:24px!important;padding-bottom:24px!important} |  | ||||||
| .w3-padding-32{padding-top:32px!important;padding-bottom:32px!important}.w3-padding-48{padding-top:48px!important;padding-bottom:48px!important} |  | ||||||
| .w3-padding-64{padding-top:64px!important;padding-bottom:64px!important} |  | ||||||
| .w3-padding-top-64{padding-top:64px!important}.w3-padding-top-48{padding-top:48px!important} |  | ||||||
| .w3-padding-top-32{padding-top:32px!important}.w3-padding-top-24{padding-top:24px!important} |  | ||||||
| .w3-left{float:left!important}.w3-right{float:right!important} |  | ||||||
| .w3-button:hover{color:#000!important;background-color:#ccc!important} |  | ||||||
| .w3-transparent,.w3-hover-none:hover{background-color:transparent!important} |  | ||||||
| .w3-hover-none:hover{box-shadow:none!important} |  | ||||||
| /* Colors */ |  | ||||||
| .w3-amber,.w3-hover-amber:hover{color:#000!important;background-color:#ffc107!important} |  | ||||||
| .w3-aqua,.w3-hover-aqua:hover{color:#000!important;background-color:#00ffff!important} |  | ||||||
| .w3-blue,.w3-hover-blue:hover{color:#fff!important;background-color:#2196F3!important} |  | ||||||
| .w3-light-blue,.w3-hover-light-blue:hover{color:#000!important;background-color:#87CEEB!important} |  | ||||||
| .w3-brown,.w3-hover-brown:hover{color:#fff!important;background-color:#795548!important} |  | ||||||
| .w3-cyan,.w3-hover-cyan:hover{color:#000!important;background-color:#00bcd4!important} |  | ||||||
| .w3-blue-grey,.w3-hover-blue-grey:hover,.w3-blue-gray,.w3-hover-blue-gray:hover{color:#fff!important;background-color:#607d8b!important} |  | ||||||
| .w3-green,.w3-hover-green:hover{color:#fff!important;background-color:#4CAF50!important} |  | ||||||
| .w3-light-green,.w3-hover-light-green:hover{color:#000!important;background-color:#8bc34a!important} |  | ||||||
| .w3-indigo,.w3-hover-indigo:hover{color:#fff!important;background-color:#3f51b5!important} |  | ||||||
| .w3-khaki,.w3-hover-khaki:hover{color:#000!important;background-color:#f0e68c!important} |  | ||||||
| .w3-lime,.w3-hover-lime:hover{color:#000!important;background-color:#cddc39!important} |  | ||||||
| .w3-orange,.w3-hover-orange:hover{color:#000!important;background-color:#ff9800!important} |  | ||||||
| .w3-deep-orange,.w3-hover-deep-orange:hover{color:#fff!important;background-color:#ff5722!important} |  | ||||||
| .w3-pink,.w3-hover-pink:hover{color:#fff!important;background-color:#e91e63!important} |  | ||||||
| .w3-purple,.w3-hover-purple:hover{color:#fff!important;background-color:#9c27b0!important} |  | ||||||
| .w3-deep-purple,.w3-hover-deep-purple:hover{color:#fff!important;background-color:#673ab7!important} |  | ||||||
| .w3-red,.w3-hover-red:hover{color:#fff!important;background-color:#f44336!important} |  | ||||||
| .w3-sand,.w3-hover-sand:hover{color:#000!important;background-color:#fdf5e6!important} |  | ||||||
| .w3-teal,.w3-hover-teal:hover{color:#fff!important;background-color:#009688!important} |  | ||||||
| .w3-yellow,.w3-hover-yellow:hover{color:#000!important;background-color:#ffeb3b!important} |  | ||||||
| .w3-white,.w3-hover-white:hover{color:#000!important;background-color:#fff!important} |  | ||||||
| .w3-black,.w3-hover-black:hover{color:#fff!important;background-color:#000!important} |  | ||||||
| .w3-grey,.w3-hover-grey:hover,.w3-gray,.w3-hover-gray:hover{color:#000!important;background-color:#9e9e9e!important} |  | ||||||
| .w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,.w3-hover-light-gray:hover{color:#000!important;background-color:#f1f1f1!important} |  | ||||||
| .w3-dark-grey,.w3-hover-dark-grey:hover,.w3-dark-gray,.w3-hover-dark-gray:hover{color:#fff!important;background-color:#616161!important} |  | ||||||
| .w3-pale-red,.w3-hover-pale-red:hover{color:#000!important;background-color:#ffdddd!important} |  | ||||||
| .w3-pale-green,.w3-hover-pale-green:hover{color:#000!important;background-color:#ddffdd!important} |  | ||||||
| .w3-pale-yellow,.w3-hover-pale-yellow:hover{color:#000!important;background-color:#ffffcc!important} |  | ||||||
| .w3-pale-blue,.w3-hover-pale-blue:hover{color:#000!important;background-color:#ddffff!important} |  | ||||||
| .w3-text-amber,.w3-hover-text-amber:hover{color:#ffc107!important} |  | ||||||
| .w3-text-aqua,.w3-hover-text-aqua:hover{color:#00ffff!important} |  | ||||||
| .w3-text-blue,.w3-hover-text-blue:hover{color:#2196F3!important} |  | ||||||
| .w3-text-light-blue,.w3-hover-text-light-blue:hover{color:#87CEEB!important} |  | ||||||
| .w3-text-brown,.w3-hover-text-brown:hover{color:#795548!important} |  | ||||||
| .w3-text-cyan,.w3-hover-text-cyan:hover{color:#00bcd4!important} |  | ||||||
| .w3-text-blue-grey,.w3-hover-text-blue-grey:hover,.w3-text-blue-gray,.w3-hover-text-blue-gray:hover{color:#607d8b!important} |  | ||||||
| .w3-text-green,.w3-hover-text-green:hover{color:#4CAF50!important} |  | ||||||
| .w3-text-light-green,.w3-hover-text-light-green:hover{color:#8bc34a!important} |  | ||||||
| .w3-text-indigo,.w3-hover-text-indigo:hover{color:#3f51b5!important} |  | ||||||
| .w3-text-khaki,.w3-hover-text-khaki:hover{color:#b4aa50!important} |  | ||||||
| .w3-text-lime,.w3-hover-text-lime:hover{color:#cddc39!important} |  | ||||||
| .w3-text-orange,.w3-hover-text-orange:hover{color:#ff9800!important} |  | ||||||
| .w3-text-deep-orange,.w3-hover-text-deep-orange:hover{color:#ff5722!important} |  | ||||||
| .w3-text-pink,.w3-hover-text-pink:hover{color:#e91e63!important} |  | ||||||
| .w3-text-purple,.w3-hover-text-purple:hover{color:#9c27b0!important} |  | ||||||
| .w3-text-deep-purple,.w3-hover-text-deep-purple:hover{color:#673ab7!important} |  | ||||||
| .w3-text-red,.w3-hover-text-red:hover{color:#f44336!important} |  | ||||||
| .w3-text-sand,.w3-hover-text-sand:hover{color:#fdf5e6!important} |  | ||||||
| .w3-text-teal,.w3-hover-text-teal:hover{color:#009688!important} |  | ||||||
| .w3-text-yellow,.w3-hover-text-yellow:hover{color:#d2be0e!important} |  | ||||||
| .w3-text-white,.w3-hover-text-white:hover{color:#fff!important} |  | ||||||
| .w3-text-black,.w3-hover-text-black:hover{color:#000!important} |  | ||||||
| .w3-text-grey,.w3-hover-text-grey:hover,.w3-text-gray,.w3-hover-text-gray:hover{color:#757575!important} |  | ||||||
| .w3-text-light-grey,.w3-hover-text-light-grey:hover,.w3-text-light-gray,.w3-hover-text-light-gray:hover{color:#f1f1f1!important} |  | ||||||
| .w3-text-dark-grey,.w3-hover-text-dark-grey:hover,.w3-text-dark-gray,.w3-hover-text-dark-gray:hover{color:#3a3a3a!important} |  | ||||||
| .w3-border-amber,.w3-hover-border-amber:hover{border-color:#ffc107!important} |  | ||||||
| .w3-border-aqua,.w3-hover-border-aqua:hover{border-color:#00ffff!important} |  | ||||||
| .w3-border-blue,.w3-hover-border-blue:hover{border-color:#2196F3!important} |  | ||||||
| .w3-border-light-blue,.w3-hover-border-light-blue:hover{border-color:#87CEEB!important} |  | ||||||
| .w3-border-brown,.w3-hover-border-brown:hover{border-color:#795548!important} |  | ||||||
| .w3-border-cyan,.w3-hover-border-cyan:hover{border-color:#00bcd4!important} |  | ||||||
| .w3-border-blue-grey,.w3-hover-border-blue-grey:hover,.w3-border-blue-gray,.w3-hover-border-blue-gray:hover{border-color:#607d8b!important} |  | ||||||
| .w3-border-green,.w3-hover-border-green:hover{border-color:#4CAF50!important} |  | ||||||
| .w3-border-light-green,.w3-hover-border-light-green:hover{border-color:#8bc34a!important} |  | ||||||
| .w3-border-indigo,.w3-hover-border-indigo:hover{border-color:#3f51b5!important} |  | ||||||
| .w3-border-khaki,.w3-hover-border-khaki:hover{border-color:#f0e68c!important} |  | ||||||
| .w3-border-lime,.w3-hover-border-lime:hover{border-color:#cddc39!important} |  | ||||||
| .w3-border-orange,.w3-hover-border-orange:hover{border-color:#ff9800!important} |  | ||||||
| .w3-border-deep-orange,.w3-hover-border-deep-orange:hover{border-color:#ff5722!important} |  | ||||||
| .w3-border-pink,.w3-hover-border-pink:hover{border-color:#e91e63!important} |  | ||||||
| .w3-border-purple,.w3-hover-border-purple:hover{border-color:#9c27b0!important} |  | ||||||
| .w3-border-deep-purple,.w3-hover-border-deep-purple:hover{border-color:#673ab7!important} |  | ||||||
| .w3-border-red,.w3-hover-border-red:hover{border-color:#f44336!important} |  | ||||||
| .w3-border-sand,.w3-hover-border-sand:hover{border-color:#fdf5e6!important} |  | ||||||
| .w3-border-teal,.w3-hover-border-teal:hover{border-color:#009688!important} |  | ||||||
| .w3-border-yellow,.w3-hover-border-yellow:hover{border-color:#ffeb3b!important} |  | ||||||
| .w3-border-white,.w3-hover-border-white:hover{border-color:#fff!important} |  | ||||||
| .w3-border-black,.w3-hover-border-black:hover{border-color:#000!important} |  | ||||||
| .w3-border-grey,.w3-hover-border-grey:hover,.w3-border-gray,.w3-hover-border-gray:hover{border-color:#9e9e9e!important} |  | ||||||
| .w3-border-light-grey,.w3-hover-border-light-grey:hover,.w3-border-light-gray,.w3-hover-border-light-gray:hover{border-color:#f1f1f1!important} |  | ||||||
| .w3-border-dark-grey,.w3-hover-border-dark-grey:hover,.w3-border-dark-gray,.w3-hover-border-dark-gray:hover{border-color:#616161!important} |  | ||||||
| .w3-border-pale-red,.w3-hover-border-pale-red:hover{border-color:#ffe7e7!important}.w3-border-pale-green,.w3-hover-border-pale-green:hover{border-color:#e7ffe7!important} |  | ||||||
| .w3-border-pale-yellow,.w3-hover-border-pale-yellow:hover{border-color:#ffffcc!important}.w3-border-pale-blue,.w3-hover-border-pale-blue:hover{border-color:#e7ffff!important} |  | ||||||
| @@ -1,5 +1,5 @@ | |||||||
| { | { | ||||||
| 	"type": "tildefriends-app", | 	"type": "tildefriends-app", | ||||||
| 	"emoji": "🦟", | 	"emoji": "🦟", | ||||||
| 	"previous": "&cUqvSDUls3jn0haD85LPFAGdkc8wFuy347TtATNcJgg=.sha256" | 	"previous": "&TegdzvFE+im94shygaHkgDYSaSrwY2h0OKUXSRPBQDM=.sha256" | ||||||
| } | } | ||||||
|   | |||||||
| @@ -85,9 +85,6 @@ tfrpc.register(async function store_message(message) { | |||||||
| tfrpc.register(function apps() { | tfrpc.register(function apps() { | ||||||
| 	return core.apps(); | 	return core.apps(); | ||||||
| }); | }); | ||||||
| tfrpc.register(function getActiveIdentity() { |  | ||||||
| 	return ssb.getActiveIdentity(); |  | ||||||
| }); |  | ||||||
| tfrpc.register(async function try_decrypt(id, content) { | tfrpc.register(async function try_decrypt(id, content) { | ||||||
| 	return await ssb.privateMessageDecrypt(id, content); | 	return await ssb.privateMessageDecrypt(id, content); | ||||||
| }); | }); | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								apps/issues/lit-all.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								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
											
										
									
								
							| @@ -4,6 +4,48 @@ import * as tfutils from './tf-utils.js'; | |||||||
|  |  | ||||||
| const k_project = '%Hr+4xEVtjplidSKBlRWi4Aw/0Tfw7B+1OR9BzlDKmOI=.sha256'; | const k_project = '%Hr+4xEVtjplidSKBlRWi4Aw/0Tfw7B+1OR9BzlDKmOI=.sha256'; | ||||||
|  |  | ||||||
|  | class TfIdPickerElement extends LitElement { | ||||||
|  | 	static get properties() { | ||||||
|  | 		return { | ||||||
|  | 			ids: {type: Array}, | ||||||
|  | 			selected: {type: String}, | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	constructor() { | ||||||
|  | 		super(); | ||||||
|  | 		this.load(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	async load() { | ||||||
|  | 		this.selected = await tfrpc.rpc.localStorageGet('whoami'); | ||||||
|  | 		this.ids = (await tfrpc.rpc.getIdentities()) || []; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	changed(event) { | ||||||
|  | 		this.selected = event.srcElement.value; | ||||||
|  | 		tfrpc.rpc.localStorageSet('whoami', this.selected); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	render() { | ||||||
|  | 		if (this.ids) { | ||||||
|  | 			return html` | ||||||
|  | 				<select @change=${this.changed} style="max-width: 100%"> | ||||||
|  | 					${this.ids.map( | ||||||
|  | 						(id) => | ||||||
|  | 							html`<option ?selected=${id == this.selected} value=${id}> | ||||||
|  | 								${id} | ||||||
|  | 							</option>` | ||||||
|  | 					)} | ||||||
|  | 				</select> | ||||||
|  | 			`; | ||||||
|  | 		} else { | ||||||
|  | 			return html`<div>Loading...</div>`; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | customElements.define('tf-id-picker', TfIdPickerElement); | ||||||
|  |  | ||||||
| class TfComposeElement extends LitElement { | class TfComposeElement extends LitElement { | ||||||
| 	static get properties() { | 	static get properties() { | ||||||
| 		return { | 		return { | ||||||
| @@ -63,10 +105,10 @@ class TfIssuesAppElement extends LitElement { | |||||||
| 		let issues = {}; | 		let issues = {}; | ||||||
| 		let messages = await tfrpc.rpc.query( | 		let messages = await tfrpc.rpc.query( | ||||||
| 			` | 			` | ||||||
| 			WITH issues AS (SELECT messages.id, json(messages.content) AS content, messages.author, messages.timestamp FROM messages_refs JOIN messages ON | 			WITH issues AS (SELECT messages.* FROM messages_refs JOIN messages ON | ||||||
| 				messages.id = messages_refs.message | 				messages.id = messages_refs.message | ||||||
| 				WHERE messages_refs.ref = ? AND json_extract(messages.content, '$.type') = 'issue'), | 				WHERE messages_refs.ref = ? AND json_extract(messages.content, '$.type') = 'issue'), | ||||||
| 			edits AS (SELECT messages.id, json(messages.content) AS content, messages.author, messages.timestamp FROM issues JOIN messages_refs ON | 			edits AS (SELECT messages.* FROM issues JOIN messages_refs ON | ||||||
| 				issues.id = messages_refs.ref JOIN messages ON | 				issues.id = messages_refs.ref JOIN messages ON | ||||||
| 				messages.id = messages_refs.message | 				messages.id = messages_refs.message | ||||||
| 				WHERE json_extract(messages.content, '$.type') IN ('issue-edit', 'post')) | 				WHERE json_extract(messages.content, '$.type') IN ('issue-edit', 'post')) | ||||||
| @@ -164,7 +206,7 @@ class TfIssuesAppElement extends LitElement { | |||||||
| 		if ( | 		if ( | ||||||
| 			confirm(`Are you sure you want to ${open ? 'open' : 'close'} this issue?`) | 			confirm(`Are you sure you want to ${open ? 'open' : 'close'} this issue?`) | ||||||
| 		) { | 		) { | ||||||
| 			let whoami = await tfrpc.rpc.getActiveIdentity(); | 			let whoami = this.shadowRoot.getElementById('picker').selected; | ||||||
| 			await tfrpc.rpc.appendMessage(whoami, { | 			await tfrpc.rpc.appendMessage(whoami, { | ||||||
| 				type: 'issue-edit', | 				type: 'issue-edit', | ||||||
| 				issues: [ | 				issues: [ | ||||||
| @@ -179,7 +221,7 @@ class TfIssuesAppElement extends LitElement { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	async create_issue(event) { | 	async create_issue(event) { | ||||||
| 		let whoami = await tfrpc.rpc.getActiveIdentity(); | 		let whoami = this.shadowRoot.getElementById('picker').selected; | ||||||
| 		await tfrpc.rpc.appendMessage(whoami, { | 		await tfrpc.rpc.appendMessage(whoami, { | ||||||
| 			type: 'issue', | 			type: 'issue', | ||||||
| 			project: k_project, | 			project: k_project, | ||||||
| @@ -189,7 +231,7 @@ class TfIssuesAppElement extends LitElement { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	async reply_to_issue(event) { | 	async reply_to_issue(event) { | ||||||
| 		let whoami = await tfrpc.rpc.getActiveIdentity(); | 		let whoami = this.shadowRoot.getElementById('picker').selected; | ||||||
| 		await tfrpc.rpc.appendMessage(whoami, { | 		await tfrpc.rpc.appendMessage(whoami, { | ||||||
| 			type: 'post', | 			type: 'post', | ||||||
| 			text: event.detail.value, | 			text: event.detail.value, | ||||||
| @@ -207,7 +249,10 @@ class TfIssuesAppElement extends LitElement { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	render() { | 	render() { | ||||||
| 		let header = html` <h1>Tilde Friends Issues</h1> `; | 		let header = html` | ||||||
|  | 			<h1>Tilde Friends Issues</h1> | ||||||
|  | 			<tf-id-picker id="picker"></tf-id-picker> | ||||||
|  | 		`; | ||||||
| 		if (this.selected) { | 		if (this.selected) { | ||||||
| 			return html` | 			return html` | ||||||
| 				${header} | 				${header} | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								apps/journal/lit-all.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								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
											
										
									
								
							| @@ -1,5 +1,5 @@ | |||||||
| { | { | ||||||
| 	"type": "tildefriends-app", | 	"type": "tildefriends-app", | ||||||
| 	"emoji": "🚪", | 	"emoji": "📦", | ||||||
| 	"previous": "&HXCdDG8gGYXElTyEFbg85jqa6lDXNL2ENPIA9UoJNbI=.sha256" | 	"previous": "&IU+TwyM7TznD8NBfnw7tgW2zxVlMqTVxSqWFjuosLwo=.sha256" | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								apps/sneaker/lit-all.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								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", | 	"type": "tildefriends-app", | ||||||
| 	"emoji": "🐌", | 	"emoji": "🐌", | ||||||
| 	"previous": "&vEaOZjrNb0u9rhNqrQ8eU9TlOFlo4HsgW6hbI7VdIT0=.sha256" | 	"previous": "&Xs1X5TzLCk6KVr+5IDc80JAHYxJyoD10cXKBUYpFqWQ=.sha256" | ||||||
| } | } | ||||||
|   | |||||||
| @@ -100,9 +100,6 @@ tfrpc.register(async function try_decrypt(id, content) { | |||||||
| tfrpc.register(async function encrypt(id, recipients, content) { | tfrpc.register(async function encrypt(id, recipients, content) { | ||||||
| 	return await ssb.privateMessageEncrypt(id, recipients, content); | 	return await ssb.privateMessageEncrypt(id, recipients, content); | ||||||
| }); | }); | ||||||
| tfrpc.register(async function getActiveIdentity() { |  | ||||||
| 	return await ssb.getActiveIdentity(); |  | ||||||
| }); |  | ||||||
| ssb.addEventListener('broadcasts', async function () { | ssb.addEventListener('broadcasts', async function () { | ||||||
| 	await tfrpc.rpc.set('broadcasts', await ssb.getBroadcasts()); | 	await tfrpc.rpc.set('broadcasts', await ssb.getBroadcasts()); | ||||||
| }); | }); | ||||||
| @@ -110,9 +107,6 @@ ssb.addEventListener('broadcasts', async function () { | |||||||
| core.register('onConnectionsChanged', async function () { | core.register('onConnectionsChanged', async function () { | ||||||
| 	await tfrpc.rpc.set('connections', await ssb.connections()); | 	await tfrpc.rpc.set('connections', await ssb.connections()); | ||||||
| }); | }); | ||||||
| core.register('setActiveIdentity', async function (id) { |  | ||||||
| 	await tfrpc.rpc.set('identity', id); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| async function main() { | async function main() { | ||||||
| 	if (typeof database !== 'undefined') { | 	if (typeof database !== 'undefined') { | ||||||
|   | |||||||
| @@ -1,23 +1,19 @@ | |||||||
| function textNode(text) { | function textNode(text) { | ||||||
| 	const node = new commonmark.Node('text', undefined); |   const node = new commonmark.Node("text", undefined); | ||||||
|   node.literal = text; |   node.literal = text; | ||||||
|   return node; |   return node; | ||||||
| } | } | ||||||
|  |  | ||||||
| function linkNode(text, link) { | function linkNode(text, link) { | ||||||
| 	const linkNode = new commonmark.Node('link', undefined); |   const linkNode = new commonmark.Node("link", undefined); | ||||||
| 	if (link.startsWith('#')) { |  | ||||||
|   linkNode.destination = `#q=${encodeURIComponent(link)}`; |   linkNode.destination = `#q=${encodeURIComponent(link)}`; | ||||||
| 	} else { |  | ||||||
| 		linkNode.destination = link; |  | ||||||
| 	} |  | ||||||
|   linkNode.appendChild(textNode(text)); |   linkNode.appendChild(textNode(text)); | ||||||
|   return linkNode; |   return linkNode; | ||||||
| } | } | ||||||
|  |  | ||||||
| function splitMatches(text, regexp) { | function splitMatches(text, regexp) { | ||||||
|   // Regexp must be sticky. |   // Regexp must be sticky. | ||||||
| 	regexp = new RegExp(regexp, 'gm'); |   regexp = new RegExp(regexp, "gm"); | ||||||
|  |  | ||||||
|   let i = 0; |   let i = 0; | ||||||
|   const result = []; |   const result = []; | ||||||
| @@ -43,13 +39,13 @@ function splitMatches(text, regexp) { | |||||||
|   return result; |   return result; | ||||||
| } | } | ||||||
|  |  | ||||||
| const regex = new RegExp('(?:https?://[^ ]+[^ .,])|(?:(?<!\\w)#[\\w-]+)|(?:@[A-Za-z0-9+/]+=.ed25519)|(?:[%&][A-Za-z0-9+/]+=.sha256)'); | const regex = new RegExp("(?<!\\w)#[\\w-]+"); | ||||||
|  |  | ||||||
| function split(textNodes) { | function split(textNodes) { | ||||||
| 	const text = textNodes.map((n) => n.literal).join(''); |   const text = textNodes.map(n => n.literal).join(""); | ||||||
|   const parts = splitMatches(text, regex); |   const parts = splitMatches(text, regex); | ||||||
|  |  | ||||||
| 	return parts.map((part) => { |   return parts.map(part => { | ||||||
|     if (part[1]) { |     if (part[1]) { | ||||||
|       return linkNode(part[0], part[0]); |       return linkNode(part[0], part[0]); | ||||||
|     } else { |     } else { | ||||||
| @@ -65,17 +61,17 @@ export function transform(parsed) { | |||||||
|   let nodes = []; |   let nodes = []; | ||||||
|   while ((event = walker.next())) { |   while ((event = walker.next())) { | ||||||
|     const node = event.node; |     const node = event.node; | ||||||
| 		if (event.entering && node.type === 'text') { |     if (event.entering && node.type === "text") { | ||||||
|       nodes.push(node); |       nodes.push(node); | ||||||
|     } else { |     } else { | ||||||
|       if (nodes.length > 0) { |       if (nodes.length > 0) { | ||||||
|         split(nodes) |         split(nodes) | ||||||
|           .reverse() |           .reverse() | ||||||
| 					.forEach((newNode) => { |           .forEach(newNode => { | ||||||
|             nodes[0].insertAfter(newNode); |             nodes[0].insertAfter(newNode); | ||||||
|           }); |           }); | ||||||
|  |  | ||||||
| 				nodes.forEach((n) => n.unlink()); |         nodes.forEach(n => n.unlink()); | ||||||
|         nodes = []; |         nodes = []; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @@ -84,10 +80,10 @@ export function transform(parsed) { | |||||||
|   if (nodes.length > 0) { |   if (nodes.length > 0) { | ||||||
|     split(nodes) |     split(nodes) | ||||||
|       .reverse() |       .reverse() | ||||||
| 			.forEach((newNode) => { |       .forEach(newNode => { | ||||||
|         nodes[0].insertAfter(newNode); |         nodes[0].insertAfter(newNode); | ||||||
|       }); |       }); | ||||||
| 		nodes.forEach((n) => n.unlink()); |     nodes.forEach(n => n.unlink()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   return parsed; |   return parsed; | ||||||
|   | |||||||
							
								
								
									
										91
									
								
								apps/ssb/commonmark-linkify.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								apps/ssb/commonmark-linkify.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | |||||||
|  | function textNode(text) { | ||||||
|  |   const node = new commonmark.Node("text", undefined); | ||||||
|  |   node.literal = text; | ||||||
|  |   return node; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function linkNode(text, url) { | ||||||
|  |   const urlNode = new commonmark.Node("link", undefined); | ||||||
|  |   urlNode.destination = url; | ||||||
|  |   urlNode.appendChild(textNode(text)); | ||||||
|  |  | ||||||
|  |   return urlNode; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function splitMatches(text, regexp) { | ||||||
|  |   // Regexp must be sticky. | ||||||
|  |   regexp = new RegExp(regexp, "gm"); | ||||||
|  |  | ||||||
|  |   let i = 0; | ||||||
|  |   const result = []; | ||||||
|  |  | ||||||
|  |   let match = regexp.exec(text); | ||||||
|  |   while (match) { | ||||||
|  |     const matchText = match[0]; | ||||||
|  |  | ||||||
|  |     if (match.index > i) { | ||||||
|  |       result.push([text.substring(i, match.index), false]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     result.push([matchText, true]); | ||||||
|  |     i = match.index + matchText.length; | ||||||
|  |  | ||||||
|  |     match = regexp.exec(text); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (i < text.length) { | ||||||
|  |     result.push([text.substring(i, text.length), false]); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const urlRegexp = new RegExp("https?://[^ ]+[^ .,]"); | ||||||
|  |  | ||||||
|  | function splitURLs(textNodes) { | ||||||
|  |   const text = textNodes.map(n => n.literal).join(""); | ||||||
|  |   const parts = splitMatches(text, urlRegexp); | ||||||
|  |  | ||||||
|  |   return parts.map(part => { | ||||||
|  |     if (part[1]) { | ||||||
|  |       return linkNode(part[0], part[0]); | ||||||
|  |     } else { | ||||||
|  |       return textNode(part[0]); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export function transform(parsed) { | ||||||
|  |   const walker = parsed.walker(); | ||||||
|  |   let event; | ||||||
|  |  | ||||||
|  |   let nodes = []; | ||||||
|  |   while ((event = walker.next())) { | ||||||
|  |     const node = event.node; | ||||||
|  |     if (event.entering && node.type === "text") { | ||||||
|  |       nodes.push(node); | ||||||
|  |     } else { | ||||||
|  |       if (nodes.length > 0) { | ||||||
|  |         splitURLs(nodes) | ||||||
|  |           .reverse() | ||||||
|  |           .forEach(newNode => { | ||||||
|  |             nodes[0].insertAfter(newNode); | ||||||
|  |           }); | ||||||
|  |  | ||||||
|  |         nodes.forEach(n => n.unlink()); | ||||||
|  |         nodes = []; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (nodes.length > 0) { | ||||||
|  |     splitURLs(nodes) | ||||||
|  |       .reverse() | ||||||
|  |       .forEach(newNode => { | ||||||
|  |         nodes[0].insertAfter(newNode); | ||||||
|  |       }); | ||||||
|  |     nodes.forEach(n => n.unlink()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return parsed; | ||||||
|  | } | ||||||
| @@ -1,5 +1,3 @@ | |||||||
| import * as tfrpc from '/static/tfrpc.js'; |  | ||||||
|  |  | ||||||
| let g_emojis; | let g_emojis; | ||||||
|  |  | ||||||
| function get_emojis() { | function get_emojis() { | ||||||
| @@ -12,24 +10,8 @@ function get_emojis() { | |||||||
| 	}); | 	}); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function get_recent(author) { | export function picker(callback, anchor) { | ||||||
| 	let recent = await tfrpc.rpc.query( | 	get_emojis().then(function (json) { | ||||||
| 		` |  | ||||||
| 		SELECT DISTINCT content ->> '$.vote.expression' AS value |  | ||||||
| 		FROM messages |  | ||||||
| 		WHERE author = ? AND |  | ||||||
| 		content ->> '$.type' = 'vote' |  | ||||||
| 		ORDER BY timestamp DESC LIMIT 10 |  | ||||||
| 	`, |  | ||||||
| 		[author] |  | ||||||
| 	); |  | ||||||
| 	return recent.map((x) => x.value); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export async function picker(callback, anchor, author) { |  | ||||||
| 	let json = await get_emojis(); |  | ||||||
| 	let recent = await get_recent(author); |  | ||||||
|  |  | ||||||
| 		let div = document.createElement('div'); | 		let div = document.createElement('div'); | ||||||
| 		div.id = 'emoji_picker'; | 		div.id = 'emoji_picker'; | ||||||
| 		div.style.color = '#000'; | 		div.style.color = '#000'; | ||||||
| @@ -84,40 +66,6 @@ export async function picker(callback, anchor, author) { | |||||||
| 			} | 			} | ||||||
| 			let search = input.value.toLowerCase(); | 			let search = input.value.toLowerCase(); | ||||||
| 			let any_at_all = false; | 			let any_at_all = false; | ||||||
| 		if (recent) { |  | ||||||
| 			let emoji_to_name = {}; |  | ||||||
| 			for (let row of Object.values(json)) { |  | ||||||
| 				for (let entry of Object.entries(row)) { |  | ||||||
| 					emoji_to_name[entry[1]] = entry[0]; |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			let header = document.createElement('div'); |  | ||||||
| 			header.appendChild(document.createTextNode('Recent')); |  | ||||||
| 			list.appendChild(header); |  | ||||||
| 			let any = false; |  | ||||||
| 			for (let entry of recent) { |  | ||||||
| 				if ( |  | ||||||
| 					search && |  | ||||||
| 					search.length && |  | ||||||
| 					(emoji_to_name[entry] || '').toLowerCase().indexOf(search) == -1 |  | ||||||
| 				) { |  | ||||||
| 					continue; |  | ||||||
| 				} |  | ||||||
| 				let emoji = document.createElement('span'); |  | ||||||
| 				const k_size = '1.25em'; |  | ||||||
| 				emoji.style.display = 'inline-block'; |  | ||||||
| 				emoji.style.overflow = 'hidden'; |  | ||||||
| 				emoji.style.cursor = 'pointer'; |  | ||||||
| 				emoji.onclick = chosen; |  | ||||||
| 				emoji.title = emoji_to_name[entry] || entry; |  | ||||||
| 				emoji.appendChild(document.createTextNode(entry)); |  | ||||||
| 				list.appendChild(emoji); |  | ||||||
| 				any = true; |  | ||||||
| 			} |  | ||||||
| 			if (!any) { |  | ||||||
| 				list.removeChild(header); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 			for (let row of Object.entries(json)) { | 			for (let row of Object.entries(json)) { | ||||||
| 				let header = document.createElement('div'); | 				let header = document.createElement('div'); | ||||||
| 				header.appendChild(document.createTextNode(row[0])); | 				header.appendChild(document.createTextNode(row[0])); | ||||||
| @@ -162,4 +110,5 @@ export async function picker(callback, anchor, author) { | |||||||
| 		console.log('adding click'); | 		console.log('adding click'); | ||||||
| 		document.body.addEventListener('mousedown', cleanup); | 		document.body.addEventListener('mousedown', cleanup); | ||||||
| 		window.addEventListener('keydown', key_down); | 		window.addEventListener('keydown', key_down); | ||||||
|  | 	}); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| <!doctype html> | <!doctype html> | ||||||
| <html> | <html style="color: #fff"> | ||||||
| 	<head> | 	<head> | ||||||
| 		<title>Tilde Friends</title> | 		<title>Tilde Friends</title> | ||||||
| 		<base target="_top" /> | 		<base target="_top" /> | ||||||
| @@ -10,14 +10,14 @@ | |||||||
| 			} | 			} | ||||||
| 		</style> | 		</style> | ||||||
| 	</head> | 	</head> | ||||||
| 	<body style="margin: 0; padding: 0"> | 	<body style="background-color: #223a5e"> | ||||||
| 		<tf-app></tf-app> | 		<tf-app class="w3-deep-purple" /> | ||||||
| 		<tf-reactions-modal id="reactions_modal"></tf-reactions-modal> |  | ||||||
| 		<script> | 		<script> | ||||||
| 			window.litDisableBundleWarning = true; | 			window.litDisableBundleWarning = true; | ||||||
| 		</script> | 		</script> | ||||||
| 		<script src="filesaver.min.js"></script> | 		<script src="filesaver.min.js"></script> | ||||||
| 		<script src="commonmark.min.js"></script> | 		<script src="commonmark.min.js"></script> | ||||||
|  | 		<script src="commonmark-linkify.js" type="module"></script> | ||||||
| 		<script src="commonmark-hashtag.js" type="module"></script> | 		<script src="commonmark-hashtag.js" type="module"></script> | ||||||
| 		<script src="script.js" type="module"></script> | 		<script src="script.js" type="module"></script> | ||||||
| 	</body> | 	</body> | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								apps/ssb/lit-all.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								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
											
										
									
								
							| @@ -1,13 +1,13 @@ | |||||||
| import {LitElement, html} from './lit-all.min.js'; | import {LitElement, html} from './lit-all.min.js'; | ||||||
| import * as tfrpc from '/static/tfrpc.js'; | import * as tfrpc from '/static/tfrpc.js'; | ||||||
|  |  | ||||||
|  | import * as tf_id_picker from './tf-id-picker.js'; | ||||||
| import * as tf_app from './tf-app.js'; | import * as tf_app from './tf-app.js'; | ||||||
| import * as tf_message from './tf-message.js'; | import * as tf_message from './tf-message.js'; | ||||||
| import * as tf_user from './tf-user.js'; | import * as tf_user from './tf-user.js'; | ||||||
| import * as tf_compose from './tf-compose.js'; | import * as tf_compose from './tf-compose.js'; | ||||||
| import * as tf_news from './tf-news.js'; | import * as tf_news from './tf-news.js'; | ||||||
| import * as tf_profile from './tf-profile.js'; | import * as tf_profile from './tf-profile.js'; | ||||||
| import * as tf_reactions_modal from './tf-reactions-modal.js'; |  | ||||||
| import * as tf_tab_mentions from './tf-tab-mentions.js'; | import * as tf_tab_mentions from './tf-tab-mentions.js'; | ||||||
| import * as tf_tab_news from './tf-tab-news.js'; | import * as tf_tab_news from './tf-tab-news.js'; | ||||||
| import * as tf_tab_news_feed from './tf-tab-news-feed.js'; | import * as tf_tab_news_feed from './tf-tab-news-feed.js'; | ||||||
|   | |||||||
| @@ -52,15 +52,13 @@ class TfElement extends LitElement { | |||||||
| 				self.broadcasts = value; | 				self.broadcasts = value; | ||||||
| 			} else if (name === 'connections') { | 			} else if (name === 'connections') { | ||||||
| 				self.connections = value; | 				self.connections = value; | ||||||
| 			} else if (name === 'identity') { |  | ||||||
| 				self.whoami = value; |  | ||||||
| 			} | 			} | ||||||
| 		}); | 		}); | ||||||
| 		this.initial_load(); | 		this.initial_load(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	async initial_load() { | 	async initial_load() { | ||||||
| 		let whoami = await tfrpc.rpc.getActiveIdentity(); | 		let whoami = await tfrpc.rpc.localStorageGet('whoami'); | ||||||
| 		let ids = (await tfrpc.rpc.getIdentities()) || []; | 		let ids = (await tfrpc.rpc.getIdentities()) || []; | ||||||
| 		this.whoami = whoami ?? (ids.length ? ids[0] : undefined); | 		this.whoami = whoami ?? (ids.length ? ids[0] : undefined); | ||||||
| 		this.ids = ids; | 		this.ids = ids; | ||||||
| @@ -195,6 +193,29 @@ class TfElement extends LitElement { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	render_id_picker() { | ||||||
|  | 		return html` | ||||||
|  | 			<div style="display: flex; gap: 8px"> | ||||||
|  | 				<tf-id-picker | ||||||
|  | 					id="picker" | ||||||
|  | 					style="flex: 1 1 auto" | ||||||
|  | 					selected=${this.whoami} | ||||||
|  | 					.ids=${this.ids} | ||||||
|  | 					.users=${this.users} | ||||||
|  | 					@change=${this._handle_whoami_changed} | ||||||
|  | 				></tf-id-picker> | ||||||
|  | 				<button | ||||||
|  | 					class="w3-button w3-dark-grey w3-border" | ||||||
|  | 					style="flex: 0 0 auto" | ||||||
|  | 					@click=${this.create_identity} | ||||||
|  | 					id="create_identity" | ||||||
|  | 				> | ||||||
|  | 					Create Identity | ||||||
|  | 				</button> | ||||||
|  | 			</div> | ||||||
|  | 		`; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	async load_recent_tags() { | 	async load_recent_tags() { | ||||||
| 		let start = new Date(); | 		let start = new Date(); | ||||||
| 		this.tags = await tfrpc.rpc.query( | 		this.tags = await tfrpc.rpc.query( | ||||||
| @@ -234,15 +255,7 @@ class TfElement extends LitElement { | |||||||
| 			by_count.push({count: v.of, id: id}); | 			by_count.push({count: v.of, id: id}); | ||||||
| 		} | 		} | ||||||
| 		console.log(by_count.sort((x, y) => y.count - x.count).slice(0, 20)); | 		console.log(by_count.sort((x, y) => y.count - x.count).slice(0, 20)); | ||||||
| 		let start_time = new Date(); |  | ||||||
| 		users = await this.fetch_about(Object.keys(following).sort(), users); | 		users = await this.fetch_about(Object.keys(following).sort(), users); | ||||||
| 		console.log( |  | ||||||
| 			'about took', |  | ||||||
| 			(new Date() - start_time) / 1000.0, |  | ||||||
| 			'seconds for', |  | ||||||
| 			Object.keys(users).length, |  | ||||||
| 			'users' |  | ||||||
| 		); |  | ||||||
| 		this.following = Object.keys(following); | 		this.following = Object.keys(following); | ||||||
| 		this.users = users; | 		this.users = users; | ||||||
| 		await tags; | 		await tags; | ||||||
| @@ -339,15 +352,15 @@ class TfElement extends LitElement { | |||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
| 		let tabs = html` | 		let tabs = html` | ||||||
| 			<div class="w3-bar w3-theme-l1"> | 			<div class="w3-bar w3-black"> | ||||||
| 				${Object.entries(k_tabs).map( | 				${Object.entries(k_tabs).map( | ||||||
| 					([k, v]) => html` | 					([k, v]) => html` | ||||||
| 						<button | 						<button | ||||||
| 							title=${v} | 							title=${v} | ||||||
| 							class="w3-bar-item w3-padding-large w3-hover-theme tab ${self.tab == | 							class="w3-bar-item w3-padding-large w3-hover-gray tab ${self.tab == | ||||||
| 							v | 							v | ||||||
| 								? 'w3-theme-l2' | 								? 'w3-red' | ||||||
| 								: 'w3-theme-l1'}" | 								: 'w3-black'}" | ||||||
| 							@click=${() => self.set_tab(v)} | 							@click=${() => self.set_tab(v)} | ||||||
| 						> | 						> | ||||||
| 							${k} | 							${k} | ||||||
| @@ -358,27 +371,15 @@ class TfElement extends LitElement { | |||||||
| 		`; | 		`; | ||||||
| 		let contents = !this.loaded | 		let contents = !this.loaded | ||||||
| 			? this.loading | 			? this.loading | ||||||
| 				? html`<div | 				? html`<div>Loading...</div>` | ||||||
| 							class="w3-panel w3-theme-l5 w3-card-4 w3-padding-large w3-round-xlarge" |  | ||||||
| 						> |  | ||||||
| 							Loading... |  | ||||||
| 						</div> |  | ||||||
| 						${this.render_tab()}` |  | ||||||
| 				: html`<div>Select or create an identity.</div>` | 				: html`<div>Select or create an identity.</div>` | ||||||
| 			: this.render_tab(); | 			: this.render_tab(); | ||||||
| 		return html` | 		return html` | ||||||
| 			<div | 			${this.render_id_picker()} ${tabs} | ||||||
| 				style="width: 100vw; min-height: 100vh; height: 100%" |  | ||||||
| 				class="w3-theme-dark" |  | ||||||
| 			> |  | ||||||
| 				${tabs} |  | ||||||
| 				<div style="padding: 8px"> |  | ||||||
| 			${this.tags.map( | 			${this.tags.map( | ||||||
| 				(x) => html`<tf-tag tag=${x.tag} count=${x.count}></tf-tag>` | 				(x) => html`<tf-tag tag=${x.tag} count=${x.count}></tf-tag>` | ||||||
| 			)} | 			)} | ||||||
| 			${contents} | 			${contents} | ||||||
| 				</div> |  | ||||||
| 			</div> |  | ||||||
| 		`; | 		`; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| import {LitElement, html, unsafeHTML, live} from './lit-all.min.js'; | import {LitElement, html, unsafeHTML} from './lit-all.min.js'; | ||||||
| import * as tfutils from './tf-utils.js'; | import * as tfutils from './tf-utils.js'; | ||||||
| import * as tfrpc from '/static/tfrpc.js'; | import * as tfrpc from '/static/tfrpc.js'; | ||||||
| import {styles} from './tf-styles.js'; | import {styles} from './tf-styles.js'; | ||||||
| @@ -13,7 +13,6 @@ class TfComposeElement extends LitElement { | |||||||
| 			branch: {type: String}, | 			branch: {type: String}, | ||||||
| 			apps: {type: Object}, | 			apps: {type: Object}, | ||||||
| 			drafts: {type: Object}, | 			drafts: {type: Object}, | ||||||
| 			author: {type: String}, |  | ||||||
| 		}; | 		}; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -26,7 +25,6 @@ class TfComposeElement extends LitElement { | |||||||
| 		this.branch = undefined; | 		this.branch = undefined; | ||||||
| 		this.apps = undefined; | 		this.apps = undefined; | ||||||
| 		this.drafts = {}; | 		this.drafts = {}; | ||||||
| 		this.author = undefined; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	process_text(text) { | 	process_text(text) { | ||||||
| @@ -66,7 +64,7 @@ class TfComposeElement extends LitElement { | |||||||
| 			updated = true; | 			updated = true; | ||||||
| 		} | 		} | ||||||
| 		if (updated) { | 		if (updated) { | ||||||
| 			setTimeout(() => this.notify(draft), 0); | 			this.requestUpdate(); | ||||||
| 		} | 		} | ||||||
| 		return tfutils.markdown(text); | 		return tfutils.markdown(text); | ||||||
| 	} | 	} | ||||||
| @@ -74,7 +72,7 @@ class TfComposeElement extends LitElement { | |||||||
| 	input(event) { | 	input(event) { | ||||||
| 		let edit = this.renderRoot.getElementById('edit'); | 		let edit = this.renderRoot.getElementById('edit'); | ||||||
| 		let preview = this.renderRoot.getElementById('preview'); | 		let preview = this.renderRoot.getElementById('preview'); | ||||||
| 		preview.innerHTML = this.process_text(edit.innerText); | 		preview.innerHTML = this.process_text(edit.value); | ||||||
| 		let content_warning = this.renderRoot.getElementById('content_warning'); | 		let content_warning = this.renderRoot.getElementById('content_warning'); | ||||||
| 		let content_warning_preview = this.renderRoot.getElementById( | 		let content_warning_preview = this.renderRoot.getElementById( | ||||||
| 			'content_warning_preview' | 			'content_warning_preview' | ||||||
| @@ -82,10 +80,6 @@ class TfComposeElement extends LitElement { | |||||||
| 		if (content_warning && content_warning_preview) { | 		if (content_warning && content_warning_preview) { | ||||||
| 			content_warning_preview.innerText = content_warning.value; | 			content_warning_preview.innerText = content_warning.value; | ||||||
| 		} | 		} | ||||||
| 		let draft = this.get_draft(); |  | ||||||
| 		draft.text = edit.innerText; |  | ||||||
| 		draft.content_warning = content_warning?.innerText; |  | ||||||
| 		setTimeout(() => this.notify(draft), 0); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	notify(draft) { | 	notify(draft) { | ||||||
| @@ -101,6 +95,14 @@ class TfComposeElement extends LitElement { | |||||||
| 		); | 		); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	change() { | ||||||
|  | 		let draft = this.get_draft(); | ||||||
|  | 		draft.text = this.renderRoot.getElementById('edit')?.value; | ||||||
|  | 		draft.content_warning = | ||||||
|  | 			this.renderRoot.getElementById('content_warning')?.value; | ||||||
|  | 		this.notify(draft); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	convert_to_format(buffer, type, mime_type) { | 	convert_to_format(buffer, type, mime_type) { | ||||||
| 		return new Promise(function (resolve, reject) { | 		return new Promise(function (resolve, reject) { | ||||||
| 			let img = new Image(); | 			let img = new Image(); | ||||||
| @@ -167,7 +169,8 @@ class TfComposeElement extends LitElement { | |||||||
| 				size: buffer.length ?? buffer.byteLength, | 				size: buffer.length ?? buffer.byteLength, | ||||||
| 			}; | 			}; | ||||||
| 			let edit = self.renderRoot.getElementById('edit'); | 			let edit = self.renderRoot.getElementById('edit'); | ||||||
| 			edit.innerText += `\n`; | 			edit.value += `\n`; | ||||||
|  | 			self.change(); | ||||||
| 			self.input(); | 			self.input(); | ||||||
| 		} catch (e) { | 		} catch (e) { | ||||||
| 			alert(e?.message); | 			alert(e?.message); | ||||||
| @@ -194,7 +197,7 @@ class TfComposeElement extends LitElement { | |||||||
| 		let edit = this.renderRoot.getElementById('edit'); | 		let edit = this.renderRoot.getElementById('edit'); | ||||||
| 		let message = { | 		let message = { | ||||||
| 			type: 'post', | 			type: 'post', | ||||||
| 			text: edit.innerText, | 			text: edit.value, | ||||||
| 		}; | 		}; | ||||||
| 		if (this.root || this.branch) { | 		if (this.root || this.branch) { | ||||||
| 			message.root = this.root; | 			message.root = this.root; | ||||||
| @@ -222,8 +225,8 @@ class TfComposeElement extends LitElement { | |||||||
| 		} | 		} | ||||||
| 		try { | 		try { | ||||||
| 			await tfrpc.rpc.appendMessage(this.whoami, message).then(function () { | 			await tfrpc.rpc.appendMessage(this.whoami, message).then(function () { | ||||||
| 				edit.innerText = ''; | 				edit.value = ''; | ||||||
| 				self.input(); | 				self.change(); | ||||||
| 				self.notify(undefined); | 				self.notify(undefined); | ||||||
| 				self.requestUpdate(); | 				self.requestUpdate(); | ||||||
| 			}); | 			}); | ||||||
| @@ -233,11 +236,17 @@ class TfComposeElement extends LitElement { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	discard() { | 	discard() { | ||||||
|  | 		let edit = this.renderRoot.getElementById('edit'); | ||||||
|  | 		edit.value = ''; | ||||||
|  | 		this.change(); | ||||||
|  | 		let preview = this.renderRoot.getElementById('preview'); | ||||||
|  | 		preview.innerHTML = ''; | ||||||
| 		this.notify(undefined); | 		this.notify(undefined); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	attach() { | 	attach() { | ||||||
| 		let self = this; | 		let self = this; | ||||||
|  | 		let edit = this.renderRoot.getElementById('edit'); | ||||||
| 		let input = document.createElement('input'); | 		let input = document.createElement('input'); | ||||||
| 		input.type = 'file'; | 		input.type = 'file'; | ||||||
| 		input.onchange = function (event) { | 		input.onchange = function (event) { | ||||||
| @@ -275,38 +284,22 @@ class TfComposeElement extends LitElement { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	firstUpdated() { | 	firstUpdated() { | ||||||
| 		let values = Object.entries(this.users).map((x) => ({ |  | ||||||
| 			key: x[1].name ?? x[0], |  | ||||||
| 			value: x[0], |  | ||||||
| 		})); |  | ||||||
| 		if (this.author) { |  | ||||||
| 			values = [].concat( |  | ||||||
| 				[ |  | ||||||
| 					{ |  | ||||||
| 						key: this.users[this.author]?.name, |  | ||||||
| 						value: this.author, |  | ||||||
| 					}, |  | ||||||
| 				], |  | ||||||
| 				values |  | ||||||
| 			); |  | ||||||
| 		} |  | ||||||
| 		let tribute = new Tribute({ | 		let tribute = new Tribute({ | ||||||
| 			collection: [ | 			collection: [ | ||||||
| 				{ | 				{ | ||||||
| 					values: values, | 					values: Object.entries(this.users).map((x) => ({ | ||||||
|  | 						key: x[1].name, | ||||||
|  | 						value: x[0], | ||||||
|  | 					})), | ||||||
| 					selectTemplate: function (item) { | 					selectTemplate: function (item) { | ||||||
| 						return item | 						return `[@${item.original.key}](${item.original.value})`; | ||||||
| 							? `[@${item.original.key}](${item.original.value})` |  | ||||||
| 							: undefined; |  | ||||||
| 					}, | 					}, | ||||||
| 				}, | 				}, | ||||||
| 				{ | 				{ | ||||||
| 					trigger: '&', | 					trigger: '&', | ||||||
| 					values: this.autocomplete, | 					values: this.autocomplete, | ||||||
| 					selectTemplate: function (item) { | 					selectTemplate: function (item) { | ||||||
| 						return item | 						return ``; | ||||||
| 							? `` |  | ||||||
| 							: undefined; |  | ||||||
| 					}, | 					}, | ||||||
| 				}, | 				}, | ||||||
| 			], | 			], | ||||||
| @@ -317,10 +310,10 @@ class TfComposeElement extends LitElement { | |||||||
| 	updated() { | 	updated() { | ||||||
| 		super.updated(); | 		super.updated(); | ||||||
| 		let edit = this.renderRoot.getElementById('edit'); | 		let edit = this.renderRoot.getElementById('edit'); | ||||||
| 		if (this.last_updated_text !== edit.innerText) { | 		if (this.last_updated_text !== edit.value) { | ||||||
| 			let preview = this.renderRoot.getElementById('preview'); | 			let preview = this.renderRoot.getElementById('preview'); | ||||||
| 			preview.innerHTML = this.process_text(edit.innerText); | 			preview.innerHTML = this.process_text(edit.value); | ||||||
| 			this.last_updated_text = edit.innerText; | 			this.last_updated_text = edit.value; | ||||||
| 		} | 		} | ||||||
| 		let encrypt = this.renderRoot.getElementById('encrypt_to'); | 		let encrypt = this.renderRoot.getElementById('encrypt_to'); | ||||||
| 		if (encrypt) { | 		if (encrypt) { | ||||||
| @@ -340,7 +333,8 @@ class TfComposeElement extends LitElement { | |||||||
| 	remove_mention(id) { | 	remove_mention(id) { | ||||||
| 		let draft = this.get_draft(); | 		let draft = this.get_draft(); | ||||||
| 		delete draft.mentions[id]; | 		delete draft.mentions[id]; | ||||||
| 		setTimeout(() => this.notify(), 0); | 		this.notify(draft); | ||||||
|  | 		this.requestUpdate(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	render_mention(mention) { | 	render_mention(mention) { | ||||||
| @@ -348,7 +342,7 @@ class TfComposeElement extends LitElement { | |||||||
| 		return html` <div style="display: flex; flex-direction: row"> | 		return html` <div style="display: flex; flex-direction: row"> | ||||||
| 			<div style="align-self: center; margin: 0.5em"> | 			<div style="align-self: center; margin: 0.5em"> | ||||||
| 				<button | 				<button | ||||||
| 					class="w3-button w3-theme-d1" | 					class="w3-button w3-dark-grey" | ||||||
| 					title="Remove ${mention.name} mention" | 					title="Remove ${mention.name} mention" | ||||||
| 					@click=${() => self.remove_mention(mention.link)} | 					@click=${() => self.remove_mention(mention.link)} | ||||||
| 				> | 				> | ||||||
| @@ -402,16 +396,16 @@ class TfComposeElement extends LitElement { | |||||||
| 		if (this.apps) { | 		if (this.apps) { | ||||||
| 			return html` | 			return html` | ||||||
| 				<div class="w3-card-4 w3-margin w3-padding"> | 				<div class="w3-card-4 w3-margin w3-padding"> | ||||||
| 					<select id="select" class="w3-select w3-theme-d1"> | 					<select id="select" class="w3-select w3-dark-grey"> | ||||||
| 						${Object.keys(self.apps).map( | 						${Object.keys(self.apps).map( | ||||||
| 							(app) => html`<option value=${app}>${app}</option>` | 							(app) => html`<option value=${app}>${app}</option>` | ||||||
| 						)} | 						)} | ||||||
| 					</select> | 					</select> | ||||||
| 					<button class="w3-button w3-theme-d1" @click=${attach_selected_app}> | 					<button class="w3-button w3-dark-grey" @click=${attach_selected_app}> | ||||||
| 						Attach | 						Attach | ||||||
| 					</button> | 					</button> | ||||||
| 					<button | 					<button | ||||||
| 						class="w3-button w3-theme-d1" | 						class="w3-button w3-dark-grey" | ||||||
| 						@click=${() => (this.apps = null)} | 						@click=${() => (this.apps = null)} | ||||||
| 					> | 					> | ||||||
| 						Cancel | 						Cancel | ||||||
| @@ -427,12 +421,12 @@ class TfComposeElement extends LitElement { | |||||||
| 			self.apps = await tfrpc.rpc.apps(); | 			self.apps = await tfrpc.rpc.apps(); | ||||||
| 		} | 		} | ||||||
| 		if (!this.apps) { | 		if (!this.apps) { | ||||||
| 			return html`<button class="w3-button w3-theme-d1" @click=${attach_app}> | 			return html`<button class="w3-button w3-dark-grey" @click=${attach_app}> | ||||||
| 				Attach App | 				Attach App | ||||||
| 			</button>`; | 			</button>`; | ||||||
| 		} else { | 		} else { | ||||||
| 			return html`<button | 			return html`<button | ||||||
| 				class="w3-button w3-theme-d1" | 				class="w3-button w3-dark-grey" | ||||||
| 				@click=${() => (this.apps = null)} | 				@click=${() => (this.apps = null)} | ||||||
| 			> | 			> | ||||||
| 				Discard App | 				Discard App | ||||||
| @@ -454,15 +448,15 @@ class TfComposeElement extends LitElement { | |||||||
| 			return html` | 			return html` | ||||||
| 				<div class="w3-container w3-padding"> | 				<div class="w3-container w3-padding"> | ||||||
| 					<p> | 					<p> | ||||||
| 						<input type="checkbox" class="w3-check w3-theme-d1" id="cw" @change=${() => self.set_content_warning(undefined)} checked="checked"></input> | 						<input type="checkbox" class="w3-check w3-dark-grey" id="cw" @change=${() => self.set_content_warning(undefined)} checked="checked"></input> | ||||||
| 						<label for="cw">CW</label> | 						<label for="cw">CW</label> | ||||||
| 					</p> | 					</p> | ||||||
| 					<input type="text" class="w3-input w3-border w3-theme-d1" id="content_warning" placeholder="Enter a content warning here." @input=${this.input} @change=${this.change} value=${draft.content_warning}></input> | 					<input type="text" class="w3-input w3-border w3-dark-grey" id="content_warning" placeholder="Enter a content warning here." @input=${this.input} @change=${this.change} value=${draft.content_warning}></input> | ||||||
| 				</div> | 				</div> | ||||||
| 			`; | 			`; | ||||||
| 		} else { | 		} else { | ||||||
| 			return html` | 			return html` | ||||||
| 				<input type="checkbox" class="w3-check w3-theme-d1" id="cw" @change=${() => self.set_content_warning('')}></input> | 				<input type="checkbox" class="w3-check w3-dark-grey" id="cw" @change=${() => self.set_content_warning('')}></input> | ||||||
| 				<label for="cw">CW</label> | 				<label for="cw">CW</label> | ||||||
| 			`; | 			`; | ||||||
| 		} | 		} | ||||||
| @@ -492,14 +486,14 @@ class TfComposeElement extends LitElement { | |||||||
| 			<div style="display: flex; flex-direction: row; width: 100%"> | 			<div style="display: flex; flex-direction: row; width: 100%"> | ||||||
| 				<label for="encrypt_to">🔐 To:</label> | 				<label for="encrypt_to">🔐 To:</label> | ||||||
| 				<input type="text" id="encrypt_to" style="display: flex; flex: 1 1" @input=${this.update_encrypt}></input> | 				<input type="text" id="encrypt_to" style="display: flex; flex: 1 1" @input=${this.update_encrypt}></input> | ||||||
| 				<button class="w3-button w3-theme-d1" @click=${() => this.set_encrypt(undefined)}>🚮</button> | 				<button class="w3-button w3-dark-grey" @click=${() => this.set_encrypt(undefined)}>🚮</button> | ||||||
| 			</div> | 			</div> | ||||||
| 			<ul> | 			<ul> | ||||||
| 				${draft.encrypt_to.map( | 				${draft.encrypt_to.map( | ||||||
| 					(x) => html` | 					(x) => html` | ||||||
| 					<li> | 					<li> | ||||||
| 						<tf-user id=${x} .users=${this.users}></tf-user> | 						<tf-user id=${x} .users=${this.users}></tf-user> | ||||||
| 						<input type="button" class="w3-button w3-theme-d1" value="🚮" @click=${() => this.set_encrypt(draft.encrypt_to.filter((id) => id != x))}></input> | 						<input type="button" class="w3-button w3-dark-grey" value="🚮" @click=${() => this.set_encrypt(draft.encrypt_to.filter((id) => id != x))}></input> | ||||||
| 					</li>` | 					</li>` | ||||||
| 				)} | 				)} | ||||||
| 			</ul> | 			</ul> | ||||||
| @@ -518,7 +512,7 @@ class TfComposeElement extends LitElement { | |||||||
| 		let draft = self.get_draft(); | 		let draft = self.get_draft(); | ||||||
| 		let content_warning = | 		let content_warning = | ||||||
| 			draft.content_warning !== undefined | 			draft.content_warning !== undefined | ||||||
| 				? html`<div class="w3-panel w3-round-xlarge w3-theme-d2"> | 				? html`<div class="w3-panel w3-round-xlarge w3-blue"> | ||||||
| 						<p id="content_warning_preview">${draft.content_warning}</p> | 						<p id="content_warning_preview">${draft.content_warning}</p> | ||||||
| 					</div>` | 					</div>` | ||||||
| 				: undefined; | 				: undefined; | ||||||
| @@ -526,31 +520,34 @@ class TfComposeElement extends LitElement { | |||||||
| 			draft.encrypt_to !== undefined | 			draft.encrypt_to !== undefined | ||||||
| 				? undefined | 				? undefined | ||||||
| 				: html`<button | 				: html`<button | ||||||
| 						class="w3-button w3-theme-d1" | 						class="w3-button w3-dark-grey" | ||||||
| 						@click=${() => this.set_encrypt([])} | 						@click=${() => this.set_encrypt([])} | ||||||
| 					> | 					> | ||||||
| 						🔐 | 						🔐 | ||||||
| 					</button>`; | 					</button>`; | ||||||
| 		let result = html` | 		let result = html` | ||||||
| 			<div | 			<div | ||||||
| 				class="w3-card-4 w3-theme-d4 w3-padding-small" | 				class="w3-card-4 w3-blue-grey w3-padding" | ||||||
| 				style="box-sizing: border-box" | 				style="box-sizing: border-box" | ||||||
| 			> | 			> | ||||||
| 				${this.render_encrypt()} | 				${this.render_encrypt()} | ||||||
| 				<div class="w3-container w3-padding-small"> | 				<div style="display: flex; flex-direction: row; width: 100%; gap: 4px"> | ||||||
| 					<div class="w3-half"> | 					<div style="flex: 1 0 50%"> | ||||||
| 						<span | 						<p> | ||||||
| 							class="w3-input w3-theme-d1 w3-border" | 							<textarea | ||||||
| 							style="resize: vertical; width: 100%; overflow: hidden; white-space: pre-wrap" | 								class="w3-input w3-dark-grey w3-border" | ||||||
|  | 								style="resize: vertical" | ||||||
| 								placeholder="Write a post here." | 								placeholder="Write a post here." | ||||||
| 								id="edit" | 								id="edit" | ||||||
| 								@input=${this.input} | 								@input=${this.input} | ||||||
|  | 								@change=${this.change} | ||||||
| 								@paste=${this.paste} | 								@paste=${this.paste} | ||||||
| 							contenteditable | 							> | ||||||
| 							.innerText=${live(draft.text ?? '')} | ${draft.text}</textarea | ||||||
| 						></span> | 							> | ||||||
|  | 						</p> | ||||||
| 					</div> | 					</div> | ||||||
| 					<div class="w3-half w3-padding"> | 					<div style="flex: 1 0 50%"> | ||||||
| 						${content_warning} | 						${content_warning} | ||||||
| 						<div id="preview"></div> | 						<div id="preview"></div> | ||||||
| 					</div> | 					</div> | ||||||
| @@ -559,14 +556,18 @@ class TfComposeElement extends LitElement { | |||||||
| 					self.render_mention(x) | 					self.render_mention(x) | ||||||
| 				)} | 				)} | ||||||
| 				${this.render_attach_app()} ${this.render_content_warning()} | 				${this.render_attach_app()} ${this.render_content_warning()} | ||||||
| 				<button class="w3-button w3-theme-d1" id="submit" @click=${this.submit}> | 				<button | ||||||
|  | 					class="w3-button w3-dark-grey" | ||||||
|  | 					id="submit" | ||||||
|  | 					@click=${this.submit} | ||||||
|  | 				> | ||||||
| 					Submit | 					Submit | ||||||
| 				</button> | 				</button> | ||||||
| 				<button class="w3-button w3-theme-d1" @click=${this.attach}> | 				<button class="w3-button w3-dark-grey" @click=${this.attach}> | ||||||
| 					Attach | 					Attach | ||||||
| 				</button> | 				</button> | ||||||
| 				${this.render_attach_app_button()} ${encrypt} | 				${this.render_attach_app_button()} ${encrypt} | ||||||
| 				<button class="w3-button w3-theme-d1" @click=${this.discard}> | 				<button class="w3-button w3-dark-grey" @click=${this.discard}> | ||||||
| 					Discard | 					Discard | ||||||
| 				</button> | 				</button> | ||||||
| 			</div> | 			</div> | ||||||
|   | |||||||
							
								
								
									
										54
									
								
								apps/ssb/tf-id-picker.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								apps/ssb/tf-id-picker.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | |||||||
|  | import {LitElement, html} from './lit-all.min.js'; | ||||||
|  | import * as tfrpc from '/static/tfrpc.js'; | ||||||
|  | import {styles} from './tf-styles.js'; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  ** Provide a list of IDs, and this lets the user pick one. | ||||||
|  |  */ | ||||||
|  | class TfIdentityPickerElement extends LitElement { | ||||||
|  | 	static get properties() { | ||||||
|  | 		return { | ||||||
|  | 			ids: {type: Array}, | ||||||
|  | 			selected: {type: String}, | ||||||
|  | 			users: {type: Object}, | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static styles = styles; | ||||||
|  |  | ||||||
|  | 	constructor() { | ||||||
|  | 		super(); | ||||||
|  | 		this.ids = []; | ||||||
|  | 		this.users = {}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	changed(event) { | ||||||
|  | 		this.selected = event.srcElement.value; | ||||||
|  | 		this.dispatchEvent( | ||||||
|  | 			new Event('change', { | ||||||
|  | 				srcElement: this, | ||||||
|  | 			}) | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	render() { | ||||||
|  | 		return html` | ||||||
|  | 			<select | ||||||
|  | 				class="w3-select w3-dark-grey w3-padding w3-border" | ||||||
|  | 				@change=${this.changed} | ||||||
|  | 				style="max-width: 100%; overflow: hidden" | ||||||
|  | 			> | ||||||
|  | 				${(this.ids ?? []).map( | ||||||
|  | 					(id) => | ||||||
|  | 						html`<option ?selected=${id == this.selected} value=${id}> | ||||||
|  | 							${this.users[id]?.name | ||||||
|  | 								? this.users[id]?.name + ' - ' | ||||||
|  | 								: undefined}<small>${id}</small> | ||||||
|  | 						</option>` | ||||||
|  | 				)} | ||||||
|  | 			</select> | ||||||
|  | 		`; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | customElements.define('tf-id-picker', TfIdentityPickerElement); | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| import {LitElement, html, render, unsafeHTML} from './lit-all.min.js'; | import {LitElement, html, unsafeHTML} from './lit-all.min.js'; | ||||||
| import * as tfrpc from '/static/tfrpc.js'; | import * as tfrpc from '/static/tfrpc.js'; | ||||||
| import * as tfutils from './tf-utils.js'; | import * as tfutils from './tf-utils.js'; | ||||||
| import * as emojis from './emojis.js'; | import * as emojis from './emojis.js'; | ||||||
| @@ -54,12 +54,6 @@ class TfMessageElement extends LitElement { | |||||||
| 		); | 		); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	show_reactions() { |  | ||||||
| 		let modal = document.getElementById('reactions_modal'); |  | ||||||
| 		modal.users = this.users; |  | ||||||
| 		modal.votes = this.message?.votes || []; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	render_votes() { | 	render_votes() { | ||||||
| 		function normalize_expression(expression) { | 		function normalize_expression(expression) { | ||||||
| 			if (expression === 'Like' || !expression) { | 			if (expression === 'Like' || !expression) { | ||||||
| @@ -72,8 +66,7 @@ class TfMessageElement extends LitElement { | |||||||
| 				return expression; | 				return expression; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if (this.message?.votes?.length) { | 		return html`<div> | ||||||
| 			return html`<div class="w3-button" @click=${this.show_reactions}> |  | ||||||
| 			${(this.message.votes || []).map( | 			${(this.message.votes || []).map( | ||||||
| 				(vote) => html` | 				(vote) => html` | ||||||
| 					<span | 					<span | ||||||
| @@ -87,7 +80,6 @@ class TfMessageElement extends LitElement { | |||||||
| 			)} | 			)} | ||||||
| 		</div>`; | 		</div>`; | ||||||
| 	} | 	} | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	render_raw() { | 	render_raw() { | ||||||
| 		let raw = { | 		let raw = { | ||||||
| @@ -133,7 +125,7 @@ class TfMessageElement extends LitElement { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	react(event) { | 	react(event) { | ||||||
| 		emojis.picker((x) => this.vote(x), null, this.whoami); | 		emojis.picker((x) => this.vote(x)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	show_image(link) { | 	show_image(link) { | ||||||
| @@ -247,7 +239,9 @@ ${JSON.stringify(mention, null, 2)}</pre | |||||||
| 		if (mentions.length) { | 		if (mentions.length) { | ||||||
| 			let self = this; | 			let self = this; | ||||||
| 			return html` | 			return html` | ||||||
| 				<fieldset style="padding: 0.5em; border: 1px solid black"> | 				<fieldset | ||||||
|  | 					style="background-color: rgba(0, 0, 0, 0.1); padding: 0.5em; border: 1px solid black" | ||||||
|  | 				> | ||||||
| 					<legend>Mentions</legend> | 					<legend>Mentions</legend> | ||||||
| 					${mentions.map((x) => self.render_mention(x))} | 					${mentions.map((x) => self.render_mention(x))} | ||||||
| 				</fieldset> | 				</fieldset> | ||||||
| @@ -288,14 +282,14 @@ ${JSON.stringify(mention, null, 2)}</pre | |||||||
| 		if (this.message.child_messages?.length) { | 		if (this.message.child_messages?.length) { | ||||||
| 			if (!this.expanded[this.message.id]) { | 			if (!this.expanded[this.message.id]) { | ||||||
| 				return html`<button | 				return html`<button | ||||||
| 					class="w3-button w3-theme-d1" | 					class="w3-button w3-dark-grey" | ||||||
| 					@click=${() => self.set_expanded(true)} | 					@click=${() => self.set_expanded(true)} | ||||||
| 				> | 				> | ||||||
| 					+ ${this.total_child_messages(this.message) + ' More'} | 					+ ${this.total_child_messages(this.message) + ' More'} | ||||||
| 				</button>`; | 				</button>`; | ||||||
| 			} else { | 			} else { | ||||||
| 				return html`<button | 				return html`<button | ||||||
| 						class="w3-button w3-theme-d1" | 						class="w3-button w3-dark-grey" | ||||||
| 						@click=${() => self.set_expanded(false)} | 						@click=${() => self.set_expanded(false)} | ||||||
| 					> | 					> | ||||||
| 						Collapse</button | 						Collapse</button | ||||||
| @@ -337,23 +331,20 @@ ${JSON.stringify(mention, null, 2)}</pre | |||||||
| 		if (this.message?.decrypted?.type == 'post') { | 		if (this.message?.decrypted?.type == 'post') { | ||||||
| 			content = this.message.decrypted; | 			content = this.message.decrypted; | ||||||
| 		} | 		} | ||||||
| 		let class_background = this.message?.decrypted |  | ||||||
| 			? 'w3-pale-red' |  | ||||||
| 			: 'w3-theme-d4'; |  | ||||||
| 		let self = this; | 		let self = this; | ||||||
| 		let raw_button; | 		let raw_button; | ||||||
| 		switch (this.format) { | 		switch (this.format) { | ||||||
| 			case 'raw': | 			case 'raw': | ||||||
| 				if (content?.type == 'post' || content?.type == 'blog') { | 				if (content?.type == 'post' || content?.type == 'blog') { | ||||||
| 					raw_button = html`<button | 					raw_button = html`<button | ||||||
| 						class="w3-button w3-theme-d1" | 						class="w3-button w3-dark-grey" | ||||||
| 						@click=${() => (self.format = 'md')} | 						@click=${() => (self.format = 'md')} | ||||||
| 					> | 					> | ||||||
| 						Markdown | 						Markdown | ||||||
| 					</button>`; | 					</button>`; | ||||||
| 				} else { | 				} else { | ||||||
| 					raw_button = html`<button | 					raw_button = html`<button | ||||||
| 						class="w3-button w3-theme-d1" | 						class="w3-button w3-dark-grey" | ||||||
| 						@click=${() => (self.format = 'message')} | 						@click=${() => (self.format = 'message')} | ||||||
| 					> | 					> | ||||||
| 						Message | 						Message | ||||||
| @@ -362,7 +353,7 @@ ${JSON.stringify(mention, null, 2)}</pre | |||||||
| 				break; | 				break; | ||||||
| 			case 'md': | 			case 'md': | ||||||
| 				raw_button = html`<button | 				raw_button = html`<button | ||||||
| 					class="w3-button w3-theme-d1" | 					class="w3-button w3-dark-grey" | ||||||
| 					@click=${() => (self.format = 'message')} | 					@click=${() => (self.format = 'message')} | ||||||
| 				> | 				> | ||||||
| 					Message | 					Message | ||||||
| @@ -370,7 +361,7 @@ ${JSON.stringify(mention, null, 2)}</pre | |||||||
| 				break; | 				break; | ||||||
| 			case 'decrypted': | 			case 'decrypted': | ||||||
| 				raw_button = html`<button | 				raw_button = html`<button | ||||||
| 					class="w3-button w3-theme-d1" | 					class="w3-button w3-dark-grey" | ||||||
| 					@click=${() => (self.format = 'raw')} | 					@click=${() => (self.format = 'raw')} | ||||||
| 				> | 				> | ||||||
| 					Raw | 					Raw | ||||||
| @@ -379,14 +370,14 @@ ${JSON.stringify(mention, null, 2)}</pre | |||||||
| 			default: | 			default: | ||||||
| 				if (this.message.decrypted) { | 				if (this.message.decrypted) { | ||||||
| 					raw_button = html`<button | 					raw_button = html`<button | ||||||
| 						class="w3-button w3-theme-d1" | 						class="w3-button w3-dark-grey" | ||||||
| 						@click=${() => (self.format = 'decrypted')} | 						@click=${() => (self.format = 'decrypted')} | ||||||
| 					> | 					> | ||||||
| 						Decrypted | 						Decrypted | ||||||
| 					</button>`; | 					</button>`; | ||||||
| 				} else { | 				} else { | ||||||
| 					raw_button = html`<button | 					raw_button = html`<button | ||||||
| 						class="w3-button w3-theme-d1" | 						class="w3-button w3-dark-grey" | ||||||
| 						@click=${() => (self.format = 'raw')} | 						@click=${() => (self.format = 'raw')} | ||||||
| 					> | 					> | ||||||
| 						Raw | 						Raw | ||||||
| @@ -398,8 +389,8 @@ ${JSON.stringify(mention, null, 2)}</pre | |||||||
| 			let body; | 			let body; | ||||||
| 			return html` | 			return html` | ||||||
| 				<div | 				<div | ||||||
| 					class="w3-card-4 w3-theme-d4 w3-border-theme" | 					class="w3-card-4" | ||||||
| 					style="margin-top: 8px; padding: 16px; display: inline-block; overflow-wrap: anywhere" | 					style="background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px; display: inline-block; overflow-wrap: anywhere" | ||||||
| 				> | 				> | ||||||
| 					<tf-user id=${self.message.author} .users=${self.users}></tf-user> | 					<tf-user id=${self.message.author} .users=${self.users}></tf-user> | ||||||
| 					<span style="padding-right: 8px" | 					<span style="padding-right: 8px" | ||||||
| @@ -409,24 +400,13 @@ ${JSON.stringify(mention, null, 2)}</pre | |||||||
| 					> | 					> | ||||||
| 					${raw_button} ${self.format == 'raw' ? self.render_raw() : inner} | 					${raw_button} ${self.format == 'raw' ? self.render_raw() : inner} | ||||||
| 					${self.render_votes()} | 					${self.render_votes()} | ||||||
| 					${(self.message.child_messages || []).map( |  | ||||||
| 						(x) => html` |  | ||||||
| 							<tf-message |  | ||||||
| 								.message=${x} |  | ||||||
| 								whoami=${self.whoami} |  | ||||||
| 								.users=${self.users} |  | ||||||
| 								.drafts=${self.drafts} |  | ||||||
| 								.expanded=${self.expanded} |  | ||||||
| 							></tf-message> |  | ||||||
| 						` |  | ||||||
| 					)} |  | ||||||
| 				</div> | 				</div> | ||||||
| 			`; | 			`; | ||||||
| 		} | 		} | ||||||
| 		if (this.message?.type === 'contact_group') { | 		if (this.message?.type === 'contact_group') { | ||||||
| 			return html` <div | 			return html` <div | ||||||
| 				class="w3-card-4 w3-theme-d4 w3-border-theme" | 				class="w3-card-4" | ||||||
| 				style="margin-top: 8px; padding: 16px; overflow-wrap: anywhere" | 				style="border: 1px solid black; background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px; overflow-wrap: anywhere" | ||||||
| 			> | 			> | ||||||
| 				${this.message.messages.map( | 				${this.message.messages.map( | ||||||
| 					(x) => | 					(x) => | ||||||
| @@ -441,8 +421,8 @@ ${JSON.stringify(mention, null, 2)}</pre | |||||||
| 			</div>`; | 			</div>`; | ||||||
| 		} else if (this.message.placeholder) { | 		} else if (this.message.placeholder) { | ||||||
| 			return html` <div | 			return html` <div | ||||||
| 				class="w3-card-4 w3-theme-d4 w3-border-theme" | 				class="w3-card-4" | ||||||
| 				style="margin-top: 8px; padding: 16px; overflow-wrap: anywhere" | 				style="border: 1px solid black; background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px; overflow-wrap: anywhere" | ||||||
| 			> | 			> | ||||||
| 				<a target="_top" href=${'#' + this.message.id}>${this.message.id}</a> | 				<a target="_top" href=${'#' + this.message.id}>${this.message.id}</a> | ||||||
| 				(placeholder) | 				(placeholder) | ||||||
| @@ -518,11 +498,13 @@ ${JSON.stringify(mention, null, 2)}</pre | |||||||
| 									branch=${this.message.id} | 									branch=${this.message.id} | ||||||
| 									.drafts=${this.drafts} | 									.drafts=${this.drafts} | ||||||
| 									@tf-discard=${this.discard_reply} | 									@tf-discard=${this.discard_reply} | ||||||
| 									author=${this.message.author} |  | ||||||
| 								></tf-compose> | 								></tf-compose> | ||||||
| 							` | 							` | ||||||
| 						: html` | 						: html` | ||||||
| 								<button class="w3-button w3-theme-d1" @click=${this.show_reply}> | 								<button | ||||||
|  | 									class="w3-button w3-dark-grey" | ||||||
|  | 									@click=${this.show_reply} | ||||||
|  | 								> | ||||||
| 									Reply | 									Reply | ||||||
| 								</button> | 								</button> | ||||||
| 							`; | 							`; | ||||||
| @@ -551,7 +533,7 @@ ${JSON.stringify(content, null, 2)}</pre | |||||||
| 				} | 				} | ||||||
| 				let content_warning = html` | 				let content_warning = html` | ||||||
| 					<div | 					<div | ||||||
| 						class="w3-panel w3-round-xlarge w3-theme-l4" | 						class="w3-panel w3-round-xlarge w3-blue" | ||||||
| 						style="cursor: pointer" | 						style="cursor: pointer" | ||||||
| 						@click=${(x) => this.toggle_expanded(':cw')} | 						@click=${(x) => this.toggle_expanded(':cw')} | ||||||
| 					> | 					> | ||||||
| @@ -571,6 +553,9 @@ ${JSON.stringify(content, null, 2)}</pre | |||||||
| 				let is_encrypted = this.message?.decrypted | 				let is_encrypted = this.message?.decrypted | ||||||
| 					? html`<span style="align-self: center">🔓</span>` | 					? html`<span style="align-self: center">🔓</span>` | ||||||
| 					: undefined; | 					: undefined; | ||||||
|  | 				let style_background = this.message?.decrypted | ||||||
|  | 					? 'rgba(255, 0, 0, 0.2)' | ||||||
|  | 					: 'rgba(255, 255, 255, 0.1)'; | ||||||
| 				return html` | 				return html` | ||||||
| 					<style> | 					<style> | ||||||
| 						code { | 						code { | ||||||
| @@ -587,8 +572,8 @@ ${JSON.stringify(content, null, 2)}</pre | |||||||
| 						} | 						} | ||||||
| 					</style> | 					</style> | ||||||
| 					<div | 					<div | ||||||
| 						class="w3-card-4 ${class_background} w3-border-theme" | 						class="w3-card-4" | ||||||
| 						style="margin-top: 8px; padding: 16px" | 						style="border: 1px solid black; background-color: ${style_background}; margin-top: 8px; padding: 16px" | ||||||
| 					> | 					> | ||||||
| 						<div style="display: flex; flex-direction: row"> | 						<div style="display: flex; flex-direction: row"> | ||||||
| 							<tf-user id=${this.message.author} .users=${this.users}></tf-user> | 							<tf-user id=${this.message.author} .users=${this.users}></tf-user> | ||||||
| @@ -603,7 +588,7 @@ ${JSON.stringify(content, null, 2)}</pre | |||||||
| 						${payload} ${this.render_votes()} | 						${payload} ${this.render_votes()} | ||||||
| 						<p> | 						<p> | ||||||
| 							${reply} | 							${reply} | ||||||
| 							<button class="w3-button w3-theme-d1" @click=${this.react}> | 							<button class="w3-button w3-dark-grey" @click=${this.react}> | ||||||
| 								React | 								React | ||||||
| 							</button> | 							</button> | ||||||
| 						</p> | 						</p> | ||||||
| @@ -614,6 +599,9 @@ ${JSON.stringify(content, null, 2)}</pre | |||||||
| 				let is_encrypted = this.message?.decrypted | 				let is_encrypted = this.message?.decrypted | ||||||
| 					? html`<span style="align-self: center">🔓</span>` | 					? html`<span style="align-self: center">🔓</span>` | ||||||
| 					: undefined; | 					: undefined; | ||||||
|  | 				let style_background = this.message?.decrypted | ||||||
|  | 					? 'rgba(255, 0, 0, 0.2)' | ||||||
|  | 					: 'rgba(255, 255, 255, 0.1)'; | ||||||
| 				return html` | 				return html` | ||||||
| 					<style> | 					<style> | ||||||
| 						code { | 						code { | ||||||
| @@ -630,8 +618,8 @@ ${JSON.stringify(content, null, 2)}</pre | |||||||
| 						} | 						} | ||||||
| 					</style> | 					</style> | ||||||
| 					<div | 					<div | ||||||
| 						class="w3-card-4 ${class_background} w3-border-theme" | 						class="w3-card-4" | ||||||
| 						style="margin-top: 8px; padding: 16px" | 						style="border: 1px solid black; background-color: ${style_background}; margin-top: 8px; padding: 16px" | ||||||
| 					> | 					> | ||||||
| 						<div style="display: flex; flex-direction: row"> | 						<div style="display: flex; flex-direction: row"> | ||||||
| 							<tf-user id=${this.message.author} .users=${this.users}></tf-user> | 							<tf-user id=${this.message.author} .users=${this.users}></tf-user> | ||||||
| @@ -645,7 +633,7 @@ ${JSON.stringify(content, null, 2)}</pre | |||||||
| 						</div> | 						</div> | ||||||
| 						${content.text} ${this.render_votes()} | 						${content.text} ${this.render_votes()} | ||||||
| 						<p> | 						<p> | ||||||
| 							<button class="w3-button w3-theme-d1" @click=${this.react}> | 							<button class="w3-button w3-dark-grey" @click=${this.react}> | ||||||
| 								React | 								React | ||||||
| 							</button> | 							</button> | ||||||
| 						</p> | 						</p> | ||||||
| @@ -697,11 +685,13 @@ ${JSON.stringify(content, null, 2)}</pre | |||||||
| 									branch=${this.message.id} | 									branch=${this.message.id} | ||||||
| 									.drafts=${this.drafts} | 									.drafts=${this.drafts} | ||||||
| 									@tf-discard=${this.discard_reply} | 									@tf-discard=${this.discard_reply} | ||||||
| 									author=${this.message.author} |  | ||||||
| 								></tf-compose> | 								></tf-compose> | ||||||
| 							` | 							` | ||||||
| 						: html` | 						: html` | ||||||
| 								<button class="w3-button w3-theme-d1" @click=${this.show_reply}> | 								<button | ||||||
|  | 									class="w3-button w3-dark-grey" | ||||||
|  | 									@click=${this.show_reply} | ||||||
|  | 								> | ||||||
| 									Reply | 									Reply | ||||||
| 								</button> | 								</button> | ||||||
| 							`; | 							`; | ||||||
| @@ -721,8 +711,8 @@ ${JSON.stringify(content, null, 2)}</pre | |||||||
| 						} | 						} | ||||||
| 					</style> | 					</style> | ||||||
| 					<div | 					<div | ||||||
| 						class="w3-card-4 w3-theme-d4 w3-border-theme" | 						class="w3-card-4" | ||||||
| 						style="margin-top: 8px; padding: 16px" | 						style="border: 1px solid black; background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px" | ||||||
| 					> | 					> | ||||||
| 						<div style="display: flex; flex-direction: row"> | 						<div style="display: flex; flex-direction: row"> | ||||||
| 							<tf-user id=${this.message.author} .users=${this.users}></tf-user> | 							<tf-user id=${this.message.author} .users=${this.users}></tf-user> | ||||||
| @@ -738,7 +728,7 @@ ${JSON.stringify(content, null, 2)}</pre | |||||||
| 						${this.render_mentions()} | 						${this.render_mentions()} | ||||||
| 						<div> | 						<div> | ||||||
| 							${reply} | 							${reply} | ||||||
| 							<button class="w3-button w3-theme-d1" @click=${this.react}> | 							<button class="w3-button w3-dark-grey" @click=${this.react}> | ||||||
| 								React | 								React | ||||||
| 							</button> | 							</button> | ||||||
| 						</div> | 						</div> | ||||||
|   | |||||||
| @@ -215,49 +215,49 @@ class TfProfileElement extends LitElement { | |||||||
| 				let server_follow; | 				let server_follow; | ||||||
| 				if (this.server_follows_me === true) { | 				if (this.server_follows_me === true) { | ||||||
| 					server_follow = html`<button | 					server_follow = html`<button | ||||||
| 						class="w3-button w3-theme-d1" | 						class="w3-button w3-dark-grey" | ||||||
| 						@click=${() => this.server_follow_me(false)} | 						@click=${() => this.server_follow_me(false)} | ||||||
| 					> | 					> | ||||||
| 						Server, Stop Following Me | 						Server, Stop Following Me | ||||||
| 					</button>`; | 					</button>`; | ||||||
| 				} else if (this.server_follows_me === false) { | 				} else if (this.server_follows_me === false) { | ||||||
| 					server_follow = html`<button | 					server_follow = html`<button | ||||||
| 						class="w3-button w3-theme-d1" | 						class="w3-button w3-dark-grey" | ||||||
| 						@click=${() => this.server_follow_me(true)} | 						@click=${() => this.server_follow_me(true)} | ||||||
| 					> | 					> | ||||||
| 						Server, Follow Me | 						Server, Follow Me | ||||||
| 					</button>`; | 					</button>`; | ||||||
| 				} | 				} | ||||||
| 				edit = html` | 				edit = html` | ||||||
| 					<button class="w3-button w3-theme-d1" @click=${this.save_edits}> | 					<button class="w3-button w3-dark-grey" @click=${this.save_edits}> | ||||||
| 						Save Profile | 						Save Profile | ||||||
| 					</button> | 					</button> | ||||||
| 					<button class="w3-button w3-theme-d1" @click=${this.discard_edits}> | 					<button class="w3-button w3-dark-grey" @click=${this.discard_edits}> | ||||||
| 						Discard | 						Discard | ||||||
| 					</button> | 					</button> | ||||||
| 					${server_follow} | 					${server_follow} | ||||||
| 				`; | 				`; | ||||||
| 			} else { | 			} else { | ||||||
| 				edit = html`<button class="w3-button w3-theme-d1" @click=${this.edit}> | 				edit = html`<button class="w3-button w3-dark-grey" @click=${this.edit}> | ||||||
| 					Edit Profile | 					Edit Profile | ||||||
| 				</button>`; | 				</button>`; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if (this.id !== this.whoami && this.following !== undefined) { | 		if (this.id !== this.whoami && this.following !== undefined) { | ||||||
| 			follow = this.following | 			follow = this.following | ||||||
| 				? html`<button class="w3-button w3-theme-d1" @click=${this.unfollow}> | 				? html`<button class="w3-button w3-dark-grey" @click=${this.unfollow}> | ||||||
| 						Unfollow | 						Unfollow | ||||||
| 					</button>` | 					</button>` | ||||||
| 				: html`<button class="w3-button w3-theme-d1" @click=${this.follow}> | 				: html`<button class="w3-button w3-dark-grey" @click=${this.follow}> | ||||||
| 						Follow | 						Follow | ||||||
| 					</button>`; | 					</button>`; | ||||||
| 		} | 		} | ||||||
| 		if (this.id !== this.whoami && this.blocking !== undefined) { | 		if (this.id !== this.whoami && this.blocking !== undefined) { | ||||||
| 			block = this.blocking | 			block = this.blocking | ||||||
| 				? html`<button class="w3-button w3-theme-d1" @click=${this.unblock}> | 				? html`<button class="w3-button w3-dark-grey" @click=${this.unblock}> | ||||||
| 						Unblock | 						Unblock | ||||||
| 					</button>` | 					</button>` | ||||||
| 				: html`<button class="w3-button w3-theme-d1" @click=${this.block}> | 				: html`<button class="w3-button w3-dark-grey" @click=${this.block}> | ||||||
| 						Block | 						Block | ||||||
| 					</button>`; | 					</button>`; | ||||||
| 		} | 		} | ||||||
| @@ -267,16 +267,16 @@ class TfProfileElement extends LitElement { | |||||||
| 				<div class="w3-container"> | 				<div class="w3-container"> | ||||||
| 					<div> | 					<div> | ||||||
| 						<label for="name">Name:</label> | 						<label for="name">Name:</label> | ||||||
| 						<input class="w3-input w3-theme-d1" type="text" id="name" value=${this.editing.name} @input=${(event) => (this.editing = Object.assign({}, this.editing, {name: event.srcElement.value}))}></input> | 						<input class="w3-input w3-dark-grey" type="text" id="name" value=${this.editing.name} @input=${(event) => (this.editing = Object.assign({}, this.editing, {name: event.srcElement.value}))}></input> | ||||||
| 					</div> | 					</div> | ||||||
| 					<div><label for="description">Description:</label></div> | 					<div><label for="description">Description:</label></div> | ||||||
| 					<textarea class="w3-input w3-theme-d1" style="resize: vertical" rows="8" id="description" @input=${(event) => (this.editing = Object.assign({}, this.editing, {description: event.srcElement.value}))}>${this.editing.description}</textarea> | 					<textarea class="w3-input w3-dark-grey" style="resize: vertical" rows="8" id="description" @input=${(event) => (this.editing = Object.assign({}, this.editing, {description: event.srcElement.value}))}>${this.editing.description}</textarea> | ||||||
| 					<div> | 					<div> | ||||||
| 						<label for="public_web_hosting">Public Web Hosting:</label> | 						<label for="public_web_hosting">Public Web Hosting:</label> | ||||||
| 						<input class="w3-check w3-theme-d1" type="checkbox" id="public_web_hosting" ?checked=${this.editing.publicWebHosting} @input=${(event) => (self.editing = Object.assign({}, self.editing, {publicWebHosting: event.srcElement.checked}))}></input> | 						<input class="w3-check w3-dark-grey" type="checkbox" id="public_web_hosting" ?checked=${this.editing.publicWebHosting} @input=${(event) => (self.editing = Object.assign({}, self.editing, {publicWebHosting: event.srcElement.checked}))}></input> | ||||||
| 					</div> | 					</div> | ||||||
| 					<div> | 					<div> | ||||||
| 						<button class="w3-button w3-theme-d1" @click=${this.attach_image}>Attach Image</button> | 						<button class="w3-button w3-dark-grey" @click=${this.attach_image}>Attach Image</button> | ||||||
| 					</div> | 					</div> | ||||||
| 				</div> | 				</div> | ||||||
| 			</div>` | 			</div>` | ||||||
|   | |||||||
| @@ -1,68 +0,0 @@ | |||||||
| import {LitElement, html, unsafeHTML} from './lit-all.min.js'; |  | ||||||
| import {styles} from './tf-styles.js'; |  | ||||||
|  |  | ||||||
| class TfReactionsModalElement extends LitElement { |  | ||||||
| 	static get properties() { |  | ||||||
| 		return { |  | ||||||
| 			users: {type: Object}, |  | ||||||
| 			votes: {type: Array}, |  | ||||||
| 		}; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	static styles = styles; |  | ||||||
|  |  | ||||||
| 	constructor() { |  | ||||||
| 		super(); |  | ||||||
| 		this.votes = []; |  | ||||||
| 		this.users = {}; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	clear() { |  | ||||||
| 		this.votes = []; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	render() { |  | ||||||
| 		let self = this; |  | ||||||
| 		return this.votes?.length |  | ||||||
| 			? html` <div |  | ||||||
| 					class="w3-modal w3-animate-opacity" |  | ||||||
| 					style="display: block; box-sizing: border-box" |  | ||||||
| 				> |  | ||||||
| 					<div class="w3-modal-content w3-card-4 w3-theme-d1"> |  | ||||||
| 						<div class="w3-container w3-padding"> |  | ||||||
| 							<header class="w3-container"> |  | ||||||
| 								<h2>Reactions</h2> |  | ||||||
| 								<span class="w3-button w3-display-topright" @click=${this.clear} |  | ||||||
| 									>×</span |  | ||||||
| 								> |  | ||||||
| 							</header> |  | ||||||
| 							<ul class="w3-theme-dark w3-container w3-ul"> |  | ||||||
| 								${this.votes.map( |  | ||||||
| 									(x) => html` |  | ||||||
| 										<li class="w3-bar"> |  | ||||||
| 											<span class="w3-bar-item" |  | ||||||
| 												>${x?.content?.vote?.expression}</span |  | ||||||
| 											> |  | ||||||
| 											<tf-user |  | ||||||
| 												class="w3-bar-item" |  | ||||||
| 												id=${x.author} |  | ||||||
| 												.users=${this.users} |  | ||||||
| 											></tf-user> |  | ||||||
| 											<span class="w3-bar-item w3-right" |  | ||||||
| 												>${new Date(x?.timestamp).toLocaleString()}</span |  | ||||||
| 											> |  | ||||||
| 										</li> |  | ||||||
| 									` |  | ||||||
| 								)} |  | ||||||
| 							</ul> |  | ||||||
| 							<footer class="w3-container w3-padding"> |  | ||||||
| 								<button class="w3-button" @click=${this.clear}>Close</button> |  | ||||||
| 							</footer> |  | ||||||
| 						</div> |  | ||||||
| 					</div> |  | ||||||
| 				</div>` |  | ||||||
| 			: undefined; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| customElements.define('tf-reactions-modal', TfReactionsModalElement); |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -33,11 +33,9 @@ class TfTabConnectionsElement extends LitElement { | |||||||
|  |  | ||||||
| 	render_connection_summary(connection) { | 	render_connection_summary(connection) { | ||||||
| 		if (connection.address && connection.port) { | 		if (connection.address && connection.port) { | ||||||
| 			return html`<div> | 			return html`(<small>${connection.address}:${connection.port}</small>)`; | ||||||
| 				<small>${connection.address}:${connection.port}</small> |  | ||||||
| 			</div>`; |  | ||||||
| 		} else if (connection.tunnel) { | 		} else if (connection.tunnel) { | ||||||
| 			return html`<div>room peer</div>`; | 			return html`(room peer)`; | ||||||
| 		} else { | 		} else { | ||||||
| 			return JSON.stringify(connection); | 			return JSON.stringify(connection); | ||||||
| 		} | 		} | ||||||
| @@ -63,7 +61,7 @@ class TfTabConnectionsElement extends LitElement { | |||||||
| 		return html` | 		return html` | ||||||
| 			<li> | 			<li> | ||||||
| 				<button | 				<button | ||||||
| 					class="w3-button w3-theme-d1" | 					class="w3-button w3-dark-grey" | ||||||
| 					@click=${() => self._tunnel(connection.tunnel.id, connection.pubkey)} | 					@click=${() => self._tunnel(connection.tunnel.id, connection.pubkey)} | ||||||
| 				> | 				> | ||||||
| 					Connect | 					Connect | ||||||
| @@ -75,17 +73,15 @@ class TfTabConnectionsElement extends LitElement { | |||||||
|  |  | ||||||
| 	render_broadcast(connection) { | 	render_broadcast(connection) { | ||||||
| 		return html` | 		return html` | ||||||
| 			<li class="w3-bar" style="overflow: hidden; overflow-wrap: nowrap"> | 			<li> | ||||||
| 				<button | 				<button | ||||||
| 					class="w3-bar-item w3-button w3-theme-d1" | 					class="w3-button w3-dark-grey" | ||||||
| 					@click=${() => tfrpc.rpc.connect(connection)} | 					@click=${() => tfrpc.rpc.connect(connection)} | ||||||
| 				> | 				> | ||||||
| 					Connect | 					Connect | ||||||
| 				</button> | 				</button> | ||||||
| 				<div class="w3-bar-item"> |  | ||||||
| 				<tf-user id=${connection.pubkey} .users=${this.users}></tf-user> | 				<tf-user id=${connection.pubkey} .users=${this.users}></tf-user> | ||||||
| 				${this.render_connection_summary(connection)} | 				${this.render_connection_summary(connection)} | ||||||
| 				</div> |  | ||||||
| 			</li> | 			</li> | ||||||
| 		`; | 		`; | ||||||
| 	} | 	} | ||||||
| @@ -98,7 +94,7 @@ class TfTabConnectionsElement extends LitElement { | |||||||
| 	render_connection(connection) { | 	render_connection(connection) { | ||||||
| 		return html` | 		return html` | ||||||
| 			<button | 			<button | ||||||
| 				class="w3-button w3-theme-d1" | 				class="w3-button w3-dark-grey" | ||||||
| 				@click=${() => tfrpc.rpc.closeConnection(connection.id)} | 				@click=${() => tfrpc.rpc.closeConnection(connection.id)} | ||||||
| 			> | 			> | ||||||
| 				Close | 				Close | ||||||
| @@ -107,15 +103,6 @@ class TfTabConnectionsElement extends LitElement { | |||||||
| 			${connection.tunnel !== undefined | 			${connection.tunnel !== undefined | ||||||
| 				? '🚇' | 				? '🚇' | ||||||
| 				: html`(${connection.host}:${connection.port})`} | 				: html`(${connection.host}:${connection.port})`} | ||||||
| 			<div> |  | ||||||
| 				${connection.requests.map( |  | ||||||
| 					(x) => html` |  | ||||||
| 						<span class="w3-tag w3-small" |  | ||||||
| 							>${x.request_number > 0 ? '🟩' : '🟥'} ${x.name}</span |  | ||||||
| 						> |  | ||||||
| 					` |  | ||||||
| 				)} |  | ||||||
| 			</div> |  | ||||||
| 			<ul> | 			<ul> | ||||||
| 				${this.connections | 				${this.connections | ||||||
| 					.filter((x) => x.tunnel === this.connections.indexOf(connection)) | 					.filter((x) => x.tunnel === this.connections.indexOf(connection)) | ||||||
| @@ -128,64 +115,56 @@ class TfTabConnectionsElement extends LitElement { | |||||||
| 	render() { | 	render() { | ||||||
| 		let self = this; | 		let self = this; | ||||||
| 		return html` | 		return html` | ||||||
| 			<div class="w3-container" style="box-sizing: border-box"> | 			<div class="w3-container"> | ||||||
| 				<h2>New Connection</h2> | 				<h2>New Connection</h2> | ||||||
| 				<textarea class="w3-input w3-theme-d1" id="code"></textarea> | 				<textarea class="w3-input w3-dark-grey" id="code"></textarea> | ||||||
| 				<button | 				<button | ||||||
| 					class="w3-button w3-theme-d1" | 					class="w3-button w3-dark-grey" | ||||||
| 					@click=${() => | 					@click=${() => | ||||||
| 						tfrpc.rpc.connect(self.renderRoot.getElementById('code').value)} | 						tfrpc.rpc.connect(self.renderRoot.getElementById('code').value)} | ||||||
| 				> | 				> | ||||||
| 					Connect | 					Connect | ||||||
| 				</button> | 				</button> | ||||||
| 				<h2>Broadcasts</h2> | 				<h2>Broadcasts</h2> | ||||||
| 				<ul class="w3-ul w3-border"> | 				<ul> | ||||||
| 					${this.broadcasts | 					${this.broadcasts | ||||||
| 						.filter((x) => x.address) | 						.filter((x) => x.address) | ||||||
| 						.map((x) => self.render_broadcast(x))} | 						.map((x) => self.render_broadcast(x))} | ||||||
| 				</ul> | 				</ul> | ||||||
| 				<h2>Connections</h2> | 				<h2>Connections</h2> | ||||||
| 				<ul class="w3-ul w3-border"> | 				<ul> | ||||||
| 					${this.connections | 					${this.connections | ||||||
| 						.filter((x) => x.tunnel === undefined) | 						.filter((x) => x.tunnel === undefined) | ||||||
| 						.map( | 						.map((x) => html` <li>${this.render_connection(x)}</li> `)} | ||||||
| 							(x) => html` |  | ||||||
| 								<li class="w3-bar">${this.render_connection(x)}</li> |  | ||||||
| 							` |  | ||||||
| 						)} |  | ||||||
| 				</ul> | 				</ul> | ||||||
| 				<h2>Stored Connections</h2> | 				<h2>Stored Connections (WIP)</h2> | ||||||
| 				<ul class="w3-ul w3-border"> | 				<ul> | ||||||
| 					${this.stored_connections.map( | 					${this.stored_connections.map( | ||||||
| 						(x) => html` | 						(x) => html` | ||||||
| 							<li class="w3-bar"> | 							<li> | ||||||
| 								<button | 								<button | ||||||
| 									class="w3-bar-item w3-button w3-theme-d1" | 									class="w3-button w3-dark-grey" | ||||||
| 									@click=${() => self.forget_stored_connection(x)} | 									@click=${() => self.forget_stored_connection(x)} | ||||||
| 								> | 								> | ||||||
| 									Forget | 									Forget | ||||||
| 								</button> | 								</button> | ||||||
| 								<button | 								<button | ||||||
| 									class="w3-bar-item w3-button w3-theme-d1" | 									class="w3-button w3-dark-grey" | ||||||
| 									@click=${() => tfrpc.rpc.connect(x)} | 									@click=${() => tfrpc.rpc.connect(x)} | ||||||
| 								> | 								> | ||||||
| 									Connect | 									Connect | ||||||
| 								</button> | 								</button> | ||||||
| 								<div class="w3-bar-item"> | 								${x.address}:${x.port} | ||||||
| 								<tf-user id=${x.pubkey} .users=${self.users}></tf-user> | 								<tf-user id=${x.pubkey} .users=${self.users}></tf-user> | ||||||
| 									<div><small>${x.address}:${x.port}</small></div> |  | ||||||
| 								</div> |  | ||||||
| 							</li> | 							</li> | ||||||
| 						` | 						` | ||||||
| 					)} | 					)} | ||||||
| 				</ul> | 				</ul> | ||||||
| 				<h2>Local Accounts</h2> | 				<h2>Local Accounts</h2> | ||||||
| 				<ul class="w3-ul w3-border"> | 				<ul> | ||||||
| 					${this.identities.map( | 					${this.identities.map( | ||||||
| 						(x) => | 						(x) => | ||||||
| 							html`<li class="w3-bar"> | 							html`<li><tf-user id=${x} .users=${this.users}></tf-user></li>` | ||||||
| 								<tf-user id=${x} .users=${this.users}></tf-user> |  | ||||||
| 							</li>` |  | ||||||
| 					)} | 					)} | ||||||
| 				</ul> | 				</ul> | ||||||
| 			</div> | 			</div> | ||||||
|   | |||||||
| @@ -187,7 +187,7 @@ class TfTabNewsFeedElement extends LitElement { | |||||||
| 		if (!this.hash.startsWith('#@') && !this.hash.startsWith('#%')) { | 		if (!this.hash.startsWith('#@') && !this.hash.startsWith('#%')) { | ||||||
| 			more = html` | 			more = html` | ||||||
| 				<p> | 				<p> | ||||||
| 					<button class="w3-button w3-theme-d1" @click=${this.load_more}> | 					<button class="w3-button w3-dark-grey" @click=${this.load_more}> | ||||||
| 						Load More | 						Load More | ||||||
| 					</button> | 					</button> | ||||||
| 				</p> | 				</p> | ||||||
|   | |||||||
| @@ -84,7 +84,10 @@ class TfTabNewsElement extends LitElement { | |||||||
| 		} else { | 		} else { | ||||||
| 			delete this.drafts[id]; | 			delete this.drafts[id]; | ||||||
| 		} | 		} | ||||||
|  | 		/* Only trigger a re-render if we're creating a new draft or discarding an old one. */ | ||||||
|  | 		if ((previous !== undefined) != (event.detail.draft !== undefined)) { | ||||||
| 			this.drafts = Object.assign({}, this.drafts); | 			this.drafts = Object.assign({}, this.drafts); | ||||||
|  | 		} | ||||||
| 		tfrpc.rpc.localStorageSet('drafts', JSON.stringify(this.drafts)); | 		tfrpc.rpc.localStorageSet('drafts', JSON.stringify(this.drafts)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -116,7 +119,7 @@ class TfTabNewsElement extends LitElement { | |||||||
| 		return html` | 		return html` | ||||||
| 			<p class="w3-bar"> | 			<p class="w3-bar"> | ||||||
| 				<button | 				<button | ||||||
| 					class="w3-bar-item w3-button w3-theme-d1" | 					class="w3-bar-item w3-button w3-dark-grey" | ||||||
| 					@click=${this.show_more} | 					@click=${this.show_more} | ||||||
| 				> | 				> | ||||||
| 					${this.new_messages_text()} | 					${this.new_messages_text()} | ||||||
|   | |||||||
| @@ -110,14 +110,14 @@ class TfTabQueryElement extends LitElement { | |||||||
| 				<textarea | 				<textarea | ||||||
| 					id="search" | 					id="search" | ||||||
| 					rows="8" | 					rows="8" | ||||||
| 					class="w3-input w3-theme-d1" | 					class="w3-input w3-dark-grey" | ||||||
| 					style="flex: 1; resize: vertical" | 					style="flex: 1; resize: vertical" | ||||||
| 					@keydown=${this.search_keydown} | 					@keydown=${this.search_keydown} | ||||||
| 				> | 				> | ||||||
| ${this.query}</textarea | ${this.query}</textarea | ||||||
| 				> | 				> | ||||||
| 				<button | 				<button | ||||||
| 					class="w3-button w3-theme-d1" | 					class="w3-button w3-dark-grey" | ||||||
| 					@click=${(event) => | 					@click=${(event) => | ||||||
| 						self.search(self.renderRoot.getElementById('search').value)} | 						self.search(self.renderRoot.getElementById('search').value)} | ||||||
| 				> | 				> | ||||||
|   | |||||||
| @@ -78,8 +78,8 @@ class TfTabSearchElement extends LitElement { | |||||||
| 		let self = this; | 		let self = this; | ||||||
| 		return html` | 		return html` | ||||||
| 			<div style="display: flex; flex-direction: row; gap: 4px"> | 			<div style="display: flex; flex-direction: row; gap: 4px"> | ||||||
| 				<input type="text" class="w3-input w3-theme-d1" id="search" value=${this.query} style="flex: 1" @keydown=${this.search_keydown}></input> | 				<input type="text" class="w3-input w3-dark-grey" id="search" value=${this.query} style="flex: 1" @keydown=${this.search_keydown}></input> | ||||||
| 				<button class="w3-button w3-theme-d1" @click=${(event) => self.search(self.renderRoot.getElementById('search').value)}>Search</button> | 				<button class="w3-button w3-dark-grey" @click=${(event) => self.search(self.renderRoot.getElementById('search').value)}>Search</button> | ||||||
| 			</div> | 			</div> | ||||||
| 			<tf-news id="news" whoami=${this.whoami} .messages=${this.messages} .users=${this.users} .expanded=${this.expanded} @tf-expand=${this.on_expand}></tf-news> | 			<tf-news id="news" whoami=${this.whoami} .messages=${this.messages} .users=${this.users} .expanded=${this.expanded} @tf-expand=${this.on_expand}></tf-news> | ||||||
| 		`; | 		`; | ||||||
|   | |||||||
| @@ -1,7 +1,6 @@ | |||||||
|  | import * as linkify from './commonmark-linkify.js'; | ||||||
| import * as hashtagify from './commonmark-hashtag.js'; | import * as hashtagify from './commonmark-hashtag.js'; | ||||||
|  |  | ||||||
| const k_code_classes = 'w3-theme-l4 w3-theme-border w3-round'; |  | ||||||
|  |  | ||||||
| function image(node, entering) { | function image(node, entering) { | ||||||
| 	if ( | 	if ( | ||||||
| 		node.firstChild?.type === 'text' && | 		node.firstChild?.type === 'text' && | ||||||
| @@ -62,32 +61,13 @@ function image(node, entering) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| function code(node) { |  | ||||||
| 	let attrs = this.attrs(node); |  | ||||||
| 	attrs.push(['class', k_code_classes]); |  | ||||||
| 	this.tag('code', attrs); |  | ||||||
| 	this.out(node.literal); |  | ||||||
| 	this.tag('/code'); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function attrs(node) { |  | ||||||
| 	let result = commonmark.HtmlRenderer.prototype.attrs.bind(this)(node); |  | ||||||
| 	if (node.type == 'block_quote') { |  | ||||||
| 		result.push(['class', 'w3-theme-d1']); |  | ||||||
| 	} else if (node.type == 'code_block') { |  | ||||||
| 		result.push(['class', k_code_classes]); |  | ||||||
| 	} |  | ||||||
| 	return result; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export function markdown(md) { | export function markdown(md) { | ||||||
| 	let reader = new commonmark.Parser({safe: true}); | 	let reader = new commonmark.Parser({safe: true}); | ||||||
| 	let writer = new commonmark.HtmlRenderer(); | 	let writer = new commonmark.HtmlRenderer(); | ||||||
| 	writer.image = image; | 	writer.image = image; | ||||||
| 	writer.code = code; |  | ||||||
| 	writer.attrs = attrs; |  | ||||||
| 	let parsed = reader.parse(md || ''); | 	let parsed = reader.parse(md || ''); | ||||||
| 	parsed = hashtagify.transform(parsed); | 	parsed = hashtagify.transform(parsed); | ||||||
|  | 	parsed = linkify.transform(parsed); | ||||||
| 	let walker = parsed.walker(); | 	let walker = parsed.walker(); | ||||||
| 	let event, node; | 	let event, node; | ||||||
| 	while ((event = walker.next())) { | 	while ((event = walker.next())) { | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								apps/user_settings.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								apps/user_settings.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | {"type": "tildefriends-app", "emoji": "⚙️"} | ||||||
							
								
								
									
										60
									
								
								apps/user_settings/app.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								apps/user_settings/app.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | |||||||
|  | import * as tfrpc from '/tfrpc.js'; | ||||||
|  |  | ||||||
|  | tfrpc.register(async function getIdentities() { | ||||||
|  | 	return ssb.getIdentities(); | ||||||
|  | }); | ||||||
|  | tfrpc.register(async function createID(id) { | ||||||
|  | 	return await ssb.createIdentity(); | ||||||
|  | }); | ||||||
|  | tfrpc.register(async function getPrivateKey(id) { | ||||||
|  | 	return bip39Words(await ssb.getPrivateKey(id)); | ||||||
|  | }); | ||||||
|  | tfrpc.register(async function addID(id) { | ||||||
|  | 	return await ssb.addIdentity(bip39Bytes(id)); | ||||||
|  | }); | ||||||
|  | tfrpc.register(async function deleteID(id) { | ||||||
|  | 	return await ssb.deleteIdentity(id); | ||||||
|  | }); | ||||||
|  | tfrpc.register(async function getThemes() { | ||||||
|  | 	// TODO | ||||||
|  | 	return ['solarized', 'gruvbox', 'light']; | ||||||
|  | }); | ||||||
|  | tfrpc.register(async function getTheme() { | ||||||
|  | 	// TODO | ||||||
|  | 	return 'gruvbox'; | ||||||
|  | }); | ||||||
|  | tfrpc.register(async function setTheme() { | ||||||
|  | 	// TODO | ||||||
|  | 	console.warn('setTheme called - not implemented'); | ||||||
|  | 	return null; | ||||||
|  | }); | ||||||
|  | tfrpc.register(async function reload() { | ||||||
|  | 	await main(); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | async function main() { | ||||||
|  | 	// Get body.html | ||||||
|  | 	const body = utf8Decode(await getFile('body.html')); | ||||||
|  |  | ||||||
|  | 	// Build the document | ||||||
|  | 	const document = ` | ||||||
|  | 	<!DOCTYPE html> | ||||||
|  | 	<html> | ||||||
|  | 		<head> | ||||||
|  | 			<link rel="stylesheet" href="/static/tildefriends-v1.css"/> | ||||||
|  | 			<script src="tf-theme-picker.js" type="module"></script> | ||||||
|  | 			<script src="tf-password-form.js" type="module"></script> | ||||||
|  | 			<script src="tf-delete-account-btn.js" type="module"></script> | ||||||
|  | 			<script src="tf-identity-manager.js" type="module"></script> | ||||||
|  | 		</head> | ||||||
|  |  | ||||||
|  | 		<body class="flex-column"> | ||||||
|  | 			${body} | ||||||
|  | 		</body> | ||||||
|  | 	</html>`; | ||||||
|  |  | ||||||
|  | 	// Send it to the browser | ||||||
|  | 	app.setDocument(document); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | main(); | ||||||
							
								
								
									
										20
									
								
								apps/user_settings/body.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								apps/user_settings/body.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | <h1>Your settings</h1> | ||||||
|  |  | ||||||
|  | <div class="box flex-column"> | ||||||
|  | 	<h2>Appearance</h2> | ||||||
|  |  | ||||||
|  | 	<tf-theme-picker></tf-theme-picker> | ||||||
|  | </div> | ||||||
|  |  | ||||||
|  | <div class="box flex-column"> | ||||||
|  | 	<h2>Danger Zone</h2> | ||||||
|  |  | ||||||
|  | 	<h3>Manage your identities</h3> | ||||||
|  | 	<tf-identity-manager></tf-identity-manager> | ||||||
|  |  | ||||||
|  | 	<h3>Change my password</h3> | ||||||
|  | 	<tf-password-form></tf-password-form> | ||||||
|  |  | ||||||
|  | 	<h3>Delete your account</h3> | ||||||
|  | 	<tf-delete-account-btn></tf-delete-account-btn> | ||||||
|  | </div> | ||||||
							
								
								
									
										120
									
								
								apps/user_settings/lit-all.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								apps/user_settings/lit-all.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								apps/user_settings/lit-all.min.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								apps/user_settings/lit-all.min.js.map
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										36
									
								
								apps/user_settings/tf-delete-account-btn.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								apps/user_settings/tf-delete-account-btn.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | import {LitElement, html} from './lit-all.min.js'; | ||||||
|  | import * as tfrpc from '/static/tfrpc.js'; | ||||||
|  |  | ||||||
|  | class TfDeleteAccountButtonElement extends LitElement { | ||||||
|  | 	static get properties() { | ||||||
|  | 		return {}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	constructor() { | ||||||
|  | 		super(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	deleteAccount() { | ||||||
|  | 		const res = confirm( | ||||||
|  | 			'Are you really sure you want to delete your account ?' | ||||||
|  | 		); | ||||||
|  |  | ||||||
|  | 		if (!res) return; | ||||||
|  |  | ||||||
|  | 		console.warn('TODO'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	render() { | ||||||
|  | 		return html` | ||||||
|  | 			<link rel="stylesheet" href="/static/tildefriends-v1.css" /> | ||||||
|  |  | ||||||
|  | 			<span>This action is irreversible !</span> | ||||||
|  |  | ||||||
|  | 			<button class="red" @click=${this.deleteAccount}> | ||||||
|  | 				[Not implemented] Delete my Tilde Friends account | ||||||
|  | 			</button> | ||||||
|  | 		`; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | customElements.define('tf-delete-account-btn', TfDeleteAccountButtonElement); | ||||||
							
								
								
									
										118
									
								
								apps/user_settings/tf-identity-manager.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								apps/user_settings/tf-identity-manager.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | |||||||
|  | import {LitElement, html} from './lit-all.min.js'; | ||||||
|  | import * as tfrpc from '/static/tfrpc.js'; | ||||||
|  |  | ||||||
|  | class TfIdentityManagerElement extends LitElement { | ||||||
|  | 	static get properties() { | ||||||
|  | 		return { | ||||||
|  | 			ids: {type: Array}, | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	constructor() { | ||||||
|  | 		super(); | ||||||
|  | 		this.ids = []; | ||||||
|  | 		this.load(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	async load() { | ||||||
|  | 		this.ids = await tfrpc.rpc.getIdentities(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	async createIdentity() { | ||||||
|  | 		try { | ||||||
|  | 			const id = await tfrpc.rpc.createID(); | ||||||
|  | 			alert('Successfully created: ' + id); | ||||||
|  | 			await tfrpc.rpc.reload(); | ||||||
|  | 		} catch (err) { | ||||||
|  | 			alert('Error creating identity: ' + err); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	async importIdentity() { | ||||||
|  | 		const words = this.renderRoot?.querySelector('#import-id-textarea').value; | ||||||
|  | 		if (!words) return; | ||||||
|  |  | ||||||
|  | 		try { | ||||||
|  | 			const newID = await tfrpc.rpc.addID(words); | ||||||
|  |  | ||||||
|  | 			if (newID) alert('Successfully imported a new identity.'); | ||||||
|  | 			else alert('This identity already exists or is invalid.'); | ||||||
|  | 			await tfrpc.rpc.reload(); | ||||||
|  | 		} catch (err) { | ||||||
|  | 			alert('Error importing identity: ' + err); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	async exportIdentity(id) { | ||||||
|  | 		alert( | ||||||
|  | 			'Your private key is:\n' + | ||||||
|  | 				(await tfrpc.rpc.getPrivateKey(id)) + | ||||||
|  | 				'\nDo not share it with anyone!' | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	async deleteIdentity(id) { | ||||||
|  | 		try { | ||||||
|  | 			if ( | ||||||
|  | 				prompt( | ||||||
|  | 					'Are you sure you want to delete "' + | ||||||
|  | 						id + | ||||||
|  | 						'"?  It cannot be recovered without the exported phrase.\\n\\nEnter the word "DELETE" to confirm you wish to delete it.' | ||||||
|  | 				) === 'DELETE' | ||||||
|  | 			) { | ||||||
|  | 				if (await tfrpc.rpc.deleteID(id)) { | ||||||
|  | 					alert('Successfully deleted ID: ' + id); | ||||||
|  | 				} | ||||||
|  | 				await tfrpc.rpc.reload(); | ||||||
|  | 			} | ||||||
|  | 		} catch (e) { | ||||||
|  | 			alert('Error deleting ID: ' + e); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	render() { | ||||||
|  | 		return html` <link rel="stylesheet" href="/static/tildefriends-v1.css" /> | ||||||
|  | 			<style> | ||||||
|  | 				.id-span { | ||||||
|  | 					font-family: monospace; | ||||||
|  | 					margin-left: 8px; | ||||||
|  | 				} | ||||||
|  | 			</style> | ||||||
|  |  | ||||||
|  | 			<h4>Create a new identity</h4> | ||||||
|  | 			<button id="create-id" class="green" @click=${this.createIdentity}> | ||||||
|  | 				Create Identity | ||||||
|  | 			</button> | ||||||
|  |  | ||||||
|  | 			<h4>Import an SSB Identity from 12 BIP39 English Words</h4> | ||||||
|  | 			<textarea id="import-id-textarea" style="width: 100%" rows="4"></textarea> | ||||||
|  | 			<button class="green" @click=${this.importIdentity}> | ||||||
|  | 				Import Identity | ||||||
|  | 			</button> | ||||||
|  |  | ||||||
|  | 			<h4>Warning !</h4> | ||||||
|  | 			<strong | ||||||
|  | 				>Anybody that knows your private key can gain total access over your | ||||||
|  | 				account.</strong | ||||||
|  | 			> | ||||||
|  | 			<br /><br /> | ||||||
|  | 			Tilde Friends' contributors will never ask you for your private key ! | ||||||
|  |  | ||||||
|  | 			<ul> | ||||||
|  | 				${this.ids.map( | ||||||
|  | 					(id) => | ||||||
|  | 						html` <li> | ||||||
|  | 							<button class="blue" @click=${() => this.exportIdentity(id)}> | ||||||
|  | 								Export Identity | ||||||
|  | 							</button> | ||||||
|  | 							<button class="red" @click=${() => this.deleteIdentity(id)}> | ||||||
|  | 								Delete Identity | ||||||
|  | 							</button> | ||||||
|  | 							<span class="id-span">${id}</span> | ||||||
|  | 						</li>` | ||||||
|  | 				)} | ||||||
|  | 			</ul>`; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | customElements.define('tf-identity-manager', TfIdentityManagerElement); | ||||||
							
								
								
									
										82
									
								
								apps/user_settings/tf-password-form.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								apps/user_settings/tf-password-form.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | |||||||
|  | import {LitElement, html} from './lit-all.min.js'; | ||||||
|  | import * as tfrpc from '/static/tfrpc.js'; | ||||||
|  |  | ||||||
|  | class TfPasswordFormElement extends LitElement { | ||||||
|  | 	static get properties() { | ||||||
|  | 		return { | ||||||
|  | 			//selected: {type: String}, | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	constructor() { | ||||||
|  | 		super(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Checks a password against different requirements | ||||||
|  | 	 * @param {string} password the password to validate | ||||||
|  | 	 * @returns | ||||||
|  | 	 */ | ||||||
|  | 	validatePassword(password) { | ||||||
|  | 		// TODO(tasiaiso) | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	submitPassword() { | ||||||
|  | 		const currentPwd = this.shadowRoot.getElementById('current').value; | ||||||
|  | 		const newPwd = this.shadowRoot.getElementById('new').value; | ||||||
|  | 		const repeatPwd = this.shadowRoot.getElementById('Repeat').value; | ||||||
|  |  | ||||||
|  | 		if (!(newPwd === repeatPwd)) { | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// TODO | ||||||
|  | 		// tfrpc.changePassword() | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	render() { | ||||||
|  | 		return html` | ||||||
|  | 			<link rel="stylesheet" href="/static/tildefriends-v1.css" /> | ||||||
|  |  | ||||||
|  | 			<style> | ||||||
|  | 				.grid { | ||||||
|  | 					display: grid; | ||||||
|  | 					grid-template-columns: auto auto; | ||||||
|  | 				} | ||||||
|  | 			</style> | ||||||
|  |  | ||||||
|  | 			<div class="grid"> | ||||||
|  | 				<label for="current">Current password:</label> | ||||||
|  | 				<input | ||||||
|  | 					type="password" | ||||||
|  | 					id="current" | ||||||
|  | 					name="current" | ||||||
|  | 					autocomplete="current-password" | ||||||
|  | 				/> | ||||||
|  |  | ||||||
|  | 				<label for="new">Enter new password:</label> | ||||||
|  | 				<input | ||||||
|  | 					type="password" | ||||||
|  | 					id="new" | ||||||
|  | 					name="new" | ||||||
|  | 					autocomplete="new-password" | ||||||
|  | 				/> | ||||||
|  |  | ||||||
|  | 				<label for="repeat">Repeat new password:</label> | ||||||
|  | 				<input | ||||||
|  | 					type="password" | ||||||
|  | 					id="repeat" | ||||||
|  | 					name="repeat" | ||||||
|  | 					autocomplete="new-password" | ||||||
|  | 				/> | ||||||
|  | 			</div> | ||||||
|  |  | ||||||
|  | 			<button @click=${this.submitPassword} class="red"> | ||||||
|  | 				[Not implemented] Change my password | ||||||
|  | 			</button> | ||||||
|  | 		`; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | customElements.define('tf-password-form', TfPasswordFormElement); | ||||||
							
								
								
									
										51
									
								
								apps/user_settings/tf-theme-picker.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								apps/user_settings/tf-theme-picker.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | import {LitElement, html, nothing} from './lit-all.min.js'; | ||||||
|  | import * as tfrpc from '/static/tfrpc.js'; | ||||||
|  |  | ||||||
|  | class TfThemePickerElement extends LitElement { | ||||||
|  | 	static get properties() { | ||||||
|  | 		return { | ||||||
|  | 			selected: {type: String}, | ||||||
|  | 			themes: {type: Array}, | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	constructor() { | ||||||
|  | 		super(); | ||||||
|  | 		this.load(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	async load() { | ||||||
|  | 		this.themes = await tfrpc.rpc.getThemes(); | ||||||
|  | 		this.selected = await tfrpc.rpc.getTheme(); | ||||||
|  |  | ||||||
|  | 		let select = this.renderRoot?.querySelector('#theme-select'); | ||||||
|  | 		select.value = this.selected; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	changed(event) { | ||||||
|  | 		this.selected = event.srcElement.value; | ||||||
|  | 		console.log('selected theme', this.selected); | ||||||
|  | 		// TODO | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	render() { | ||||||
|  | 		return html` | ||||||
|  | 			<link rel="stylesheet" href="/static/tildefriends-v1.css" /> | ||||||
|  |  | ||||||
|  | 			<label for="theme">[Not implemented] Choose your theme:</label> | ||||||
|  |  | ||||||
|  | 			<select | ||||||
|  | 				name="theme" | ||||||
|  | 				id="theme-select" | ||||||
|  | 				?hidden=${!this.themes?.length} | ||||||
|  | 				@change=${this.changed} | ||||||
|  | 			> | ||||||
|  | 				${(this.themes ?? []).map( | ||||||
|  | 					(name) => html`<option value=${name}>${name}</option>` | ||||||
|  | 				)} | ||||||
|  | 			</select> | ||||||
|  | 		`; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | customElements.define('tf-theme-picker', TfThemePickerElement); | ||||||
| @@ -1,5 +1,5 @@ | |||||||
| { | { | ||||||
| 	"type": "tildefriends-app", | 	"type": "tildefriends-app", | ||||||
| 	"emoji": "👋", | 	"emoji": "👋", | ||||||
| 	"previous": "&W5aJp2DgOW5rQ0AOIC9Ut3DpsahPrO6PjkJ1PQbNRdM=.sha256" | 	"previous": "&zFISmRDAv+SXFonfZ9/sHNhrmMe+poTU22gwZzuSkT4=.sha256" | ||||||
| } | } | ||||||
|   | |||||||
| @@ -55,7 +55,7 @@ | |||||||
| 					</p> | 					</p> | ||||||
| 					<a | 					<a | ||||||
| 						class="w3-button w3-black w3-padding-large" | 						class="w3-button w3-black w3-padding-large" | ||||||
| 						href="https://dev.tildefriends.net/cory/tildefriends/releases" | 						href="https://www.tildefriends.net/~cory/releases/" | ||||||
| 						><i class="fa fa-download"></i> Download</a | 						><i class="fa fa-download"></i> Download</a | ||||||
| 					> | 					> | ||||||
| 					<a | 					<a | ||||||
| @@ -63,11 +63,6 @@ | |||||||
| 						href="https://www.tildefriends.net/~cory/apps/" | 						href="https://www.tildefriends.net/~cory/apps/" | ||||||
| 						><i class="fa fa-link"></i> Try It</a | 						><i class="fa fa-link"></i> Try It</a | ||||||
| 					> | 					> | ||||||
| 					<a |  | ||||||
| 						class="w3-button w3-black w3-padding-large" |  | ||||||
| 						href="https://dev.tildefriends.net/" |  | ||||||
| 						><i class="fa fa-mug-hot"></i> Code</a |  | ||||||
| 					> |  | ||||||
| 				</div> | 				</div> | ||||||
| 				<div class="w3-col l4 m6"> | 				<div class="w3-col l4 m6"> | ||||||
| 					<img src="tildefriends.png" class="w3-image w3-right w3-hide-small" /> | 					<img src="tildefriends.png" class="w3-image w3-right w3-hide-small" /> | ||||||
| @@ -75,60 +70,6 @@ | |||||||
| 			</div> | 			</div> | ||||||
| 		</div> | 		</div> | ||||||
|  |  | ||||||
| 		<!-- Getting Starting Section --> |  | ||||||
| 		<div class="w3-indigo w3-center"> |  | ||||||
| 			<div class="w3-row-padding w3-padding-64"> |  | ||||||
| 				<div class="w3-jumbo"> |  | ||||||
| 					<i class="fa fa-rocket"></i> <b>Getting Started</b> |  | ||||||
| 				</div> |  | ||||||
| 				<div> |  | ||||||
| 					<h2>First-time user checklist:</h2> |  | ||||||
| 					<ol type="1" style="text-align: left"> |  | ||||||
| 						<li> |  | ||||||
| 							<a href="https://dev.tildefriends.net/cory/tildefriends/releases" |  | ||||||
| 								>Download</a |  | ||||||
| 							> |  | ||||||
| 							Tilde Friends and run your own instance, or use |  | ||||||
| 							<a href="https://www.tildefriends.net/" |  | ||||||
| 								>https://www.tildefriends.net/</a |  | ||||||
| 							>. |  | ||||||
| 						</li> |  | ||||||
| 						<li> |  | ||||||
| 							Create an account to identify yourself with that instance by |  | ||||||
| 							username and password. |  | ||||||
| 						</li> |  | ||||||
| 						<li> |  | ||||||
| 							Create an SSB identity in the <b>ssb</b> app. This will generate a |  | ||||||
| 							keypair used to identify yourself to other users and sign your |  | ||||||
| 							messages so that they can be verified as from you. |  | ||||||
| 						</li> |  | ||||||
| 						<li> |  | ||||||
| 							Describe yourself in your profile in the <b>ssb</b> app. Give |  | ||||||
| 							yourself a name and an avatar if you like. |  | ||||||
| 						</li> |  | ||||||
| 						<li> |  | ||||||
| 							Connect to others. You will automatically discover peers on the |  | ||||||
| 							same instance and same network if there are any. Or use |  | ||||||
| 							<a href="https://github.com/staltz/ssb-room/blob/master/FAQ.md" |  | ||||||
| 								>rooms</a |  | ||||||
| 							> |  | ||||||
| 							and pubs to reach more distant users. |  | ||||||
| 							<a href="https://www.tildefriends.net/~cory/room/" |  | ||||||
| 								>tildefriends.net itself</a |  | ||||||
| 							> |  | ||||||
| 							operates as a room, so you can connect and see who else is online |  | ||||||
| 							and establish a connection. |  | ||||||
| 						</li> |  | ||||||
| 						<li>Follow people to grow your network.</li> |  | ||||||
| 						<li> |  | ||||||
| 							Use the <b>edit</b> link at the top of any page to start modifying |  | ||||||
| 							and making apps. |  | ||||||
| 						</li> |  | ||||||
| 					</ol> |  | ||||||
| 				</div> |  | ||||||
| 			</div> |  | ||||||
| 		</div> |  | ||||||
|  |  | ||||||
| 		<!-- SSB Section --> | 		<!-- SSB Section --> | ||||||
| 		<div class="w3-light-grey"> | 		<div class="w3-light-grey"> | ||||||
| 			<div class="w3-row-padding w3-padding-64"> | 			<div class="w3-row-padding w3-padding-64"> | ||||||
| @@ -258,7 +199,7 @@ | |||||||
| 			</div> | 			</div> | ||||||
|  |  | ||||||
| 			<div class="w3-row" style="margin-top: 64px"> | 			<div class="w3-row" style="margin-top: 64px"> | ||||||
| 				<a href="https://codemirror.net/docs/changelog/" class="w3-col s3"> | 				<a href="https://codemirror.net/5/" class="w3-col s3"> | ||||||
| 					<i class="fa fa-keyboard w3-text-indigo w3-jumbo"></i> | 					<i class="fa fa-keyboard w3-text-indigo w3-jumbo"></i> | ||||||
| 					<p>CodeMirror</p> | 					<p>CodeMirror</p> | ||||||
| 				</a> | 				</a> | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| { | { | ||||||
| 	"type": "tildefriends-app", | 	"type": "tildefriends-app", | ||||||
| 	"emoji": "📝", | 	"emoji": "📝", | ||||||
| 	"previous": "&DaYqKHRBKhjFGaOzbKZ1+/pLspJeEkDJYTF2B50tH6k=.sha256" | 	"previous": "&DnfuAUGzzalSh9NgZXnzDc9Ru5aM0omfRJ4h27jYw4k=.sha256" | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,9 +4,6 @@ import * as utils from './utils.js'; | |||||||
| let g_hash; | let g_hash; | ||||||
| let g_collection_notifies = {}; | let g_collection_notifies = {}; | ||||||
|  |  | ||||||
| tfrpc.register(async function getActiveIdentity() { |  | ||||||
| 	return ssb.getActiveIdentity(); |  | ||||||
| }); |  | ||||||
| tfrpc.register(async function getOwnerIdentities() { | tfrpc.register(async function getOwnerIdentities() { | ||||||
| 	return ssb.getOwnerIdentities(); | 	return ssb.getOwnerIdentities(); | ||||||
| }); | }); | ||||||
| @@ -57,9 +54,6 @@ core.register('message', async function message_handler(message) { | |||||||
| 		await tfrpc.rpc.hash_changed(message.hash); | 		await tfrpc.rpc.hash_changed(message.hash); | ||||||
| 	} | 	} | ||||||
| }); | }); | ||||||
| core.register('setActiveIdentity', async function setActiveIdentityHandler(id) { |  | ||||||
| 	await tfrpc.rpc.setActiveIdentity(id); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| tfrpc.register(function set_hash(hash) { | tfrpc.register(function set_hash(hash) { | ||||||
| 	if (g_hash != hash) { | 	if (g_hash != hash) { | ||||||
|   | |||||||
| @@ -10,6 +10,7 @@ | |||||||
| 			window.litDisableBundleWarning = true; | 			window.litDisableBundleWarning = true; | ||||||
| 		</script> | 		</script> | ||||||
| 		<script src="tf-collection.js" type="module"></script> | 		<script src="tf-collection.js" type="module"></script> | ||||||
|  | 		<script src="tf-id-picker.js" type="module"></script> | ||||||
| 		<script src="tf-wiki-doc.js" type="module"></script> | 		<script src="tf-wiki-doc.js" type="module"></script> | ||||||
| 		<script src="tf-wiki-app.js" type="module"></script> | 		<script src="tf-wiki-app.js" type="module"></script> | ||||||
| 	</body> | 	</body> | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								apps/wiki/lit-all.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								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
											
										
									
								
							
							
								
								
									
										44
									
								
								apps/wiki/tf-id-picker.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								apps/wiki/tf-id-picker.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | import {LitElement, html} from './lit-all.min.js'; | ||||||
|  | import * as tfrpc from '/static/tfrpc.js'; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  ** Provide a list of IDs, and this lets the user pick one. | ||||||
|  |  */ | ||||||
|  | class TfIdentityPickerElement extends LitElement { | ||||||
|  | 	static get properties() { | ||||||
|  | 		return { | ||||||
|  | 			ids: {type: Array}, | ||||||
|  | 			selected: {type: String}, | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	constructor() { | ||||||
|  | 		super(); | ||||||
|  | 		this.ids = []; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	changed(event) { | ||||||
|  | 		this.selected = event.srcElement.value; | ||||||
|  | 		this.dispatchEvent( | ||||||
|  | 			new Event('change', { | ||||||
|  | 				srcElement: this, | ||||||
|  | 			}) | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	render() { | ||||||
|  | 		return html` | ||||||
|  | 			<link rel="stylesheet" href="tildefriends.css" /> | ||||||
|  | 			<select @change=${this.changed} style="max-width: 100%"> | ||||||
|  | 				${(this.ids ?? []).map( | ||||||
|  | 					(id) => | ||||||
|  | 						html`<option ?selected=${id == this.selected} value=${id}> | ||||||
|  | 							${id} | ||||||
|  | 						</option>` | ||||||
|  | 				)} | ||||||
|  | 			</select> | ||||||
|  | 		`; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | customElements.define('tf-id-picker', TfIdentityPickerElement); | ||||||
| @@ -31,16 +31,13 @@ class TfCollectionsAppElement extends LitElement { | |||||||
| 		tfrpc.register(function hash_changed(hash) { | 		tfrpc.register(function hash_changed(hash) { | ||||||
| 			self.notify_hash_changed(hash); | 			self.notify_hash_changed(hash); | ||||||
| 		}); | 		}); | ||||||
| 		tfrpc.register(function setActiveIdentity(id) { |  | ||||||
| 			self.whoami = id; |  | ||||||
| 		}); |  | ||||||
| 		tfrpc.rpc.get_hash().then((hash) => self.notify_hash_changed(hash)); | 		tfrpc.rpc.get_hash().then((hash) => self.notify_hash_changed(hash)); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	async load() { | 	async load() { | ||||||
| 		this.ids = await tfrpc.rpc.getIdentities(); | 		this.ids = await tfrpc.rpc.getIdentities(); | ||||||
| 		this.owner_ids = await tfrpc.rpc.getOwnerIdentities(); | 		this.owner_ids = await tfrpc.rpc.getOwnerIdentities(); | ||||||
| 		this.whoami = await tfrpc.rpc.getActiveIdentity(); | 		this.whoami = await tfrpc.rpc.localStorageGet('collections_whoami'); | ||||||
| 		let ids = [...new Set([...this.owner_ids, this.whoami])].sort(); | 		let ids = [...new Set([...this.owner_ids, this.whoami])].sort(); | ||||||
| 		this.following = Object.keys(await tfrpc.rpc.following(ids, 1)).sort(); | 		this.following = Object.keys(await tfrpc.rpc.following(ids, 1)).sort(); | ||||||
|  |  | ||||||
| @@ -276,6 +273,9 @@ class TfCollectionsAppElement extends LitElement { | |||||||
| 					margin-right: 16px; | 					margin-right: 16px; | ||||||
| 				} | 				} | ||||||
| 			</style> | 			</style> | ||||||
|  | 			<div> | ||||||
|  | 				<tf-id-picker .ids=${this.ids} selected=${this.whoami} @change=${this.on_whoami_changed} ?hidden=${!this.ids?.length}></tf-id-picker> | ||||||
|  | 			</div> | ||||||
| 			<div> | 			<div> | ||||||
| 				${keyed( | 				${keyed( | ||||||
| 					this.whoami, | 					this.whoami, | ||||||
|   | |||||||
| @@ -96,7 +96,7 @@ export async function collection( | |||||||
| 		let rows = []; | 		let rows = []; | ||||||
| 		await ssb.sqlAsync( | 		await ssb.sqlAsync( | ||||||
| 			` | 			` | ||||||
| 				SELECT messages.id, author, json(content) AS content, timestamp | 				SELECT messages.id, author, content, timestamp | ||||||
| 				FROM messages | 				FROM messages | ||||||
| 				JOIN json_each(?1) AS id ON messages.author = id.value | 				JOIN json_each(?1) AS id ON messages.author = id.value | ||||||
| 				WHERE | 				WHERE | ||||||
|   | |||||||
							
								
								
									
										
											BIN
										
									
								
								bleh.tar.xz
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								bleh.tar.xz
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										30
									
								
								core/app.js
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								core/app.js
									
									
									
									
									
								
							| @@ -1,3 +1,4 @@ | |||||||
|  | import * as auth from './auth.js'; | ||||||
| import * as core from './core.js'; | import * as core from './core.js'; | ||||||
|  |  | ||||||
| let g_next_id = 1; | let g_next_id = 1; | ||||||
| @@ -86,7 +87,8 @@ App.prototype.send = function (message) { | |||||||
| function socket(request, response, client) { | function socket(request, response, client) { | ||||||
| 	let process; | 	let process; | ||||||
| 	let options = {}; | 	let options = {}; | ||||||
| 	let credentials = httpd.auth_query(request.headers); | 	let credentials = auth.query(request.headers); | ||||||
|  | 	let refresh = auth.makeRefresh(credentials); | ||||||
|  |  | ||||||
| 	response.onClose = async function () { | 	response.onClose = async function () { | ||||||
| 		if (process && process.task) { | 		if (process && process.task) { | ||||||
| @@ -141,21 +143,12 @@ function socket(request, response, client) { | |||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 				response.send( | 				response.send( | ||||||
| 					JSON.stringify( | 					JSON.stringify({ | ||||||
| 						Object.assign( |  | ||||||
| 							{ |  | ||||||
| 						action: 'session', | 						action: 'session', | ||||||
| 						credentials: credentials, | 						credentials: credentials, | ||||||
| 						parentApp: parentApp, | 						parentApp: parentApp, | ||||||
| 						id: blobId, | 						id: blobId, | ||||||
| 							}, | 					}), | ||||||
| 							await ssb.getIdentityInfo( |  | ||||||
| 								credentials?.session?.name, |  | ||||||
| 								packageOwner, |  | ||||||
| 								packageName |  | ||||||
| 							) |  | ||||||
| 						) |  | ||||||
| 					), |  | ||||||
| 					0x1 | 					0x1 | ||||||
| 				); | 				); | ||||||
|  |  | ||||||
| @@ -219,10 +212,6 @@ function socket(request, response, client) { | |||||||
| 				if (process) { | 				if (process) { | ||||||
| 					process.resetPermission(message.permission); | 					process.resetPermission(message.permission); | ||||||
| 				} | 				} | ||||||
| 			} else if (message.action == 'setActiveIdentity') { |  | ||||||
| 				process.setActiveIdentity(message.identity); |  | ||||||
| 			} else if (message.action == 'createIdentity') { |  | ||||||
| 				process.createIdentity(); |  | ||||||
| 			} else if (message.message == 'tfrpc') { | 			} else if (message.message == 'tfrpc') { | ||||||
| 				if (message.id && g_calls[message.id]) { | 				if (message.id && g_calls[message.id]) { | ||||||
| 					if (message.error !== undefined) { | 					if (message.error !== undefined) { | ||||||
| @@ -252,7 +241,14 @@ function socket(request, response, client) { | |||||||
| 		} | 		} | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	response.upgrade(100, {}); | 	response.upgrade( | ||||||
|  | 		100, | ||||||
|  | 		refresh | ||||||
|  | 			? { | ||||||
|  | 					'Set-Cookie': `session=${refresh.token}; path=/; Max-Age=${refresh.interval}; Secure; SameSite=Strict`, | ||||||
|  | 				} | ||||||
|  | 			: {} | ||||||
|  | 	); | ||||||
| } | } | ||||||
|  |  | ||||||
| export {socket, App}; | export {socket, App}; | ||||||
|   | |||||||
| @@ -19,11 +19,8 @@ | |||||||
| 			Object.assign(app, g_data); | 			Object.assign(app, g_data); | ||||||
|  |  | ||||||
| 			class TfAuthElement extends LitElement { | 			class TfAuthElement extends LitElement { | ||||||
| 				static get properties() { | 				static get_properties() { | ||||||
| 					return { | 					return { | ||||||
| 						code_of_conduct: {type: String}, |  | ||||||
| 						error: {type: String}, |  | ||||||
| 						have_administrator: {type: Boolean}, |  | ||||||
| 						name: {type: String}, | 						name: {type: String}, | ||||||
| 						tab: {type: String}, | 						tab: {type: String}, | ||||||
| 					}; | 					}; | ||||||
| @@ -34,6 +31,11 @@ | |||||||
| 					this.tab = 'login'; | 					this.tab = 'login'; | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
|  | 				tab_changed(name) { | ||||||
|  | 					this.tab = name; | ||||||
|  | 					this.requestUpdate(); | ||||||
|  | 				} | ||||||
|  |  | ||||||
| 				render() { | 				render() { | ||||||
| 					let self = this; | 					let self = this; | ||||||
| 					return html` | 					return html` | ||||||
| @@ -81,16 +83,16 @@ | |||||||
| 							<h1 ?hidden=${this.name === undefined}>Welcome, ${this.name}.</h1> | 							<h1 ?hidden=${this.name === undefined}>Welcome, ${this.name}.</h1> | ||||||
|  |  | ||||||
| 							<div style="display: flex; flex-direction: row; width: 100%"> | 							<div style="display: flex; flex-direction: row; width: 100%"> | ||||||
| 								<input type="radio" name="tab" id="login" value="Login" ?checked=${this.tab == 'login'} @change=${() => (self.tab = 'login')}></input> | 								<input type="radio" name="tab" id="login" value="Login" ?checked=${this.tab == 'login'} @change=${() => self.tab_changed('login')}></input> | ||||||
| 								<label for="login" id="login_label">Login</label> | 								<label for="login" id="login_label">Login</label> | ||||||
|  |  | ||||||
| 								<input type="radio" name="tab" id="register" value="Register" ?checked=${this.tab == 'register'} @change=${() => (self.tab = 'register')}></input> | 								<input type="radio" name="tab" id="register" value="Register" ?checked=${this.tab == 'register'} @change=${() => self.tab_changed('register')}></input> | ||||||
| 								<label for="register" id="register_label">Register</label> | 								<label for="register" id="register_label">Register</label> | ||||||
|  |  | ||||||
| 								<input type="radio" name="tab" id="guest" value="Guest" ?checked=${this.tab == 'guest'} @change=${() => (self.tab = 'guest')}></input> | 								<input type="radio" name="tab" id="guest" value="Guest" ?checked=${this.tab == 'guest'} @change=${() => self.tab_changed('guest')}></input> | ||||||
| 								<label for="guest" id="guest_label">Guest</label> | 								<label for="guest" id="guest_label">Guest</label> | ||||||
|  |  | ||||||
| 								<input type="radio" name="tab" id="change" value="Change Password" ?checked=${this.tab == 'change'} @change=${() => (self.tab = 'change')}></input> | 								<input type="radio" name="tab" id="change" value="Change Password" ?checked=${this.tab == 'change'} @change=${() => self.tab_changed('change')}></input> | ||||||
| 								<label for="change" id="change_label">Change Password</label> | 								<label for="change" id="change_label">Change Password</label> | ||||||
| 							</div> | 							</div> | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										420
									
								
								core/auth.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										420
									
								
								core/auth.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,420 @@ | |||||||
|  | import * as core from './core.js'; | ||||||
|  | import * as form from './form.js'; | ||||||
|  |  | ||||||
|  | let gDatabase = new Database('auth'); | ||||||
|  |  | ||||||
|  | const kRefreshInterval = 1 * 7 * 24 * 60 * 60 * 1000; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Makes a Base64 value URL safe | ||||||
|  |  * @param {string} value | ||||||
|  |  * @returns TODOC | ||||||
|  |  */ | ||||||
|  | function b64url(value) { | ||||||
|  | 	value = value.replaceAll('+', '-').replaceAll('/', '_'); | ||||||
|  | 	let equals = value.indexOf('='); | ||||||
|  |  | ||||||
|  | 	if (equals !== -1) { | ||||||
|  | 		return value.substring(0, equals); | ||||||
|  | 	} else { | ||||||
|  | 		return value; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * TODOC | ||||||
|  |  * @param {string} value | ||||||
|  |  * @returns | ||||||
|  |  */ | ||||||
|  | function unb64url(value) { | ||||||
|  | 	value = value.replaceAll('-', '+').replaceAll('_', '/'); | ||||||
|  | 	let remainder = value.length % 4; | ||||||
|  |  | ||||||
|  | 	if (remainder == 3) { | ||||||
|  | 		return value + '='; | ||||||
|  | 	} else if (remainder == 2) { | ||||||
|  | 		return value + '=='; | ||||||
|  | 	} else { | ||||||
|  | 		return value; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Creates a JSON Web Token | ||||||
|  |  * @param {object} payload Object: {"name": "username"} | ||||||
|  |  * @returns the JWT | ||||||
|  |  */ | ||||||
|  | function makeJwt(payload) { | ||||||
|  | 	const ids = ssb.getIdentities(':auth'); | ||||||
|  | 	let id; | ||||||
|  |  | ||||||
|  | 	if (ids?.length) { | ||||||
|  | 		id = ids[0]; | ||||||
|  | 	} else { | ||||||
|  | 		id = ssb.createIdentity(':auth'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	const final_payload = b64url( | ||||||
|  | 		base64Encode( | ||||||
|  | 			JSON.stringify( | ||||||
|  | 				Object.assign({}, payload, { | ||||||
|  | 					exp: new Date().valueOf() + kRefreshInterval, | ||||||
|  | 				}) | ||||||
|  | 			) | ||||||
|  | 		) | ||||||
|  | 	); | ||||||
|  | 	const jwt = [ | ||||||
|  | 		b64url(base64Encode(JSON.stringify({alg: 'HS256', typ: 'JWT'}))), | ||||||
|  | 		final_payload, | ||||||
|  | 		b64url(ssb.hmacsha256sign(final_payload, ':auth', id)), | ||||||
|  | 	].join('.'); | ||||||
|  | 	return jwt; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Validates a JWT ? | ||||||
|  |  * @param {*} session TODOC | ||||||
|  |  * @returns | ||||||
|  |  */ | ||||||
|  | function readSession(session) { | ||||||
|  | 	let jwt_parts = session?.split('.'); | ||||||
|  |  | ||||||
|  | 	if (jwt_parts?.length === 3) { | ||||||
|  | 		let [header, payload, signature] = jwt_parts; | ||||||
|  | 		header = JSON.parse(utf8Decode(base64Decode(unb64url(header)))); | ||||||
|  |  | ||||||
|  | 		if (header.typ === 'JWT' && header.alg === 'HS256') { | ||||||
|  | 			signature = unb64url(signature); | ||||||
|  | 			let id = ssb.getIdentities(':auth'); | ||||||
|  |  | ||||||
|  | 			if (id?.length && ssb.hmacsha256verify(id[0], payload, signature)) { | ||||||
|  | 				const result = JSON.parse(utf8Decode(base64Decode(unb64url(payload)))); | ||||||
|  | 				const now = new Date().valueOf(); | ||||||
|  |  | ||||||
|  | 				if (now < result.exp) { | ||||||
|  | 					print(`JWT valid for another ${(result.exp - now) / 1000} seconds.`); | ||||||
|  | 					return result; | ||||||
|  | 				} else { | ||||||
|  | 					print(`JWT expired by ${(now - result.exp) / 1000} seconds.`); | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				print('JWT verification failed.'); | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			print('Invalid JWT header.'); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Check the provided password matches the hash | ||||||
|  |  * @param {string} password | ||||||
|  |  * @param {string} hash bcrypt hash | ||||||
|  |  * @returns true if the password matches the hash | ||||||
|  |  */ | ||||||
|  | function verifyPassword(password, hash) { | ||||||
|  | 	return bCrypt.hashpw(password, hash) === hash; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Hashes a password | ||||||
|  |  * @param {string} password | ||||||
|  |  * @returns {string} TODOC | ||||||
|  |  */ | ||||||
|  | function hashPassword(password) { | ||||||
|  | 	let salt = bCrypt.gensalt(12); | ||||||
|  | 	return bCrypt.hashpw(password, salt); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Check if there is an administrator on the instance | ||||||
|  |  * @returns TODOC | ||||||
|  |  */ | ||||||
|  | function noAdministrator() { | ||||||
|  | 	return ( | ||||||
|  | 		!core.globalSettings || | ||||||
|  | 		!core.globalSettings.permissions || | ||||||
|  | 		!Object.keys(core.globalSettings.permissions).some(function (name) { | ||||||
|  | 			return ( | ||||||
|  | 				core.globalSettings.permissions[name].indexOf('administration') != -1 | ||||||
|  | 			); | ||||||
|  | 		}) | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Makes a user an administrator | ||||||
|  |  * @param {string} name the user's name | ||||||
|  |  */ | ||||||
|  | function makeAdministrator(name) { | ||||||
|  | 	if (!core.globalSettings.permissions) { | ||||||
|  | 		core.globalSettings.permissions = {}; | ||||||
|  | 	} | ||||||
|  | 	if (!core.globalSettings.permissions[name]) { | ||||||
|  | 		core.globalSettings.permissions[name] = []; | ||||||
|  | 	} | ||||||
|  | 	if (core.globalSettings.permissions[name].indexOf('administration') == -1) { | ||||||
|  | 		core.globalSettings.permissions[name].push('administration'); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	core.setGlobalSettings(core.globalSettings); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * TODOC | ||||||
|  |  * @param {*} headers most likely an object | ||||||
|  |  * @returns | ||||||
|  |  */ | ||||||
|  | function getCookies(headers) { | ||||||
|  | 	let cookies = {}; | ||||||
|  |  | ||||||
|  | 	if (headers.cookie) { | ||||||
|  | 		let parts = headers.cookie.split(/,|;/); | ||||||
|  | 		for (let i in parts) { | ||||||
|  | 			let equals = parts[i].indexOf('='); | ||||||
|  | 			let name = parts[i].substring(0, equals).trim(); | ||||||
|  | 			let value = parts[i].substring(equals + 1).trim(); | ||||||
|  | 			cookies[name] = value; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return cookies; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Validates a username | ||||||
|  |  * @param {string} name | ||||||
|  |  * @returns false | boolean[] ? | ||||||
|  |  */ | ||||||
|  | function isNameValid(name) { | ||||||
|  | 	// TODO(tasiaiso): convert this into a regex | ||||||
|  | 	let c = name.charAt(0); | ||||||
|  | 	return ( | ||||||
|  | 		((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) && | ||||||
|  | 		name | ||||||
|  | 			.split() | ||||||
|  | 			.map( | ||||||
|  | 				(x) => | ||||||
|  | 					x >= ('a' && x <= 'z') || | ||||||
|  | 					x >= ('A' && x <= 'Z') || | ||||||
|  | 					x >= ('0' && x <= '9') | ||||||
|  | 			) | ||||||
|  | 	); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Request handler ? | ||||||
|  |  * @param {*} request TODOC | ||||||
|  |  * @param {*} response | ||||||
|  |  * @returns | ||||||
|  |  */ | ||||||
|  | function handler(request, response) { | ||||||
|  | 	// TODO(tasiaiso): split this function | ||||||
|  | 	let session = getCookies(request.headers).session; | ||||||
|  | 	if (request.uri == '/login') { | ||||||
|  | 		let formData = form.decodeForm(request.query); | ||||||
|  | 		if (query(request.headers)?.permissions?.authenticated) { | ||||||
|  | 			if (formData.return) { | ||||||
|  | 				response.writeHead(303, {Location: formData.return}); | ||||||
|  | 			} else { | ||||||
|  | 				response.writeHead(303, { | ||||||
|  | 					Location: | ||||||
|  | 						(request.client.tls ? 'https://' : 'http://') + | ||||||
|  | 						request.headers.host + | ||||||
|  | 						'/', | ||||||
|  | 					'Content-Length': '0', | ||||||
|  | 				}); | ||||||
|  | 			} | ||||||
|  | 			response.end(); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		let sessionIsNew = false; | ||||||
|  | 		let loginError; | ||||||
|  |  | ||||||
|  | 		if (request.method == 'POST' || formData.submit) { | ||||||
|  | 			sessionIsNew = true; | ||||||
|  | 			formData = form.decodeForm(utf8Decode(request.body), formData); | ||||||
|  | 			if (formData.submit == 'Login') { | ||||||
|  | 				let account = gDatabase.get('user:' + formData.name); | ||||||
|  | 				account = account ? JSON.parse(account) : account; | ||||||
|  | 				if (formData.register == '1') { | ||||||
|  | 					if ( | ||||||
|  | 						!account && | ||||||
|  | 						isNameValid(formData.name) && | ||||||
|  | 						formData.password == formData.confirm | ||||||
|  | 					) { | ||||||
|  | 						let users = new Set(); | ||||||
|  | 						let users_original = gDatabase.get('users'); | ||||||
|  | 						try { | ||||||
|  | 							users = new Set(JSON.parse(users_original)); | ||||||
|  | 						} catch {} | ||||||
|  | 						if (!users.has(formData.name)) { | ||||||
|  | 							users.add(formData.name); | ||||||
|  | 						} | ||||||
|  | 						users = JSON.stringify([...users].sort()); | ||||||
|  | 						if (users !== users_original) { | ||||||
|  | 							gDatabase.set('users', users); | ||||||
|  | 						} | ||||||
|  | 						session = makeJwt({name: formData.name}); | ||||||
|  | 						account = {password: hashPassword(formData.password)}; | ||||||
|  | 						gDatabase.set('user:' + formData.name, JSON.stringify(account)); | ||||||
|  | 						if (noAdministrator()) { | ||||||
|  | 							makeAdministrator(formData.name); | ||||||
|  | 						} | ||||||
|  | 					} else { | ||||||
|  | 						loginError = 'Error registering account.'; | ||||||
|  | 					} | ||||||
|  | 				} else if (formData.change == '1') { | ||||||
|  | 					if ( | ||||||
|  | 						account && | ||||||
|  | 						isNameValid(formData.name) && | ||||||
|  | 						formData.new_password == formData.confirm && | ||||||
|  | 						verifyPassword(formData.password, account.password) | ||||||
|  | 					) { | ||||||
|  | 						session = makeJwt({name: formData.name}); | ||||||
|  | 						account = {password: hashPassword(formData.new_password)}; | ||||||
|  | 						gDatabase.set('user:' + formData.name, JSON.stringify(account)); | ||||||
|  | 					} else { | ||||||
|  | 						loginError = 'Error changing password.'; | ||||||
|  | 					} | ||||||
|  | 				} else { | ||||||
|  | 					if ( | ||||||
|  | 						account && | ||||||
|  | 						account.password && | ||||||
|  | 						verifyPassword(formData.password, account.password) | ||||||
|  | 					) { | ||||||
|  | 						session = makeJwt({name: formData.name}); | ||||||
|  | 						if (noAdministrator()) { | ||||||
|  | 							makeAdministrator(formData.name); | ||||||
|  | 						} | ||||||
|  | 					} else { | ||||||
|  | 						loginError = 'Invalid username or password.'; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				// Proceed as Guest | ||||||
|  | 				session = makeJwt({name: 'guest'}); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		let cookie = `session=${session}; path=/; Max-Age=${kRefreshInterval}; ${request.client.tls ? 'Secure; ' : ''}SameSite=Strict; HttpOnly`; | ||||||
|  | 		let entry = readSession(session); | ||||||
|  | 		if (entry && formData.return) { | ||||||
|  | 			response.writeHead(303, { | ||||||
|  | 				Location: formData.return, | ||||||
|  | 				'Set-Cookie': cookie, | ||||||
|  | 			}); | ||||||
|  | 			response.end(); | ||||||
|  | 		} else { | ||||||
|  | 			File.readFile('core/auth.html') | ||||||
|  | 				.then(function (data) { | ||||||
|  | 					let html = utf8Decode(data); | ||||||
|  | 					let auth_data = { | ||||||
|  | 						session_is_new: sessionIsNew, | ||||||
|  | 						name: entry?.name, | ||||||
|  | 						error: loginError, | ||||||
|  | 						code_of_conduct: core.globalSettings.code_of_conduct, | ||||||
|  | 						have_administrator: !noAdministrator(), | ||||||
|  | 					}; | ||||||
|  | 					html = utf8Encode( | ||||||
|  | 						html.replace('$AUTH_DATA', JSON.stringify(auth_data)) | ||||||
|  | 					); | ||||||
|  | 					response.writeHead(200, { | ||||||
|  | 						'Content-Type': 'text/html; charset=utf-8', | ||||||
|  | 						'Set-Cookie': cookie, | ||||||
|  | 						'Content-Length': html.length, | ||||||
|  | 					}); | ||||||
|  | 					response.end(html); | ||||||
|  | 				}) | ||||||
|  | 				.catch(function (error) { | ||||||
|  | 					response.writeHead(404, { | ||||||
|  | 						'Content-Type': 'text/plain; charset=utf-8', | ||||||
|  | 						Connection: 'close', | ||||||
|  | 					}); | ||||||
|  | 					response.end('404 File not found'); | ||||||
|  | 				}); | ||||||
|  | 		} | ||||||
|  | 	} else if (request.uri == '/login/logout') { | ||||||
|  | 		response.writeHead(303, { | ||||||
|  | 			'Set-Cookie': `session=; path=/; ${request.client.tls ? 'Secure; ' : ''}SameSite=Strict; expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly`, | ||||||
|  | 			Location: '/login' + (request.query ? '?' + request.query : ''), | ||||||
|  | 		}); | ||||||
|  | 		response.end(); | ||||||
|  | 	} else { | ||||||
|  | 		response.writeHead(200, { | ||||||
|  | 			'Content-Type': 'text/plain; charset=utf-8', | ||||||
|  | 			Connection: 'close', | ||||||
|  | 		}); | ||||||
|  | 		response.end('Hello, ' + request.client.peerName + '.'); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Gets a user's permissions based on it's session ? | ||||||
|  |  * @param {*} session TODOC | ||||||
|  |  * @returns | ||||||
|  |  */ | ||||||
|  | function getPermissions(session) { | ||||||
|  | 	let permissions; | ||||||
|  | 	let entry = readSession(session); | ||||||
|  | 	if (entry) { | ||||||
|  | 		permissions = getPermissionsForUser(entry.name); | ||||||
|  | 		permissions.authenticated = entry.name !== 'guest'; | ||||||
|  | 	} | ||||||
|  | 	return permissions || {}; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Get a user's permissions ? | ||||||
|  |  * @param {string} userName TODOC | ||||||
|  |  * @returns | ||||||
|  |  */ | ||||||
|  | function getPermissionsForUser(userName) { | ||||||
|  | 	let permissions = {}; | ||||||
|  | 	if ( | ||||||
|  | 		core.globalSettings && | ||||||
|  | 		core.globalSettings.permissions && | ||||||
|  | 		core.globalSettings.permissions[userName] | ||||||
|  | 	) { | ||||||
|  | 		for (let i in core.globalSettings.permissions[userName]) { | ||||||
|  | 			permissions[core.globalSettings.permissions[userName][i]] = true; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return permissions; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * TODOC | ||||||
|  |  * @param {*} headers | ||||||
|  |  * @returns | ||||||
|  |  */ | ||||||
|  | function query(headers) { | ||||||
|  | 	let session = getCookies(headers).session; | ||||||
|  | 	let entry; | ||||||
|  | 	let autologin = tildefriends.args.autologin; | ||||||
|  | 	if ((entry = autologin ? {name: autologin} : readSession(session))) { | ||||||
|  | 		return { | ||||||
|  | 			session: entry, | ||||||
|  | 			permissions: autologin | ||||||
|  | 				? getPermissionsForUser(autologin) | ||||||
|  | 				: getPermissions(session), | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Refreshes a JWT ? | ||||||
|  |  * @param {*} credentials TODOC | ||||||
|  |  * @returns | ||||||
|  |  */ | ||||||
|  | function makeRefresh(credentials) { | ||||||
|  | 	if (credentials?.session?.name) { | ||||||
|  | 		return { | ||||||
|  | 			token: makeJwt({name: credentials.session.name}), | ||||||
|  | 			interval: kRefreshInterval, | ||||||
|  | 		}; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export {handler, query, makeRefresh}; | ||||||
							
								
								
									
										201
									
								
								core/client.js
									
									
									
									
									
								
							
							
						
						
									
										201
									
								
								core/client.js
									
									
									
									
									
								
							| @@ -56,9 +56,6 @@ class TfNavigationElement extends LitElement { | |||||||
| 			spark_lines: {type: Object}, | 			spark_lines: {type: Object}, | ||||||
| 			version: {type: Object}, | 			version: {type: Object}, | ||||||
| 			show_version: {type: Boolean}, | 			show_version: {type: Boolean}, | ||||||
| 			identity: {type: String}, |  | ||||||
| 			identities: {type: Array}, |  | ||||||
| 			names: {type: Object}, |  | ||||||
| 		}; | 		}; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -68,8 +65,6 @@ class TfNavigationElement extends LitElement { | |||||||
| 		this.show_permissions = false; | 		this.show_permissions = false; | ||||||
| 		this.status = {}; | 		this.status = {}; | ||||||
| 		this.spark_lines = {}; | 		this.spark_lines = {}; | ||||||
| 		this.identities = []; |  | ||||||
| 		this.names = {}; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| @@ -102,10 +97,10 @@ class TfNavigationElement extends LitElement { | |||||||
| 	get_spark_line(key, options) { | 	get_spark_line(key, options) { | ||||||
| 		if (!this.spark_lines[key]) { | 		if (!this.spark_lines[key]) { | ||||||
| 			let spark_line = document.createElement('tf-sparkline'); | 			let spark_line = document.createElement('tf-sparkline'); | ||||||
|  | 			spark_line.style.display = 'flex'; | ||||||
|  | 			spark_line.style.flexDirection = 'row'; | ||||||
|  | 			spark_line.style.flex = '0 50 5em'; | ||||||
| 			spark_line.title = key; | 			spark_line.title = key; | ||||||
| 			spark_line.classList.add('w3-bar-item'); |  | ||||||
| 			spark_line.classList.add('w3-hide-small'); |  | ||||||
| 			spark_line.style.paddingRight = '0'; |  | ||||||
| 			if (options) { | 			if (options) { | ||||||
| 				if (options.max) { | 				if (options.max) { | ||||||
| 					spark_line.max = options.max; | 					spark_line.max = options.max; | ||||||
| @@ -123,105 +118,16 @@ class TfNavigationElement extends LitElement { | |||||||
| 	 */ | 	 */ | ||||||
| 	render_login() { | 	render_login() { | ||||||
| 		if (this?.credentials?.session?.name) { | 		if (this?.credentials?.session?.name) { | ||||||
| 			return html`<a | 			return html`<a id="login" href="/login/logout?return=${url() + hash()}" | ||||||
| 				class="w3-bar-item w3-right" |  | ||||||
| 				id="login" |  | ||||||
| 				href="/login/logout?return=${url() + hash()}" |  | ||||||
| 				>logout ${this.credentials.session.name}</a | 				>logout ${this.credentials.session.name}</a | ||||||
| 			>`; | 			>`; | ||||||
| 		} else { | 		} else { | ||||||
| 			return html`<a | 			return html`<a id="login" href="/login?return=${url() + hash()}" | ||||||
| 				class="w3-bar-item w3-right" |  | ||||||
| 				id="login" |  | ||||||
| 				href="/login?return=${url() + hash()}" |  | ||||||
| 				>login</a | 				>login</a | ||||||
| 			>`; | 			>`; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	set_active_identity(id) { |  | ||||||
| 		send({action: 'setActiveIdentity', identity: id}); |  | ||||||
| 		this.renderRoot.getElementById('id_dropdown').classList.remove('w3-show'); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	create_identity(event) { |  | ||||||
| 		if (confirm('Are you sure you want to create a new identity?')) { |  | ||||||
| 			send({action: 'createIdentity'}); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	toggle_id_dropdown() { |  | ||||||
| 		this.renderRoot.getElementById('id_dropdown').classList.toggle('w3-show'); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	edit_profile() { |  | ||||||
| 		window.location.href = '/~core/ssb/#' + this.identity; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	render_identity() { |  | ||||||
| 		let self = this; |  | ||||||
| 		if (this.identities?.length) { |  | ||||||
| 			return html` |  | ||||||
| 				<link type="text/css" rel="stylesheet" href="/static/w3.css" /> |  | ||||||
| 				<div class="w3-dropdown-click w3-right" style="max-width: 100%"> |  | ||||||
| 					<button |  | ||||||
| 						class="w3-button w3-rest w3-cyan" |  | ||||||
| 						style="text-overflow: ellipsis; overflow: hidden; white-space: nowrap; max-width: 100%" |  | ||||||
| 						@click=${self.toggle_id_dropdown} |  | ||||||
| 					> |  | ||||||
| 						${self.names[this.identity]}${self.names[this.identity] === |  | ||||||
| 						this.identity |  | ||||||
| 							? '' |  | ||||||
| 							: html` - ${this.identity}`} |  | ||||||
| 						▾ |  | ||||||
| 					</button> |  | ||||||
| 					<div |  | ||||||
| 						id="id_dropdown" |  | ||||||
| 						class="w3-dropdown-content w3-bar-block w3-card-4" |  | ||||||
| 						style="max-width: 100%" |  | ||||||
| 					> |  | ||||||
| 						<button |  | ||||||
| 							class="w3-bar-item w3-button w3-border" |  | ||||||
| 							@click=${() => (window.location.href = '/~core/identity')} |  | ||||||
| 						> |  | ||||||
| 							Manage Identities... |  | ||||||
| 						</button> |  | ||||||
| 						<button |  | ||||||
| 							class="w3-bar-item w3-button w3-border" |  | ||||||
| 							@click=${self.edit_profile} |  | ||||||
| 						> |  | ||||||
| 							Edit Profile... |  | ||||||
| 						</button> |  | ||||||
| 						${this.identities.map( |  | ||||||
| 							(x) => html` |  | ||||||
| 								<button |  | ||||||
| 									class="w3-bar-item w3-button ${x === self.identity |  | ||||||
| 										? 'w3-cyan' |  | ||||||
| 										: ''}" |  | ||||||
| 									@click=${() => self.set_active_identity(x)} |  | ||||||
| 									style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap" |  | ||||||
| 								> |  | ||||||
| 									${self.names[x]}${self.names[x] === x ? '' : html` - ${x}`} |  | ||||||
| 								</button> |  | ||||||
| 							` |  | ||||||
| 						)} |  | ||||||
| 					</div> |  | ||||||
| 				</div> |  | ||||||
| 			`; |  | ||||||
| 		} else { |  | ||||||
| 			return html` |  | ||||||
| 				<link type="text/css" rel="stylesheet" href="/static/w3.css" /> |  | ||||||
| 				<button |  | ||||||
| 					id="create_identity" |  | ||||||
| 					@click=${this.create_identity} |  | ||||||
| 					class="w3-button w3-mobile w3-blue w3-right" |  | ||||||
| 				> |  | ||||||
| 					Create an Identity |  | ||||||
| 				</button> |  | ||||||
| 			`; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * TODOC | 	 * TODOC | ||||||
| 	 * @returns | 	 * @returns | ||||||
| @@ -240,14 +146,8 @@ class TfNavigationElement extends LitElement { | |||||||
| 						${Object.keys(this.permissions).map( | 						${Object.keys(this.permissions).map( | ||||||
| 							(key) => html` | 							(key) => html` | ||||||
| 							<div> | 							<div> | ||||||
| 									<span>${key}</span>: | 								<span>${key}</span>: ${this.permissions[key] ? '✅ Allowed' : '❌ Denied'} | ||||||
| 									${this.permissions[key] ? '✅ Allowed' : '❌ Denied'} | 								<button @click=${() => this.reset_permission(key)} class='w3-button w3-red">Reset</button> | ||||||
| 									<button |  | ||||||
| 										@click=${() => this.reset_permission(key)} |  | ||||||
| 										class="w3-button w3-red" |  | ||||||
| 									> |  | ||||||
| 										Reset |  | ||||||
| 									</button> |  | ||||||
| 							</div> | 							</div> | ||||||
| 						` | 						` | ||||||
| 						)} | 						)} | ||||||
| @@ -263,10 +163,6 @@ class TfNavigationElement extends LitElement { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	clear_error() { |  | ||||||
| 		this.status = {}; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * TODOC | 	 * TODOC | ||||||
| 	 * @returns | 	 * @returns | ||||||
| @@ -274,7 +170,6 @@ class TfNavigationElement extends LitElement { | |||||||
| 	render() { | 	render() { | ||||||
| 		let self = this; | 		let self = this; | ||||||
| 		return html` | 		return html` | ||||||
| 			<link type="text/css" rel="stylesheet" href="/static/w3.css" /> |  | ||||||
| 			<style> | 			<style> | ||||||
| 				${k_global_style} .tooltip { | 				${k_global_style} .tooltip { | ||||||
| 					position: absolute; | 					position: absolute; | ||||||
| @@ -290,17 +185,17 @@ class TfNavigationElement extends LitElement { | |||||||
| 					display: inline-block; | 					display: inline-block; | ||||||
| 				} | 				} | ||||||
| 			</style> | 			</style> | ||||||
| 			<div class="w3-black w3-bar"> | 			<div | ||||||
|  | 				style="margin: 4px; display: flex; flex-direction: row; flex-wrap: nowrap; gap: 3px; align-items: center" | ||||||
|  | 			> | ||||||
| 				<span | 				<span | ||||||
| 					class="w3-bar-item" |  | ||||||
| 					style="cursor: pointer" | 					style="cursor: pointer" | ||||||
| 					@click=${() => (this.show_version = !this.show_version)} | 					@click=${() => (this.show_version = !this.show_version)} | ||||||
| 					>😎</span | 					>😎</span | ||||||
| 				> | 				> | ||||||
| 				<span | 				<span | ||||||
| 					class="w3-bar-item" | 					?hidden=${!this.show_version} | ||||||
| 					style=${'white-space: nowrap' + | 					style="flex: 0 0; white-space: nowrap" | ||||||
| 					(this.show_version ? '' : '; display: none')} |  | ||||||
| 					title=${this.version?.name + | 					title=${this.version?.name + | ||||||
| 					' ' + | 					' ' + | ||||||
| 					Object.entries(this.version || {}) | 					Object.entries(this.version || {}) | ||||||
| @@ -309,7 +204,6 @@ class TfNavigationElement extends LitElement { | |||||||
| 					>${this.version?.number}</span | 					>${this.version?.number}</span | ||||||
| 				> | 				> | ||||||
| 				<a | 				<a | ||||||
| 					class="w3-bar-item" |  | ||||||
| 					accesskey="h" | 					accesskey="h" | ||||||
| 					@mouseover=${set_access_key_title} | 					@mouseover=${set_access_key_title} | ||||||
| 					data-tip="Open home app." | 					data-tip="Open home app." | ||||||
| @@ -318,7 +212,6 @@ class TfNavigationElement extends LitElement { | |||||||
| 					>TF</a | 					>TF</a | ||||||
| 				> | 				> | ||||||
| 				<a | 				<a | ||||||
| 					class="w3-bar-item" |  | ||||||
| 					accesskey="a" | 					accesskey="a" | ||||||
| 					@mouseover=${set_access_key_title} | 					@mouseover=${set_access_key_title} | ||||||
| 					data-tip="Open apps list." | 					data-tip="Open apps list." | ||||||
| @@ -326,7 +219,6 @@ class TfNavigationElement extends LitElement { | |||||||
| 					>apps</a | 					>apps</a | ||||||
| 				> | 				> | ||||||
| 				<a | 				<a | ||||||
| 					class="w3-bar-item" |  | ||||||
| 					accesskey="e" | 					accesskey="e" | ||||||
| 					@mouseover=${set_access_key_title} | 					@mouseover=${set_access_key_title} | ||||||
| 					data-tip="Toggle the app editor." | 					data-tip="Toggle the app editor." | ||||||
| @@ -335,7 +227,6 @@ class TfNavigationElement extends LitElement { | |||||||
| 					>edit</a | 					>edit</a | ||||||
| 				> | 				> | ||||||
| 				<a | 				<a | ||||||
| 					class="w3-bar-item" |  | ||||||
| 					accesskey="p" | 					accesskey="p" | ||||||
| 					@mouseover=${set_access_key_title} | 					@mouseover=${set_access_key_title} | ||||||
| 					data-tip="View and change permissions." | 					data-tip="View and change permissions." | ||||||
| @@ -343,34 +234,27 @@ class TfNavigationElement extends LitElement { | |||||||
| 					@click=${() => (self.show_permissions = !self.show_permissions)} | 					@click=${() => (self.show_permissions = !self.show_permissions)} | ||||||
| 					>🎛️</a | 					>🎛️</a | ||||||
| 				> | 				> | ||||||
| 				${this.render_permissions()} | 				<span | ||||||
| 				${this.status?.message && !this.status.is_error | 					style="display: inline-block; vertical-align: top; white-space: pre; color: ${this | ||||||
| 					? html` | 						.status.color ?? kErrorColor}" | ||||||
| 							<link type="text/css" rel="stylesheet" href="/static/w3.css" /> | 					>${this.status.message}</span | ||||||
| 							<div |  | ||||||
| 								class="w3-bar-item" |  | ||||||
| 								style="color: ${this.status.color ?? kStatusColor}" |  | ||||||
| 				> | 				> | ||||||
| 								${this.status.message} | 				<span id="requests"></span> | ||||||
| 							</div> | 				${this.render_permissions()} | ||||||
| 						` | 				<span | ||||||
| 					: undefined} | 					style="flex: 1 1; display: flex; flex-direction: row; white-space: nowrap; margin: 0; padding: 0" | ||||||
| 				${Object.keys(this.spark_lines) | 					>${Object.keys(this.spark_lines) | ||||||
| 						.sort() | 						.sort() | ||||||
| 					.map((x) => this.spark_lines[x])} | 						.map((x) => this.spark_lines[x]) | ||||||
| 				${this.render_login()} ${this.render_identity()} | 						.map((x) => [ | ||||||
|  | 							html`<span style="font-size: xx-small">${x.dataset.emoji}</span>`, | ||||||
|  | 							x, | ||||||
|  | 						])}</span | ||||||
|  | 				> | ||||||
|  | 				<span style="flex: 0 0; white-space: nowrap" | ||||||
|  | 					>${this.render_login()}</span | ||||||
|  | 				> | ||||||
| 			</div> | 			</div> | ||||||
| 			${this.status?.is_error |  | ||||||
| 				? html` |  | ||||||
| 					<link type="text/css" rel="stylesheet" href="/static/w3.css" /> |  | ||||||
| 					<div class="w3-model w3-animate-top" style="position: absolute; left: 50%; transform: translate(-50%); z-index: 1"> |  | ||||||
| 						<dijv class="w3-modal-content w3-card-4" style="display: block; padding: 1em"> |  | ||||||
| 							<span @click=${self.clear_error} class="w3-button w3-display-topright">×</span> |  | ||||||
| 							<div style="color: ${this.status.color ?? kErrorColor}"><b>ERROR:</b><p style="white-space: pre">${this.status.message}</p></div> |  | ||||||
| 						</div> |  | ||||||
| 					</div> |  | ||||||
| 					` |  | ||||||
| 				: undefined} |  | ||||||
| 		`; | 		`; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -694,13 +578,13 @@ class TfSparkLineElement extends LitElement { | |||||||
| 			) / 10.0; | 			) / 10.0; | ||||||
| 		return html` | 		return html` | ||||||
| 			<svg | 			<svg | ||||||
| 				style="max-width: 7.5em; margin: 0; padding: 0; background: #000; height: 1em" | 				style="max-width: 7.5em; max-height: 1.5em; margin: 0; padding: 0; background: #000" | ||||||
| 				viewBox="0 0 50 10" | 				viewBox="0 0 50 10" | ||||||
| 				xmlns="http://www.w3.org/2000/svg" | 				xmlns="http://www.w3.org/2000/svg" | ||||||
| 			> | 			> | ||||||
| 				${this.lines.map((x) => this.render_line(x))} | 				${this.lines.map((x) => this.render_line(x))} | ||||||
| 				<text x="0" y="1em" style="font: 8px sans-serif; fill: #fff"> | 				<text x="0" y="1em" style="font: 8px sans-serif; fill: #fff"> | ||||||
| 					${this.dataset.emoji}${max} | 					${max} | ||||||
| 				</text> | 				</text> | ||||||
| 			</svg> | 			</svg> | ||||||
| 		`; | 		`; | ||||||
| @@ -1116,9 +1000,9 @@ function api_postMessage(message) { | |||||||
| function api_error(error) { | function api_error(error) { | ||||||
| 	if (error) { | 	if (error) { | ||||||
| 		if (typeof error == 'string') { | 		if (typeof error == 'string') { | ||||||
| 			setStatusMessage('⚠️ ' + error, kErrorColor); | 			setStatusMessage('⚠️ ' + error, '#f00'); | ||||||
| 		} else { | 		} else { | ||||||
| 			setStatusMessage('⚠️ ' + error.message + '\n' + error.stack, kErrorColor); | 			setStatusMessage('⚠️ ' + error.message + '\n' + error.stack, '#f00'); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	console.log('error', error); | 	console.log('error', error); | ||||||
| @@ -1235,19 +1119,11 @@ function api_setHash(hash) { | |||||||
| function _receive_websocket_message(message) { | function _receive_websocket_message(message) { | ||||||
| 	if (message && message.action == 'session') { | 	if (message && message.action == 'session') { | ||||||
| 		setStatusMessage('🟢 Executing...', kStatusColor); | 		setStatusMessage('🟢 Executing...', kStatusColor); | ||||||
| 		let navigation = document.getElementsByTagName('tf-navigation')[0]; | 		document.getElementsByTagName('tf-navigation')[0].credentials = | ||||||
| 		navigation.credentials = message.credentials; | 			message.credentials; | ||||||
| 		navigation.identities = message.identities; |  | ||||||
| 		navigation.identity = message.identity; |  | ||||||
| 		navigation.names = message.names; |  | ||||||
| 	} else if (message && message.action == 'permissions') { | 	} else if (message && message.action == 'permissions') { | ||||||
| 		let navigation = document.getElementsByTagName('tf-navigation')[0]; | 		document.getElementsByTagName('tf-navigation')[0].permissions = | ||||||
| 		navigation.permissions = message.permissions ?? {}; | 			message.permissions ?? {}; | ||||||
| 	} else if (message && message.action == 'identities') { |  | ||||||
| 		let navigation = document.getElementsByTagName('tf-navigation')[0]; |  | ||||||
| 		navigation.identities = message.identities; |  | ||||||
| 		navigation.identity = message.identity; |  | ||||||
| 		navigation.names = message.names; |  | ||||||
| 	} else if (message && message.action == 'ready') { | 	} else if (message && message.action == 'ready') { | ||||||
| 		setStatusMessage(null); | 		setStatusMessage(null); | ||||||
| 		if (window.location.hash) { | 		if (window.location.hash) { | ||||||
| @@ -1335,7 +1211,6 @@ function setStatusMessage(message, color) { | |||||||
| 	document.getElementsByTagName('tf-navigation')[0].status = { | 	document.getElementsByTagName('tf-navigation')[0].status = { | ||||||
| 		message: message, | 		message: message, | ||||||
| 		color: color, | 		color: color, | ||||||
| 		is_error: color == kErrorColor, |  | ||||||
| 	}; | 	}; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										156
									
								
								core/core.js
									
									
									
									
									
								
							
							
						
						
									
										156
									
								
								core/core.js
									
									
									
									
									
								
							| @@ -1,4 +1,5 @@ | |||||||
| import * as app from './app.js'; | import * as app from './app.js'; | ||||||
|  | import * as auth from './auth.js'; | ||||||
| import * as form from './form.js'; | import * as form from './form.js'; | ||||||
| import * as http from './http.js'; | import * as http from './http.js'; | ||||||
|  |  | ||||||
| @@ -244,7 +245,6 @@ function broadcastEvent(eventName, argv) { | |||||||
| 	} | 	} | ||||||
| 	return Promise.all(promises); | 	return Promise.all(promises); | ||||||
| } | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * TODOC |  * TODOC | ||||||
|  * @param {*} message |  * @param {*} message | ||||||
| @@ -266,34 +266,6 @@ function broadcast(message) { | |||||||
| 	return Promise.all(promises); | 	return Promise.all(promises); | ||||||
| } | } | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * TODOC |  | ||||||
|  * @param {String} eventName |  | ||||||
|  * @param {*} argv |  | ||||||
|  * @returns |  | ||||||
|  */ |  | ||||||
| function broadcastAppEventToUser( |  | ||||||
| 	user, |  | ||||||
| 	packageOwner, |  | ||||||
| 	packageName, |  | ||||||
| 	eventName, |  | ||||||
| 	argv |  | ||||||
| ) { |  | ||||||
| 	let promises = []; |  | ||||||
| 	for (let process of Object.values(gProcesses)) { |  | ||||||
| 		if ( |  | ||||||
| 			process.credentials?.session?.name === user && |  | ||||||
| 			process.packageOwner == packageOwner && |  | ||||||
| 			process.packageName == packageName |  | ||||||
| 		) { |  | ||||||
| 			if (process.eventHandlers[eventName]) { |  | ||||||
| 				promises.push(invoke(process.eventHandlers[eventName], argv)); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return Promise.all(promises); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * TODOC |  * TODOC | ||||||
|  * @param {*} caller |  * @param {*} caller | ||||||
| @@ -389,8 +361,6 @@ async function getProcessBlob(blobId, key, options) { | |||||||
| 			process.key = key; | 			process.key = key; | ||||||
| 			process.credentials = options.credentials || {}; | 			process.credentials = options.credentials || {}; | ||||||
| 			process.task = new Task(); | 			process.task = new Task(); | ||||||
| 			process.packageOwner = options.packageOwner; |  | ||||||
| 			process.packageName = options.packageName; |  | ||||||
| 			process.eventHandlers = {}; | 			process.eventHandlers = {}; | ||||||
| 			if (!options?.script || options?.script === 'app.js') { | 			if (!options?.script || options?.script === 'app.js') { | ||||||
| 				process.app = new app.App(); | 				process.app = new app.App(); | ||||||
| @@ -539,64 +509,6 @@ async function getProcessBlob(blobId, key, options) { | |||||||
| 					url: options?.url, | 					url: options?.url, | ||||||
| 				}, | 				}, | ||||||
| 			}; | 			}; | ||||||
| 			process.sendIdentities = async function () { |  | ||||||
| 				process.app.send( |  | ||||||
| 					Object.assign( |  | ||||||
| 						{ |  | ||||||
| 							action: 'identities', |  | ||||||
| 						}, |  | ||||||
| 						await ssb.getIdentityInfo( |  | ||||||
| 							process?.credentials?.session?.name, |  | ||||||
| 							options?.packageOwner, |  | ||||||
| 							options?.packageName |  | ||||||
| 						) |  | ||||||
| 					) |  | ||||||
| 				); |  | ||||||
| 			}; |  | ||||||
| 			process.setActiveIdentity = async function (identity) { |  | ||||||
| 				if ( |  | ||||||
| 					process?.credentials?.session?.name && |  | ||||||
| 					options.packageOwner && |  | ||||||
| 					options.packageName |  | ||||||
| 				) { |  | ||||||
| 					await new Database(process?.credentials?.session?.name).set( |  | ||||||
| 						`id:${options.packageOwner}:${options.packageName}`, |  | ||||||
| 						identity |  | ||||||
| 					); |  | ||||||
| 				} |  | ||||||
| 				process.sendIdentities(); |  | ||||||
| 				broadcastAppEventToUser( |  | ||||||
| 					process?.credentials?.session?.name, |  | ||||||
| 					options.packageOwner, |  | ||||||
| 					options.packageName, |  | ||||||
| 					'setActiveIdentity', |  | ||||||
| 					[identity] |  | ||||||
| 				); |  | ||||||
| 			}; |  | ||||||
| 			process.createIdentity = async function () { |  | ||||||
| 				if ( |  | ||||||
| 					process.credentials && |  | ||||||
| 					process.credentials.session && |  | ||||||
| 					process.credentials.session.name |  | ||||||
| 				) { |  | ||||||
| 					let id = ssb.createIdentity(process.credentials.session.name); |  | ||||||
| 					await process.sendIdentities(); |  | ||||||
| 					broadcastAppEventToUser( |  | ||||||
| 						process?.credentials?.session?.name, |  | ||||||
| 						options.packageOwner, |  | ||||||
| 						options.packageName, |  | ||||||
| 						'setActiveIdentity', |  | ||||||
| 						[ |  | ||||||
| 							await ssb.getActiveIdentity( |  | ||||||
| 								process.credentials?.session?.name, |  | ||||||
| 								options.packageOwner, |  | ||||||
| 								options.packageName |  | ||||||
| 							), |  | ||||||
| 						] |  | ||||||
| 					); |  | ||||||
| 					return id; |  | ||||||
| 				} |  | ||||||
| 			}; |  | ||||||
| 			if (process.credentials?.permissions?.administration) { | 			if (process.credentials?.permissions?.administration) { | ||||||
| 				imports.core.globalSettingsDescriptions = function () { | 				imports.core.globalSettingsDescriptions = function () { | ||||||
| 					let settings = Object.assign({}, k_global_settings); | 					let settings = Object.assign({}, k_global_settings); | ||||||
| @@ -667,7 +579,15 @@ async function getProcessBlob(blobId, key, options) { | |||||||
| 				Object.keys(ssb).map((key) => [key, ssb[key].bind(ssb)]) | 				Object.keys(ssb).map((key) => [key, ssb[key].bind(ssb)]) | ||||||
| 			); | 			); | ||||||
| 			imports.ssb.port = tildefriends.ssb_port; | 			imports.ssb.port = tildefriends.ssb_port; | ||||||
| 			imports.ssb.createIdentity = () => process.createIdentity(); | 			imports.ssb.createIdentity = function () { | ||||||
|  | 				if ( | ||||||
|  | 					process.credentials && | ||||||
|  | 					process.credentials.session && | ||||||
|  | 					process.credentials.session.name | ||||||
|  | 				) { | ||||||
|  | 					return ssb.createIdentity(process.credentials.session.name); | ||||||
|  | 				} | ||||||
|  | 			}; | ||||||
| 			imports.ssb.addIdentity = function (id) { | 			imports.ssb.addIdentity = function (id) { | ||||||
| 				if ( | 				if ( | ||||||
| 					process.credentials && | 					process.credentials && | ||||||
| @@ -694,13 +614,6 @@ async function getProcessBlob(blobId, key, options) { | |||||||
| 					}); | 					}); | ||||||
| 				} | 				} | ||||||
| 			}; | 			}; | ||||||
| 			imports.ssb.setActiveIdentity = (id) => process.setActiveIdentity(id); |  | ||||||
| 			imports.ssb.getActiveIdentity = () => |  | ||||||
| 				ssb.getActiveIdentity( |  | ||||||
| 					process.credentials?.session?.name, |  | ||||||
| 					options.packageOwner, |  | ||||||
| 					options.packageName |  | ||||||
| 				); |  | ||||||
| 			imports.ssb.getOwnerIdentities = function () { | 			imports.ssb.getOwnerIdentities = function () { | ||||||
| 				if (options.packageOwner) { | 				if (options.packageOwner) { | ||||||
| 					return ssb.getIdentities(options.packageOwner); | 					return ssb.getIdentities(options.packageOwner); | ||||||
| @@ -785,7 +698,6 @@ async function getProcessBlob(blobId, key, options) { | |||||||
| 					); | 					); | ||||||
| 				} | 				} | ||||||
| 			}; | 			}; | ||||||
| 			imports.ssb.getIdentityInfo = undefined; |  | ||||||
| 			imports.fetch = function (url, options) { | 			imports.fetch = function (url, options) { | ||||||
| 				return http.fetch(url, options, gGlobalSettings.fetch_hosts); | 				return http.fetch(url, options, gGlobalSettings.fetch_hosts); | ||||||
| 			}; | 			}; | ||||||
| @@ -1055,7 +967,7 @@ async function useAppHandler( | |||||||
| 					}, | 					}, | ||||||
| 					respond: do_resolve, | 					respond: do_resolve, | ||||||
| 				}, | 				}, | ||||||
| 				credentials: httpd.auth_query(headers), | 				credentials: auth.query(headers), | ||||||
| 				packageOwner: packageOwner, | 				packageOwner: packageOwner, | ||||||
| 				packageName: packageName, | 				packageName: packageName, | ||||||
| 			} | 			} | ||||||
| @@ -1186,7 +1098,7 @@ async function blobHandler(request, response, blobId, uri) { | |||||||
| 		if ((match = /^\/\~(\w+)\/(\w+)$/.exec(blobId))) { | 		if ((match = /^\/\~(\w+)\/(\w+)$/.exec(blobId))) { | ||||||
| 			let user = match[1]; | 			let user = match[1]; | ||||||
| 			let appName = match[2]; | 			let appName = match[2]; | ||||||
| 			let credentials = httpd.auth_query(request.headers); | 			let credentials = auth.query(request.headers); | ||||||
| 			if ( | 			if ( | ||||||
| 				credentials && | 				credentials && | ||||||
| 				credentials.session && | 				credentials.session && | ||||||
| @@ -1249,7 +1161,7 @@ async function blobHandler(request, response, blobId, uri) { | |||||||
| 		if ((match = /^\/\~(\w+)\/(\w+)$/.exec(blobId))) { | 		if ((match = /^\/\~(\w+)\/(\w+)$/.exec(blobId))) { | ||||||
| 			let user = match[1]; | 			let user = match[1]; | ||||||
| 			let appName = match[2]; | 			let appName = match[2]; | ||||||
| 			let credentials = httpd.auth_query(request.headers); | 			let credentials = auth.query(request.headers); | ||||||
| 			if ( | 			if ( | ||||||
| 				credentials && | 				credentials && | ||||||
| 				credentials.session && | 				credentials.session && | ||||||
| @@ -1422,10 +1334,39 @@ loadSettings() | |||||||
| 		if (tildefriends.https_port && gGlobalSettings.http_redirect) { | 		if (tildefriends.https_port && gGlobalSettings.http_redirect) { | ||||||
| 			httpd.set_http_redirect(gGlobalSettings.http_redirect); | 			httpd.set_http_redirect(gGlobalSettings.http_redirect); | ||||||
| 		} | 		} | ||||||
|  | 		httpd.all('/login', auth.handler); | ||||||
|  | 		httpd.all('/login/logout', auth.handler); | ||||||
| 		httpd.all('/app/socket', app.socket); | 		httpd.all('/app/socket', app.socket); | ||||||
| 		httpd.all('', function default_http_handler(request, response) { | 		httpd.all('', function default_http_handler(request, response) { | ||||||
| 			let match; | 			let match; | ||||||
| 			if ((match = /^(\/~[^\/]+\/[^\/]+)(\/?.*)$/.exec(request.uri))) { | 			if (request.uri === '/' || request.uri === '') { | ||||||
|  | 				let host = request.headers['x-forwarded-host'] ?? request.headers.host; | ||||||
|  | 				try { | ||||||
|  | 					for (let line of (gGlobalSettings.index_map || '').split('\n')) { | ||||||
|  | 						let parts = line.split('='); | ||||||
|  | 						if (parts.length == 2 && host.match(new RegExp(parts[0], 'i'))) { | ||||||
|  | 							response.writeHead(303, { | ||||||
|  | 								Location: | ||||||
|  | 									(request.client.tls ? 'https://' : 'http://') + | ||||||
|  | 									host + | ||||||
|  | 									parts[1], | ||||||
|  | 								'Content-Length': '0', | ||||||
|  | 							}); | ||||||
|  | 							return response.end(); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} catch (e) { | ||||||
|  | 					print(e); | ||||||
|  | 				} | ||||||
|  | 				response.writeHead(303, { | ||||||
|  | 					Location: | ||||||
|  | 						(request.client.tls ? 'https://' : 'http://') + | ||||||
|  | 						host + | ||||||
|  | 						gGlobalSettings.index, | ||||||
|  | 					'Content-Length': '0', | ||||||
|  | 				}); | ||||||
|  | 				return response.end(); | ||||||
|  | 			} else if ((match = /^(\/~[^\/]+\/[^\/]+)(\/?.*)$/.exec(request.uri))) { | ||||||
| 				return blobHandler(request, response, match[1], match[2]); | 				return blobHandler(request, response, match[1], match[2]); | ||||||
| 			} else if ( | 			} else if ( | ||||||
| 				(match = /^\/([&\%][^\.]{44}(?:\.\w+)?)(\/?.*)/.exec(request.uri)) | 				(match = /^\/([&\%][^\.]{44}(?:\.\w+)?)(\/?.*)/.exec(request.uri)) | ||||||
| @@ -1465,15 +1406,8 @@ loadSettings() | |||||||
| 			async function start_tls() { | 			async function start_tls() { | ||||||
| 				const kCertificatePath = 'data/httpd/certificate.pem'; | 				const kCertificatePath = 'data/httpd/certificate.pem'; | ||||||
| 				const kPrivateKeyPath = 'data/httpd/privatekey.pem'; | 				const kPrivateKeyPath = 'data/httpd/privatekey.pem'; | ||||||
| 				let privateKey; | 				let privateKey = utf8Decode(await File.readFile(kPrivateKeyPath)); | ||||||
| 				let certificate; | 				let certificate = utf8Decode(await File.readFile(kCertificatePath)); | ||||||
| 				try { |  | ||||||
| 					privateKey = utf8Decode(await File.readFile(kPrivateKeyPath)); |  | ||||||
| 					certificate = utf8Decode(await File.readFile(kCertificatePath)); |  | ||||||
| 				} catch (e) { |  | ||||||
| 					print(`TLS disabled (${e.message}).`); |  | ||||||
| 					return; |  | ||||||
| 				} |  | ||||||
| 				let context = new TlsContext(); | 				let context = new TlsContext(); | ||||||
| 				context.setPrivateKey(privateKey); | 				context.setPrivateKey(privateKey); | ||||||
| 				context.setCertificate(certificate); | 				context.setCertificate(certificate); | ||||||
|   | |||||||
| @@ -15,6 +15,22 @@ body { | |||||||
| 	margin: 0; | 	margin: 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | a:link { | ||||||
|  | 	color: #268bd2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | a:visited { | ||||||
|  | 	color: #6c71c4; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | a:hover { | ||||||
|  | 	color: #859900; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | a:active { | ||||||
|  | 	color: #2aa198; | ||||||
|  | } | ||||||
|  |  | ||||||
| #logo { | #logo { | ||||||
| 	vertical-align: middle; | 	vertical-align: middle; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										114
									
								
								core/tildefriends-v1.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								core/tildefriends-v1.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | |||||||
|  | /* | ||||||
|  |  * Tilde Friends core stylesheet | ||||||
|  |  * | ||||||
|  |  * This Software is an external library that is part of | ||||||
|  |  * Tilde Friends and is shared under the MIT license. | ||||||
|  |  * | ||||||
|  |  * Inject this file in your app at tildefriends.css | ||||||
|  |  * and use this tag to import it: | ||||||
|  |  * <link rel="stylesheet" href="/static/tildefriends-v1.css"/> | ||||||
|  |  * | ||||||
|  |  * v1.0 / 2024 M03 21 | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | body { | ||||||
|  | 	color: white; | ||||||
|  | 	font-family: sans-serif; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | button, | ||||||
|  | .button, | ||||||
|  | input[type='button'], | ||||||
|  | input[type='submit'], | ||||||
|  | select { | ||||||
|  | 	border: none; | ||||||
|  | 	border-radius: 8px; | ||||||
|  | 	padding: 8px 12px; | ||||||
|  | 	text-align: center; | ||||||
|  | 	text-decoration: none; | ||||||
|  | 	display: inline-block; | ||||||
|  | 	margin: 4px; | ||||||
|  |  | ||||||
|  | 	&.red { | ||||||
|  | 		background-color: #bd1e24; | ||||||
|  | 		color: white; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	&.green { | ||||||
|  | 		background-color: #18922d; | ||||||
|  | 		color: white; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	&.blue { | ||||||
|  | 		background-color: #0067a7; | ||||||
|  | 		color: white; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	&.yellow { | ||||||
|  | 		background-color: #ee9600; | ||||||
|  | 		color: black; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	&:hover { | ||||||
|  | 		filter: brightness(0.75); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | a:link { | ||||||
|  | 	color: #268bd2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | a:visited { | ||||||
|  | 	color: #6c71c4; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | a:hover { | ||||||
|  | 	color: #859900; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | a:active { | ||||||
|  | 	color: #2aa198; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | table { | ||||||
|  | 	border-collapse: collapse; | ||||||
|  | 	width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | td, | ||||||
|  | th { | ||||||
|  | 	border: 1px solid #ffffff40; | ||||||
|  | 	text-align: left; | ||||||
|  | 	padding: 8px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | tr:nth-child(even) { | ||||||
|  | 	background-color: #ffffff20; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .flex { | ||||||
|  | 	display: flex; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .flex-column { | ||||||
|  | 	display: flex; | ||||||
|  | 	flex-direction: column; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .flex-row { | ||||||
|  | 	display: flex; | ||||||
|  | 	flex-direction: row; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .inline-flex-row { | ||||||
|  | 	display: inline-flex; | ||||||
|  | 	flex-direction: row; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .box { | ||||||
|  | 	background-color: #00000020; | ||||||
|  | 	border: 1px solid grey; | ||||||
|  | 	border-radius: 8px; | ||||||
|  | 	padding: 16px; | ||||||
|  | 	margin: 4px; | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								deps/codemirror/cm6.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								deps/codemirror/cm6.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										197
									
								
								deps/codemirror_src/package-lock.json
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										197
									
								
								deps/codemirror_src/package-lock.json
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -19,9 +19,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@codemirror/autocomplete": { |     "node_modules/@codemirror/autocomplete": { | ||||||
|       "version": "6.16.0", |       "version": "6.15.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.16.0.tgz", |       "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.15.0.tgz", | ||||||
|       "integrity": "sha512-P/LeCTtZHRTCU4xQsa89vSKWecYv1ZqwzOd5topheGRf+qtacFgBeIMQi3eL8Kt/BUNvxUWkx+5qP2jlGoARrg==", |       "integrity": "sha512-G2Zm0mXznxz97JhaaOdoEG2cVupn4JjPaS4AcNvZzhOsnnG9YVN68VzfoUw6dYTsIxT6a/cmoFEN47KAWhXaOg==", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@codemirror/language": "^6.0.0", |         "@codemirror/language": "^6.0.0", | ||||||
|         "@codemirror/state": "^6.0.0", |         "@codemirror/state": "^6.0.0", | ||||||
| @@ -36,9 +36,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@codemirror/commands": { |     "node_modules/@codemirror/commands": { | ||||||
|       "version": "6.5.0", |       "version": "6.3.3", | ||||||
|       "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.5.0.tgz", |       "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.3.3.tgz", | ||||||
|       "integrity": "sha512-rK+sj4fCAN/QfcY9BEzYMgp4wwL/q5aj/VfNSoH1RWPF9XS/dUwBkvlL3hpWgEjOqlpdN1uLC9UkjJ4tmyjJYg==", |       "integrity": "sha512-dO4hcF0fGT9tu1Pj1D2PvGvxjeGkbC6RGcZw6Qs74TH+Ed1gw98jmUgd2axWvIZEqTeTuFrg1lEB1KV6cK9h1A==", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@codemirror/language": "^6.0.0", |         "@codemirror/language": "^6.0.0", | ||||||
|         "@codemirror/state": "^6.4.0", |         "@codemirror/state": "^6.4.0", | ||||||
| @@ -59,9 +59,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@codemirror/lang-html": { |     "node_modules/@codemirror/lang-html": { | ||||||
|       "version": "6.4.9", |       "version": "6.4.8", | ||||||
|       "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.9.tgz", |       "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.8.tgz", | ||||||
|       "integrity": "sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==", |       "integrity": "sha512-tE2YK7wDlb9ZpAH6mpTPiYm6rhfdQKVDa5r9IwIFlwwgvVaKsCfuKKZoJGWsmMZIf3FQAuJ5CHMPLymOtg1hXw==", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@codemirror/autocomplete": "^6.0.0", |         "@codemirror/autocomplete": "^6.0.0", | ||||||
|         "@codemirror/lang-css": "^6.0.0", |         "@codemirror/lang-css": "^6.0.0", | ||||||
| @@ -111,9 +111,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@codemirror/lint": { |     "node_modules/@codemirror/lint": { | ||||||
|       "version": "6.7.0", |       "version": "6.5.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.7.0.tgz", |       "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.5.0.tgz", | ||||||
|       "integrity": "sha512-LTLOL2nT41ADNSCCCCw8Q/UmdAFzB23OUYSjsHTdsVaH0XEo+orhuqbDNWzrzodm14w6FOxqxpmy4LF8Lixqjw==", |       "integrity": "sha512-+5YyicIaaAZKU8K43IQi8TBy6mF6giGeWAH7N96Z5LC30Wm5JMjqxOYIE9mxwMG1NbhT2mA3l9hA4uuKUM3E5g==", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@codemirror/state": "^6.0.0", |         "@codemirror/state": "^6.0.0", | ||||||
|         "@codemirror/view": "^6.0.0", |         "@codemirror/view": "^6.0.0", | ||||||
| @@ -147,9 +147,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@codemirror/view": { |     "node_modules/@codemirror/view": { | ||||||
|       "version": "6.26.3", |       "version": "6.25.1", | ||||||
|       "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.3.tgz", |       "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.25.1.tgz", | ||||||
|       "integrity": "sha512-gmqxkPALZjkgSxIeeweY/wGQXBfwTUaLs8h7OKtSwfbj9Ct3L11lD+u1sS7XHppxFQoMDiMDp07P9f3I2jWOHw==", |       "integrity": "sha512-2LXLxsQnHDdfGzDvjzAwZh2ZviNJm7im6tGpa0IONIDnFd8RZ80D2SNi8PDi6YjKcMoMRK20v6OmKIdsrwsyoQ==", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@codemirror/state": "^6.4.0", |         "@codemirror/state": "^6.4.0", | ||||||
|         "style-mod": "^4.1.0", |         "style-mod": "^4.1.0", | ||||||
| @@ -248,9 +248,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@lezer/javascript": { |     "node_modules/@lezer/javascript": { | ||||||
|       "version": "1.4.15", |       "version": "1.4.13", | ||||||
|       "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.15.tgz", |       "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.13.tgz", | ||||||
|       "integrity": "sha512-B082ZdjI0vo2AgLqD834GlRTE9gwRX8NzHzKq5uDwEnQ9Dq+A/CEhd3nf68tiNA2f9O+8jS1NeSTUYT9IAqcTw==", |       "integrity": "sha512-5IBr8LIO3xJdJH1e9aj/ZNLE4LSbdsx25wFmGRAZsj2zSmwAYjx26JyU/BYOCpRQlu1jcv1z3vy4NB9+UkfRow==", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@lezer/common": "^1.2.0", |         "@lezer/common": "^1.2.0", | ||||||
|         "@lezer/highlight": "^1.1.3", |         "@lezer/highlight": "^1.1.3", | ||||||
| @@ -343,9 +343,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-android-arm-eabi": { |     "node_modules/@rollup/rollup-android-arm-eabi": { | ||||||
|       "version": "4.17.2", |       "version": "4.13.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.0.tgz", | ||||||
|       "integrity": "sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==", |       "integrity": "sha512-5ZYPOuaAqEH/W3gYsRkxQATBW3Ii1MfaT4EQstTnLKViLi2gLSQmlmtTpGucNP3sXEpOiI5tdGhjdE111ekyEg==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "arm" |         "arm" | ||||||
|       ], |       ], | ||||||
| @@ -355,9 +355,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-android-arm64": { |     "node_modules/@rollup/rollup-android-arm64": { | ||||||
|       "version": "4.17.2", |       "version": "4.13.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.0.tgz", | ||||||
|       "integrity": "sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==", |       "integrity": "sha512-BSbaCmn8ZadK3UAQdlauSvtaJjhlDEjS5hEVVIN3A4bbl3X+otyf/kOJV08bYiRxfejP3DXFzO2jz3G20107+Q==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "arm64" |         "arm64" | ||||||
|       ], |       ], | ||||||
| @@ -367,9 +367,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-darwin-arm64": { |     "node_modules/@rollup/rollup-darwin-arm64": { | ||||||
|       "version": "4.17.2", |       "version": "4.13.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.0.tgz", | ||||||
|       "integrity": "sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==", |       "integrity": "sha512-Ovf2evVaP6sW5Ut0GHyUSOqA6tVKfrTHddtmxGQc1CTQa1Cw3/KMCDEEICZBbyppcwnhMwcDce9ZRxdWRpVd6g==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "arm64" |         "arm64" | ||||||
|       ], |       ], | ||||||
| @@ -379,9 +379,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-darwin-x64": { |     "node_modules/@rollup/rollup-darwin-x64": { | ||||||
|       "version": "4.17.2", |       "version": "4.13.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.0.tgz", | ||||||
|       "integrity": "sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==", |       "integrity": "sha512-U+Jcxm89UTK592vZ2J9st9ajRv/hrwHdnvyuJpa5A2ngGSVHypigidkQJP+YiGL6JODiUeMzkqQzbCG3At81Gg==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "x64" |         "x64" | ||||||
|       ], |       ], | ||||||
| @@ -391,21 +391,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-linux-arm-gnueabihf": { |     "node_modules/@rollup/rollup-linux-arm-gnueabihf": { | ||||||
|       "version": "4.17.2", |       "version": "4.13.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.0.tgz", | ||||||
|       "integrity": "sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==", |       "integrity": "sha512-8wZidaUJUTIR5T4vRS22VkSMOVooG0F4N+JSwQXWSRiC6yfEsFMLTYRFHvby5mFFuExHa/yAp9juSphQQJAijQ==", | ||||||
|       "cpu": [ |  | ||||||
|         "arm" |  | ||||||
|       ], |  | ||||||
|       "optional": true, |  | ||||||
|       "os": [ |  | ||||||
|         "linux" |  | ||||||
|       ] |  | ||||||
|     }, |  | ||||||
|     "node_modules/@rollup/rollup-linux-arm-musleabihf": { |  | ||||||
|       "version": "4.17.2", |  | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.2.tgz", |  | ||||||
|       "integrity": "sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==", |  | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "arm" |         "arm" | ||||||
|       ], |       ], | ||||||
| @@ -415,9 +403,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-linux-arm64-gnu": { |     "node_modules/@rollup/rollup-linux-arm64-gnu": { | ||||||
|       "version": "4.17.2", |       "version": "4.13.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.0.tgz", | ||||||
|       "integrity": "sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==", |       "integrity": "sha512-Iu0Kno1vrD7zHQDxOmvweqLkAzjxEVqNhUIXBsZ8hu8Oak7/5VTPrxOEZXYC1nmrBVJp0ZcL2E7lSuuOVaE3+w==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "arm64" |         "arm64" | ||||||
|       ], |       ], | ||||||
| @@ -427,9 +415,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-linux-arm64-musl": { |     "node_modules/@rollup/rollup-linux-arm64-musl": { | ||||||
|       "version": "4.17.2", |       "version": "4.13.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.0.tgz", | ||||||
|       "integrity": "sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==", |       "integrity": "sha512-C31QrW47llgVyrRjIwiOwsHFcaIwmkKi3PCroQY5aVq4H0A5v/vVVAtFsI1nfBngtoRpeREvZOkIhmRwUKkAdw==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "arm64" |         "arm64" | ||||||
|       ], |       ], | ||||||
| @@ -438,22 +426,10 @@ | |||||||
|         "linux" |         "linux" | ||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { |  | ||||||
|       "version": "4.17.2", |  | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.2.tgz", |  | ||||||
|       "integrity": "sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==", |  | ||||||
|       "cpu": [ |  | ||||||
|         "ppc64" |  | ||||||
|       ], |  | ||||||
|       "optional": true, |  | ||||||
|       "os": [ |  | ||||||
|         "linux" |  | ||||||
|       ] |  | ||||||
|     }, |  | ||||||
|     "node_modules/@rollup/rollup-linux-riscv64-gnu": { |     "node_modules/@rollup/rollup-linux-riscv64-gnu": { | ||||||
|       "version": "4.17.2", |       "version": "4.13.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.0.tgz", | ||||||
|       "integrity": "sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==", |       "integrity": "sha512-Oq90dtMHvthFOPMl7pt7KmxzX7E71AfyIhh+cPhLY9oko97Zf2C9tt/XJD4RgxhaGeAraAXDtqxvKE1y/j35lA==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "riscv64" |         "riscv64" | ||||||
|       ], |       ], | ||||||
| @@ -462,22 +438,10 @@ | |||||||
|         "linux" |         "linux" | ||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-linux-s390x-gnu": { |  | ||||||
|       "version": "4.17.2", |  | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.2.tgz", |  | ||||||
|       "integrity": "sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==", |  | ||||||
|       "cpu": [ |  | ||||||
|         "s390x" |  | ||||||
|       ], |  | ||||||
|       "optional": true, |  | ||||||
|       "os": [ |  | ||||||
|         "linux" |  | ||||||
|       ] |  | ||||||
|     }, |  | ||||||
|     "node_modules/@rollup/rollup-linux-x64-gnu": { |     "node_modules/@rollup/rollup-linux-x64-gnu": { | ||||||
|       "version": "4.17.2", |       "version": "4.13.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.0.tgz", | ||||||
|       "integrity": "sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==", |       "integrity": "sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "x64" |         "x64" | ||||||
|       ], |       ], | ||||||
| @@ -487,9 +451,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-linux-x64-musl": { |     "node_modules/@rollup/rollup-linux-x64-musl": { | ||||||
|       "version": "4.17.2", |       "version": "4.13.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.0.tgz", | ||||||
|       "integrity": "sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==", |       "integrity": "sha512-9RyNqoFNdF0vu/qqX63fKotBh43fJQeYC98hCaf89DYQpv+xu0D8QFSOS0biA7cGuqJFOc1bJ+m2rhhsKcw1hw==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "x64" |         "x64" | ||||||
|       ], |       ], | ||||||
| @@ -499,9 +463,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-win32-arm64-msvc": { |     "node_modules/@rollup/rollup-win32-arm64-msvc": { | ||||||
|       "version": "4.17.2", |       "version": "4.13.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.0.tgz", | ||||||
|       "integrity": "sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==", |       "integrity": "sha512-46ue8ymtm/5PUU6pCvjlic0z82qWkxv54GTJZgHrQUuZnVH+tvvSP0LsozIDsCBFO4VjJ13N68wqrKSeScUKdA==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "arm64" |         "arm64" | ||||||
|       ], |       ], | ||||||
| @@ -511,9 +475,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-win32-ia32-msvc": { |     "node_modules/@rollup/rollup-win32-ia32-msvc": { | ||||||
|       "version": "4.17.2", |       "version": "4.13.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.0.tgz", | ||||||
|       "integrity": "sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==", |       "integrity": "sha512-P5/MqLdLSlqxbeuJ3YDeX37srC8mCflSyTrUsgbU1c/U9j6l2g2GiIdYaGD9QjdMQPMSgYm7hgg0551wHyIluw==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "ia32" |         "ia32" | ||||||
|       ], |       ], | ||||||
| @@ -523,9 +487,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-win32-x64-msvc": { |     "node_modules/@rollup/rollup-win32-x64-msvc": { | ||||||
|       "version": "4.17.2", |       "version": "4.13.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.0.tgz", | ||||||
|       "integrity": "sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==", |       "integrity": "sha512-UKXUQNbO3DOhzLRwHSpa0HnhhCgNODvfoPWv2FCXme8N/ANFfhIPMGuOT+QuKd16+B5yxZ0HdpNlqPvTMS1qfw==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "x64" |         "x64" | ||||||
|       ], |       ], | ||||||
| @@ -715,9 +679,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/rollup": { |     "node_modules/rollup": { | ||||||
|       "version": "4.17.2", |       "version": "4.13.0", | ||||||
|       "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.2.tgz", |       "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.0.tgz", | ||||||
|       "integrity": "sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==", |       "integrity": "sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@types/estree": "1.0.5" |         "@types/estree": "1.0.5" | ||||||
|       }, |       }, | ||||||
| @@ -729,22 +693,19 @@ | |||||||
|         "npm": ">=8.0.0" |         "npm": ">=8.0.0" | ||||||
|       }, |       }, | ||||||
|       "optionalDependencies": { |       "optionalDependencies": { | ||||||
|         "@rollup/rollup-android-arm-eabi": "4.17.2", |         "@rollup/rollup-android-arm-eabi": "4.13.0", | ||||||
|         "@rollup/rollup-android-arm64": "4.17.2", |         "@rollup/rollup-android-arm64": "4.13.0", | ||||||
|         "@rollup/rollup-darwin-arm64": "4.17.2", |         "@rollup/rollup-darwin-arm64": "4.13.0", | ||||||
|         "@rollup/rollup-darwin-x64": "4.17.2", |         "@rollup/rollup-darwin-x64": "4.13.0", | ||||||
|         "@rollup/rollup-linux-arm-gnueabihf": "4.17.2", |         "@rollup/rollup-linux-arm-gnueabihf": "4.13.0", | ||||||
|         "@rollup/rollup-linux-arm-musleabihf": "4.17.2", |         "@rollup/rollup-linux-arm64-gnu": "4.13.0", | ||||||
|         "@rollup/rollup-linux-arm64-gnu": "4.17.2", |         "@rollup/rollup-linux-arm64-musl": "4.13.0", | ||||||
|         "@rollup/rollup-linux-arm64-musl": "4.17.2", |         "@rollup/rollup-linux-riscv64-gnu": "4.13.0", | ||||||
|         "@rollup/rollup-linux-powerpc64le-gnu": "4.17.2", |         "@rollup/rollup-linux-x64-gnu": "4.13.0", | ||||||
|         "@rollup/rollup-linux-riscv64-gnu": "4.17.2", |         "@rollup/rollup-linux-x64-musl": "4.13.0", | ||||||
|         "@rollup/rollup-linux-s390x-gnu": "4.17.2", |         "@rollup/rollup-win32-arm64-msvc": "4.13.0", | ||||||
|         "@rollup/rollup-linux-x64-gnu": "4.17.2", |         "@rollup/rollup-win32-ia32-msvc": "4.13.0", | ||||||
|         "@rollup/rollup-linux-x64-musl": "4.17.2", |         "@rollup/rollup-win32-x64-msvc": "4.13.0", | ||||||
|         "@rollup/rollup-win32-arm64-msvc": "4.17.2", |  | ||||||
|         "@rollup/rollup-win32-ia32-msvc": "4.17.2", |  | ||||||
|         "@rollup/rollup-win32-x64-msvc": "4.17.2", |  | ||||||
|         "fsevents": "~2.3.2" |         "fsevents": "~2.3.2" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
| @@ -778,9 +739,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/smob": { |     "node_modules/smob": { | ||||||
|       "version": "1.5.0", |       "version": "1.4.1", | ||||||
|       "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz", |       "resolved": "https://registry.npmjs.org/smob/-/smob-1.4.1.tgz", | ||||||
|       "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==", |       "integrity": "sha512-9LK+E7Hv5R9u4g4C3p+jjLstaLe11MDsL21UpYaCNmapvMkYhqCV4A/f/3gyH8QjMyh6l68q9xC85vihY9ahMQ==", | ||||||
|       "dev": true |       "dev": true | ||||||
|     }, |     }, | ||||||
|     "node_modules/source-map": { |     "node_modules/source-map": { | ||||||
| @@ -819,9 +780,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/terser": { |     "node_modules/terser": { | ||||||
|       "version": "5.31.0", |       "version": "5.29.1", | ||||||
|       "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz", |       "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.1.tgz", | ||||||
|       "integrity": "sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==", |       "integrity": "sha512-lZQ/fyaIGxsbGxApKmoPTODIzELy3++mXhS5hOqaAWZjQtpq/hFHAc+rm29NND1rYRxRWKcjuARNwULNXa5RtQ==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@jridgewell/source-map": "^0.3.3", |         "@jridgewell/source-map": "^0.3.3", | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								deps/crypt_blowfish
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								deps/crypt_blowfish
									
									
									
									
										vendored
									
									
								
							 Submodule deps/crypt_blowfish deleted from 3354bb81ee
									
								
							
							
								
								
									
										29
									
								
								deps/crypt_blowfish/LINKS
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								deps/crypt_blowfish/LINKS
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | New versions of this package (crypt_blowfish): | ||||||
|  |  | ||||||
|  | 	http://www.openwall.com/crypt/ | ||||||
|  |  | ||||||
|  | A paper on the algorithm that explains its design decisions: | ||||||
|  |  | ||||||
|  | 	http://www.usenix.org/events/usenix99/provos.html | ||||||
|  |  | ||||||
|  | Unix Seventh Edition Manual, Volume 2: the password scheme (1978): | ||||||
|  |  | ||||||
|  | 	http://plan9.bell-labs.com/7thEdMan/vol2/password | ||||||
|  |  | ||||||
|  | The Openwall GNU/*/Linux (Owl) tcb suite implementing the alternative | ||||||
|  | password shadowing scheme.  This includes a PAM module which | ||||||
|  | supersedes pam_unix and uses the password hashing framework provided | ||||||
|  | with crypt_blowfish when setting new passwords. | ||||||
|  |  | ||||||
|  | 	http://www.openwall.com/tcb/ | ||||||
|  |  | ||||||
|  | pam_passwdqc, a password strength checking and policy enforcement | ||||||
|  | module for PAM-aware password changing programs: | ||||||
|  |  | ||||||
|  | 	http://www.openwall.com/passwdqc/ | ||||||
|  |  | ||||||
|  | John the Ripper password cracker: | ||||||
|  |  | ||||||
|  | 	http://www.openwall.com/john/ | ||||||
|  |  | ||||||
|  | $Owl: Owl/packages/glibc/crypt_blowfish/LINKS,v 1.4 2005/11/16 13:09:47 solar Exp $ | ||||||
							
								
								
									
										77
									
								
								deps/crypt_blowfish/Makefile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								deps/crypt_blowfish/Makefile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | |||||||
|  | # | ||||||
|  | # Written and revised by Solar Designer <solar at openwall.com> in 2000-2011. | ||||||
|  | # No copyright is claimed, and the software is hereby placed in the public | ||||||
|  | # domain.  In case this attempt to disclaim copyright and place the software | ||||||
|  | # in the public domain is deemed null and void, then the software is | ||||||
|  | # Copyright (c) 2000-2011 Solar Designer and it is hereby released to the | ||||||
|  | # general public under the following terms: | ||||||
|  | # | ||||||
|  | # Redistribution and use in source and binary forms, with or without | ||||||
|  | # modification, are permitted. | ||||||
|  | # | ||||||
|  | # There's ABSOLUTELY NO WARRANTY, express or implied. | ||||||
|  | # | ||||||
|  | # See crypt_blowfish.c for more information. | ||||||
|  | # | ||||||
|  |  | ||||||
|  | CC = gcc | ||||||
|  | AS = $(CC) | ||||||
|  | LD = $(CC) | ||||||
|  | RM = rm -f | ||||||
|  | CFLAGS = -W -Wall -Wbad-function-cast -Wcast-align -Wcast-qual -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Wundef -Wpointer-arith -O2 -fomit-frame-pointer -funroll-loops | ||||||
|  | ASFLAGS = -c | ||||||
|  | LDFLAGS = -s | ||||||
|  |  | ||||||
|  | BLOWFISH_OBJS = \ | ||||||
|  | 	crypt_blowfish.o x86.o | ||||||
|  |  | ||||||
|  | CRYPT_OBJS = \ | ||||||
|  | 	$(BLOWFISH_OBJS) crypt_gensalt.o wrapper.o | ||||||
|  |  | ||||||
|  | TEST_OBJS = \ | ||||||
|  | 	$(BLOWFISH_OBJS) crypt_gensalt.o crypt_test.o | ||||||
|  |  | ||||||
|  | TEST_THREADS_OBJS = \ | ||||||
|  | 	$(BLOWFISH_OBJS) crypt_gensalt.o crypt_test_threads.o | ||||||
|  |  | ||||||
|  | EXTRA_MANS = \ | ||||||
|  | 	crypt_r.3 crypt_rn.3 crypt_ra.3 \ | ||||||
|  | 	crypt_gensalt.3 crypt_gensalt_rn.3 crypt_gensalt_ra.3 | ||||||
|  |  | ||||||
|  | all: $(CRYPT_OBJS) man | ||||||
|  |  | ||||||
|  | check: crypt_test | ||||||
|  | 	./crypt_test | ||||||
|  |  | ||||||
|  | crypt_test: $(TEST_OBJS) | ||||||
|  | 	$(LD) $(LDFLAGS) $(TEST_OBJS) -o $@ | ||||||
|  |  | ||||||
|  | crypt_test.o: wrapper.c ow-crypt.h crypt_blowfish.h crypt_gensalt.h | ||||||
|  | 	$(CC) -c $(CFLAGS) wrapper.c -DTEST -o $@ | ||||||
|  |  | ||||||
|  | check_threads: crypt_test_threads | ||||||
|  | 	./crypt_test_threads | ||||||
|  |  | ||||||
|  | crypt_test_threads: $(TEST_THREADS_OBJS) | ||||||
|  | 	$(LD) $(LDFLAGS) $(TEST_THREADS_OBJS) -lpthread -o $@ | ||||||
|  |  | ||||||
|  | crypt_test_threads.o: wrapper.c ow-crypt.h crypt_blowfish.h crypt_gensalt.h | ||||||
|  | 	$(CC) -c $(CFLAGS) wrapper.c -DTEST -DTEST_THREADS=4 -o $@ | ||||||
|  |  | ||||||
|  | man: $(EXTRA_MANS) | ||||||
|  |  | ||||||
|  | $(EXTRA_MANS): | ||||||
|  | 	echo '.so man3/crypt.3' > $@ | ||||||
|  |  | ||||||
|  | crypt_blowfish.o: crypt_blowfish.h | ||||||
|  | crypt_gensalt.o: crypt_gensalt.h | ||||||
|  | wrapper.o: crypt.h ow-crypt.h crypt_blowfish.h crypt_gensalt.h | ||||||
|  |  | ||||||
|  | .c.o: | ||||||
|  | 	$(CC) -c $(CFLAGS) $*.c | ||||||
|  |  | ||||||
|  | .S.o: | ||||||
|  | 	$(AS) $(ASFLAGS) $*.S | ||||||
|  |  | ||||||
|  | clean: | ||||||
|  | 	$(RM) crypt_test crypt_test_threads *.o $(EXTRA_MANS) core | ||||||
							
								
								
									
										30
									
								
								deps/crypt_blowfish/PERFORMANCE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								deps/crypt_blowfish/PERFORMANCE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | These numbers are for 32 iterations ("$2a$05"): | ||||||
|  |  | ||||||
|  | 			OpenBSD 3.0 bcrypt(*)	crypt_blowfish 0.4.4 | ||||||
|  | Pentium III, 840 MHz	99 c/s			121 c/s (+22%) | ||||||
|  | Alpha 21164PC, 533 MHz	55.5 c/s		76.9 c/s (+38%) | ||||||
|  | UltraSparc IIi, 400 MHz	49.9 c/s		52.5 c/s (+5%) | ||||||
|  | Pentium, 120 MHz	8.8 c/s			20.1 c/s (+128%) | ||||||
|  | PA-RISC 7100LC, 80 MHz	8.5 c/s			16.3 c/s (+92%) | ||||||
|  |  | ||||||
|  | (*) built with -fomit-frame-pointer -funroll-loops, which I don't | ||||||
|  | think happens for libcrypt. | ||||||
|  |  | ||||||
|  | Starting with version 1.1 released in June 2011, default builds of | ||||||
|  | crypt_blowfish invoke a quick self-test on every hash computation. | ||||||
|  | This has roughly a 4.8% performance impact at "$2a$05", but only a 0.6% | ||||||
|  | impact at a more typical setting of "$2a$08". | ||||||
|  |  | ||||||
|  | The large speedup for the original Pentium is due to the assembly | ||||||
|  | code and the weird optimizations this processor requires. | ||||||
|  |  | ||||||
|  | The numbers for password cracking are 2 to 10% higher than those for | ||||||
|  | crypt_blowfish as certain things may be done out of the loop and the | ||||||
|  | code doesn't need to be reentrant. | ||||||
|  |  | ||||||
|  | Recent versions of John the Ripper (1.6.25-dev and newer) achieve an | ||||||
|  | additional 15% speedup on the Pentium Pro family of processors (which | ||||||
|  | includes Pentium III) with a separate version of the assembly code and | ||||||
|  | run-time CPU detection. | ||||||
|  |  | ||||||
|  | $Owl: Owl/packages/glibc/crypt_blowfish/PERFORMANCE,v 1.6 2011/06/21 12:09:20 solar Exp $ | ||||||
							
								
								
									
										68
									
								
								deps/crypt_blowfish/README
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								deps/crypt_blowfish/README
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | |||||||
|  | This is an implementation of a password hashing method, provided via the | ||||||
|  | crypt(3) and a reentrant interface.  It is fully compatible with | ||||||
|  | OpenBSD's bcrypt.c for prefix "$2b$", originally by Niels Provos and | ||||||
|  | David Mazieres.  (Please refer to the included crypt(3) man page for | ||||||
|  | information on minor compatibility issues for other bcrypt prefixes.) | ||||||
|  |  | ||||||
|  | I've placed this code in the public domain, with fallback to a | ||||||
|  | permissive license.  Please see the comment in crypt_blowfish.c for | ||||||
|  | more information. | ||||||
|  |  | ||||||
|  | You can use the provided routines in your own packages, or link them | ||||||
|  | into a C library.  I've provided hooks for linking into GNU libc, but | ||||||
|  | it shouldn't be too hard to get this into another C library.  Note | ||||||
|  | that simply adding this code into your libc is probably not enough to | ||||||
|  | make your system use the new password hashing algorithm.  Changes to | ||||||
|  | passwd(1), PAM modules, or whatever else your system uses will likely | ||||||
|  | be needed as well.  These are not a part of this package, but see | ||||||
|  | LINKS for a pointer to our tcb suite. | ||||||
|  |  | ||||||
|  | Instructions on using the routines in one of the two common ways are | ||||||
|  | given below.  It is recommended that you test the routines on your | ||||||
|  | system before you start.  Type "make check" or "make check_threads" | ||||||
|  | (if you have the POSIX threads library), then "make clean". | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 1. Using the routines in your programs. | ||||||
|  |  | ||||||
|  | The available interfaces are in ow-crypt.h, and this is the file you | ||||||
|  | should include.  You won't need crypt.h.  When linking, add all of the | ||||||
|  | C files and x86.S (you can compile and link it even on a non-x86, it | ||||||
|  | will produce no code in this case). | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 2. Building the routines into GNU C library. | ||||||
|  |  | ||||||
|  | For versions 2.13 and 2.14 (and likely other nearby ones), extract the | ||||||
|  | library sources as usual.  Apply the patch for glibc 2.14 provided in | ||||||
|  | this package.  Enter crypt/ and rename crypt.h to gnu-crypt.h within | ||||||
|  | that directory.  Copy the C sources, header, and assembly (x86.S) files | ||||||
|  | from this package in there as well (but be sure you don't overwrite the | ||||||
|  | Makefile).  Configure, build, and install the library as usual. | ||||||
|  |  | ||||||
|  | For versions 2.2 to 2.3.6 (and likely also for some newer ones), | ||||||
|  | extract the library sources and maybe its optional add-ons as usual. | ||||||
|  | Apply the patch for glibc 2.3.6 provided in this package.  Enter | ||||||
|  | crypt/ and rename crypt.h to gnu-crypt.h within that directory.  Copy | ||||||
|  | the C sources, header, and assembly (x86.S) files from this package in | ||||||
|  | there as well (but be sure you don't overwrite the Makefile). | ||||||
|  | Configure, build, and install the library as usual. | ||||||
|  |  | ||||||
|  | For versions 2.1 to 2.1.3, extract the library sources and the crypt | ||||||
|  | and linuxthreads add-ons as usual.  Apply the patch for glibc 2.1.3 | ||||||
|  | provided in this package.  Enter crypt/sysdeps/unix/, and rename | ||||||
|  | crypt.h to gnu-crypt.h within that directory.  Copy C sources, header, | ||||||
|  | and assembly (x86.S) files from this package in there as well (but be | ||||||
|  | sure you don't overwrite the Makefile).  Configure, build, and install | ||||||
|  | the library as usual. | ||||||
|  |  | ||||||
|  | Programs that want to use the provided interfaces will need to include | ||||||
|  | crypt.h (but not ow-crypt.h directly).  By default, prototypes for the | ||||||
|  | new routines aren't defined (but the extra functionality of crypt(3) | ||||||
|  | is indeed available).  You need to define _OW_SOURCE to obtain the new | ||||||
|  | routines as well. | ||||||
|  |  | ||||||
|  | --  | ||||||
|  | Solar Designer <solar at openwall.com> | ||||||
|  |  | ||||||
|  | $Owl: Owl/packages/glibc/crypt_blowfish/README,v 1.10 2014/07/07 15:19:04 solar Exp $ | ||||||
							
								
								
									
										575
									
								
								deps/crypt_blowfish/crypt.3
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										575
									
								
								deps/crypt_blowfish/crypt.3
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,575 @@ | |||||||
|  | .\" Written and revised by Solar Designer <solar at openwall.com> in 2000-2011. | ||||||
|  | .\" No copyright is claimed, and this man page is hereby placed in the public | ||||||
|  | .\" domain.  In case this attempt to disclaim copyright and place the man page | ||||||
|  | .\" in the public domain is deemed null and void, then the man page is | ||||||
|  | .\" Copyright (c) 2000-2011 Solar Designer and it is hereby released to the | ||||||
|  | .\" general public under the following terms: | ||||||
|  | .\" | ||||||
|  | .\" Redistribution and use in source and binary forms, with or without | ||||||
|  | .\" modification, are permitted. | ||||||
|  | .\" | ||||||
|  | .\" There's ABSOLUTELY NO WARRANTY, express or implied. | ||||||
|  | .\" | ||||||
|  | .\" This manual page in its current form is intended for use on systems | ||||||
|  | .\" based on the GNU C Library with crypt_blowfish patched into libcrypt. | ||||||
|  | .\" | ||||||
|  | .TH CRYPT 3 "July 7, 2014" "Openwall Project" "Library functions" | ||||||
|  | .ad l | ||||||
|  | .\" No macros in NAME to keep makewhatis happy. | ||||||
|  | .SH NAME | ||||||
|  | \fBcrypt\fR, \fBcrypt_r\fR, \fBcrypt_rn\fR, \fBcrypt_ra\fR, | ||||||
|  | \fBcrypt_gensalt\fR, \fBcrypt_gensalt_rn\fR, \fBcrypt_gensalt_ra\fR | ||||||
|  | \- password hashing | ||||||
|  | .SH SYNOPSIS | ||||||
|  | .B #define _XOPEN_SOURCE | ||||||
|  | .br | ||||||
|  | .B #include <unistd.h> | ||||||
|  | .sp | ||||||
|  | .in +8 | ||||||
|  | .ti -8 | ||||||
|  | .BI "char *crypt(const char *" key ", const char *" setting ); | ||||||
|  | .in -8 | ||||||
|  | .sp | ||||||
|  | .B #define _GNU_SOURCE | ||||||
|  | .br | ||||||
|  | .B #include <crypt.h> | ||||||
|  | .sp | ||||||
|  | .in +8 | ||||||
|  | .ti -8 | ||||||
|  | .BI "char *crypt_r(const char *" key ", const char *" setting ", struct crypt_data *" data ); | ||||||
|  | .in -8 | ||||||
|  | .sp | ||||||
|  | .B #define _OW_SOURCE | ||||||
|  | .br | ||||||
|  | .B #include <crypt.h> | ||||||
|  | .sp | ||||||
|  | .in +8 | ||||||
|  | .ti -8 | ||||||
|  | .BI "char *crypt_rn(const char *" key ", const char *" setting ", void *" data ", int " size ); | ||||||
|  | .ti -8 | ||||||
|  | .BI "char *crypt_ra(const char *" key ", const char *" setting ", void **" data ", int *" size ); | ||||||
|  | .ti -8 | ||||||
|  | .BI "char *crypt_gensalt(const char *" prefix ", unsigned long " count ", const char *" input ", int " size ); | ||||||
|  | .ti -8 | ||||||
|  | .BI "char *crypt_gensalt_rn(const char *" prefix ", unsigned long " count ", const char *" input ", int " size ", char *" output ", int " output_size ); | ||||||
|  | .ti -8 | ||||||
|  | .BI "char *crypt_gensalt_ra(const char *" prefix ", unsigned long " count ", const char *" input ", int " size ); | ||||||
|  | .ad b | ||||||
|  | .de crypt | ||||||
|  | .BR crypt , | ||||||
|  | .BR crypt_r , | ||||||
|  | .BR crypt_rn ", \\$1" | ||||||
|  | .ie "\\$2"" .B crypt_ra | ||||||
|  | .el .BR crypt_ra "\\$2" | ||||||
|  | .. | ||||||
|  | .de crypt_gensalt | ||||||
|  | .BR crypt_gensalt , | ||||||
|  | .BR crypt_gensalt_rn ", \\$1" | ||||||
|  | .ie "\\$2"" .B crypt_gensalt_ra | ||||||
|  | .el .BR crypt_gensalt_ra "\\$2" | ||||||
|  | .. | ||||||
|  | .SH DESCRIPTION | ||||||
|  | The | ||||||
|  | .crypt and | ||||||
|  | functions calculate a cryptographic hash function of | ||||||
|  | .I key | ||||||
|  | with one of a number of supported methods as requested with | ||||||
|  | .IR setting , | ||||||
|  | which is also used to pass a salt and possibly other parameters to | ||||||
|  | the chosen method. | ||||||
|  | The hashing methods are explained below. | ||||||
|  | .PP | ||||||
|  | Unlike | ||||||
|  | .BR crypt , | ||||||
|  | the functions | ||||||
|  | .BR crypt_r , | ||||||
|  | .BR crypt_rn " and" | ||||||
|  | .B crypt_ra | ||||||
|  | are reentrant. | ||||||
|  | They place their result and possibly their private data in a | ||||||
|  | .I data | ||||||
|  | area of | ||||||
|  | .I size | ||||||
|  | bytes as passed to them by an application and/or in memory they | ||||||
|  | allocate dynamically.  Some hashing algorithms may use the data area to | ||||||
|  | cache precomputed intermediate values across calls.  Thus, applications | ||||||
|  | must properly initialize the data area before its first use. | ||||||
|  | .B crypt_r | ||||||
|  | requires that only | ||||||
|  | .I data->initialized | ||||||
|  | be reset to zero; | ||||||
|  | .BR crypt_rn " and " crypt_ra | ||||||
|  | require that either the entire data area is zeroed or, in the case of | ||||||
|  | .BR crypt_ra , | ||||||
|  | .I *data | ||||||
|  | is NULL.  When called with a NULL | ||||||
|  | .I *data | ||||||
|  | or insufficient | ||||||
|  | .I *size | ||||||
|  | for the requested hashing algorithm, | ||||||
|  | .B crypt_ra | ||||||
|  | uses | ||||||
|  | .BR realloc (3) | ||||||
|  | to allocate the required amount of memory dynamically.  Thus, | ||||||
|  | .B crypt_ra | ||||||
|  | has the additional requirement that | ||||||
|  | .IR *data , | ||||||
|  | when non-NULL, must point to an area allocated either with a previous | ||||||
|  | call to | ||||||
|  | .B crypt_ra | ||||||
|  | or with a | ||||||
|  | .BR malloc (3) | ||||||
|  | family call. | ||||||
|  | The memory allocated by | ||||||
|  | .B crypt_ra | ||||||
|  | should be freed with | ||||||
|  | .BR free "(3)." | ||||||
|  | .PP | ||||||
|  | The | ||||||
|  | .crypt_gensalt and | ||||||
|  | functions compile a string for use as | ||||||
|  | .I setting | ||||||
|  | \- with the given | ||||||
|  | .I prefix | ||||||
|  | (used to choose a hashing method), the iteration | ||||||
|  | .I count | ||||||
|  | (if supported by the chosen method) and up to | ||||||
|  | .I size | ||||||
|  | cryptographically random | ||||||
|  | .I input | ||||||
|  | bytes for use as the actual salt. | ||||||
|  | If | ||||||
|  | .I count | ||||||
|  | is 0, a low default will be picked. | ||||||
|  | The random bytes may be obtained from | ||||||
|  | .BR /dev/urandom . | ||||||
|  | Unlike | ||||||
|  | .BR crypt_gensalt , | ||||||
|  | the functions | ||||||
|  | .BR crypt_gensalt_rn " and " crypt_gensalt_ra | ||||||
|  | are reentrant. | ||||||
|  | .B crypt_gensalt_rn | ||||||
|  | places its result in the | ||||||
|  | .I output | ||||||
|  | buffer of | ||||||
|  | .I output_size | ||||||
|  | bytes. | ||||||
|  | .B crypt_gensalt_ra | ||||||
|  | allocates memory for its result dynamically.  The memory should be | ||||||
|  | freed with | ||||||
|  | .BR free "(3)." | ||||||
|  | .SH RETURN VALUE | ||||||
|  | Upon successful completion, the functions | ||||||
|  | .crypt and | ||||||
|  | return a pointer to a string containing the setting that was actually used | ||||||
|  | and a printable encoding of the hash function value. | ||||||
|  | The entire string is directly usable as | ||||||
|  | .I setting | ||||||
|  | with other calls to | ||||||
|  | .crypt and | ||||||
|  | and as | ||||||
|  | .I prefix | ||||||
|  | with calls to | ||||||
|  | .crypt_gensalt and . | ||||||
|  | .PP | ||||||
|  | The behavior of | ||||||
|  | .B crypt | ||||||
|  | on errors isn't well standardized.  Some implementations simply can't fail | ||||||
|  | (unless the process dies, in which case they obviously can't return), | ||||||
|  | others return NULL or a fixed string.  Most implementations don't set | ||||||
|  | .IR errno , | ||||||
|  | but some do.  SUSv2 specifies only returning NULL and setting | ||||||
|  | .I errno | ||||||
|  | as a valid behavior, and defines only one possible error | ||||||
|  | .RB "(" ENOSYS , | ||||||
|  | "The functionality is not supported on this implementation.") | ||||||
|  | Unfortunately, most existing applications aren't prepared to handle | ||||||
|  | NULL returns from | ||||||
|  | .BR crypt . | ||||||
|  | The description below corresponds to this implementation of | ||||||
|  | .BR crypt " and " crypt_r | ||||||
|  | only, and to | ||||||
|  | .BR crypt_rn " and " crypt_ra . | ||||||
|  | The behavior may change to match standards, other implementations or | ||||||
|  | existing applications. | ||||||
|  | .PP | ||||||
|  | .BR crypt " and " crypt_r | ||||||
|  | may only fail (and return) when passed an invalid or unsupported | ||||||
|  | .IR setting , | ||||||
|  | in which case they return a pointer to a magic string that is | ||||||
|  | shorter than 13 characters and is guaranteed to differ from | ||||||
|  | .IR setting . | ||||||
|  | This behavior is safe for older applications which assume that | ||||||
|  | .B crypt | ||||||
|  | can't fail, when both setting new passwords and authenticating against | ||||||
|  | existing password hashes. | ||||||
|  | .BR crypt_rn " and " crypt_ra | ||||||
|  | return NULL to indicate failure.  All four functions set | ||||||
|  | .I errno | ||||||
|  | when they fail. | ||||||
|  | .PP | ||||||
|  | The functions | ||||||
|  | .crypt_gensalt and | ||||||
|  | return a pointer to the compiled string for | ||||||
|  | .IR setting , | ||||||
|  | or NULL on error in which case | ||||||
|  | .I errno | ||||||
|  | is set. | ||||||
|  | .SH ERRORS | ||||||
|  | .TP | ||||||
|  | .B EINVAL | ||||||
|  | .crypt "" : | ||||||
|  | .I setting | ||||||
|  | is invalid or not supported by this implementation; | ||||||
|  | .sp | ||||||
|  | .crypt_gensalt "" : | ||||||
|  | .I prefix | ||||||
|  | is invalid or not supported by this implementation; | ||||||
|  | .I count | ||||||
|  | is invalid for the requested | ||||||
|  | .IR prefix ; | ||||||
|  | the input | ||||||
|  | .I size | ||||||
|  | is insufficient for the smallest valid salt with the requested | ||||||
|  | .IR prefix ; | ||||||
|  | .I input | ||||||
|  | is NULL. | ||||||
|  | .TP | ||||||
|  | .B ERANGE | ||||||
|  | .BR crypt_rn : | ||||||
|  | the provided data area | ||||||
|  | .I size | ||||||
|  | is insufficient for the requested hashing algorithm; | ||||||
|  | .sp | ||||||
|  | .BR crypt_gensalt_rn : | ||||||
|  | .I output_size | ||||||
|  | is too small to hold the compiled | ||||||
|  | .I setting | ||||||
|  | string. | ||||||
|  | .TP | ||||||
|  | .B ENOMEM | ||||||
|  | .B crypt | ||||||
|  | (original glibc only): | ||||||
|  | failed to allocate memory for the output buffer (which subsequent calls | ||||||
|  | would re-use); | ||||||
|  | .sp | ||||||
|  | .BR crypt_ra : | ||||||
|  | .I *data | ||||||
|  | is NULL or | ||||||
|  | .I *size | ||||||
|  | is insufficient for the requested hashing algorithm and | ||||||
|  | .BR realloc (3) | ||||||
|  | failed; | ||||||
|  | .sp | ||||||
|  | .BR crypt_gensalt_ra : | ||||||
|  | failed to allocate memory for the compiled | ||||||
|  | .I setting | ||||||
|  | string. | ||||||
|  | .TP | ||||||
|  | .B ENOSYS | ||||||
|  | .B crypt | ||||||
|  | (SUSv2): | ||||||
|  | the functionality is not supported on this implementation; | ||||||
|  | .sp | ||||||
|  | .BR crypt , | ||||||
|  | .B crypt_r | ||||||
|  | (glibc 2.0 to 2.0.1 only): | ||||||
|  | .de no-crypt-add-on | ||||||
|  | the crypt add-on is not compiled in and | ||||||
|  | .I setting | ||||||
|  | requests something other than the MD5-based algorithm. | ||||||
|  | .. | ||||||
|  | .no-crypt-add-on | ||||||
|  | .TP | ||||||
|  | .B EOPNOTSUPP | ||||||
|  | .BR crypt , | ||||||
|  | .B crypt_r | ||||||
|  | (glibc 2.0.2 to 2.1.3 only): | ||||||
|  | .no-crypt-add-on | ||||||
|  | .SH HASHING METHODS | ||||||
|  | The implemented hashing methods are intended specifically for processing | ||||||
|  | user passwords for storage and authentication; | ||||||
|  | they are at best inefficient for most other purposes. | ||||||
|  | .PP | ||||||
|  | It is important to understand that password hashing is not a replacement | ||||||
|  | for strong passwords. | ||||||
|  | It is always possible for an attacker with access to password hashes | ||||||
|  | to try guessing candidate passwords against the hashes. | ||||||
|  | There are, however, certain properties a password hashing method may have | ||||||
|  | which make these key search attacks somewhat harder. | ||||||
|  | .PP | ||||||
|  | All of the hashing methods use salts such that the same | ||||||
|  | .I key | ||||||
|  | may produce many possible hashes. | ||||||
|  | Proper use of salts may defeat a number of attacks, including: | ||||||
|  | .TP | ||||||
|  | 1. | ||||||
|  | The ability to try candidate passwords against multiple hashes at the | ||||||
|  | price of one. | ||||||
|  | .TP | ||||||
|  | 2. | ||||||
|  | The use of pre-hashed lists of candidate passwords. | ||||||
|  | .TP | ||||||
|  | 3. | ||||||
|  | The ability to determine whether two users (or two accounts of one user) | ||||||
|  | have the same or different passwords without actually having to guess | ||||||
|  | one of the passwords. | ||||||
|  | .PP | ||||||
|  | The key search attacks depend on computing hashes of large numbers of | ||||||
|  | candidate passwords. | ||||||
|  | Thus, the computational cost of a good password hashing method must be | ||||||
|  | high \- but of course not too high to render it impractical. | ||||||
|  | .PP | ||||||
|  | All hashing methods implemented within the | ||||||
|  | .crypt and | ||||||
|  | interfaces use multiple iterations of an underlying cryptographic | ||||||
|  | primitive specifically in order to increase the cost of trying a | ||||||
|  | candidate password. | ||||||
|  | Unfortunately, due to hardware improvements, the hashing methods which | ||||||
|  | have a fixed cost become increasingly less secure over time. | ||||||
|  | .PP | ||||||
|  | In addition to salts, modern password hashing methods accept a variable | ||||||
|  | iteration | ||||||
|  | .IR count . | ||||||
|  | This makes it possible to adapt their cost to the hardware improvements | ||||||
|  | while still maintaining compatibility. | ||||||
|  | .PP | ||||||
|  | The following hashing methods are or may be implemented within the | ||||||
|  | described interfaces: | ||||||
|  | .PP | ||||||
|  | .de hash | ||||||
|  | .ad l | ||||||
|  | .TP | ||||||
|  | .I prefix | ||||||
|  | .ie "\\$1"" \{\ | ||||||
|  | "" (empty string); | ||||||
|  | .br | ||||||
|  | a string matching ^[./0-9A-Za-z]{2} (see | ||||||
|  | .BR regex (7)) | ||||||
|  | .\} | ||||||
|  | .el "\\$1" | ||||||
|  | .TP | ||||||
|  | .B Encoding syntax | ||||||
|  | \\$2 | ||||||
|  | .TP | ||||||
|  | .B Maximum password length | ||||||
|  | \\$3 (uses \\$4-bit characters) | ||||||
|  | .TP | ||||||
|  | .B Effective key size | ||||||
|  | .ie "\\$5"" limited by the hash size only | ||||||
|  | .el up to \\$5 bits | ||||||
|  | .TP | ||||||
|  | .B Hash size | ||||||
|  | \\$6 bits | ||||||
|  | .TP | ||||||
|  | .B Salt size | ||||||
|  | \\$7 bits | ||||||
|  | .TP | ||||||
|  | .B Iteration count | ||||||
|  | \\$8 | ||||||
|  | .ad b | ||||||
|  | .. | ||||||
|  | .ti -2 | ||||||
|  | .B Traditional DES-based | ||||||
|  | .br | ||||||
|  | This method is supported by almost all implementations of | ||||||
|  | .BR crypt . | ||||||
|  | Unfortunately, it no longer offers adequate security because of its many | ||||||
|  | limitations. | ||||||
|  | Thus, it should not be used for new passwords unless you absolutely have | ||||||
|  | to be able to migrate the password hashes to other systems. | ||||||
|  | .hash "" "[./0-9A-Za-z]{13}" 8 7 56 64 12 25 | ||||||
|  | .PP | ||||||
|  | .ti -2 | ||||||
|  | .B Extended BSDI-style DES-based | ||||||
|  | .br | ||||||
|  | This method is used on BSDI and is also available on at least NetBSD, | ||||||
|  | OpenBSD, and FreeBSD due to the use of David Burren's FreeSec library. | ||||||
|  | .hash _ "_[./0-9A-Za-z]{19}" unlimited 7 56 64 24 "1 to 2**24-1 (must be odd)" | ||||||
|  | .PP | ||||||
|  | .ti -2 | ||||||
|  | .B FreeBSD-style MD5-based | ||||||
|  | .br | ||||||
|  | This is Poul-Henning Kamp's MD5-based password hashing method originally | ||||||
|  | developed for FreeBSD. | ||||||
|  | It is currently supported on many free Unix-like systems, on Solaris 10 | ||||||
|  | and newer, and it is part of the official glibc. | ||||||
|  | Its main disadvantage is the fixed iteration count, which is already | ||||||
|  | too low for the currently available hardware. | ||||||
|  | .hash "$1$" "\e$1\e$[^$]{1,8}\e$[./0-9A-Za-z]{22}" unlimited 8 "" 128 "6 to 48" 1000 | ||||||
|  | .PP | ||||||
|  | .ti -2 | ||||||
|  | .BR "OpenBSD-style Blowfish-based" " (" bcrypt ) | ||||||
|  | .br | ||||||
|  | .B bcrypt | ||||||
|  | was originally developed by Niels Provos and David Mazieres for OpenBSD | ||||||
|  | and is also supported on recent versions of FreeBSD and NetBSD, | ||||||
|  | on Solaris 10 and newer, and on several GNU/*/Linux distributions. | ||||||
|  | It is, however, not part of the official glibc. | ||||||
|  | .PP | ||||||
|  | While both | ||||||
|  | .B bcrypt | ||||||
|  | and the BSDI-style DES-based hashing offer a variable iteration count, | ||||||
|  | .B bcrypt | ||||||
|  | may scale to even faster hardware, doesn't allow for certain optimizations | ||||||
|  | specific to password cracking only, doesn't have the effective key size | ||||||
|  | limitation, and uses 8-bit characters in passwords. | ||||||
|  | .hash "$2b$" "\e$2[abxy]\e$[0-9]{2}\e$[./A-Za-z0-9]{53}" 72 8 "" 184 128 "2**4 to 2**99 (current implementations are limited to 2**31 iterations)" | ||||||
|  | .PP | ||||||
|  | With | ||||||
|  | .BR bcrypt , | ||||||
|  | the | ||||||
|  | .I count | ||||||
|  | passed to | ||||||
|  | .crypt_gensalt and | ||||||
|  | is the base-2 logarithm of the actual iteration count. | ||||||
|  | .PP | ||||||
|  | .B bcrypt | ||||||
|  | hashes used the "$2a$" prefix since 1997. | ||||||
|  | However, in 2011 an implementation bug was discovered in crypt_blowfish | ||||||
|  | (versions up to 1.0.4 inclusive) affecting handling of password characters with | ||||||
|  | the 8th bit set. | ||||||
|  | Besides fixing the bug, | ||||||
|  | to provide for upgrade strategies for existing systems, two new prefixes were | ||||||
|  | introduced: "$2x$", which fully re-introduces the bug, and "$2y$", which | ||||||
|  | guarantees correct handling of both 7- and 8-bit characters. | ||||||
|  | OpenBSD 5.5 introduced the "$2b$" prefix for behavior that exactly matches | ||||||
|  | crypt_blowfish's "$2y$", and current crypt_blowfish supports it as well. | ||||||
|  | Unfortunately, the behavior of "$2a$" on password characters with the 8th bit | ||||||
|  | set has to be considered system-specific. | ||||||
|  | When generating new password hashes, the "$2b$" or "$2y$" prefix should be used. | ||||||
|  | (If such hashes ever need to be migrated to a system that does not yet support | ||||||
|  | these new prefixes, the prefix in migrated copies of the already-generated | ||||||
|  | hashes may be changed to "$2a$".) | ||||||
|  | .PP | ||||||
|  | .crypt_gensalt and | ||||||
|  | support the "$2b$", "$2y$", and "$2a$" prefixes (the latter for legacy programs | ||||||
|  | or configurations), but not "$2x$" (which must not be used for new hashes). | ||||||
|  | .crypt and | ||||||
|  | support all four of these prefixes. | ||||||
|  | .SH PORTABILITY NOTES | ||||||
|  | Programs using any of these functions on a glibc 2.x system must be | ||||||
|  | linked against | ||||||
|  | .BR libcrypt . | ||||||
|  | However, many Unix-like operating systems and older versions of the | ||||||
|  | GNU C Library include the | ||||||
|  | .BR crypt " function in " libc . | ||||||
|  | .PP | ||||||
|  | The | ||||||
|  | .BR crypt_r , | ||||||
|  | .BR crypt_rn , | ||||||
|  | .BR crypt_ra , | ||||||
|  | .crypt_gensalt and | ||||||
|  | functions are very non-portable. | ||||||
|  | .PP | ||||||
|  | The set of supported hashing methods is implementation-dependent. | ||||||
|  | .SH CONFORMING TO | ||||||
|  | The | ||||||
|  | .B crypt | ||||||
|  | function conforms to SVID, X/OPEN, and is available on BSD 4.3. | ||||||
|  | The strings returned by | ||||||
|  | .B crypt | ||||||
|  | are not required to be portable among conformant systems. | ||||||
|  | .PP | ||||||
|  | .B crypt_r | ||||||
|  | is a GNU extension. | ||||||
|  | There's also a | ||||||
|  | .B crypt_r | ||||||
|  | function on HP-UX and MKS Toolkit, but the prototypes and semantics differ. | ||||||
|  | .PP | ||||||
|  | .B crypt_gensalt | ||||||
|  | is an Openwall extension. | ||||||
|  | There's also a | ||||||
|  | .B crypt_gensalt | ||||||
|  | function on Solaris 10 and newer, but the prototypes and semantics differ. | ||||||
|  | .PP | ||||||
|  | .BR crypt_rn , | ||||||
|  | .BR crypt_ra , | ||||||
|  | .BR crypt_gensalt_rn , | ||||||
|  | and | ||||||
|  | .B crypt_gensalt_ra | ||||||
|  | are Openwall extensions. | ||||||
|  | .SH HISTORY | ||||||
|  | A rotor-based | ||||||
|  | .B crypt | ||||||
|  | function appeared in Version 6 AT&T UNIX. | ||||||
|  | The "traditional" | ||||||
|  | .B crypt | ||||||
|  | first appeared in Version 7 AT&T UNIX. | ||||||
|  | .PP | ||||||
|  | The | ||||||
|  | .B crypt_r | ||||||
|  | function was introduced during glibc 2.0 development. | ||||||
|  | .SH BUGS | ||||||
|  | The return values of | ||||||
|  | .BR crypt " and " crypt_gensalt | ||||||
|  | point to static buffers that are overwritten by subsequent calls. | ||||||
|  | These functions are not thread-safe. | ||||||
|  | .RB ( crypt | ||||||
|  | on recent versions of Solaris uses thread-specific data and actually is | ||||||
|  | thread-safe.) | ||||||
|  | .PP | ||||||
|  | The strings returned by certain other implementations of | ||||||
|  | .B crypt | ||||||
|  | on error may be stored in read-only locations or only initialized once, | ||||||
|  | which makes it unsafe to always attempt to zero out the buffer normally | ||||||
|  | pointed to by the | ||||||
|  | .B crypt | ||||||
|  | return value as it would otherwise be preferable for security reasons. | ||||||
|  | The problem could be avoided with the use of | ||||||
|  | .BR crypt_r , | ||||||
|  | .BR crypt_rn , | ||||||
|  | or | ||||||
|  | .B crypt_ra | ||||||
|  | where the application has full control over output buffers of these functions | ||||||
|  | (and often over some of their private data as well). | ||||||
|  | Unfortunately, the functions aren't (yet?) available on platforms where | ||||||
|  | .B crypt | ||||||
|  | has this undesired property. | ||||||
|  | .PP | ||||||
|  | Applications using the thread-safe | ||||||
|  | .B crypt_r | ||||||
|  | need to allocate address space for the large (over 128 KB) | ||||||
|  | .I struct crypt_data | ||||||
|  | structure.  Each thread needs a separate instance of the structure.  The | ||||||
|  | .B crypt_r | ||||||
|  | interface makes it impossible to implement a hashing algorithm which | ||||||
|  | would need to keep an even larger amount of private data, without breaking | ||||||
|  | binary compatibility. | ||||||
|  | .B crypt_ra | ||||||
|  | allows for dynamically increasing the allocation size as required by the | ||||||
|  | hashing algorithm that is actually used.  Unfortunately, | ||||||
|  | .B crypt_ra | ||||||
|  | is even more non-portable than | ||||||
|  | .BR crypt_r . | ||||||
|  | .PP | ||||||
|  | Multi-threaded applications or library functions which are meant to be | ||||||
|  | thread-safe should use | ||||||
|  | .BR crypt_gensalt_rn " or " crypt_gensalt_ra | ||||||
|  | rather than | ||||||
|  | .BR crypt_gensalt . | ||||||
|  | .SH SEE ALSO | ||||||
|  | .BR login (1), | ||||||
|  | .BR passwd (1), | ||||||
|  | .BR crypto (3), | ||||||
|  | .BR encrypt (3), | ||||||
|  | .BR free (3), | ||||||
|  | .BR getpass (3), | ||||||
|  | .BR getpwent (3), | ||||||
|  | .BR malloc (3), | ||||||
|  | .BR realloc (3), | ||||||
|  | .BR shadow (3), | ||||||
|  | .BR passwd (5), | ||||||
|  | .BR shadow (5), | ||||||
|  | .BR regex (7), | ||||||
|  | .BR pam (8) | ||||||
|  | .sp | ||||||
|  | Niels Provos and David Mazieres.  A Future-Adaptable Password Scheme. | ||||||
|  | Proceedings of the 1999 USENIX Annual Technical Conference, June 1999. | ||||||
|  | .br | ||||||
|  | http://www.usenix.org/events/usenix99/provos.html | ||||||
|  | .sp | ||||||
|  | Robert Morris and Ken Thompson.  Password Security: A Case History. | ||||||
|  | Unix Seventh Edition Manual, Volume 2, April 1978. | ||||||
|  | .br | ||||||
|  | http://plan9.bell-labs.com/7thEdMan/vol2/password | ||||||
							
								
								
									
										24
									
								
								deps/crypt_blowfish/crypt.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								deps/crypt_blowfish/crypt.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | /* | ||||||
|  |  * Written by Solar Designer <solar at openwall.com> in 2000-2002. | ||||||
|  |  * No copyright is claimed, and the software is hereby placed in the public | ||||||
|  |  * domain.  In case this attempt to disclaim copyright and place the software | ||||||
|  |  * in the public domain is deemed null and void, then the software is | ||||||
|  |  * Copyright (c) 2000-2002 Solar Designer and it is hereby released to the | ||||||
|  |  * general public under the following terms: | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted. | ||||||
|  |  * | ||||||
|  |  * There's ABSOLUTELY NO WARRANTY, express or implied. | ||||||
|  |  * | ||||||
|  |  * See crypt_blowfish.c for more information. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <gnu-crypt.h> | ||||||
|  |  | ||||||
|  | #if defined(_OW_SOURCE) || defined(__USE_OW) | ||||||
|  | #define __SKIP_GNU | ||||||
|  | #undef __SKIP_OW | ||||||
|  | #include <ow-crypt.h> | ||||||
|  | #undef __SKIP_GNU | ||||||
|  | #endif | ||||||
							
								
								
									
										907
									
								
								deps/crypt_blowfish/crypt_blowfish.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										907
									
								
								deps/crypt_blowfish/crypt_blowfish.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,907 @@ | |||||||
|  | /* | ||||||
|  |  * The crypt_blowfish homepage is: | ||||||
|  |  * | ||||||
|  |  *	http://www.openwall.com/crypt/ | ||||||
|  |  * | ||||||
|  |  * This code comes from John the Ripper password cracker, with reentrant | ||||||
|  |  * and crypt(3) interfaces added, but optimizations specific to password | ||||||
|  |  * cracking removed. | ||||||
|  |  * | ||||||
|  |  * Written by Solar Designer <solar at openwall.com> in 1998-2014. | ||||||
|  |  * No copyright is claimed, and the software is hereby placed in the public | ||||||
|  |  * domain.  In case this attempt to disclaim copyright and place the software | ||||||
|  |  * in the public domain is deemed null and void, then the software is | ||||||
|  |  * Copyright (c) 1998-2014 Solar Designer and it is hereby released to the | ||||||
|  |  * general public under the following terms: | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted. | ||||||
|  |  * | ||||||
|  |  * There's ABSOLUTELY NO WARRANTY, express or implied. | ||||||
|  |  * | ||||||
|  |  * It is my intent that you should be able to use this on your system, | ||||||
|  |  * as part of a software package, or anywhere else to improve security, | ||||||
|  |  * ensure compatibility, or for any other purpose.  I would appreciate | ||||||
|  |  * it if you give credit where it is due and keep your modifications in | ||||||
|  |  * the public domain as well, but I don't require that in order to let | ||||||
|  |  * you place this code and any modifications you make under a license | ||||||
|  |  * of your choice. | ||||||
|  |  * | ||||||
|  |  * This implementation is fully compatible with OpenBSD's bcrypt.c for prefix | ||||||
|  |  * "$2b$", originally by Niels Provos <provos at citi.umich.edu>, and it uses | ||||||
|  |  * some of his ideas.  The password hashing algorithm was designed by David | ||||||
|  |  * Mazieres <dm at lcs.mit.edu>.  For information on the level of | ||||||
|  |  * compatibility for bcrypt hash prefixes other than "$2b$", please refer to | ||||||
|  |  * the comments in BF_set_key() below and to the included crypt(3) man page. | ||||||
|  |  * | ||||||
|  |  * There's a paper on the algorithm that explains its design decisions: | ||||||
|  |  * | ||||||
|  |  *	http://www.usenix.org/events/usenix99/provos.html | ||||||
|  |  * | ||||||
|  |  * Some of the tricks in BF_ROUND might be inspired by Eric Young's | ||||||
|  |  * Blowfish library (I can't be sure if I would think of something if I | ||||||
|  |  * hadn't seen his code). | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | #include <errno.h> | ||||||
|  | #ifndef __set_errno | ||||||
|  | #define __set_errno(val) errno = (val) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | /* Just to make sure the prototypes match the actual definitions */ | ||||||
|  | #include "crypt_blowfish.h" | ||||||
|  |  | ||||||
|  | #ifdef __i386__ | ||||||
|  | #define BF_ASM				1 | ||||||
|  | #define BF_SCALE			1 | ||||||
|  | #elif defined(__x86_64__) || defined(__alpha__) || defined(__hppa__) | ||||||
|  | #define BF_ASM				0 | ||||||
|  | #define BF_SCALE			1 | ||||||
|  | #else | ||||||
|  | #define BF_ASM				0 | ||||||
|  | #define BF_SCALE			0 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | typedef unsigned int BF_word; | ||||||
|  | typedef signed int BF_word_signed; | ||||||
|  |  | ||||||
|  | /* Number of Blowfish rounds, this is also hardcoded into a few places */ | ||||||
|  | #define BF_N				16 | ||||||
|  |  | ||||||
|  | typedef BF_word BF_key[BF_N + 2]; | ||||||
|  |  | ||||||
|  | typedef struct { | ||||||
|  | 	BF_word S[4][0x100]; | ||||||
|  | 	BF_key P; | ||||||
|  | } BF_ctx; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Magic IV for 64 Blowfish encryptions that we do at the end. | ||||||
|  |  * The string is "OrpheanBeholderScryDoubt" on big-endian. | ||||||
|  |  */ | ||||||
|  | static BF_word BF_magic_w[6] = { | ||||||
|  | 	0x4F727068, 0x65616E42, 0x65686F6C, | ||||||
|  | 	0x64657253, 0x63727944, 0x6F756274 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * P-box and S-box tables initialized with digits of Pi. | ||||||
|  |  */ | ||||||
|  | static BF_ctx BF_init_state = { | ||||||
|  | 	{ | ||||||
|  | 		{ | ||||||
|  | 			0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, | ||||||
|  | 			0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, | ||||||
|  | 			0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, | ||||||
|  | 			0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, | ||||||
|  | 			0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, | ||||||
|  | 			0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, | ||||||
|  | 			0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, | ||||||
|  | 			0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, | ||||||
|  | 			0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, | ||||||
|  | 			0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, | ||||||
|  | 			0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, | ||||||
|  | 			0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, | ||||||
|  | 			0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, | ||||||
|  | 			0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, | ||||||
|  | 			0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, | ||||||
|  | 			0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, | ||||||
|  | 			0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, | ||||||
|  | 			0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, | ||||||
|  | 			0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, | ||||||
|  | 			0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, | ||||||
|  | 			0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, | ||||||
|  | 			0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, | ||||||
|  | 			0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, | ||||||
|  | 			0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, | ||||||
|  | 			0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, | ||||||
|  | 			0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, | ||||||
|  | 			0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, | ||||||
|  | 			0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, | ||||||
|  | 			0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, | ||||||
|  | 			0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, | ||||||
|  | 			0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, | ||||||
|  | 			0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, | ||||||
|  | 			0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, | ||||||
|  | 			0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, | ||||||
|  | 			0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, | ||||||
|  | 			0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, | ||||||
|  | 			0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, | ||||||
|  | 			0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, | ||||||
|  | 			0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, | ||||||
|  | 			0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, | ||||||
|  | 			0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, | ||||||
|  | 			0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, | ||||||
|  | 			0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, | ||||||
|  | 			0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, | ||||||
|  | 			0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, | ||||||
|  | 			0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, | ||||||
|  | 			0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, | ||||||
|  | 			0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, | ||||||
|  | 			0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, | ||||||
|  | 			0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, | ||||||
|  | 			0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, | ||||||
|  | 			0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, | ||||||
|  | 			0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, | ||||||
|  | 			0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, | ||||||
|  | 			0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, | ||||||
|  | 			0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, | ||||||
|  | 			0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, | ||||||
|  | 			0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, | ||||||
|  | 			0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, | ||||||
|  | 			0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, | ||||||
|  | 			0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, | ||||||
|  | 			0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, | ||||||
|  | 			0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, | ||||||
|  | 			0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a | ||||||
|  | 		}, { | ||||||
|  | 			0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, | ||||||
|  | 			0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, | ||||||
|  | 			0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, | ||||||
|  | 			0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, | ||||||
|  | 			0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, | ||||||
|  | 			0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, | ||||||
|  | 			0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, | ||||||
|  | 			0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, | ||||||
|  | 			0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, | ||||||
|  | 			0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, | ||||||
|  | 			0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, | ||||||
|  | 			0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, | ||||||
|  | 			0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, | ||||||
|  | 			0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, | ||||||
|  | 			0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, | ||||||
|  | 			0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, | ||||||
|  | 			0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, | ||||||
|  | 			0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, | ||||||
|  | 			0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, | ||||||
|  | 			0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, | ||||||
|  | 			0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, | ||||||
|  | 			0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, | ||||||
|  | 			0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, | ||||||
|  | 			0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, | ||||||
|  | 			0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, | ||||||
|  | 			0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, | ||||||
|  | 			0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, | ||||||
|  | 			0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, | ||||||
|  | 			0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, | ||||||
|  | 			0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, | ||||||
|  | 			0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, | ||||||
|  | 			0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, | ||||||
|  | 			0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, | ||||||
|  | 			0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, | ||||||
|  | 			0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, | ||||||
|  | 			0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, | ||||||
|  | 			0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, | ||||||
|  | 			0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, | ||||||
|  | 			0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, | ||||||
|  | 			0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, | ||||||
|  | 			0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, | ||||||
|  | 			0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, | ||||||
|  | 			0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, | ||||||
|  | 			0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, | ||||||
|  | 			0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, | ||||||
|  | 			0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, | ||||||
|  | 			0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, | ||||||
|  | 			0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, | ||||||
|  | 			0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, | ||||||
|  | 			0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, | ||||||
|  | 			0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, | ||||||
|  | 			0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, | ||||||
|  | 			0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, | ||||||
|  | 			0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, | ||||||
|  | 			0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, | ||||||
|  | 			0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061, | ||||||
|  | 			0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, | ||||||
|  | 			0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, | ||||||
|  | 			0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, | ||||||
|  | 			0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, | ||||||
|  | 			0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, | ||||||
|  | 			0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, | ||||||
|  | 			0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, | ||||||
|  | 			0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 | ||||||
|  | 		}, { | ||||||
|  | 			0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, | ||||||
|  | 			0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, | ||||||
|  | 			0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, | ||||||
|  | 			0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, | ||||||
|  | 			0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, | ||||||
|  | 			0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, | ||||||
|  | 			0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, | ||||||
|  | 			0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, | ||||||
|  | 			0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, | ||||||
|  | 			0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, | ||||||
|  | 			0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, | ||||||
|  | 			0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, | ||||||
|  | 			0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, | ||||||
|  | 			0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, | ||||||
|  | 			0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, | ||||||
|  | 			0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, | ||||||
|  | 			0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, | ||||||
|  | 			0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, | ||||||
|  | 			0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, | ||||||
|  | 			0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, | ||||||
|  | 			0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, | ||||||
|  | 			0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, | ||||||
|  | 			0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, | ||||||
|  | 			0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, | ||||||
|  | 			0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, | ||||||
|  | 			0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, | ||||||
|  | 			0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, | ||||||
|  | 			0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, | ||||||
|  | 			0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, | ||||||
|  | 			0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, | ||||||
|  | 			0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, | ||||||
|  | 			0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, | ||||||
|  | 			0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, | ||||||
|  | 			0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, | ||||||
|  | 			0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, | ||||||
|  | 			0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, | ||||||
|  | 			0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, | ||||||
|  | 			0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, | ||||||
|  | 			0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, | ||||||
|  | 			0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, | ||||||
|  | 			0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, | ||||||
|  | 			0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, | ||||||
|  | 			0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, | ||||||
|  | 			0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, | ||||||
|  | 			0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, | ||||||
|  | 			0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, | ||||||
|  | 			0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, | ||||||
|  | 			0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, | ||||||
|  | 			0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, | ||||||
|  | 			0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, | ||||||
|  | 			0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, | ||||||
|  | 			0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, | ||||||
|  | 			0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, | ||||||
|  | 			0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, | ||||||
|  | 			0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, | ||||||
|  | 			0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, | ||||||
|  | 			0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, | ||||||
|  | 			0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, | ||||||
|  | 			0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, | ||||||
|  | 			0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, | ||||||
|  | 			0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, | ||||||
|  | 			0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, | ||||||
|  | 			0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, | ||||||
|  | 			0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 | ||||||
|  | 		}, { | ||||||
|  | 			0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, | ||||||
|  | 			0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, | ||||||
|  | 			0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, | ||||||
|  | 			0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, | ||||||
|  | 			0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, | ||||||
|  | 			0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, | ||||||
|  | 			0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, | ||||||
|  | 			0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, | ||||||
|  | 			0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, | ||||||
|  | 			0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, | ||||||
|  | 			0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, | ||||||
|  | 			0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, | ||||||
|  | 			0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, | ||||||
|  | 			0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51, | ||||||
|  | 			0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, | ||||||
|  | 			0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, | ||||||
|  | 			0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, | ||||||
|  | 			0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, | ||||||
|  | 			0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, | ||||||
|  | 			0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd, | ||||||
|  | 			0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, | ||||||
|  | 			0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, | ||||||
|  | 			0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, | ||||||
|  | 			0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, | ||||||
|  | 			0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, | ||||||
|  | 			0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, | ||||||
|  | 			0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, | ||||||
|  | 			0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, | ||||||
|  | 			0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, | ||||||
|  | 			0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, | ||||||
|  | 			0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, | ||||||
|  | 			0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, | ||||||
|  | 			0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, | ||||||
|  | 			0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, | ||||||
|  | 			0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, | ||||||
|  | 			0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, | ||||||
|  | 			0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, | ||||||
|  | 			0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, | ||||||
|  | 			0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, | ||||||
|  | 			0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, | ||||||
|  | 			0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, | ||||||
|  | 			0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, | ||||||
|  | 			0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, | ||||||
|  | 			0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525, | ||||||
|  | 			0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, | ||||||
|  | 			0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, | ||||||
|  | 			0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, | ||||||
|  | 			0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, | ||||||
|  | 			0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, | ||||||
|  | 			0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d, | ||||||
|  | 			0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, | ||||||
|  | 			0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, | ||||||
|  | 			0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, | ||||||
|  | 			0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, | ||||||
|  | 			0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, | ||||||
|  | 			0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, | ||||||
|  | 			0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, | ||||||
|  | 			0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, | ||||||
|  | 			0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, | ||||||
|  | 			0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, | ||||||
|  | 			0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, | ||||||
|  | 			0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9, | ||||||
|  | 			0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, | ||||||
|  | 			0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 | ||||||
|  | 		} | ||||||
|  | 	}, { | ||||||
|  | 		0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, | ||||||
|  | 		0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89, | ||||||
|  | 		0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, | ||||||
|  | 		0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, | ||||||
|  | 		0x9216d5d9, 0x8979fb1b | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static unsigned char BF_itoa64[64 + 1] = | ||||||
|  | 	"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; | ||||||
|  |  | ||||||
|  | static unsigned char BF_atoi64[0x60] = { | ||||||
|  | 	64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1, | ||||||
|  | 	54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64, | ||||||
|  | 	64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, | ||||||
|  | 	17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 64, 64, 64, 64, 64, | ||||||
|  | 	64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, | ||||||
|  | 	43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #define BF_safe_atoi64(dst, src) \ | ||||||
|  | { \ | ||||||
|  | 	tmp = (unsigned char)(src); \ | ||||||
|  | 	if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \ | ||||||
|  | 	tmp = BF_atoi64[tmp]; \ | ||||||
|  | 	if (tmp > 63) return -1; \ | ||||||
|  | 	(dst) = tmp; \ | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int BF_decode(BF_word *dst, const char *src, int size) | ||||||
|  | { | ||||||
|  | 	unsigned char *dptr = (unsigned char *)dst; | ||||||
|  | 	unsigned char *end = dptr + size; | ||||||
|  | 	const unsigned char *sptr = (const unsigned char *)src; | ||||||
|  | 	unsigned int tmp, c1, c2, c3, c4; | ||||||
|  |  | ||||||
|  | 	do { | ||||||
|  | 		BF_safe_atoi64(c1, *sptr++); | ||||||
|  | 		BF_safe_atoi64(c2, *sptr++); | ||||||
|  | 		*dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4); | ||||||
|  | 		if (dptr >= end) break; | ||||||
|  |  | ||||||
|  | 		BF_safe_atoi64(c3, *sptr++); | ||||||
|  | 		*dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2); | ||||||
|  | 		if (dptr >= end) break; | ||||||
|  |  | ||||||
|  | 		BF_safe_atoi64(c4, *sptr++); | ||||||
|  | 		*dptr++ = ((c3 & 0x03) << 6) | c4; | ||||||
|  | 	} while (dptr < end); | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void BF_encode(char *dst, const BF_word *src, int size) | ||||||
|  | { | ||||||
|  | 	const unsigned char *sptr = (const unsigned char *)src; | ||||||
|  | 	const unsigned char *end = sptr + size; | ||||||
|  | 	unsigned char *dptr = (unsigned char *)dst; | ||||||
|  | 	unsigned int c1, c2; | ||||||
|  |  | ||||||
|  | 	do { | ||||||
|  | 		c1 = *sptr++; | ||||||
|  | 		*dptr++ = BF_itoa64[c1 >> 2]; | ||||||
|  | 		c1 = (c1 & 0x03) << 4; | ||||||
|  | 		if (sptr >= end) { | ||||||
|  | 			*dptr++ = BF_itoa64[c1]; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		c2 = *sptr++; | ||||||
|  | 		c1 |= c2 >> 4; | ||||||
|  | 		*dptr++ = BF_itoa64[c1]; | ||||||
|  | 		c1 = (c2 & 0x0f) << 2; | ||||||
|  | 		if (sptr >= end) { | ||||||
|  | 			*dptr++ = BF_itoa64[c1]; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		c2 = *sptr++; | ||||||
|  | 		c1 |= c2 >> 6; | ||||||
|  | 		*dptr++ = BF_itoa64[c1]; | ||||||
|  | 		*dptr++ = BF_itoa64[c2 & 0x3f]; | ||||||
|  | 	} while (sptr < end); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void BF_swap(BF_word *x, int count) | ||||||
|  | { | ||||||
|  | 	static int endianness_check = 1; | ||||||
|  | 	char *is_little_endian = (char *)&endianness_check; | ||||||
|  | 	BF_word tmp; | ||||||
|  |  | ||||||
|  | 	if (*is_little_endian) | ||||||
|  | 	do { | ||||||
|  | 		tmp = *x; | ||||||
|  | 		tmp = (tmp << 16) | (tmp >> 16); | ||||||
|  | 		*x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF); | ||||||
|  | 	} while (--count); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #if BF_SCALE | ||||||
|  | /* Architectures which can shift addresses left by 2 bits with no extra cost */ | ||||||
|  | #define BF_ROUND(L, R, N) \ | ||||||
|  | 	tmp1 = L & 0xFF; \ | ||||||
|  | 	tmp2 = L >> 8; \ | ||||||
|  | 	tmp2 &= 0xFF; \ | ||||||
|  | 	tmp3 = L >> 16; \ | ||||||
|  | 	tmp3 &= 0xFF; \ | ||||||
|  | 	tmp4 = L >> 24; \ | ||||||
|  | 	tmp1 = data.ctx.S[3][tmp1]; \ | ||||||
|  | 	tmp2 = data.ctx.S[2][tmp2]; \ | ||||||
|  | 	tmp3 = data.ctx.S[1][tmp3]; \ | ||||||
|  | 	tmp3 += data.ctx.S[0][tmp4]; \ | ||||||
|  | 	tmp3 ^= tmp2; \ | ||||||
|  | 	R ^= data.ctx.P[N + 1]; \ | ||||||
|  | 	tmp3 += tmp1; \ | ||||||
|  | 	R ^= tmp3; | ||||||
|  | #else | ||||||
|  | /* Architectures with no complicated addressing modes supported */ | ||||||
|  | #define BF_INDEX(S, i) \ | ||||||
|  | 	(*((BF_word *)(((unsigned char *)S) + (i)))) | ||||||
|  | #define BF_ROUND(L, R, N) \ | ||||||
|  | 	tmp1 = L & 0xFF; \ | ||||||
|  | 	tmp1 <<= 2; \ | ||||||
|  | 	tmp2 = L >> 6; \ | ||||||
|  | 	tmp2 &= 0x3FC; \ | ||||||
|  | 	tmp3 = L >> 14; \ | ||||||
|  | 	tmp3 &= 0x3FC; \ | ||||||
|  | 	tmp4 = L >> 22; \ | ||||||
|  | 	tmp4 &= 0x3FC; \ | ||||||
|  | 	tmp1 = BF_INDEX(data.ctx.S[3], tmp1); \ | ||||||
|  | 	tmp2 = BF_INDEX(data.ctx.S[2], tmp2); \ | ||||||
|  | 	tmp3 = BF_INDEX(data.ctx.S[1], tmp3); \ | ||||||
|  | 	tmp3 += BF_INDEX(data.ctx.S[0], tmp4); \ | ||||||
|  | 	tmp3 ^= tmp2; \ | ||||||
|  | 	R ^= data.ctx.P[N + 1]; \ | ||||||
|  | 	tmp3 += tmp1; \ | ||||||
|  | 	R ^= tmp3; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Encrypt one block, BF_N is hardcoded here. | ||||||
|  |  */ | ||||||
|  | #define BF_ENCRYPT \ | ||||||
|  | 	L ^= data.ctx.P[0]; \ | ||||||
|  | 	BF_ROUND(L, R, 0); \ | ||||||
|  | 	BF_ROUND(R, L, 1); \ | ||||||
|  | 	BF_ROUND(L, R, 2); \ | ||||||
|  | 	BF_ROUND(R, L, 3); \ | ||||||
|  | 	BF_ROUND(L, R, 4); \ | ||||||
|  | 	BF_ROUND(R, L, 5); \ | ||||||
|  | 	BF_ROUND(L, R, 6); \ | ||||||
|  | 	BF_ROUND(R, L, 7); \ | ||||||
|  | 	BF_ROUND(L, R, 8); \ | ||||||
|  | 	BF_ROUND(R, L, 9); \ | ||||||
|  | 	BF_ROUND(L, R, 10); \ | ||||||
|  | 	BF_ROUND(R, L, 11); \ | ||||||
|  | 	BF_ROUND(L, R, 12); \ | ||||||
|  | 	BF_ROUND(R, L, 13); \ | ||||||
|  | 	BF_ROUND(L, R, 14); \ | ||||||
|  | 	BF_ROUND(R, L, 15); \ | ||||||
|  | 	tmp4 = R; \ | ||||||
|  | 	R = L; \ | ||||||
|  | 	L = tmp4 ^ data.ctx.P[BF_N + 1]; | ||||||
|  |  | ||||||
|  | #if BF_ASM | ||||||
|  | #define BF_body() \ | ||||||
|  | 	_BF_body_r(&data.ctx); | ||||||
|  | #else | ||||||
|  | #define BF_body() \ | ||||||
|  | 	L = R = 0; \ | ||||||
|  | 	ptr = data.ctx.P; \ | ||||||
|  | 	do { \ | ||||||
|  | 		ptr += 2; \ | ||||||
|  | 		BF_ENCRYPT; \ | ||||||
|  | 		*(ptr - 2) = L; \ | ||||||
|  | 		*(ptr - 1) = R; \ | ||||||
|  | 	} while (ptr < &data.ctx.P[BF_N + 2]); \ | ||||||
|  | \ | ||||||
|  | 	ptr = data.ctx.S[0]; \ | ||||||
|  | 	do { \ | ||||||
|  | 		ptr += 2; \ | ||||||
|  | 		BF_ENCRYPT; \ | ||||||
|  | 		*(ptr - 2) = L; \ | ||||||
|  | 		*(ptr - 1) = R; \ | ||||||
|  | 	} while (ptr < &data.ctx.S[3][0xFF]); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | static void BF_set_key(const char *key, BF_key expanded, BF_key initial, | ||||||
|  |     unsigned char flags) | ||||||
|  | { | ||||||
|  | 	const char *ptr = key; | ||||||
|  | 	unsigned int bug, i, j; | ||||||
|  | 	BF_word safety, sign, diff, tmp[2]; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * There was a sign extension bug in older revisions of this function.  While | ||||||
|  |  * we would have liked to simply fix the bug and move on, we have to provide | ||||||
|  |  * a backwards compatibility feature (essentially the bug) for some systems and | ||||||
|  |  * a safety measure for some others.  The latter is needed because for certain | ||||||
|  |  * multiple inputs to the buggy algorithm there exist easily found inputs to | ||||||
|  |  * the correct algorithm that produce the same hash.  Thus, we optionally | ||||||
|  |  * deviate from the correct algorithm just enough to avoid such collisions. | ||||||
|  |  * While the bug itself affected the majority of passwords containing | ||||||
|  |  * characters with the 8th bit set (although only a percentage of those in a | ||||||
|  |  * collision-producing way), the anti-collision safety measure affects | ||||||
|  |  * only a subset of passwords containing the '\xff' character (not even all of | ||||||
|  |  * those passwords, just some of them).  This character is not found in valid | ||||||
|  |  * UTF-8 sequences and is rarely used in popular 8-bit character encodings. | ||||||
|  |  * Thus, the safety measure is unlikely to cause much annoyance, and is a | ||||||
|  |  * reasonable tradeoff to use when authenticating against existing hashes that | ||||||
|  |  * are not reliably known to have been computed with the correct algorithm. | ||||||
|  |  * | ||||||
|  |  * We use an approach that tries to minimize side-channel leaks of password | ||||||
|  |  * information - that is, we mostly use fixed-cost bitwise operations instead | ||||||
|  |  * of branches or table lookups.  (One conditional branch based on password | ||||||
|  |  * length remains.  It is not part of the bug aftermath, though, and is | ||||||
|  |  * difficult and possibly unreasonable to avoid given the use of C strings by | ||||||
|  |  * the caller, which results in similar timing leaks anyway.) | ||||||
|  |  * | ||||||
|  |  * For actual implementation, we set an array index in the variable "bug" | ||||||
|  |  * (0 means no bug, 1 means sign extension bug emulation) and a flag in the | ||||||
|  |  * variable "safety" (bit 16 is set when the safety measure is requested). | ||||||
|  |  * Valid combinations of settings are: | ||||||
|  |  * | ||||||
|  |  * Prefix "$2a$": bug = 0, safety = 0x10000 | ||||||
|  |  * Prefix "$2b$": bug = 0, safety = 0 | ||||||
|  |  * Prefix "$2x$": bug = 1, safety = 0 | ||||||
|  |  * Prefix "$2y$": bug = 0, safety = 0 | ||||||
|  |  */ | ||||||
|  | 	bug = (unsigned int)flags & 1; | ||||||
|  | 	safety = ((BF_word)flags & 2) << 15; | ||||||
|  |  | ||||||
|  | 	sign = diff = 0; | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < BF_N + 2; i++) { | ||||||
|  | 		tmp[0] = tmp[1] = 0; | ||||||
|  | 		for (j = 0; j < 4; j++) { | ||||||
|  | 			tmp[0] <<= 8; | ||||||
|  | 			tmp[0] |= (unsigned char)*ptr; /* correct */ | ||||||
|  | 			tmp[1] <<= 8; | ||||||
|  | 			tmp[1] |= (BF_word_signed)(signed char)*ptr; /* bug */ | ||||||
|  | /* | ||||||
|  |  * Sign extension in the first char has no effect - nothing to overwrite yet, | ||||||
|  |  * and those extra 24 bits will be fully shifted out of the 32-bit word.  For | ||||||
|  |  * chars 2, 3, 4 in each four-char block, we set bit 7 of "sign" if sign | ||||||
|  |  * extension in tmp[1] occurs.  Once this flag is set, it remains set. | ||||||
|  |  */ | ||||||
|  | 			if (j) | ||||||
|  | 				sign |= tmp[1] & 0x80; | ||||||
|  | 			if (!*ptr) | ||||||
|  | 				ptr = key; | ||||||
|  | 			else | ||||||
|  | 				ptr++; | ||||||
|  | 		} | ||||||
|  | 		diff |= tmp[0] ^ tmp[1]; /* Non-zero on any differences */ | ||||||
|  |  | ||||||
|  | 		expanded[i] = tmp[bug]; | ||||||
|  | 		initial[i] = BF_init_state.P[i] ^ tmp[bug]; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * At this point, "diff" is zero iff the correct and buggy algorithms produced | ||||||
|  |  * exactly the same result.  If so and if "sign" is non-zero, which indicates | ||||||
|  |  * that there was a non-benign sign extension, this means that we have a | ||||||
|  |  * collision between the correctly computed hash for this password and a set of | ||||||
|  |  * passwords that could be supplied to the buggy algorithm.  Our safety measure | ||||||
|  |  * is meant to protect from such many-buggy to one-correct collisions, by | ||||||
|  |  * deviating from the correct algorithm in such cases.  Let's check for this. | ||||||
|  |  */ | ||||||
|  | 	diff |= diff >> 16; /* still zero iff exact match */ | ||||||
|  | 	diff &= 0xffff; /* ditto */ | ||||||
|  | 	diff += 0xffff; /* bit 16 set iff "diff" was non-zero (on non-match) */ | ||||||
|  | 	sign <<= 9; /* move the non-benign sign extension flag to bit 16 */ | ||||||
|  | 	sign &= ~diff & safety; /* action needed? */ | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * If we have determined that we need to deviate from the correct algorithm, | ||||||
|  |  * flip bit 16 in initial expanded key.  (The choice of 16 is arbitrary, but | ||||||
|  |  * let's stick to it now.  It came out of the approach we used above, and it's | ||||||
|  |  * not any worse than any other choice we could make.) | ||||||
|  |  * | ||||||
|  |  * It is crucial that we don't do the same to the expanded key used in the main | ||||||
|  |  * Eksblowfish loop.  By doing it to only one of these two, we deviate from a | ||||||
|  |  * state that could be directly specified by a password to the buggy algorithm | ||||||
|  |  * (and to the fully correct one as well, but that's a side-effect). | ||||||
|  |  */ | ||||||
|  | 	initial[0] ^= sign; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static const unsigned char flags_by_subtype[26] = | ||||||
|  | 	{2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | ||||||
|  | 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0}; | ||||||
|  |  | ||||||
|  | static char *BF_crypt(const char *key, const char *setting, | ||||||
|  | 	char *output, int size, | ||||||
|  | 	BF_word min) | ||||||
|  | { | ||||||
|  | #if BF_ASM | ||||||
|  | 	extern void _BF_body_r(BF_ctx *ctx); | ||||||
|  | #endif | ||||||
|  | 	struct { | ||||||
|  | 		BF_ctx ctx; | ||||||
|  | 		BF_key expanded_key; | ||||||
|  | 		union { | ||||||
|  | 			BF_word salt[4]; | ||||||
|  | 			BF_word output[6]; | ||||||
|  | 		} binary; | ||||||
|  | 	} data; | ||||||
|  | 	BF_word L, R; | ||||||
|  | 	BF_word tmp1, tmp2, tmp3, tmp4; | ||||||
|  | 	BF_word *ptr; | ||||||
|  | 	BF_word count; | ||||||
|  | 	int i; | ||||||
|  |  | ||||||
|  | 	if (size < 7 + 22 + 31 + 1) { | ||||||
|  | 		__set_errno(ERANGE); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (setting[0] != '$' || | ||||||
|  | 	    setting[1] != '2' || | ||||||
|  | 	    setting[2] < 'a' || setting[2] > 'z' || | ||||||
|  | 	    !flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a'] || | ||||||
|  | 	    setting[3] != '$' || | ||||||
|  | 	    setting[4] < '0' || setting[4] > '3' || | ||||||
|  | 	    setting[5] < '0' || setting[5] > '9' || | ||||||
|  | 	    (setting[4] == '3' && setting[5] > '1') || | ||||||
|  | 	    setting[6] != '$') { | ||||||
|  | 		__set_errno(EINVAL); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0')); | ||||||
|  | 	if (count < min || BF_decode(data.binary.salt, &setting[7], 16)) { | ||||||
|  | 		__set_errno(EINVAL); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 	BF_swap(data.binary.salt, 4); | ||||||
|  |  | ||||||
|  | 	BF_set_key(key, data.expanded_key, data.ctx.P, | ||||||
|  | 	    flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a']); | ||||||
|  |  | ||||||
|  | 	memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S)); | ||||||
|  |  | ||||||
|  | 	L = R = 0; | ||||||
|  | 	for (i = 0; i < BF_N + 2; i += 2) { | ||||||
|  | 		L ^= data.binary.salt[i & 2]; | ||||||
|  | 		R ^= data.binary.salt[(i & 2) + 1]; | ||||||
|  | 		BF_ENCRYPT; | ||||||
|  | 		data.ctx.P[i] = L; | ||||||
|  | 		data.ctx.P[i + 1] = R; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ptr = data.ctx.S[0]; | ||||||
|  | 	do { | ||||||
|  | 		ptr += 4; | ||||||
|  | 		L ^= data.binary.salt[(BF_N + 2) & 3]; | ||||||
|  | 		R ^= data.binary.salt[(BF_N + 3) & 3]; | ||||||
|  | 		BF_ENCRYPT; | ||||||
|  | 		*(ptr - 4) = L; | ||||||
|  | 		*(ptr - 3) = R; | ||||||
|  |  | ||||||
|  | 		L ^= data.binary.salt[(BF_N + 4) & 3]; | ||||||
|  | 		R ^= data.binary.salt[(BF_N + 5) & 3]; | ||||||
|  | 		BF_ENCRYPT; | ||||||
|  | 		*(ptr - 2) = L; | ||||||
|  | 		*(ptr - 1) = R; | ||||||
|  | 	} while (ptr < &data.ctx.S[3][0xFF]); | ||||||
|  |  | ||||||
|  | 	do { | ||||||
|  | 		int done; | ||||||
|  |  | ||||||
|  | 		for (i = 0; i < BF_N + 2; i += 2) { | ||||||
|  | 			data.ctx.P[i] ^= data.expanded_key[i]; | ||||||
|  | 			data.ctx.P[i + 1] ^= data.expanded_key[i + 1]; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		done = 0; | ||||||
|  | 		do { | ||||||
|  | 			BF_body(); | ||||||
|  | 			if (done) | ||||||
|  | 				break; | ||||||
|  | 			done = 1; | ||||||
|  |  | ||||||
|  | 			tmp1 = data.binary.salt[0]; | ||||||
|  | 			tmp2 = data.binary.salt[1]; | ||||||
|  | 			tmp3 = data.binary.salt[2]; | ||||||
|  | 			tmp4 = data.binary.salt[3]; | ||||||
|  | 			for (i = 0; i < BF_N; i += 4) { | ||||||
|  | 				data.ctx.P[i] ^= tmp1; | ||||||
|  | 				data.ctx.P[i + 1] ^= tmp2; | ||||||
|  | 				data.ctx.P[i + 2] ^= tmp3; | ||||||
|  | 				data.ctx.P[i + 3] ^= tmp4; | ||||||
|  | 			} | ||||||
|  | 			data.ctx.P[16] ^= tmp1; | ||||||
|  | 			data.ctx.P[17] ^= tmp2; | ||||||
|  | 		} while (1); | ||||||
|  | 	} while (--count); | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < 6; i += 2) { | ||||||
|  | 		L = BF_magic_w[i]; | ||||||
|  | 		R = BF_magic_w[i + 1]; | ||||||
|  |  | ||||||
|  | 		count = 64; | ||||||
|  | 		do { | ||||||
|  | 			BF_ENCRYPT; | ||||||
|  | 		} while (--count); | ||||||
|  |  | ||||||
|  | 		data.binary.output[i] = L; | ||||||
|  | 		data.binary.output[i + 1] = R; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	memcpy(output, setting, 7 + 22 - 1); | ||||||
|  | 	output[7 + 22 - 1] = BF_itoa64[(int) | ||||||
|  | 		BF_atoi64[(int)setting[7 + 22 - 1] - 0x20] & 0x30]; | ||||||
|  |  | ||||||
|  | /* This has to be bug-compatible with the original implementation, so | ||||||
|  |  * only encode 23 of the 24 bytes. :-) */ | ||||||
|  | 	BF_swap(data.binary.output, 6); | ||||||
|  | 	BF_encode(&output[7 + 22], data.binary.output, 23); | ||||||
|  | 	output[7 + 22 + 31] = '\0'; | ||||||
|  |  | ||||||
|  | 	return output; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int _crypt_output_magic(const char *setting, char *output, int size) | ||||||
|  | { | ||||||
|  | 	if (size < 3) | ||||||
|  | 		return -1; | ||||||
|  |  | ||||||
|  | 	output[0] = '*'; | ||||||
|  | 	output[1] = '0'; | ||||||
|  | 	output[2] = '\0'; | ||||||
|  |  | ||||||
|  | 	if (setting[0] == '*' && setting[1] == '0') | ||||||
|  | 		output[1] = '1'; | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Please preserve the runtime self-test.  It serves two purposes at once: | ||||||
|  |  * | ||||||
|  |  * 1. We really can't afford the risk of producing incompatible hashes e.g. | ||||||
|  |  * when there's something like gcc bug 26587 again, whereas an application or | ||||||
|  |  * library integrating this code might not also integrate our external tests or | ||||||
|  |  * it might not run them after every build.  Even if it does, the miscompile | ||||||
|  |  * might only occur on the production build, but not on a testing build (such | ||||||
|  |  * as because of different optimization settings).  It is painful to recover | ||||||
|  |  * from incorrectly-computed hashes - merely fixing whatever broke is not | ||||||
|  |  * enough.  Thus, a proactive measure like this self-test is needed. | ||||||
|  |  * | ||||||
|  |  * 2. We don't want to leave sensitive data from our actual password hash | ||||||
|  |  * computation on the stack or in registers.  Previous revisions of the code | ||||||
|  |  * would do explicit cleanups, but simply running the self-test after hash | ||||||
|  |  * computation is more reliable. | ||||||
|  |  * | ||||||
|  |  * The performance cost of this quick self-test is around 0.6% at the "$2a$08" | ||||||
|  |  * setting. | ||||||
|  |  */ | ||||||
|  | char *_crypt_blowfish_rn(const char *key, const char *setting, | ||||||
|  | 	char *output, int size) | ||||||
|  | { | ||||||
|  | 	const char *test_key = "8b \xd0\xc1\xd2\xcf\xcc\xd8"; | ||||||
|  | 	const char *test_setting = "$2a$00$abcdefghijklmnopqrstuu"; | ||||||
|  | 	static const char * const test_hashes[2] = | ||||||
|  | 		{"i1D709vfamulimlGcq0qq3UvuUasvEa\0\x55", /* 'a', 'b', 'y' */ | ||||||
|  | 		"VUrPmXD6q/nVSSp7pNDhCR9071IfIRe\0\x55"}; /* 'x' */ | ||||||
|  | 	const char *test_hash = test_hashes[0]; | ||||||
|  | 	char *retval; | ||||||
|  | 	const char *p; | ||||||
|  | 	int save_errno, ok; | ||||||
|  | 	struct { | ||||||
|  | 		char s[7 + 22 + 1]; | ||||||
|  | 		char o[7 + 22 + 31 + 1 + 1 + 1]; | ||||||
|  | 	} buf; | ||||||
|  |  | ||||||
|  | /* Hash the supplied password */ | ||||||
|  | 	_crypt_output_magic(setting, output, size); | ||||||
|  | 	retval = BF_crypt(key, setting, output, size, 16); | ||||||
|  | 	save_errno = errno; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Do a quick self-test.  It is important that we make both calls to BF_crypt() | ||||||
|  |  * from the same scope such that they likely use the same stack locations, | ||||||
|  |  * which makes the second call overwrite the first call's sensitive data on the | ||||||
|  |  * stack and makes it more likely that any alignment related issues would be | ||||||
|  |  * detected by the self-test. | ||||||
|  |  */ | ||||||
|  | 	memcpy(buf.s, test_setting, sizeof(buf.s)); | ||||||
|  | 	if (retval) { | ||||||
|  | 		unsigned int flags = flags_by_subtype[ | ||||||
|  | 		    (unsigned int)(unsigned char)setting[2] - 'a']; | ||||||
|  | 		test_hash = test_hashes[flags & 1]; | ||||||
|  | 		buf.s[2] = setting[2]; | ||||||
|  | 	} | ||||||
|  | 	memset(buf.o, 0x55, sizeof(buf.o)); | ||||||
|  | 	buf.o[sizeof(buf.o) - 1] = 0; | ||||||
|  | 	p = BF_crypt(test_key, buf.s, buf.o, sizeof(buf.o) - (1 + 1), 1); | ||||||
|  |  | ||||||
|  | 	ok = (p == buf.o && | ||||||
|  | 	    !memcmp(p, buf.s, 7 + 22) && | ||||||
|  | 	    !memcmp(p + (7 + 22), test_hash, 31 + 1 + 1 + 1)); | ||||||
|  |  | ||||||
|  | 	{ | ||||||
|  | 		const char *k = "\xff\xa3" "34" "\xff\xff\xff\xa3" "345"; | ||||||
|  | 		BF_key ae, ai, ye, yi; | ||||||
|  | 		BF_set_key(k, ae, ai, 2); /* $2a$ */ | ||||||
|  | 		BF_set_key(k, ye, yi, 4); /* $2y$ */ | ||||||
|  | 		ai[0] ^= 0x10000; /* undo the safety (for comparison) */ | ||||||
|  | 		ok = ok && ai[0] == 0xdb9c59bc && ye[17] == 0x33343500 && | ||||||
|  | 		    !memcmp(ae, ye, sizeof(ae)) && | ||||||
|  | 		    !memcmp(ai, yi, sizeof(ai)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	__set_errno(save_errno); | ||||||
|  | 	if (ok) | ||||||
|  | 		return retval; | ||||||
|  |  | ||||||
|  | /* Should not happen */ | ||||||
|  | 	_crypt_output_magic(setting, output, size); | ||||||
|  | 	__set_errno(EINVAL); /* pretend we don't support this hash type */ | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | char *_crypt_gensalt_blowfish_rn(const char *prefix, unsigned long count, | ||||||
|  | 	const char *input, int size, char *output, int output_size) | ||||||
|  | { | ||||||
|  | 	if (size < 16 || output_size < 7 + 22 + 1 || | ||||||
|  | 	    (count && (count < 4 || count > 31)) || | ||||||
|  | 	    prefix[0] != '$' || prefix[1] != '2' || | ||||||
|  | 	    (prefix[2] != 'a' && prefix[2] != 'b' && prefix[2] != 'y')) { | ||||||
|  | 		if (output_size > 0) output[0] = '\0'; | ||||||
|  | 		__set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (!count) count = 5; | ||||||
|  |  | ||||||
|  | 	output[0] = '$'; | ||||||
|  | 	output[1] = '2'; | ||||||
|  | 	output[2] = prefix[2]; | ||||||
|  | 	output[3] = '$'; | ||||||
|  | 	output[4] = '0' + count / 10; | ||||||
|  | 	output[5] = '0' + count % 10; | ||||||
|  | 	output[6] = '$'; | ||||||
|  |  | ||||||
|  | 	BF_encode(&output[7], (const BF_word *)input, 16); | ||||||
|  | 	output[7 + 22] = '\0'; | ||||||
|  |  | ||||||
|  | 	return output; | ||||||
|  | } | ||||||
							
								
								
									
										27
									
								
								deps/crypt_blowfish/crypt_blowfish.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								deps/crypt_blowfish/crypt_blowfish.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | /* | ||||||
|  |  * Written by Solar Designer <solar at openwall.com> in 2000-2011. | ||||||
|  |  * No copyright is claimed, and the software is hereby placed in the public | ||||||
|  |  * domain.  In case this attempt to disclaim copyright and place the software | ||||||
|  |  * in the public domain is deemed null and void, then the software is | ||||||
|  |  * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the | ||||||
|  |  * general public under the following terms: | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted. | ||||||
|  |  * | ||||||
|  |  * There's ABSOLUTELY NO WARRANTY, express or implied. | ||||||
|  |  * | ||||||
|  |  * See crypt_blowfish.c for more information. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef _CRYPT_BLOWFISH_H | ||||||
|  | #define _CRYPT_BLOWFISH_H | ||||||
|  |  | ||||||
|  | extern int _crypt_output_magic(const char *setting, char *output, int size); | ||||||
|  | extern char *_crypt_blowfish_rn(const char *key, const char *setting, | ||||||
|  | 	char *output, int size); | ||||||
|  | extern char *_crypt_gensalt_blowfish_rn(const char *prefix, | ||||||
|  | 	unsigned long count, | ||||||
|  | 	const char *input, int size, char *output, int output_size); | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										124
									
								
								deps/crypt_blowfish/crypt_gensalt.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								deps/crypt_blowfish/crypt_gensalt.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,124 @@ | |||||||
|  | /* | ||||||
|  |  * Written by Solar Designer <solar at openwall.com> in 2000-2011. | ||||||
|  |  * No copyright is claimed, and the software is hereby placed in the public | ||||||
|  |  * domain.  In case this attempt to disclaim copyright and place the software | ||||||
|  |  * in the public domain is deemed null and void, then the software is | ||||||
|  |  * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the | ||||||
|  |  * general public under the following terms: | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted. | ||||||
|  |  * | ||||||
|  |  * There's ABSOLUTELY NO WARRANTY, express or implied. | ||||||
|  |  * | ||||||
|  |  * See crypt_blowfish.c for more information. | ||||||
|  |  * | ||||||
|  |  * This file contains salt generation functions for the traditional and | ||||||
|  |  * other common crypt(3) algorithms, except for bcrypt which is defined | ||||||
|  |  * entirely in crypt_blowfish.c. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | #include <errno.h> | ||||||
|  | #ifndef __set_errno | ||||||
|  | #define __set_errno(val) errno = (val) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | /* Just to make sure the prototypes match the actual definitions */ | ||||||
|  | #include "crypt_gensalt.h" | ||||||
|  |  | ||||||
|  | unsigned char _crypt_itoa64[64 + 1] = | ||||||
|  | 	"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; | ||||||
|  |  | ||||||
|  | char *_crypt_gensalt_traditional_rn(const char *prefix, unsigned long count, | ||||||
|  | 	const char *input, int size, char *output, int output_size) | ||||||
|  | { | ||||||
|  | 	(void) prefix; | ||||||
|  |  | ||||||
|  | 	if (size < 2 || output_size < 2 + 1 || (count && count != 25)) { | ||||||
|  | 		if (output_size > 0) output[0] = '\0'; | ||||||
|  | 		__set_errno((output_size < 2 + 1) ? ERANGE : EINVAL); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	output[0] = _crypt_itoa64[(unsigned int)input[0] & 0x3f]; | ||||||
|  | 	output[1] = _crypt_itoa64[(unsigned int)input[1] & 0x3f]; | ||||||
|  | 	output[2] = '\0'; | ||||||
|  |  | ||||||
|  | 	return output; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | char *_crypt_gensalt_extended_rn(const char *prefix, unsigned long count, | ||||||
|  | 	const char *input, int size, char *output, int output_size) | ||||||
|  | { | ||||||
|  | 	unsigned long value; | ||||||
|  |  | ||||||
|  | 	(void) prefix; | ||||||
|  |  | ||||||
|  | /* Even iteration counts make it easier to detect weak DES keys from a look | ||||||
|  |  * at the hash, so they should be avoided */ | ||||||
|  | 	if (size < 3 || output_size < 1 + 4 + 4 + 1 || | ||||||
|  | 	    (count && (count > 0xffffff || !(count & 1)))) { | ||||||
|  | 		if (output_size > 0) output[0] = '\0'; | ||||||
|  | 		__set_errno((output_size < 1 + 4 + 4 + 1) ? ERANGE : EINVAL); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (!count) count = 725; | ||||||
|  |  | ||||||
|  | 	output[0] = '_'; | ||||||
|  | 	output[1] = _crypt_itoa64[count & 0x3f]; | ||||||
|  | 	output[2] = _crypt_itoa64[(count >> 6) & 0x3f]; | ||||||
|  | 	output[3] = _crypt_itoa64[(count >> 12) & 0x3f]; | ||||||
|  | 	output[4] = _crypt_itoa64[(count >> 18) & 0x3f]; | ||||||
|  | 	value = (unsigned long)(unsigned char)input[0] | | ||||||
|  | 		((unsigned long)(unsigned char)input[1] << 8) | | ||||||
|  | 		((unsigned long)(unsigned char)input[2] << 16); | ||||||
|  | 	output[5] = _crypt_itoa64[value & 0x3f]; | ||||||
|  | 	output[6] = _crypt_itoa64[(value >> 6) & 0x3f]; | ||||||
|  | 	output[7] = _crypt_itoa64[(value >> 12) & 0x3f]; | ||||||
|  | 	output[8] = _crypt_itoa64[(value >> 18) & 0x3f]; | ||||||
|  | 	output[9] = '\0'; | ||||||
|  |  | ||||||
|  | 	return output; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | char *_crypt_gensalt_md5_rn(const char *prefix, unsigned long count, | ||||||
|  | 	const char *input, int size, char *output, int output_size) | ||||||
|  | { | ||||||
|  | 	unsigned long value; | ||||||
|  |  | ||||||
|  | 	(void) prefix; | ||||||
|  |  | ||||||
|  | 	if (size < 3 || output_size < 3 + 4 + 1 || (count && count != 1000)) { | ||||||
|  | 		if (output_size > 0) output[0] = '\0'; | ||||||
|  | 		__set_errno((output_size < 3 + 4 + 1) ? ERANGE : EINVAL); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	output[0] = '$'; | ||||||
|  | 	output[1] = '1'; | ||||||
|  | 	output[2] = '$'; | ||||||
|  | 	value = (unsigned long)(unsigned char)input[0] | | ||||||
|  | 		((unsigned long)(unsigned char)input[1] << 8) | | ||||||
|  | 		((unsigned long)(unsigned char)input[2] << 16); | ||||||
|  | 	output[3] = _crypt_itoa64[value & 0x3f]; | ||||||
|  | 	output[4] = _crypt_itoa64[(value >> 6) & 0x3f]; | ||||||
|  | 	output[5] = _crypt_itoa64[(value >> 12) & 0x3f]; | ||||||
|  | 	output[6] = _crypt_itoa64[(value >> 18) & 0x3f]; | ||||||
|  | 	output[7] = '\0'; | ||||||
|  |  | ||||||
|  | 	if (size >= 6 && output_size >= 3 + 4 + 4 + 1) { | ||||||
|  | 		value = (unsigned long)(unsigned char)input[3] | | ||||||
|  | 			((unsigned long)(unsigned char)input[4] << 8) | | ||||||
|  | 			((unsigned long)(unsigned char)input[5] << 16); | ||||||
|  | 		output[7] = _crypt_itoa64[value & 0x3f]; | ||||||
|  | 		output[8] = _crypt_itoa64[(value >> 6) & 0x3f]; | ||||||
|  | 		output[9] = _crypt_itoa64[(value >> 12) & 0x3f]; | ||||||
|  | 		output[10] = _crypt_itoa64[(value >> 18) & 0x3f]; | ||||||
|  | 		output[11] = '\0'; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return output; | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								deps/crypt_blowfish/crypt_gensalt.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								deps/crypt_blowfish/crypt_gensalt.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | /* | ||||||
|  |  * Written by Solar Designer <solar at openwall.com> in 2000-2011. | ||||||
|  |  * No copyright is claimed, and the software is hereby placed in the public | ||||||
|  |  * domain.  In case this attempt to disclaim copyright and place the software | ||||||
|  |  * in the public domain is deemed null and void, then the software is | ||||||
|  |  * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the | ||||||
|  |  * general public under the following terms: | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted. | ||||||
|  |  * | ||||||
|  |  * There's ABSOLUTELY NO WARRANTY, express or implied. | ||||||
|  |  * | ||||||
|  |  * See crypt_blowfish.c for more information. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef _CRYPT_GENSALT_H | ||||||
|  | #define _CRYPT_GENSALT_H | ||||||
|  |  | ||||||
|  | extern unsigned char _crypt_itoa64[]; | ||||||
|  | extern char *_crypt_gensalt_traditional_rn(const char *prefix, | ||||||
|  | 	unsigned long count, | ||||||
|  | 	const char *input, int size, char *output, int output_size); | ||||||
|  | extern char *_crypt_gensalt_extended_rn(const char *prefix, | ||||||
|  | 	unsigned long count, | ||||||
|  | 	const char *input, int size, char *output, int output_size); | ||||||
|  | extern char *_crypt_gensalt_md5_rn(const char *prefix, unsigned long count, | ||||||
|  | 	const char *input, int size, char *output, int output_size); | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										53
									
								
								deps/crypt_blowfish/glibc-2.1.3-crypt.diff
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								deps/crypt_blowfish/glibc-2.1.3-crypt.diff
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | |||||||
|  | --- glibc-2.1.3.orig/crypt/sysdeps/unix/Makefile	1997-03-05 00:33:59 +0000 | ||||||
|  | +++ glibc-2.1.3/crypt/sysdeps/unix/Makefile	2000-06-11 03:13:41 +0000 | ||||||
|  | @@ -1,4 +1,4 @@ | ||||||
|  |  ifeq ($(subdir),md5-crypt) | ||||||
|  | -libcrypt-routines += crypt crypt_util | ||||||
|  | -dont_distribute += crypt.c crypt_util.c | ||||||
|  | +libcrypt-routines += crypt crypt_util crypt_blowfish x86 crypt_gensalt wrapper | ||||||
|  | +dont_distribute += crypt.c crypt_util.c crypt_blowfish.c x86.S crypt_gensalt.c wrapper.c | ||||||
|  |  endif | ||||||
|  | --- glibc-2.1.3.orig/crypt/sysdeps/unix/crypt-entry.c	1998-12-10 12:49:04 +0000 | ||||||
|  | +++ glibc-2.1.3/crypt/sysdeps/unix/crypt-entry.c	2000-06-11 03:14:57 +0000 | ||||||
|  | @@ -70,7 +70,7 @@ extern struct crypt_data _ufc_foobar; | ||||||
|  |   */ | ||||||
|  |   | ||||||
|  |  char * | ||||||
|  | -__crypt_r (key, salt, data) | ||||||
|  | +__des_crypt_r (key, salt, data) | ||||||
|  |       const char *key; | ||||||
|  |       const char *salt; | ||||||
|  |       struct crypt_data * __restrict data; | ||||||
|  | @@ -115,6 +115,7 @@ __crypt_r (key, salt, data) | ||||||
|  |    _ufc_output_conversion_r (res[0], res[1], salt, data); | ||||||
|  |    return data->crypt_3_buf; | ||||||
|  |  } | ||||||
|  | +#if 0 | ||||||
|  |  weak_alias (__crypt_r, crypt_r) | ||||||
|  |   | ||||||
|  |  char * | ||||||
|  | @@ -147,3 +148,4 @@ __fcrypt (key, salt) | ||||||
|  |    return crypt (key, salt); | ||||||
|  |  } | ||||||
|  |  #endif | ||||||
|  | +#endif | ||||||
|  | --- glibc-2.1.3.orig/md5-crypt/Makefile	1998-07-02 22:46:47 +0000 | ||||||
|  | +++ glibc-2.1.3/md5-crypt/Makefile	2000-06-11 03:12:34 +0000 | ||||||
|  | @@ -21,7 +21,7 @@ | ||||||
|  |  # | ||||||
|  |  subdir	:= md5-crypt | ||||||
|  |   | ||||||
|  | -headers := crypt.h | ||||||
|  | +headers := crypt.h gnu-crypt.h ow-crypt.h | ||||||
|  |   | ||||||
|  |  distribute := md5.h | ||||||
|  |   | ||||||
|  | --- glibc-2.1.3.orig/md5-crypt/Versions	1998-07-02 22:32:07 +0000 | ||||||
|  | +++ glibc-2.1.3/md5-crypt/Versions	2000-06-11 09:11:03 +0000 | ||||||
|  | @@ -1,5 +1,6 @@ | ||||||
|  |  libcrypt { | ||||||
|  |    GLIBC_2.0 { | ||||||
|  |      crypt; crypt_r; encrypt; encrypt_r; fcrypt; setkey; setkey_r; | ||||||
|  | +    crypt_rn; crypt_ra; crypt_gensalt; crypt_gensalt_rn; crypt_gensalt_ra; | ||||||
|  |    } | ||||||
|  |  } | ||||||
							
								
								
									
										55
									
								
								deps/crypt_blowfish/glibc-2.14-crypt.diff
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								deps/crypt_blowfish/glibc-2.14-crypt.diff
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | |||||||
|  | diff -urp glibc-2.14.orig/crypt/Makefile glibc-2.14/crypt/Makefile | ||||||
|  | --- glibc-2.14.orig/crypt/Makefile	2011-05-31 04:12:33 +0000 | ||||||
|  | +++ glibc-2.14/crypt/Makefile	2011-07-16 21:40:56 +0000 | ||||||
|  | @@ -22,6 +22,7 @@ | ||||||
|  |  subdir	:= crypt | ||||||
|  |   | ||||||
|  |  headers := crypt.h | ||||||
|  | +headers += gnu-crypt.h ow-crypt.h | ||||||
|  |   | ||||||
|  |  extra-libs := libcrypt | ||||||
|  |  extra-libs-others := $(extra-libs) | ||||||
|  | @@ -29,6 +30,8 @@ extra-libs-others := $(extra-libs) | ||||||
|  |  libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt crypt \ | ||||||
|  |  		     crypt_util | ||||||
|  |   | ||||||
|  | +libcrypt-routines += crypt_blowfish x86 crypt_gensalt wrapper | ||||||
|  | + | ||||||
|  |  tests := cert md5c-test sha256c-test sha512c-test | ||||||
|  |   | ||||||
|  |  distribute := ufc-crypt.h crypt-private.h ufc.c speeds.c README.ufc-crypt \ | ||||||
|  | diff -urp glibc-2.14.orig/crypt/Versions glibc-2.14/crypt/Versions | ||||||
|  | --- glibc-2.14.orig/crypt/Versions	2011-05-31 04:12:33 +0000 | ||||||
|  | +++ glibc-2.14/crypt/Versions	2011-07-16 21:40:56 +0000 | ||||||
|  | @@ -1,5 +1,6 @@ | ||||||
|  |  libcrypt { | ||||||
|  |    GLIBC_2.0 { | ||||||
|  |      crypt; crypt_r; encrypt; encrypt_r; fcrypt; setkey; setkey_r; | ||||||
|  | +    crypt_rn; crypt_ra; crypt_gensalt; crypt_gensalt_rn; crypt_gensalt_ra; | ||||||
|  |    } | ||||||
|  |  } | ||||||
|  | diff -urp glibc-2.14.orig/crypt/crypt-entry.c glibc-2.14/crypt/crypt-entry.c | ||||||
|  | --- glibc-2.14.orig/crypt/crypt-entry.c	2011-05-31 04:12:33 +0000 | ||||||
|  | +++ glibc-2.14/crypt/crypt-entry.c	2011-07-16 21:40:56 +0000 | ||||||
|  | @@ -82,7 +82,7 @@ extern struct crypt_data _ufc_foobar; | ||||||
|  |   */ | ||||||
|  |   | ||||||
|  |  char * | ||||||
|  | -__crypt_r (key, salt, data) | ||||||
|  | +__des_crypt_r (key, salt, data) | ||||||
|  |       const char *key; | ||||||
|  |       const char *salt; | ||||||
|  |       struct crypt_data * __restrict data; | ||||||
|  | @@ -137,6 +137,7 @@ __crypt_r (key, salt, data) | ||||||
|  |    _ufc_output_conversion_r (res[0], res[1], salt, data); | ||||||
|  |    return data->crypt_3_buf; | ||||||
|  |  } | ||||||
|  | +#if 0 | ||||||
|  |  weak_alias (__crypt_r, crypt_r) | ||||||
|  |   | ||||||
|  |  char * | ||||||
|  | @@ -177,3 +178,4 @@ __fcrypt (key, salt) | ||||||
|  |    return crypt (key, salt); | ||||||
|  |  } | ||||||
|  |  #endif | ||||||
|  | +#endif | ||||||
							
								
								
									
										52
									
								
								deps/crypt_blowfish/glibc-2.3.6-crypt.diff
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								deps/crypt_blowfish/glibc-2.3.6-crypt.diff
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | |||||||
|  | --- glibc-2.3.6.orig/crypt/Makefile	2001-07-06 04:54:45 +0000 | ||||||
|  | +++ glibc-2.3.6/crypt/Makefile	2004-02-27 00:23:48 +0000 | ||||||
|  | @@ -21,14 +21,14 @@ | ||||||
|  |  # | ||||||
|  |  subdir	:= crypt | ||||||
|  |   | ||||||
|  | -headers := crypt.h | ||||||
|  | +headers := crypt.h gnu-crypt.h ow-crypt.h | ||||||
|  |   | ||||||
|  |  distribute := md5.h | ||||||
|  |   | ||||||
|  |  extra-libs := libcrypt | ||||||
|  |  extra-libs-others := $(extra-libs) | ||||||
|  |   | ||||||
|  | -libcrypt-routines := crypt-entry md5-crypt md5 crypt crypt_util | ||||||
|  | +libcrypt-routines := crypt-entry md5-crypt md5 crypt crypt_util crypt_blowfish x86 crypt_gensalt wrapper | ||||||
|  |   | ||||||
|  |  tests = cert md5test md5c-test | ||||||
|  |   | ||||||
|  | --- glibc-2.3.6.orig/crypt/Versions	2000-03-04 00:47:30 +0000 | ||||||
|  | +++ glibc-2.3.6/crypt/Versions	2004-02-27 00:25:15 +0000 | ||||||
|  | @@ -1,5 +1,6 @@ | ||||||
|  |  libcrypt { | ||||||
|  |    GLIBC_2.0 { | ||||||
|  |      crypt; crypt_r; encrypt; encrypt_r; fcrypt; setkey; setkey_r; | ||||||
|  | +    crypt_rn; crypt_ra; crypt_gensalt; crypt_gensalt_rn; crypt_gensalt_ra; | ||||||
|  |    } | ||||||
|  |  } | ||||||
|  | --- glibc-2.3.6.orig/crypt/crypt-entry.c	2001-07-06 05:18:49 +0000 | ||||||
|  | +++ glibc-2.3.6/crypt/crypt-entry.c	2004-02-27 00:12:32 +0000 | ||||||
|  | @@ -70,7 +70,7 @@ extern struct crypt_data _ufc_foobar; | ||||||
|  |   */ | ||||||
|  |   | ||||||
|  |  char * | ||||||
|  | -__crypt_r (key, salt, data) | ||||||
|  | +__des_crypt_r (key, salt, data) | ||||||
|  |       const char *key; | ||||||
|  |       const char *salt; | ||||||
|  |       struct crypt_data * __restrict data; | ||||||
|  | @@ -115,6 +115,7 @@ __crypt_r (key, salt, data) | ||||||
|  |    _ufc_output_conversion_r (res[0], res[1], salt, data); | ||||||
|  |    return data->crypt_3_buf; | ||||||
|  |  } | ||||||
|  | +#if 0 | ||||||
|  |  weak_alias (__crypt_r, crypt_r) | ||||||
|  |   | ||||||
|  |  char * | ||||||
|  | @@ -147,3 +148,4 @@ __fcrypt (key, salt) | ||||||
|  |    return crypt (key, salt); | ||||||
|  |  } | ||||||
|  |  #endif | ||||||
|  | +#endif | ||||||
							
								
								
									
										43
									
								
								deps/crypt_blowfish/ow-crypt.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								deps/crypt_blowfish/ow-crypt.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | |||||||
|  | /* | ||||||
|  |  * Written by Solar Designer <solar at openwall.com> in 2000-2011. | ||||||
|  |  * No copyright is claimed, and the software is hereby placed in the public | ||||||
|  |  * domain.  In case this attempt to disclaim copyright and place the software | ||||||
|  |  * in the public domain is deemed null and void, then the software is | ||||||
|  |  * Copyright (c) 2000-2011 Solar Designer and it is hereby released to the | ||||||
|  |  * general public under the following terms: | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted. | ||||||
|  |  * | ||||||
|  |  * There's ABSOLUTELY NO WARRANTY, express or implied. | ||||||
|  |  * | ||||||
|  |  * See crypt_blowfish.c for more information. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef _OW_CRYPT_H | ||||||
|  | #define _OW_CRYPT_H | ||||||
|  |  | ||||||
|  | #ifndef __GNUC__ | ||||||
|  | #undef __const | ||||||
|  | #define __const const | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef __SKIP_GNU | ||||||
|  | extern char *crypt(__const char *key, __const char *setting); | ||||||
|  | extern char *crypt_r(__const char *key, __const char *setting, void *data); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef __SKIP_OW | ||||||
|  | extern char *crypt_rn(__const char *key, __const char *setting, | ||||||
|  | 	void *data, int size); | ||||||
|  | extern char *crypt_ra(__const char *key, __const char *setting, | ||||||
|  | 	void **data, int *size); | ||||||
|  | extern char *crypt_gensalt(__const char *prefix, unsigned long count, | ||||||
|  | 	__const char *input, int size); | ||||||
|  | extern char *crypt_gensalt_rn(__const char *prefix, unsigned long count, | ||||||
|  | 	__const char *input, int size, char *output, int output_size); | ||||||
|  | extern char *crypt_gensalt_ra(__const char *prefix, unsigned long count, | ||||||
|  | 	__const char *input, int size); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										551
									
								
								deps/crypt_blowfish/wrapper.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										551
									
								
								deps/crypt_blowfish/wrapper.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,551 @@ | |||||||
|  | /* | ||||||
|  |  * Written by Solar Designer <solar at openwall.com> in 2000-2014. | ||||||
|  |  * No copyright is claimed, and the software is hereby placed in the public | ||||||
|  |  * domain.  In case this attempt to disclaim copyright and place the software | ||||||
|  |  * in the public domain is deemed null and void, then the software is | ||||||
|  |  * Copyright (c) 2000-2014 Solar Designer and it is hereby released to the | ||||||
|  |  * general public under the following terms: | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted. | ||||||
|  |  * | ||||||
|  |  * There's ABSOLUTELY NO WARRANTY, express or implied. | ||||||
|  |  * | ||||||
|  |  * See crypt_blowfish.c for more information. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | #include <errno.h> | ||||||
|  | #ifndef __set_errno | ||||||
|  | #define __set_errno(val) errno = (val) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef TEST | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <signal.h> | ||||||
|  | #include <time.h> | ||||||
|  | #include <sys/time.h> | ||||||
|  | #include <sys/times.h> | ||||||
|  | #ifdef TEST_THREADS | ||||||
|  | #include <pthread.h> | ||||||
|  | #endif | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #define CRYPT_OUTPUT_SIZE		(7 + 22 + 31 + 1) | ||||||
|  | #define CRYPT_GENSALT_OUTPUT_SIZE	(7 + 22 + 1) | ||||||
|  |  | ||||||
|  | #if defined(__GLIBC__) && defined(_LIBC) | ||||||
|  | #define __SKIP_GNU | ||||||
|  | #endif | ||||||
|  | #include "ow-crypt.h" | ||||||
|  |  | ||||||
|  | #include "crypt_blowfish.h" | ||||||
|  | #include "crypt_gensalt.h" | ||||||
|  |  | ||||||
|  | #if defined(__GLIBC__) && defined(_LIBC) | ||||||
|  | /* crypt.h from glibc-crypt-2.1 will define struct crypt_data for us */ | ||||||
|  | #include "crypt.h" | ||||||
|  | extern char *__md5_crypt_r(const char *key, const char *salt, | ||||||
|  | 	char *buffer, int buflen); | ||||||
|  | /* crypt-entry.c needs to be patched to define __des_crypt_r rather than | ||||||
|  |  * __crypt_r, and not define crypt_r and crypt at all */ | ||||||
|  | extern char *__des_crypt_r(const char *key, const char *salt, | ||||||
|  | 	struct crypt_data *data); | ||||||
|  | extern struct crypt_data _ufc_foobar; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | static int _crypt_data_alloc(void **data, int *size, int need) | ||||||
|  | { | ||||||
|  | 	void *updated; | ||||||
|  |  | ||||||
|  | 	if (*data && *size >= need) return 0; | ||||||
|  |  | ||||||
|  | 	updated = realloc(*data, need); | ||||||
|  |  | ||||||
|  | 	if (!updated) { | ||||||
|  | #ifndef __GLIBC__ | ||||||
|  | 		/* realloc(3) on glibc sets errno, so we don't need to bother */ | ||||||
|  | 		__set_errno(ENOMEM); | ||||||
|  | #endif | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | #if defined(__GLIBC__) && defined(_LIBC) | ||||||
|  | 	if (need >= sizeof(struct crypt_data)) | ||||||
|  | 		((struct crypt_data *)updated)->initialized = 0; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	*data = updated; | ||||||
|  | 	*size = need; | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char *_crypt_retval_magic(char *retval, const char *setting, | ||||||
|  | 	char *output, int size) | ||||||
|  | { | ||||||
|  | 	if (retval) | ||||||
|  | 		return retval; | ||||||
|  |  | ||||||
|  | 	if (_crypt_output_magic(setting, output, size)) | ||||||
|  | 		return NULL; /* shouldn't happen */ | ||||||
|  |  | ||||||
|  | 	return output; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #if defined(__GLIBC__) && defined(_LIBC) | ||||||
|  | /* | ||||||
|  |  * Applications may re-use the same instance of struct crypt_data without | ||||||
|  |  * resetting the initialized field in order to let crypt_r() skip some of | ||||||
|  |  * its initialization code.  Thus, it is important that our multiple hashing | ||||||
|  |  * algorithms either don't conflict with each other in their use of the | ||||||
|  |  * data area or reset the initialized field themselves whenever required. | ||||||
|  |  * Currently, the hashing algorithms simply have no conflicts: the first | ||||||
|  |  * field of struct crypt_data is the 128-byte large DES key schedule which | ||||||
|  |  * __des_crypt_r() calculates each time it is called while the two other | ||||||
|  |  * hashing algorithms use less than 128 bytes of the data area. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | char *__crypt_rn(__const char *key, __const char *setting, | ||||||
|  | 	void *data, int size) | ||||||
|  | { | ||||||
|  | 	if (setting[0] == '$' && setting[1] == '2') | ||||||
|  | 		return _crypt_blowfish_rn(key, setting, (char *)data, size); | ||||||
|  | 	if (setting[0] == '$' && setting[1] == '1') | ||||||
|  | 		return __md5_crypt_r(key, setting, (char *)data, size); | ||||||
|  | 	if (setting[0] == '$' || setting[0] == '_') { | ||||||
|  | 		__set_errno(EINVAL); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 	if (size >= sizeof(struct crypt_data)) | ||||||
|  | 		return __des_crypt_r(key, setting, (struct crypt_data *)data); | ||||||
|  | 	__set_errno(ERANGE); | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | char *__crypt_ra(__const char *key, __const char *setting, | ||||||
|  | 	void **data, int *size) | ||||||
|  | { | ||||||
|  | 	if (setting[0] == '$' && setting[1] == '2') { | ||||||
|  | 		if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE)) | ||||||
|  | 			return NULL; | ||||||
|  | 		return _crypt_blowfish_rn(key, setting, (char *)*data, *size); | ||||||
|  | 	} | ||||||
|  | 	if (setting[0] == '$' && setting[1] == '1') { | ||||||
|  | 		if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE)) | ||||||
|  | 			return NULL; | ||||||
|  | 		return __md5_crypt_r(key, setting, (char *)*data, *size); | ||||||
|  | 	} | ||||||
|  | 	if (setting[0] == '$' || setting[0] == '_') { | ||||||
|  | 		__set_errno(EINVAL); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 	if (_crypt_data_alloc(data, size, sizeof(struct crypt_data))) | ||||||
|  | 		return NULL; | ||||||
|  | 	return __des_crypt_r(key, setting, (struct crypt_data *)*data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | char *__crypt_r(__const char *key, __const char *setting, | ||||||
|  | 	struct crypt_data *data) | ||||||
|  | { | ||||||
|  | 	return _crypt_retval_magic( | ||||||
|  | 		__crypt_rn(key, setting, data, sizeof(*data)), | ||||||
|  | 		setting, (char *)data, sizeof(*data)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | char *__crypt(__const char *key, __const char *setting) | ||||||
|  | { | ||||||
|  | 	return _crypt_retval_magic( | ||||||
|  | 		__crypt_rn(key, setting, &_ufc_foobar, sizeof(_ufc_foobar)), | ||||||
|  | 		setting, (char *)&_ufc_foobar, sizeof(_ufc_foobar)); | ||||||
|  | } | ||||||
|  | #else | ||||||
|  | char *crypt_rn(const char *key, const char *setting, void *data, int size) | ||||||
|  | { | ||||||
|  | 	return _crypt_blowfish_rn(key, setting, (char *)data, size); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | char *crypt_ra(const char *key, const char *setting, | ||||||
|  | 	void **data, int *size) | ||||||
|  | { | ||||||
|  | 	if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE)) | ||||||
|  | 		return NULL; | ||||||
|  | 	return _crypt_blowfish_rn(key, setting, (char *)*data, *size); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | char *crypt_r(const char *key, const char *setting, void *data) | ||||||
|  | { | ||||||
|  | 	return _crypt_retval_magic( | ||||||
|  | 		crypt_rn(key, setting, data, CRYPT_OUTPUT_SIZE), | ||||||
|  | 		setting, (char *)data, CRYPT_OUTPUT_SIZE); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | char *crypt(const char *key, const char *setting) | ||||||
|  | { | ||||||
|  | 	static char output[CRYPT_OUTPUT_SIZE]; | ||||||
|  |  | ||||||
|  | 	return _crypt_retval_magic( | ||||||
|  | 		crypt_rn(key, setting, output, sizeof(output)), | ||||||
|  | 		setting, output, sizeof(output)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #define __crypt_gensalt_rn crypt_gensalt_rn | ||||||
|  | #define __crypt_gensalt_ra crypt_gensalt_ra | ||||||
|  | #define __crypt_gensalt crypt_gensalt | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | char *__crypt_gensalt_rn(const char *prefix, unsigned long count, | ||||||
|  | 	const char *input, int size, char *output, int output_size) | ||||||
|  | { | ||||||
|  | 	char *(*use)(const char *_prefix, unsigned long _count, | ||||||
|  | 		const char *_input, int _size, | ||||||
|  | 		char *_output, int _output_size); | ||||||
|  |  | ||||||
|  | 	/* This may be supported on some platforms in the future */ | ||||||
|  | 	if (!input) { | ||||||
|  | 		__set_errno(EINVAL); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (!strncmp(prefix, "$2a$", 4) || !strncmp(prefix, "$2b$", 4) || | ||||||
|  | 	    !strncmp(prefix, "$2y$", 4)) | ||||||
|  | 		use = _crypt_gensalt_blowfish_rn; | ||||||
|  | 	else | ||||||
|  | 	if (!strncmp(prefix, "$1$", 3)) | ||||||
|  | 		use = _crypt_gensalt_md5_rn; | ||||||
|  | 	else | ||||||
|  | 	if (prefix[0] == '_') | ||||||
|  | 		use = _crypt_gensalt_extended_rn; | ||||||
|  | 	else | ||||||
|  | 	if (!prefix[0] || | ||||||
|  | 	    (prefix[0] && prefix[1] && | ||||||
|  | 	    memchr(_crypt_itoa64, prefix[0], 64) && | ||||||
|  | 	    memchr(_crypt_itoa64, prefix[1], 64))) | ||||||
|  | 		use = _crypt_gensalt_traditional_rn; | ||||||
|  | 	else { | ||||||
|  | 		__set_errno(EINVAL); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return use(prefix, count, input, size, output, output_size); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | char *__crypt_gensalt_ra(const char *prefix, unsigned long count, | ||||||
|  | 	const char *input, int size) | ||||||
|  | { | ||||||
|  | 	char output[CRYPT_GENSALT_OUTPUT_SIZE]; | ||||||
|  | 	char *retval; | ||||||
|  |  | ||||||
|  | 	retval = __crypt_gensalt_rn(prefix, count, | ||||||
|  | 		input, size, output, sizeof(output)); | ||||||
|  |  | ||||||
|  | 	if (retval) { | ||||||
|  | 		retval = strdup(retval); | ||||||
|  | #ifndef __GLIBC__ | ||||||
|  | 		/* strdup(3) on glibc sets errno, so we don't need to bother */ | ||||||
|  | 		if (!retval) | ||||||
|  | 			__set_errno(ENOMEM); | ||||||
|  | #endif | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return retval; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | char *__crypt_gensalt(const char *prefix, unsigned long count, | ||||||
|  | 	const char *input, int size) | ||||||
|  | { | ||||||
|  | 	static char output[CRYPT_GENSALT_OUTPUT_SIZE]; | ||||||
|  |  | ||||||
|  | 	return __crypt_gensalt_rn(prefix, count, | ||||||
|  | 		input, size, output, sizeof(output)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #if defined(__GLIBC__) && defined(_LIBC) | ||||||
|  | weak_alias(__crypt_rn, crypt_rn) | ||||||
|  | weak_alias(__crypt_ra, crypt_ra) | ||||||
|  | weak_alias(__crypt_r, crypt_r) | ||||||
|  | weak_alias(__crypt, crypt) | ||||||
|  | weak_alias(__crypt_gensalt_rn, crypt_gensalt_rn) | ||||||
|  | weak_alias(__crypt_gensalt_ra, crypt_gensalt_ra) | ||||||
|  | weak_alias(__crypt_gensalt, crypt_gensalt) | ||||||
|  | weak_alias(crypt, fcrypt) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef TEST | ||||||
|  | static const char *tests[][3] = { | ||||||
|  | 	{"$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW", | ||||||
|  | 		"U*U"}, | ||||||
|  | 	{"$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK", | ||||||
|  | 		"U*U*"}, | ||||||
|  | 	{"$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a", | ||||||
|  | 		"U*U*U"}, | ||||||
|  | 	{"$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui", | ||||||
|  | 		"0123456789abcdefghijklmnopqrstuvwxyz" | ||||||
|  | 		"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" | ||||||
|  | 		"chars after 72 are ignored"}, | ||||||
|  | 	{"$2x$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e", | ||||||
|  | 		"\xa3"}, | ||||||
|  | 	{"$2x$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e", | ||||||
|  | 		"\xff\xff\xa3"}, | ||||||
|  | 	{"$2y$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e", | ||||||
|  | 		"\xff\xff\xa3"}, | ||||||
|  | 	{"$2a$05$/OK.fbVrR/bpIqNJ5ianF.nqd1wy.pTMdcvrRWxyiGL2eMz.2a85.", | ||||||
|  | 		"\xff\xff\xa3"}, | ||||||
|  | 	{"$2b$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e", | ||||||
|  | 		"\xff\xff\xa3"}, | ||||||
|  | 	{"$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq", | ||||||
|  | 		"\xa3"}, | ||||||
|  | 	{"$2a$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq", | ||||||
|  | 		"\xa3"}, | ||||||
|  | 	{"$2b$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq", | ||||||
|  | 		"\xa3"}, | ||||||
|  | 	{"$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi", | ||||||
|  | 		"1\xa3" "345"}, | ||||||
|  | 	{"$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi", | ||||||
|  | 		"\xff\xa3" "345"}, | ||||||
|  | 	{"$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi", | ||||||
|  | 		"\xff\xa3" "34" "\xff\xff\xff\xa3" "345"}, | ||||||
|  | 	{"$2y$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi", | ||||||
|  | 		"\xff\xa3" "34" "\xff\xff\xff\xa3" "345"}, | ||||||
|  | 	{"$2a$05$/OK.fbVrR/bpIqNJ5ianF.ZC1JEJ8Z4gPfpe1JOr/oyPXTWl9EFd.", | ||||||
|  | 		"\xff\xa3" "34" "\xff\xff\xff\xa3" "345"}, | ||||||
|  | 	{"$2y$05$/OK.fbVrR/bpIqNJ5ianF.nRht2l/HRhr6zmCp9vYUvvsqynflf9e", | ||||||
|  | 		"\xff\xa3" "345"}, | ||||||
|  | 	{"$2a$05$/OK.fbVrR/bpIqNJ5ianF.nRht2l/HRhr6zmCp9vYUvvsqynflf9e", | ||||||
|  | 		"\xff\xa3" "345"}, | ||||||
|  | 	{"$2a$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS", | ||||||
|  | 		"\xa3" "ab"}, | ||||||
|  | 	{"$2x$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS", | ||||||
|  | 		"\xa3" "ab"}, | ||||||
|  | 	{"$2y$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS", | ||||||
|  | 		"\xa3" "ab"}, | ||||||
|  | 	{"$2x$05$6bNw2HLQYeqHYyBfLMsv/OiwqTymGIGzFsA4hOTWebfehXHNprcAS", | ||||||
|  | 		"\xd1\x91"}, | ||||||
|  | 	{"$2x$05$6bNw2HLQYeqHYyBfLMsv/O9LIGgn8OMzuDoHfof8AQimSGfcSWxnS", | ||||||
|  | 		"\xd0\xc1\xd2\xcf\xcc\xd8"}, | ||||||
|  | 	{"$2a$05$/OK.fbVrR/bpIqNJ5ianF.swQOIzjOiJ9GHEPuhEkvqrUyvWhEMx6", | ||||||
|  | 		"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" | ||||||
|  | 		"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" | ||||||
|  | 		"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" | ||||||
|  | 		"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" | ||||||
|  | 		"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" | ||||||
|  | 		"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" | ||||||
|  | 		"chars after 72 are ignored as usual"}, | ||||||
|  | 	{"$2a$05$/OK.fbVrR/bpIqNJ5ianF.R9xrDjiycxMbQE2bp.vgqlYpW5wx2yy", | ||||||
|  | 		"\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" | ||||||
|  | 		"\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" | ||||||
|  | 		"\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" | ||||||
|  | 		"\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" | ||||||
|  | 		"\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55" | ||||||
|  | 		"\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55"}, | ||||||
|  | 	{"$2a$05$/OK.fbVrR/bpIqNJ5ianF.9tQZzcJfm3uj2NvJ/n5xkhpqLrMpWCe", | ||||||
|  | 		"\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" | ||||||
|  | 		"\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" | ||||||
|  | 		"\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" | ||||||
|  | 		"\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" | ||||||
|  | 		"\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff" | ||||||
|  | 		"\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff"}, | ||||||
|  | 	{"$2a$05$CCCCCCCCCCCCCCCCCCCCC.7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy", | ||||||
|  | 		""}, | ||||||
|  | 	{"*0", "", "$2a$03$CCCCCCCCCCCCCCCCCCCCC."}, | ||||||
|  | 	{"*0", "", "$2a$32$CCCCCCCCCCCCCCCCCCCCC."}, | ||||||
|  | 	{"*0", "", "$2c$05$CCCCCCCCCCCCCCCCCCCCC."}, | ||||||
|  | 	{"*0", "", "$2z$05$CCCCCCCCCCCCCCCCCCCCC."}, | ||||||
|  | 	{"*0", "", "$2`$05$CCCCCCCCCCCCCCCCCCCCC."}, | ||||||
|  | 	{"*0", "", "$2{$05$CCCCCCCCCCCCCCCCCCCCC."}, | ||||||
|  | 	{"*1", "", "*0"}, | ||||||
|  | 	{NULL} | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #define which				tests[0] | ||||||
|  |  | ||||||
|  | static volatile sig_atomic_t running; | ||||||
|  |  | ||||||
|  | static void handle_timer(int signum) | ||||||
|  | { | ||||||
|  | 	(void) signum; | ||||||
|  | 	running = 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void *run(void *arg) | ||||||
|  | { | ||||||
|  | 	unsigned long count = 0; | ||||||
|  | 	int i = 0; | ||||||
|  | 	void *data = NULL; | ||||||
|  | 	int size = 0x12345678; | ||||||
|  |  | ||||||
|  | 	do { | ||||||
|  | 		const char *hash = tests[i][0]; | ||||||
|  | 		const char *key = tests[i][1]; | ||||||
|  | 		const char *setting = tests[i][2]; | ||||||
|  |  | ||||||
|  | 		if (!tests[++i][0]) | ||||||
|  | 			i = 0; | ||||||
|  |  | ||||||
|  | 		if (setting && strlen(hash) < 30) /* not for benchmark */ | ||||||
|  | 			continue; | ||||||
|  |  | ||||||
|  | 		if (strcmp(crypt_ra(key, hash, &data, &size), hash)) { | ||||||
|  | 			printf("%d: FAILED (crypt_ra/%d/%lu)\n", | ||||||
|  | 				(int)((char *)arg - (char *)0), i, count); | ||||||
|  | 			free(data); | ||||||
|  | 			return NULL; | ||||||
|  | 		} | ||||||
|  | 		count++; | ||||||
|  | 	} while (running); | ||||||
|  |  | ||||||
|  | 	free(data); | ||||||
|  | 	return count + (char *)0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int main(void) | ||||||
|  | { | ||||||
|  | 	struct itimerval it; | ||||||
|  | 	struct tms buf; | ||||||
|  | 	clock_t clk_tck, start_real, start_virtual, end_real, end_virtual; | ||||||
|  | 	unsigned long count; | ||||||
|  | 	void *data; | ||||||
|  | 	int size; | ||||||
|  | 	char *setting1, *setting2; | ||||||
|  | 	int i; | ||||||
|  | #ifdef TEST_THREADS | ||||||
|  | 	pthread_t t[TEST_THREADS]; | ||||||
|  | 	void *t_retval; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	data = NULL; | ||||||
|  | 	size = 0x12345678; | ||||||
|  |  | ||||||
|  | 	for (i = 0; tests[i][0]; i++) { | ||||||
|  | 		const char *hash = tests[i][0]; | ||||||
|  | 		const char *key = tests[i][1]; | ||||||
|  | 		const char *setting = tests[i][2]; | ||||||
|  | 		const char *p; | ||||||
|  | 		int ok = !setting || strlen(hash) >= 30; | ||||||
|  | 		int o_size; | ||||||
|  | 		char s_buf[30], o_buf[61]; | ||||||
|  | 		if (!setting) { | ||||||
|  | 			memcpy(s_buf, hash, sizeof(s_buf) - 1); | ||||||
|  | 			s_buf[sizeof(s_buf) - 1] = 0; | ||||||
|  | 			setting = s_buf; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		__set_errno(0); | ||||||
|  | 		p = crypt(key, setting); | ||||||
|  | 		if ((!ok && !errno) || strcmp(p, hash)) { | ||||||
|  | 			printf("FAILED (crypt/%d)\n", i); | ||||||
|  | 			return 1; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (ok && strcmp(crypt(key, hash), hash)) { | ||||||
|  | 			printf("FAILED (crypt/%d)\n", i); | ||||||
|  | 			return 1; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		for (o_size = -1; o_size <= (int)sizeof(o_buf); o_size++) { | ||||||
|  | 			int ok_n = ok && o_size == (int)sizeof(o_buf); | ||||||
|  | 			const char *x = "abc"; | ||||||
|  | 			strcpy(o_buf, x); | ||||||
|  | 			if (o_size >= 3) { | ||||||
|  | 				x = "*0"; | ||||||
|  | 				if (setting[0] == '*' && setting[1] == '0') | ||||||
|  | 					x = "*1"; | ||||||
|  | 			} | ||||||
|  | 			__set_errno(0); | ||||||
|  | 			p = crypt_rn(key, setting, o_buf, o_size); | ||||||
|  | 			if ((ok_n && (!p || strcmp(p, hash))) || | ||||||
|  | 			    (!ok_n && (!errno || p || strcmp(o_buf, x)))) { | ||||||
|  | 				printf("FAILED (crypt_rn/%d)\n", i); | ||||||
|  | 				return 1; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		__set_errno(0); | ||||||
|  | 		p = crypt_ra(key, setting, &data, &size); | ||||||
|  | 		if ((ok && (!p || strcmp(p, hash))) || | ||||||
|  | 		    (!ok && (!errno || p || strcmp((char *)data, hash)))) { | ||||||
|  | 			printf("FAILED (crypt_ra/%d)\n", i); | ||||||
|  | 			return 1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	setting1 = crypt_gensalt(which[0], 12, data, size); | ||||||
|  | 	if (!setting1 || strncmp(setting1, "$2a$12$", 7)) { | ||||||
|  | 		puts("FAILED (crypt_gensalt)\n"); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	setting2 = crypt_gensalt_ra(setting1, 12, data, size); | ||||||
|  | 	if (strcmp(setting1, setting2)) { | ||||||
|  | 		puts("FAILED (crypt_gensalt_ra/1)\n"); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	(*(char *)data)++; | ||||||
|  | 	setting1 = crypt_gensalt_ra(setting2, 12, data, size); | ||||||
|  | 	if (!strcmp(setting1, setting2)) { | ||||||
|  | 		puts("FAILED (crypt_gensalt_ra/2)\n"); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	free(setting1); | ||||||
|  | 	free(setting2); | ||||||
|  | 	free(data); | ||||||
|  |  | ||||||
|  | #if defined(_SC_CLK_TCK) || !defined(CLK_TCK) | ||||||
|  | 	clk_tck = sysconf(_SC_CLK_TCK); | ||||||
|  | #else | ||||||
|  | 	clk_tck = CLK_TCK; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	running = 1; | ||||||
|  | 	signal(SIGALRM, handle_timer); | ||||||
|  |  | ||||||
|  | 	memset(&it, 0, sizeof(it)); | ||||||
|  | 	it.it_value.tv_sec = 5; | ||||||
|  | 	setitimer(ITIMER_REAL, &it, NULL); | ||||||
|  |  | ||||||
|  | 	start_real = times(&buf); | ||||||
|  | 	start_virtual = buf.tms_utime + buf.tms_stime; | ||||||
|  |  | ||||||
|  | 	count = (char *)run((char *)0) - (char *)0; | ||||||
|  |  | ||||||
|  | 	end_real = times(&buf); | ||||||
|  | 	end_virtual = buf.tms_utime + buf.tms_stime; | ||||||
|  | 	if (end_virtual == start_virtual) end_virtual++; | ||||||
|  |  | ||||||
|  | 	printf("%.1f c/s real, %.1f c/s virtual\n", | ||||||
|  | 		(float)count * clk_tck / (end_real - start_real), | ||||||
|  | 		(float)count * clk_tck / (end_virtual - start_virtual)); | ||||||
|  |  | ||||||
|  | #ifdef TEST_THREADS | ||||||
|  | 	running = 1; | ||||||
|  | 	it.it_value.tv_sec = 60; | ||||||
|  | 	setitimer(ITIMER_REAL, &it, NULL); | ||||||
|  | 	start_real = times(&buf); | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < TEST_THREADS; i++) | ||||||
|  | 	if (pthread_create(&t[i], NULL, run, i + (char *)0)) { | ||||||
|  | 		perror("pthread_create"); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < TEST_THREADS; i++) { | ||||||
|  | 		if (pthread_join(t[i], &t_retval)) { | ||||||
|  | 			perror("pthread_join"); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		if (!t_retval) continue; | ||||||
|  | 		count = (char *)t_retval - (char *)0; | ||||||
|  | 		end_real = times(&buf); | ||||||
|  | 		printf("%d: %.1f c/s real\n", i, | ||||||
|  | 			(float)count * clk_tck / (end_real - start_real)); | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | #endif | ||||||
							
								
								
									
										203
									
								
								deps/crypt_blowfish/x86.S
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								deps/crypt_blowfish/x86.S
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,203 @@ | |||||||
|  | /* | ||||||
|  |  * Written by Solar Designer <solar at openwall.com> in 1998-2010. | ||||||
|  |  * No copyright is claimed, and the software is hereby placed in the public | ||||||
|  |  * domain.  In case this attempt to disclaim copyright and place the software | ||||||
|  |  * in the public domain is deemed null and void, then the software is | ||||||
|  |  * Copyright (c) 1998-2010 Solar Designer and it is hereby released to the | ||||||
|  |  * general public under the following terms: | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted. | ||||||
|  |  * | ||||||
|  |  * There's ABSOLUTELY NO WARRANTY, express or implied. | ||||||
|  |  * | ||||||
|  |  * See crypt_blowfish.c for more information. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifdef __i386__ | ||||||
|  |  | ||||||
|  | #if defined(__OpenBSD__) && !defined(__ELF__) | ||||||
|  | #define UNDERSCORES | ||||||
|  | #define ALIGN_LOG | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if defined(__CYGWIN32__) || defined(__MINGW32__) | ||||||
|  | #define UNDERSCORES | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef __DJGPP__ | ||||||
|  | #define UNDERSCORES | ||||||
|  | #define ALIGN_LOG | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef UNDERSCORES | ||||||
|  | #define _BF_body_r			__BF_body_r | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifdef ALIGN_LOG | ||||||
|  | #define DO_ALIGN(log)			.align (log) | ||||||
|  | #elif defined(DUMBAS) | ||||||
|  | #define DO_ALIGN(log)			.align 1 << log | ||||||
|  | #else | ||||||
|  | #define DO_ALIGN(log)			.align (1 << (log)) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #define BF_FRAME			0x200 | ||||||
|  | #define ctx				%esp | ||||||
|  |  | ||||||
|  | #define BF_ptr				(ctx) | ||||||
|  |  | ||||||
|  | #define S(N, r)				N+BF_FRAME(ctx,r,4) | ||||||
|  | #ifdef DUMBAS | ||||||
|  | #define P(N)				0x1000+N+N+N+N+BF_FRAME(ctx) | ||||||
|  | #else | ||||||
|  | #define P(N)				0x1000+4*N+BF_FRAME(ctx) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * This version of the assembly code is optimized primarily for the original | ||||||
|  |  * Intel Pentium but is also careful to avoid partial register stalls on the | ||||||
|  |  * Pentium Pro family of processors (tested up to Pentium III Coppermine). | ||||||
|  |  * | ||||||
|  |  * It is possible to do 15% faster on the Pentium Pro family and probably on | ||||||
|  |  * many non-Intel x86 processors, but, unfortunately, that would make things | ||||||
|  |  * twice slower for the original Pentium. | ||||||
|  |  * | ||||||
|  |  * An additional 2% speedup may be achieved with non-reentrant code. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #define L				%esi | ||||||
|  | #define R				%edi | ||||||
|  | #define tmp1				%eax | ||||||
|  | #define tmp1_lo				%al | ||||||
|  | #define tmp2				%ecx | ||||||
|  | #define tmp2_hi				%ch | ||||||
|  | #define tmp3				%edx | ||||||
|  | #define tmp3_lo				%dl | ||||||
|  | #define tmp4				%ebx | ||||||
|  | #define tmp4_hi				%bh | ||||||
|  | #define tmp5				%ebp | ||||||
|  |  | ||||||
|  | .text | ||||||
|  |  | ||||||
|  | #define BF_ROUND(L, R, N) \ | ||||||
|  | 	xorl L,tmp2; \ | ||||||
|  | 	xorl tmp1,tmp1; \ | ||||||
|  | 	movl tmp2,L; \ | ||||||
|  | 	shrl $16,tmp2; \ | ||||||
|  | 	movl L,tmp4; \ | ||||||
|  | 	movb tmp2_hi,tmp1_lo; \ | ||||||
|  | 	andl $0xFF,tmp2; \ | ||||||
|  | 	movb tmp4_hi,tmp3_lo; \ | ||||||
|  | 	andl $0xFF,tmp4; \ | ||||||
|  | 	movl S(0,tmp1),tmp1; \ | ||||||
|  | 	movl S(0x400,tmp2),tmp5; \ | ||||||
|  | 	addl tmp5,tmp1; \ | ||||||
|  | 	movl S(0x800,tmp3),tmp5; \ | ||||||
|  | 	xorl tmp5,tmp1; \ | ||||||
|  | 	movl S(0xC00,tmp4),tmp5; \ | ||||||
|  | 	addl tmp1,tmp5; \ | ||||||
|  | 	movl 4+P(N),tmp2; \ | ||||||
|  | 	xorl tmp5,R | ||||||
|  |  | ||||||
|  | #define BF_ENCRYPT_START \ | ||||||
|  | 	BF_ROUND(L, R, 0); \ | ||||||
|  | 	BF_ROUND(R, L, 1); \ | ||||||
|  | 	BF_ROUND(L, R, 2); \ | ||||||
|  | 	BF_ROUND(R, L, 3); \ | ||||||
|  | 	BF_ROUND(L, R, 4); \ | ||||||
|  | 	BF_ROUND(R, L, 5); \ | ||||||
|  | 	BF_ROUND(L, R, 6); \ | ||||||
|  | 	BF_ROUND(R, L, 7); \ | ||||||
|  | 	BF_ROUND(L, R, 8); \ | ||||||
|  | 	BF_ROUND(R, L, 9); \ | ||||||
|  | 	BF_ROUND(L, R, 10); \ | ||||||
|  | 	BF_ROUND(R, L, 11); \ | ||||||
|  | 	BF_ROUND(L, R, 12); \ | ||||||
|  | 	BF_ROUND(R, L, 13); \ | ||||||
|  | 	BF_ROUND(L, R, 14); \ | ||||||
|  | 	BF_ROUND(R, L, 15); \ | ||||||
|  | 	movl BF_ptr,tmp5; \ | ||||||
|  | 	xorl L,tmp2; \ | ||||||
|  | 	movl P(17),L | ||||||
|  |  | ||||||
|  | #define BF_ENCRYPT_END \ | ||||||
|  | 	xorl R,L; \ | ||||||
|  | 	movl tmp2,R | ||||||
|  |  | ||||||
|  | DO_ALIGN(5) | ||||||
|  | .globl _BF_body_r | ||||||
|  | _BF_body_r: | ||||||
|  | 	movl 4(%esp),%eax | ||||||
|  | 	pushl %ebp | ||||||
|  | 	pushl %ebx | ||||||
|  | 	pushl %esi | ||||||
|  | 	pushl %edi | ||||||
|  | 	subl $BF_FRAME-8,%eax | ||||||
|  | 	xorl L,L | ||||||
|  | 	cmpl %esp,%eax | ||||||
|  | 	ja BF_die | ||||||
|  | 	xchgl %eax,%esp | ||||||
|  | 	xorl R,R | ||||||
|  | 	pushl %eax | ||||||
|  | 	leal 0x1000+BF_FRAME-4(ctx),%eax | ||||||
|  | 	movl 0x1000+BF_FRAME-4(ctx),tmp2 | ||||||
|  | 	pushl %eax | ||||||
|  | 	xorl tmp3,tmp3 | ||||||
|  | BF_loop_P: | ||||||
|  | 	BF_ENCRYPT_START | ||||||
|  | 	addl $8,tmp5 | ||||||
|  | 	BF_ENCRYPT_END | ||||||
|  | 	leal 0x1000+18*4+BF_FRAME(ctx),tmp1 | ||||||
|  | 	movl tmp5,BF_ptr | ||||||
|  | 	cmpl tmp5,tmp1 | ||||||
|  | 	movl L,-8(tmp5) | ||||||
|  | 	movl R,-4(tmp5) | ||||||
|  | 	movl P(0),tmp2 | ||||||
|  | 	ja BF_loop_P | ||||||
|  | 	leal BF_FRAME(ctx),tmp5 | ||||||
|  | 	xorl tmp3,tmp3 | ||||||
|  | 	movl tmp5,BF_ptr | ||||||
|  | BF_loop_S: | ||||||
|  | 	BF_ENCRYPT_START | ||||||
|  | 	BF_ENCRYPT_END | ||||||
|  | 	movl P(0),tmp2 | ||||||
|  | 	movl L,(tmp5) | ||||||
|  | 	movl R,4(tmp5) | ||||||
|  | 	BF_ENCRYPT_START | ||||||
|  | 	BF_ENCRYPT_END | ||||||
|  | 	movl P(0),tmp2 | ||||||
|  | 	movl L,8(tmp5) | ||||||
|  | 	movl R,12(tmp5) | ||||||
|  | 	BF_ENCRYPT_START | ||||||
|  | 	BF_ENCRYPT_END | ||||||
|  | 	movl P(0),tmp2 | ||||||
|  | 	movl L,16(tmp5) | ||||||
|  | 	movl R,20(tmp5) | ||||||
|  | 	BF_ENCRYPT_START | ||||||
|  | 	addl $32,tmp5 | ||||||
|  | 	BF_ENCRYPT_END | ||||||
|  | 	leal 0x1000+BF_FRAME(ctx),tmp1 | ||||||
|  | 	movl tmp5,BF_ptr | ||||||
|  | 	cmpl tmp5,tmp1 | ||||||
|  | 	movl P(0),tmp2 | ||||||
|  | 	movl L,-8(tmp5) | ||||||
|  | 	movl R,-4(tmp5) | ||||||
|  | 	ja BF_loop_S | ||||||
|  | 	movl 4(%esp),%esp | ||||||
|  | 	popl %edi | ||||||
|  | 	popl %esi | ||||||
|  | 	popl %ebx | ||||||
|  | 	popl %ebp | ||||||
|  | 	ret | ||||||
|  |  | ||||||
|  | BF_die: | ||||||
|  | /* Oops, need to re-compile with a larger BF_FRAME. */ | ||||||
|  | 	hlt | ||||||
|  | 	jmp BF_die | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if defined(__ELF__) && defined(__linux__) | ||||||
|  | .section .note.GNU-stack,"",@progbits | ||||||
|  | #endif | ||||||
							
								
								
									
										1
									
								
								deps/libbacktrace
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								deps/libbacktrace
									
									
									
									
										vendored
									
									
								
							 Submodule deps/libbacktrace deleted from 11427f31a6
									
								
							
							
								
								
									
										5
									
								
								deps/libbacktrace/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								deps/libbacktrace/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | *~ | ||||||
|  | *.o | ||||||
|  | *.lo | ||||||
|  | *.a | ||||||
|  | *.la | ||||||
							
								
								
									
										9286
									
								
								deps/libbacktrace/Isaac.Newton-Opticks.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9286
									
								
								deps/libbacktrace/Isaac.Newton-Opticks.txt
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										29
									
								
								deps/libbacktrace/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								deps/libbacktrace/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | # Copyright (C) 2012-2016 Free Software Foundation, Inc. | ||||||
|  |  | ||||||
|  | # Redistribution and use in source and binary forms, with or without | ||||||
|  | # modification, are permitted provided that the following conditions are | ||||||
|  | # met: | ||||||
|  |  | ||||||
|  | #     (1) Redistributions of source code must retain the above copyright | ||||||
|  | #     notice, this list of conditions and the following disclaimer.  | ||||||
|  |  | ||||||
|  | #     (2) Redistributions in binary form must reproduce the above copyright | ||||||
|  | #     notice, this list of conditions and the following disclaimer in | ||||||
|  | #     the documentation and/or other materials provided with the | ||||||
|  | #     distribution.   | ||||||
|  |      | ||||||
|  | #     (3) The name of the author may not be used to | ||||||
|  | #     endorse or promote products derived from this software without | ||||||
|  | #     specific prior written permission. | ||||||
|  |  | ||||||
|  | # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||||||
|  | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||||
|  | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||||
|  | # DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, | ||||||
|  | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||||
|  | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||||
|  | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||||
|  | # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||||||
|  | # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||||||
|  | # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||||
|  | # POSSIBILITY OF SUCH DAMAGE. | ||||||
							
								
								
									
										623
									
								
								deps/libbacktrace/Makefile.am
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										623
									
								
								deps/libbacktrace/Makefile.am
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,623 @@ | |||||||
|  | # Makefile.am -- Backtrace Makefile. | ||||||
|  | # Copyright (C) 2012-2021 Free Software Foundation, Inc. | ||||||
|  |  | ||||||
|  | # Redistribution and use in source and binary forms, with or without | ||||||
|  | # modification, are permitted provided that the following conditions are | ||||||
|  | # met: | ||||||
|  |  | ||||||
|  | #     (1) Redistributions of source code must retain the above copyright | ||||||
|  | #     notice, this list of conditions and the following disclaimer. | ||||||
|  |  | ||||||
|  | #     (2) Redistributions in binary form must reproduce the above copyright | ||||||
|  | #     notice, this list of conditions and the following disclaimer in | ||||||
|  | #     the documentation and/or other materials provided with the | ||||||
|  | #     distribution. | ||||||
|  |  | ||||||
|  | #     (3) The name of the author may not be used to | ||||||
|  | #     endorse or promote products derived from this software without | ||||||
|  | #     specific prior written permission. | ||||||
|  |  | ||||||
|  | # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||||||
|  | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||||
|  | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||||
|  | # DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, | ||||||
|  | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||||
|  | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||||
|  | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||||
|  | # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||||||
|  | # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||||||
|  | # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||||
|  | # POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  | ||||||
|  | ACLOCAL_AMFLAGS = -I config | ||||||
|  |  | ||||||
|  | AM_CPPFLAGS = | ||||||
|  |  | ||||||
|  | AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG) | ||||||
|  |  | ||||||
|  | include_HEADERS = backtrace.h backtrace-supported.h | ||||||
|  |  | ||||||
|  | lib_LTLIBRARIES = libbacktrace.la | ||||||
|  |  | ||||||
|  | libbacktrace_la_SOURCES = \ | ||||||
|  | 	backtrace.h \ | ||||||
|  | 	atomic.c \ | ||||||
|  | 	dwarf.c \ | ||||||
|  | 	fileline.c \ | ||||||
|  | 	internal.h \ | ||||||
|  | 	posix.c \ | ||||||
|  | 	print.c \ | ||||||
|  | 	sort.c \ | ||||||
|  | 	state.c | ||||||
|  |  | ||||||
|  | BACKTRACE_FILES = \ | ||||||
|  | 	backtrace.c \ | ||||||
|  | 	simple.c \ | ||||||
|  | 	nounwind.c | ||||||
|  |  | ||||||
|  | FORMAT_FILES = \ | ||||||
|  | 	elf.c \ | ||||||
|  | 	macho.c \ | ||||||
|  | 	pecoff.c \ | ||||||
|  | 	unknown.c \ | ||||||
|  | 	xcoff.c | ||||||
|  |  | ||||||
|  | VIEW_FILES = \ | ||||||
|  | 	read.c \ | ||||||
|  | 	mmapio.c | ||||||
|  |  | ||||||
|  | ALLOC_FILES = \ | ||||||
|  | 	alloc.c \ | ||||||
|  | 	mmap.c | ||||||
|  |  | ||||||
|  | EXTRA_libbacktrace_la_SOURCES = \ | ||||||
|  | 	$(BACKTRACE_FILES) \ | ||||||
|  | 	$(FORMAT_FILES) \ | ||||||
|  | 	$(VIEW_FILES) \ | ||||||
|  | 	$(ALLOC_FILES) | ||||||
|  |  | ||||||
|  | libbacktrace_la_LIBADD = \ | ||||||
|  | 	$(BACKTRACE_FILE) \ | ||||||
|  | 	$(FORMAT_FILE) \ | ||||||
|  | 	$(VIEW_FILE) \ | ||||||
|  | 	$(ALLOC_FILE) | ||||||
|  |  | ||||||
|  | libbacktrace_la_DEPENDENCIES = $(libbacktrace_la_LIBADD) | ||||||
|  |  | ||||||
|  | # Testsuite. | ||||||
|  |  | ||||||
|  | # Add a test to this variable if you want it to be built as a program, | ||||||
|  | # with SOURCES, etc. | ||||||
|  | check_PROGRAMS = | ||||||
|  |  | ||||||
|  | # Add a test to this variable if you want it to be run. | ||||||
|  | TESTS = | ||||||
|  |  | ||||||
|  | # Add a test to this variable if you want it to be built as a Makefile | ||||||
|  | # target and run. | ||||||
|  | MAKETESTS = | ||||||
|  |  | ||||||
|  | # Add a test to this variable if you want it to be built as a program, | ||||||
|  | # with SOURCES, etc., and run. | ||||||
|  | BUILDTESTS = | ||||||
|  |  | ||||||
|  | # Add a file to this variable if you want it to be built for testing. | ||||||
|  | check_DATA = | ||||||
|  |  | ||||||
|  | # Flags to use when compiling test programs. | ||||||
|  | libbacktrace_TEST_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) -g | ||||||
|  |  | ||||||
|  | if USE_DSYMUTIL | ||||||
|  |  | ||||||
|  | %.dSYM: % | ||||||
|  | 	$(DSYMUTIL) $< | ||||||
|  |  | ||||||
|  | endif USE_DSYMUTIL | ||||||
|  |  | ||||||
|  | if NATIVE | ||||||
|  | check_LTLIBRARIES = libbacktrace_alloc.la | ||||||
|  |  | ||||||
|  | libbacktrace_alloc_la_SOURCES = $(libbacktrace_la_SOURCES) | ||||||
|  | libbacktrace_alloc_la_LIBADD = $(BACKTRACE_FILE) $(FORMAT_FILE) read.lo alloc.lo | ||||||
|  |  | ||||||
|  | libbacktrace_alloc_la_DEPENDENCIES = $(libbacktrace_alloc_la_LIBADD) | ||||||
|  |  | ||||||
|  | check_LTLIBRARIES += libbacktrace_noformat.la | ||||||
|  |  | ||||||
|  | libbacktrace_noformat_la_SOURCES = $(libbacktrace_la_SOURCES) | ||||||
|  | libbacktrace_noformat_la_LIBADD = $(BACKTRACE_FILE) $(VIEW_FILE) $(ALLOC_FILE) | ||||||
|  |  | ||||||
|  | libbacktrace_noformat_la_DEPENDENCIES = $(libbacktrace_noformat_la_LIBADD) | ||||||
|  |  | ||||||
|  | if HAVE_ELF | ||||||
|  | if HAVE_OBJCOPY_DEBUGLINK | ||||||
|  |  | ||||||
|  | TEST_BUILD_ID_DIR=$(abs_builddir)/usr/lib/debug/.build-id/ | ||||||
|  |  | ||||||
|  | check_LTLIBRARIES += libbacktrace_elf_for_test.la | ||||||
|  |  | ||||||
|  | libbacktrace_elf_for_test_la_SOURCES = $(libbacktrace_la_SOURCES) | ||||||
|  | libbacktrace_elf_for_test_la_LIBADD = $(BACKTRACE_FILE) elf_for_test.lo \ | ||||||
|  | 	$(VIEW_FILE) $(ALLOC_FILE) | ||||||
|  |  | ||||||
|  | elf_for_test.c: elf.c | ||||||
|  | 	SEARCH='^#define SYSTEM_BUILD_ID_DIR.*$$'; \ | ||||||
|  | 	REPLACE="#define SYSTEM_BUILD_ID_DIR \"$(TEST_BUILD_ID_DIR)\""; \ | ||||||
|  | 	$(SED) "s%$$SEARCH%$$REPLACE%" \ | ||||||
|  | 		$< \ | ||||||
|  | 		> $@.tmp | ||||||
|  | 	mv $@.tmp $@ | ||||||
|  |  | ||||||
|  | endif HAVE_OBJCOPY_DEBUGLINK | ||||||
|  | endif HAVE_ELF | ||||||
|  |  | ||||||
|  | elf_%.c: elf.c | ||||||
|  | 	SEARCH='#error "Unknown BACKTRACE_ELF_SIZE"'; \ | ||||||
|  | 	REPLACE='#undef BACKTRACE_ELF_SIZE\ | ||||||
|  | 	#define BACKTRACE_ELF_SIZE'; \ | ||||||
|  | 	$(SED) "s/^$$SEARCH\$$/$$REPLACE $*/" \ | ||||||
|  | 		$< \ | ||||||
|  | 		> $@.tmp | ||||||
|  | 	mv $@.tmp $@ | ||||||
|  |  | ||||||
|  | xcoff_%.c: xcoff.c | ||||||
|  | 	SEARCH='#error "Unknown BACKTRACE_XCOFF_SIZE"'; \ | ||||||
|  | 	REPLACE='#undef BACKTRACE_XCOFF_SIZE\ | ||||||
|  | 	#define BACKTRACE_XCOFF_SIZE'; \ | ||||||
|  | 	$(SED) "s/^$$SEARCH\$$/$$REPLACE $*/" \ | ||||||
|  | 		$< \ | ||||||
|  | 		> $@.tmp | ||||||
|  | 	mv $@.tmp $@ | ||||||
|  |  | ||||||
|  | test_elf_32_SOURCES = test_format.c testlib.c | ||||||
|  | test_elf_32_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | test_elf_32_LDADD = libbacktrace_noformat.la elf_32.lo | ||||||
|  |  | ||||||
|  | BUILDTESTS += test_elf_32 | ||||||
|  |  | ||||||
|  | test_elf_64_SOURCES = test_format.c testlib.c | ||||||
|  | test_elf_64_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | test_elf_64_LDADD = libbacktrace_noformat.la elf_64.lo | ||||||
|  |  | ||||||
|  | BUILDTESTS += test_elf_64 | ||||||
|  |  | ||||||
|  | test_macho_SOURCES = test_format.c testlib.c | ||||||
|  | test_macho_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | test_macho_LDADD = libbacktrace_noformat.la macho.lo | ||||||
|  |  | ||||||
|  | BUILDTESTS += test_macho | ||||||
|  |  | ||||||
|  | test_xcoff_32_SOURCES = test_format.c testlib.c | ||||||
|  | test_xcoff_32_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | test_xcoff_32_LDADD = libbacktrace_noformat.la xcoff_32.lo | ||||||
|  |  | ||||||
|  | BUILDTESTS += test_xcoff_32 | ||||||
|  |  | ||||||
|  | test_xcoff_64_SOURCES = test_format.c testlib.c | ||||||
|  | test_xcoff_64_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | test_xcoff_64_LDADD = libbacktrace_noformat.la xcoff_64.lo | ||||||
|  |  | ||||||
|  | BUILDTESTS += test_xcoff_64 | ||||||
|  |  | ||||||
|  | test_pecoff_SOURCES = test_format.c testlib.c | ||||||
|  | test_pecoff_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | test_pecoff_LDADD = libbacktrace_noformat.la pecoff.lo | ||||||
|  |  | ||||||
|  | BUILDTESTS += test_pecoff | ||||||
|  |  | ||||||
|  | test_unknown_SOURCES = test_format.c testlib.c | ||||||
|  | test_unknown_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | test_unknown_LDADD = libbacktrace_noformat.la unknown.lo | ||||||
|  |  | ||||||
|  | BUILDTESTS += test_unknown | ||||||
|  |  | ||||||
|  | unittest_SOURCES = unittest.c testlib.c | ||||||
|  | unittest_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | unittest_LDADD = libbacktrace.la | ||||||
|  |  | ||||||
|  | BUILDTESTS += unittest | ||||||
|  |  | ||||||
|  | unittest_alloc_SOURCES = $(unittest_SOURCES) | ||||||
|  | unittest_alloc_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | unittest_alloc_LDADD = libbacktrace_alloc.la | ||||||
|  |  | ||||||
|  | BUILDTESTS += unittest_alloc | ||||||
|  |  | ||||||
|  | check_LTLIBRARIES += libbacktrace_instrumented_alloc.la | ||||||
|  |  | ||||||
|  | libbacktrace_instrumented_alloc_la_SOURCES = $(libbacktrace_la_SOURCES) | ||||||
|  | libbacktrace_instrumented_alloc_la_LIBADD = $(BACKTRACE_FILE) $(FORMAT_FILE) \ | ||||||
|  | 	read.lo instrumented_alloc.lo | ||||||
|  |  | ||||||
|  | libbacktrace_instrumented_alloc_la_DEPENDENCIES = \ | ||||||
|  | 	$(libbacktrace_instrumented_alloc_la_LIBADD) | ||||||
|  |  | ||||||
|  | instrumented_alloc.lo: alloc.c | ||||||
|  |  | ||||||
|  | allocfail_SOURCES = allocfail.c testlib.c | ||||||
|  | allocfail_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | allocfail_LDADD = libbacktrace_instrumented_alloc.la | ||||||
|  |  | ||||||
|  | check_PROGRAMS += allocfail | ||||||
|  |  | ||||||
|  | allocfail.sh: allocfail | ||||||
|  |  | ||||||
|  | TESTS += allocfail.sh | ||||||
|  |  | ||||||
|  | if USE_DSYMUTIL | ||||||
|  | check_DATA += allocfail.dSYM | ||||||
|  | endif USE_DSYMUTIL | ||||||
|  |  | ||||||
|  | if HAVE_ELF | ||||||
|  | if HAVE_BUILDID | ||||||
|  | if HAVE_OBJCOPY_DEBUGLINK | ||||||
|  |  | ||||||
|  | b2test_SOURCES = $(btest_SOURCES) | ||||||
|  | b2test_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | b2test_LDFLAGS = -Wl,--build-id | ||||||
|  | b2test_LDADD = libbacktrace_elf_for_test.la | ||||||
|  |  | ||||||
|  | check_PROGRAMS += b2test | ||||||
|  | MAKETESTS += b2test_buildid | ||||||
|  |  | ||||||
|  | if HAVE_DWZ | ||||||
|  |  | ||||||
|  | b3test_SOURCES = $(btest_SOURCES) | ||||||
|  | b3test_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | b3test_LDFLAGS = -Wl,--build-id | ||||||
|  | b3test_LDADD = libbacktrace_elf_for_test.la | ||||||
|  |  | ||||||
|  | check_PROGRAMS += b3test | ||||||
|  | MAKETESTS += b3test_dwz_buildid | ||||||
|  |  | ||||||
|  | endif HAVE_DWZ | ||||||
|  |  | ||||||
|  | endif HAVE_OBJCOPY_DEBUGLINK | ||||||
|  | endif HAVE_BUILDID | ||||||
|  | endif HAVE_ELF | ||||||
|  |  | ||||||
|  | btest_SOURCES = btest.c testlib.c | ||||||
|  | btest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -O | ||||||
|  | btest_LDADD = libbacktrace.la | ||||||
|  |  | ||||||
|  | BUILDTESTS += btest | ||||||
|  |  | ||||||
|  | if USE_DSYMUTIL | ||||||
|  | check_DATA += btest.dSYM | ||||||
|  | endif USE_DSYMUTIL | ||||||
|  |  | ||||||
|  | if HAVE_ELF | ||||||
|  |  | ||||||
|  | btest_lto_SOURCES = btest.c testlib.c | ||||||
|  | btest_lto_CFLAGS = $(libbacktrace_TEST_CFLAGS) -O -flto | ||||||
|  | btest_lto_LDADD = libbacktrace.la | ||||||
|  |  | ||||||
|  | BUILDTESTS += btest_lto | ||||||
|  |  | ||||||
|  | endif HAVE_ELF | ||||||
|  |  | ||||||
|  | btest_alloc_SOURCES = $(btest_SOURCES) | ||||||
|  | btest_alloc_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | btest_alloc_LDADD = libbacktrace_alloc.la | ||||||
|  |  | ||||||
|  | BUILDTESTS += btest_alloc | ||||||
|  |  | ||||||
|  | if USE_DSYMUTIL | ||||||
|  | check_DATA += btest_alloc.dSYM | ||||||
|  | endif USE_DSYMUTIL | ||||||
|  |  | ||||||
|  | if HAVE_DWZ | ||||||
|  |  | ||||||
|  | %_dwz: % | ||||||
|  | 	rm -f $@ $@_common.debug | ||||||
|  | 	cp $< $@_1 | ||||||
|  | 	cp $< $@_2 | ||||||
|  | 	if $(DWZ) -m $@_common.debug $@_1 $@_2; then \ | ||||||
|  | 	  rm -f $@_2; \ | ||||||
|  | 	  mv $@_1 $@; \ | ||||||
|  | 	else \ | ||||||
|  | 	  echo "Ignoring dwz errors, assuming that test passes"; \ | ||||||
|  | 	  cp $< $@; \ | ||||||
|  | 	fi | ||||||
|  |  | ||||||
|  | MAKETESTS += btest_dwz | ||||||
|  |  | ||||||
|  | if HAVE_OBJCOPY_DEBUGLINK | ||||||
|  |  | ||||||
|  | MAKETESTS += btest_dwz_gnudebuglink | ||||||
|  |  | ||||||
|  | endif HAVE_OBJCOPY_DEBUGLINK | ||||||
|  |  | ||||||
|  | endif HAVE_DWZ | ||||||
|  |  | ||||||
|  | stest_SOURCES = stest.c | ||||||
|  | stest_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | stest_LDADD = libbacktrace.la | ||||||
|  |  | ||||||
|  | BUILDTESTS += stest | ||||||
|  |  | ||||||
|  | if USE_DSYMUTIL | ||||||
|  | check_DATA += stest.dSYM | ||||||
|  | endif USE_DSYMUTIL | ||||||
|  |  | ||||||
|  | stest_alloc_SOURCES = $(stest_SOURCES) | ||||||
|  | stest_alloc_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | stest_alloc_LDADD = libbacktrace_alloc.la | ||||||
|  |  | ||||||
|  | BUILDTESTS += stest_alloc | ||||||
|  |  | ||||||
|  | if USE_DSYMUTIL | ||||||
|  | check_DATA += stest_alloc.dSYM | ||||||
|  | endif USE_DSYMUTIL | ||||||
|  |  | ||||||
|  | if HAVE_ELF | ||||||
|  |  | ||||||
|  | ztest_SOURCES = ztest.c testlib.c | ||||||
|  | ztest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -DSRCDIR=\"$(srcdir)\" | ||||||
|  | ztest_LDADD = libbacktrace.la | ||||||
|  | ztest_alloc_LDADD = libbacktrace_alloc.la | ||||||
|  |  | ||||||
|  | if HAVE_ZLIB | ||||||
|  | ztest_LDADD += -lz | ||||||
|  | ztest_alloc_LDADD += -lz | ||||||
|  | endif | ||||||
|  | ztest_LDADD += $(CLOCK_GETTIME_LINK) | ||||||
|  | ztest_alloc_LDADD += $(CLOCK_GETTIME_LINK) | ||||||
|  |  | ||||||
|  | BUILDTESTS += ztest | ||||||
|  |  | ||||||
|  | ztest_alloc_SOURCES = $(ztest_SOURCES) | ||||||
|  | ztest_alloc_CFLAGS = $(ztest_CFLAGS) | ||||||
|  |  | ||||||
|  | BUILDTESTS += ztest_alloc | ||||||
|  |  | ||||||
|  | zstdtest_SOURCES = zstdtest.c testlib.c | ||||||
|  | zstdtest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -DSRCDIR=\"$(srcdir)\" | ||||||
|  | zstdtest_LDADD = libbacktrace.la | ||||||
|  | zstdtest_alloc_LDADD = libbacktrace_alloc.la | ||||||
|  |  | ||||||
|  | if HAVE_ZSTD | ||||||
|  | zstdtest_LDADD += -lzstd | ||||||
|  | zstdtest_alloc_LDADD += -lzstd | ||||||
|  | endif | ||||||
|  | zstdtest_LDADD += $(CLOCK_GETTIME_LINK) | ||||||
|  | zstdtest_alloc_LDADD += $(CLOCK_GETTIME_LINK) | ||||||
|  |  | ||||||
|  | BUILDTESTS += zstdtest | ||||||
|  |  | ||||||
|  | zstdtest_alloc_SOURCES = $(zstdtest_SOURCES) | ||||||
|  | zstdtest_alloc_CFLAGS = $(zstdtest_CFLAGS) | ||||||
|  |  | ||||||
|  | BUILDTESTS += zstdtest_alloc | ||||||
|  |  | ||||||
|  | endif HAVE_ELF | ||||||
|  |  | ||||||
|  | edtest_SOURCES = edtest.c edtest2_build.c testlib.c | ||||||
|  | edtest_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | edtest_LDADD = libbacktrace.la | ||||||
|  |  | ||||||
|  | BUILDTESTS += edtest | ||||||
|  |  | ||||||
|  | if USE_DSYMUTIL | ||||||
|  | check_DATA += edtest.dSYM | ||||||
|  | endif USE_DSYMUTIL | ||||||
|  |  | ||||||
|  | edtest_alloc_SOURCES = $(edtest_SOURCES) | ||||||
|  | edtest_alloc_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | edtest_alloc_LDADD = libbacktrace_alloc.la | ||||||
|  |  | ||||||
|  | if USE_DSYMUTIL | ||||||
|  | check_DATA += edtest_alloc.dSYM | ||||||
|  | endif USE_DSYMUTIL | ||||||
|  |  | ||||||
|  | BUILDTESTS += edtest_alloc | ||||||
|  |  | ||||||
|  | edtest2_build.c: gen_edtest2_build; @true | ||||||
|  | gen_edtest2_build: $(srcdir)/edtest2.c | ||||||
|  | 	cat $(srcdir)/edtest2.c > tmp-edtest2_build.c | ||||||
|  | 	$(SHELL) $(srcdir)/move-if-change tmp-edtest2_build.c edtest2_build.c | ||||||
|  | 	echo timestamp > $@ | ||||||
|  |  | ||||||
|  | if HAVE_PTHREAD | ||||||
|  |  | ||||||
|  | BUILDTESTS += ttest | ||||||
|  |  | ||||||
|  | ttest_SOURCES = ttest.c testlib.c | ||||||
|  | ttest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -pthread | ||||||
|  | ttest_LDADD = libbacktrace.la | ||||||
|  |  | ||||||
|  | if USE_DSYMUTIL | ||||||
|  | check_DATA += ttest.dSYM | ||||||
|  | endif USE_DSYMUTIL | ||||||
|  |  | ||||||
|  | BUILDTESTS += ttest_alloc | ||||||
|  |  | ||||||
|  | ttest_alloc_SOURCES = $(ttest_SOURCES) | ||||||
|  | ttest_alloc_CFLAGS = $(ttest_CFLAGS) | ||||||
|  | ttest_alloc_LDADD = libbacktrace_alloc.la | ||||||
|  |  | ||||||
|  | if USE_DSYMUTIL | ||||||
|  | check_DATA += ttest_alloc.dSYM | ||||||
|  | endif USE_DSYMUTIL | ||||||
|  |  | ||||||
|  | endif HAVE_PTHREAD | ||||||
|  |  | ||||||
|  | if HAVE_OBJCOPY_DEBUGLINK | ||||||
|  |  | ||||||
|  | MAKETESTS += btest_gnudebuglink | ||||||
|  |  | ||||||
|  | %_gnudebuglink: % | ||||||
|  | 	$(OBJCOPY) --only-keep-debug $< $@.debug | ||||||
|  | 	$(OBJCOPY) --strip-debug --add-gnu-debuglink=$@.debug $< $@ | ||||||
|  |  | ||||||
|  | endif HAVE_OBJCOPY_DEBUGLINK | ||||||
|  |  | ||||||
|  | %_buildid: % | ||||||
|  | 	./install-debuginfo-for-buildid.sh \ | ||||||
|  | 	  "$(TEST_BUILD_ID_DIR)" \ | ||||||
|  | 	  $< | ||||||
|  | 	$(OBJCOPY) --strip-debug $< $@ | ||||||
|  |  | ||||||
|  | if HAVE_COMPRESSED_DEBUG | ||||||
|  |  | ||||||
|  | ctestg_SOURCES = btest.c testlib.c | ||||||
|  | ctestg_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | ctestg_LDFLAGS = -Wl,--compress-debug-sections=zlib-gnu | ||||||
|  | ctestg_LDADD = libbacktrace.la | ||||||
|  |  | ||||||
|  | ctesta_SOURCES = btest.c testlib.c | ||||||
|  | ctesta_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | ctesta_LDFLAGS = -Wl,--compress-debug-sections=zlib-gabi | ||||||
|  | ctesta_LDADD = libbacktrace.la | ||||||
|  |  | ||||||
|  | BUILDTESTS += ctestg ctesta | ||||||
|  |  | ||||||
|  | if HAVE_COMPRESSED_DEBUG_ZSTD | ||||||
|  |  | ||||||
|  | ctestzstd_SOURCES = btest.c testlib.c | ||||||
|  | ctestzstd_CFLAGS = $(libbacktrace_TEST_CFLAGS) | ||||||
|  | ctestzstd_LDFLAGS = -Wl,--compress-debug-sections=zstd | ||||||
|  | ctestzstd_LDADD = libbacktrace.la | ||||||
|  |  | ||||||
|  | BUILDTESTS += ctestzstd | ||||||
|  |  | ||||||
|  | endif | ||||||
|  |  | ||||||
|  | ctestg_alloc_SOURCES = $(ctestg_SOURCES) | ||||||
|  | ctestg_alloc_CFLAGS = $(ctestg_CFLAGS) | ||||||
|  | ctestg_alloc_LDFLAGS = $(ctestg_LDFLAGS) | ||||||
|  | ctestg_alloc_LDADD = libbacktrace_alloc.la | ||||||
|  |  | ||||||
|  | ctesta_alloc_SOURCES = $(ctesta_SOURCES) | ||||||
|  | ctesta_alloc_CFLAGS = $(ctesta_CFLAGS) | ||||||
|  | ctesta_alloc_LDFLAGS = $(ctesta_LDFLAGS) | ||||||
|  | ctesta_alloc_LDADD = libbacktrace_alloc.la | ||||||
|  |  | ||||||
|  | BUILDTESTS += ctestg_alloc ctesta_alloc | ||||||
|  |  | ||||||
|  | endif | ||||||
|  |  | ||||||
|  | if HAVE_DWARF5 | ||||||
|  |  | ||||||
|  | dwarf5_SOURCES = btest.c testlib.c | ||||||
|  | dwarf5_CFLAGS = $(libbacktrace_TEST_CFLAGS) -gdwarf-5 | ||||||
|  | dwarf5_LDADD = libbacktrace.la | ||||||
|  |  | ||||||
|  | BUILDTESTS += dwarf5 | ||||||
|  |  | ||||||
|  | if USE_DSYMUTIL | ||||||
|  | check_DATA += dwarf5.dSYM | ||||||
|  | endif USE_DSYMUTIL | ||||||
|  |  | ||||||
|  | dwarf5_alloc_SOURCES = $(dwarf5_SOURCES) | ||||||
|  | dwarf5_alloc_CFLAGS = $(dwarf5_CFLAGS) | ||||||
|  | dwarf5_alloc_LDADD = libbacktrace_alloc.la | ||||||
|  |  | ||||||
|  | BUILDTESTS += dwarf5_alloc | ||||||
|  |  | ||||||
|  | if USE_DSYMUTIL | ||||||
|  | check_DATA += dwarf5_alloc.dSYM | ||||||
|  | endif USE_DSYMUTIL | ||||||
|  |  | ||||||
|  | endif | ||||||
|  |  | ||||||
|  | mtest_SOURCES = mtest.c testlib.c | ||||||
|  | mtest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -O | ||||||
|  | mtest_LDADD = libbacktrace.la | ||||||
|  |  | ||||||
|  | BUILDTESTS += mtest | ||||||
|  |  | ||||||
|  | if USE_DSYMUTIL | ||||||
|  | check_DATA += mtest.dSYM | ||||||
|  | endif USE_DSYMUTIL | ||||||
|  |  | ||||||
|  | if HAVE_MINIDEBUG | ||||||
|  |  | ||||||
|  | MAKETESTS += mtest_minidebug | ||||||
|  |  | ||||||
|  | %_minidebug: % | ||||||
|  | 	$(NM) -D $< -P --defined-only | $(AWK) '{ print $$1 }' | sort > $<.dsyms | ||||||
|  | 	$(NM) $< -P --defined-only | $(AWK) '{ if ($$2 == "T" || $$2 == "t" || $$2 == "D") print $$1 }' | sort > $<.fsyms | ||||||
|  | 	$(COMM) -13 $<.dsyms $<.fsyms > $<.keepsyms | ||||||
|  | 	$(OBJCOPY) --only-keep-debug $< $<.dbg | ||||||
|  | 	$(OBJCOPY) -S --remove-section .gdb_index --remove-section .comment --keep-symbols=$<.keepsyms $<.dbg $<.mdbg | ||||||
|  | 	$(OBJCOPY) --strip-all --remove-section ..comment $< $<.strip | ||||||
|  | 	rm -f $<.mdbg.xz | ||||||
|  | 	$(XZ) $<.mdbg | ||||||
|  | 	$(OBJCOPY) --add-section .gnu_debugdata=$<.mdbg.xz $<.strip | ||||||
|  | 	mv $<.strip $@ | ||||||
|  |  | ||||||
|  | endif HAVE_MINIDEBUG | ||||||
|  |  | ||||||
|  | endif NATIVE | ||||||
|  |  | ||||||
|  | if HAVE_ELF | ||||||
|  |  | ||||||
|  | xztest_SOURCES = xztest.c testlib.c | ||||||
|  | xztest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -DSRCDIR=\"$(srcdir)\" | ||||||
|  | xztest_LDADD = libbacktrace.la | ||||||
|  |  | ||||||
|  | xztest_alloc_SOURCES = $(xztest_SOURCES) | ||||||
|  | xztest_alloc_CFLAGS = $(xztest_CFLAGS) | ||||||
|  | xztest_alloc_LDADD = libbacktrace_alloc.la | ||||||
|  |  | ||||||
|  | if HAVE_LIBLZMA | ||||||
|  | xztest_LDADD += -llzma | ||||||
|  | xztest_alloc_LDADD += -llzma | ||||||
|  | endif | ||||||
|  |  | ||||||
|  | xztest_LDADD += $(CLOCK_GETTIME_LINK) | ||||||
|  | xztest_alloc_LDADD += $(CLOCK_GETTIME_LINK) | ||||||
|  |  | ||||||
|  | BUILDTESTS += xztest xztest_alloc | ||||||
|  |  | ||||||
|  | endif HAVE_ELF | ||||||
|  |  | ||||||
|  | check_PROGRAMS += $(BUILDTESTS) | ||||||
|  |  | ||||||
|  | TESTS += $(MAKETESTS) $(BUILDTESTS) | ||||||
|  |  | ||||||
|  | CLEANFILES = \ | ||||||
|  | 	$(MAKETESTS) $(BUILDTESTS) *.debug elf_for_test.c edtest2_build.c \ | ||||||
|  | 	gen_edtest2_build \ | ||||||
|  | 	*.dsyms *.fsyms *.keepsyms *.dbg *.mdbg *.mdbg.xz *.strip | ||||||
|  |  | ||||||
|  | clean-local: | ||||||
|  | 	-rm -rf usr | ||||||
|  |  | ||||||
|  | # We can't use automake's automatic dependency tracking, because it | ||||||
|  | # breaks when using bootstrap-lean.  Automatic dependency tracking | ||||||
|  | # with GCC bootstrap will cause some of the objects to depend on | ||||||
|  | # header files in prev-gcc/include, e.g., stddef.h and stdarg.h.  When | ||||||
|  | # using bootstrap-lean, prev-gcc is removed after each stage.  When | ||||||
|  | # running "make install", those header files will be gone, causing the | ||||||
|  | # library to be rebuilt at install time.  That may not succeed. | ||||||
|  |  | ||||||
|  | # These manual dependencies do not include dependencies on unwind.h, | ||||||
|  | # even though that is part of GCC, because where to find it depends on | ||||||
|  | # whether we are being built as a host library or a target library. | ||||||
|  |  | ||||||
|  | alloc.lo: config.h backtrace.h internal.h | ||||||
|  | backtrace.lo: config.h backtrace.h internal.h | ||||||
|  | btest.lo: filenames.h backtrace.h backtrace-supported.h | ||||||
|  | dwarf.lo: config.h filenames.h backtrace.h internal.h | ||||||
|  | elf.lo: config.h backtrace.h internal.h | ||||||
|  | fileline.lo: config.h backtrace.h internal.h | ||||||
|  | macho.lo: config.h backtrace.h internal.h | ||||||
|  | mmap.lo: config.h backtrace.h internal.h | ||||||
|  | mmapio.lo: config.h backtrace.h internal.h | ||||||
|  | mtest.lo: backtrace.h backtrace-supported.h | ||||||
|  | nounwind.lo: config.h internal.h | ||||||
|  | pecoff.lo: config.h backtrace.h internal.h | ||||||
|  | posix.lo: config.h backtrace.h internal.h | ||||||
|  | print.lo: config.h backtrace.h internal.h | ||||||
|  | read.lo: config.h backtrace.h internal.h | ||||||
|  | simple.lo: config.h backtrace.h internal.h | ||||||
|  | sort.lo: config.h backtrace.h internal.h | ||||||
|  | stest.lo: config.h backtrace.h internal.h | ||||||
|  | state.lo: config.h backtrace.h backtrace-supported.h internal.h | ||||||
|  | unknown.lo: config.h backtrace.h internal.h | ||||||
|  | xcoff.lo: config.h backtrace.h internal.h | ||||||
|  | xztest.lo: config.h backtrace.h backtrace-supported.h internal.h testlib.h | ||||||
|  | ztest.lo: config.h backtrace.h backtrace-supported.h internal.h testlib.h | ||||||
|  |  | ||||||
							
								
								
									
										2666
									
								
								deps/libbacktrace/Makefile.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2666
									
								
								deps/libbacktrace/Makefile.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										36
									
								
								deps/libbacktrace/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								deps/libbacktrace/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | # libbacktrace | ||||||
|  | A C library that may be linked into a C/C++ program to produce symbolic backtraces | ||||||
|  |  | ||||||
|  | Initially written by Ian Lance Taylor <iant@golang.org>. | ||||||
|  |  | ||||||
|  | This is version 1.0. | ||||||
|  | It is likely that this will always be version 1.0. | ||||||
|  |  | ||||||
|  | The libbacktrace library may be linked into a program or library and | ||||||
|  | used to produce symbolic backtraces. | ||||||
|  | Sample uses would be to print a detailed backtrace when an error | ||||||
|  | occurs or to gather detailed profiling information. | ||||||
|  | In general the functions provided by this library are async-signal-safe, | ||||||
|  | meaning that they may be safely called from a signal handler. | ||||||
|  |  | ||||||
|  | The libbacktrace library is provided under a BSD license. | ||||||
|  | See the source files for the exact license text. | ||||||
|  |  | ||||||
|  | The public functions are declared and documented in the header file | ||||||
|  | backtrace.h, which should be #include'd by a user of the library. | ||||||
|  |  | ||||||
|  | Building libbacktrace will generate a file backtrace-supported.h, | ||||||
|  | which a user of the library may use to determine whether backtraces | ||||||
|  | will work. | ||||||
|  | See the source file backtrace-supported.h.in for the macros that it | ||||||
|  | defines. | ||||||
|  |  | ||||||
|  | As of October 2020, libbacktrace supports ELF, PE/COFF, Mach-O, and | ||||||
|  | XCOFF executables with DWARF debugging information. | ||||||
|  | In other words, it supports GNU/Linux, *BSD, macOS, Windows, and AIX. | ||||||
|  | The library is written to make it straightforward to add support for | ||||||
|  | other object file and debugging formats. | ||||||
|  |  | ||||||
|  | The library relies on the C++ unwind API defined at | ||||||
|  | https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html | ||||||
|  | This API is provided by GCC and clang. | ||||||
							
								
								
									
										864
									
								
								deps/libbacktrace/aclocal.m4
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										864
									
								
								deps/libbacktrace/aclocal.m4
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,864 @@ | |||||||
|  | # generated automatically by aclocal 1.15.1 -*- Autoconf -*- | ||||||
|  |  | ||||||
|  | # Copyright (C) 1996-2017 Free Software Foundation, Inc. | ||||||
|  |  | ||||||
|  | # This file is free software; the Free Software Foundation | ||||||
|  | # gives unlimited permission to copy and/or distribute it, | ||||||
|  | # with or without modifications, as long as this notice is preserved. | ||||||
|  |  | ||||||
|  | # This program is distributed in the hope that it will be useful, | ||||||
|  | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without | ||||||
|  | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A | ||||||
|  | # PARTICULAR PURPOSE. | ||||||
|  |  | ||||||
|  | m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) | ||||||
|  | m4_ifndef([AC_AUTOCONF_VERSION], | ||||||
|  |   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl | ||||||
|  | m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, | ||||||
|  | [m4_warning([this file was generated for autoconf 2.69. | ||||||
|  | You have another version of autoconf.  It may work, but is not guaranteed to. | ||||||
|  | If you have problems, you may need to regenerate the build system entirely. | ||||||
|  | To do so, use the procedure documented by the package, typically 'autoreconf'.])]) | ||||||
|  |  | ||||||
|  | # Copyright (C) 2002-2017 Free Software Foundation, Inc. | ||||||
|  | # | ||||||
|  | # This file is free software; the Free Software Foundation | ||||||
|  | # gives unlimited permission to copy and/or distribute it, | ||||||
|  | # with or without modifications, as long as this notice is preserved. | ||||||
|  |  | ||||||
|  | # AM_AUTOMAKE_VERSION(VERSION) | ||||||
|  | # ---------------------------- | ||||||
|  | # Automake X.Y traces this macro to ensure aclocal.m4 has been | ||||||
|  | # generated from the m4 files accompanying Automake X.Y. | ||||||
|  | # (This private macro should not be called outside this file.) | ||||||
|  | AC_DEFUN([AM_AUTOMAKE_VERSION], | ||||||
|  | [am__api_version='1.15' | ||||||
|  | dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to | ||||||
|  | dnl require some minimum version.  Point them to the right macro. | ||||||
|  | m4_if([$1], [1.15.1], [], | ||||||
|  |       [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl | ||||||
|  | ]) | ||||||
|  |  | ||||||
|  | # _AM_AUTOCONF_VERSION(VERSION) | ||||||
|  | # ----------------------------- | ||||||
|  | # aclocal traces this macro to find the Autoconf version. | ||||||
|  | # This is a private macro too.  Using m4_define simplifies | ||||||
|  | # the logic in aclocal, which can simply ignore this definition. | ||||||
|  | m4_define([_AM_AUTOCONF_VERSION], []) | ||||||
|  |  | ||||||
|  | # AM_SET_CURRENT_AUTOMAKE_VERSION | ||||||
|  | # ------------------------------- | ||||||
|  | # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. | ||||||
|  | # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. | ||||||
|  | AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], | ||||||
|  | [AM_AUTOMAKE_VERSION([1.15.1])dnl | ||||||
|  | m4_ifndef([AC_AUTOCONF_VERSION], | ||||||
|  |   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl | ||||||
|  | _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) | ||||||
|  |  | ||||||
|  | # AM_AUX_DIR_EXPAND                                         -*- Autoconf -*- | ||||||
|  |  | ||||||
|  | # Copyright (C) 2001-2017 Free Software Foundation, Inc. | ||||||
|  | # | ||||||
|  | # This file is free software; the Free Software Foundation | ||||||
|  | # gives unlimited permission to copy and/or distribute it, | ||||||
|  | # with or without modifications, as long as this notice is preserved. | ||||||
|  |  | ||||||
|  | # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets | ||||||
|  | # $ac_aux_dir to '$srcdir/foo'.  In other projects, it is set to | ||||||
|  | # '$srcdir', '$srcdir/..', or '$srcdir/../..'. | ||||||
|  | # | ||||||
|  | # Of course, Automake must honor this variable whenever it calls a | ||||||
|  | # tool from the auxiliary directory.  The problem is that $srcdir (and | ||||||
|  | # therefore $ac_aux_dir as well) can be either absolute or relative, | ||||||
|  | # depending on how configure is run.  This is pretty annoying, since | ||||||
|  | # it makes $ac_aux_dir quite unusable in subdirectories: in the top | ||||||
|  | # source directory, any form will work fine, but in subdirectories a | ||||||
|  | # relative path needs to be adjusted first. | ||||||
|  | # | ||||||
|  | # $ac_aux_dir/missing | ||||||
|  | #    fails when called from a subdirectory if $ac_aux_dir is relative | ||||||
|  | # $top_srcdir/$ac_aux_dir/missing | ||||||
|  | #    fails if $ac_aux_dir is absolute, | ||||||
|  | #    fails when called from a subdirectory in a VPATH build with | ||||||
|  | #          a relative $ac_aux_dir | ||||||
|  | # | ||||||
|  | # The reason of the latter failure is that $top_srcdir and $ac_aux_dir | ||||||
|  | # are both prefixed by $srcdir.  In an in-source build this is usually | ||||||
|  | # harmless because $srcdir is '.', but things will broke when you | ||||||
|  | # start a VPATH build or use an absolute $srcdir. | ||||||
|  | # | ||||||
|  | # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, | ||||||
|  | # iff we strip the leading $srcdir from $ac_aux_dir.  That would be: | ||||||
|  | #   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` | ||||||
|  | # and then we would define $MISSING as | ||||||
|  | #   MISSING="\${SHELL} $am_aux_dir/missing" | ||||||
|  | # This will work as long as MISSING is not called from configure, because | ||||||
|  | # unfortunately $(top_srcdir) has no meaning in configure. | ||||||
|  | # However there are other variables, like CC, which are often used in | ||||||
|  | # configure, and could therefore not use this "fixed" $ac_aux_dir. | ||||||
|  | # | ||||||
|  | # Another solution, used here, is to always expand $ac_aux_dir to an | ||||||
|  | # absolute PATH.  The drawback is that using absolute paths prevent a | ||||||
|  | # configured tree to be moved without reconfiguration. | ||||||
|  |  | ||||||
|  | AC_DEFUN([AM_AUX_DIR_EXPAND], | ||||||
|  | [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl | ||||||
|  | # Expand $ac_aux_dir to an absolute path. | ||||||
|  | am_aux_dir=`cd "$ac_aux_dir" && pwd` | ||||||
|  | ]) | ||||||
|  |  | ||||||
|  | # AM_CONDITIONAL                                            -*- Autoconf -*- | ||||||
|  |  | ||||||
|  | # Copyright (C) 1997-2017 Free Software Foundation, Inc. | ||||||
|  | # | ||||||
|  | # This file is free software; the Free Software Foundation | ||||||
|  | # gives unlimited permission to copy and/or distribute it, | ||||||
|  | # with or without modifications, as long as this notice is preserved. | ||||||
|  |  | ||||||
|  | # AM_CONDITIONAL(NAME, SHELL-CONDITION) | ||||||
|  | # ------------------------------------- | ||||||
|  | # Define a conditional. | ||||||
|  | AC_DEFUN([AM_CONDITIONAL], | ||||||
|  | [AC_PREREQ([2.52])dnl | ||||||
|  |  m4_if([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])], | ||||||
|  |        [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl | ||||||
|  | AC_SUBST([$1_TRUE])dnl | ||||||
|  | AC_SUBST([$1_FALSE])dnl | ||||||
|  | _AM_SUBST_NOTMAKE([$1_TRUE])dnl | ||||||
|  | _AM_SUBST_NOTMAKE([$1_FALSE])dnl | ||||||
|  | m4_define([_AM_COND_VALUE_$1], [$2])dnl | ||||||
|  | if $2; then | ||||||
|  |   $1_TRUE= | ||||||
|  |   $1_FALSE='#' | ||||||
|  | else | ||||||
|  |   $1_TRUE='#' | ||||||
|  |   $1_FALSE= | ||||||
|  | fi | ||||||
|  | AC_CONFIG_COMMANDS_PRE( | ||||||
|  | [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then | ||||||
|  |   AC_MSG_ERROR([[conditional "$1" was never defined. | ||||||
|  | Usually this means the macro was only invoked conditionally.]]) | ||||||
|  | fi])]) | ||||||
|  |  | ||||||
|  | # Do all the work for Automake.                             -*- Autoconf -*- | ||||||
|  |  | ||||||
|  | # Copyright (C) 1996-2017 Free Software Foundation, Inc. | ||||||
|  | # | ||||||
|  | # This file is free software; the Free Software Foundation | ||||||
|  | # gives unlimited permission to copy and/or distribute it, | ||||||
|  | # with or without modifications, as long as this notice is preserved. | ||||||
|  |  | ||||||
|  | # This macro actually does too much.  Some checks are only needed if | ||||||
|  | # your package does certain things.  But this isn't really a big deal. | ||||||
|  |  | ||||||
|  | dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. | ||||||
|  | m4_define([AC_PROG_CC], | ||||||
|  | m4_defn([AC_PROG_CC]) | ||||||
|  | [_AM_PROG_CC_C_O | ||||||
|  | ]) | ||||||
|  |  | ||||||
|  | # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) | ||||||
|  | # AM_INIT_AUTOMAKE([OPTIONS]) | ||||||
|  | # ----------------------------------------------- | ||||||
|  | # The call with PACKAGE and VERSION arguments is the old style | ||||||
|  | # call (pre autoconf-2.50), which is being phased out.  PACKAGE | ||||||
|  | # and VERSION should now be passed to AC_INIT and removed from | ||||||
|  | # the call to AM_INIT_AUTOMAKE. | ||||||
|  | # We support both call styles for the transition.  After | ||||||
|  | # the next Automake release, Autoconf can make the AC_INIT | ||||||
|  | # arguments mandatory, and then we can depend on a new Autoconf | ||||||
|  | # release and drop the old call support. | ||||||
|  | AC_DEFUN([AM_INIT_AUTOMAKE], | ||||||
|  | [AC_PREREQ([2.65])dnl | ||||||
|  | dnl Autoconf wants to disallow AM_ names.  We explicitly allow | ||||||
|  | dnl the ones we care about. | ||||||
|  | m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl | ||||||
|  | AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl | ||||||
|  | AC_REQUIRE([AC_PROG_INSTALL])dnl | ||||||
|  | if test "`cd $srcdir && pwd`" != "`pwd`"; then | ||||||
|  |   # Use -I$(srcdir) only when $(srcdir) != ., so that make's output | ||||||
|  |   # is not polluted with repeated "-I." | ||||||
|  |   AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl | ||||||
|  |   # test to see if srcdir already configured | ||||||
|  |   if test -f $srcdir/config.status; then | ||||||
|  |     AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) | ||||||
|  |   fi | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # test whether we have cygpath | ||||||
|  | if test -z "$CYGPATH_W"; then | ||||||
|  |   if (cygpath --version) >/dev/null 2>/dev/null; then | ||||||
|  |     CYGPATH_W='cygpath -w' | ||||||
|  |   else | ||||||
|  |     CYGPATH_W=echo | ||||||
|  |   fi | ||||||
|  | fi | ||||||
|  | AC_SUBST([CYGPATH_W]) | ||||||
|  |  | ||||||
|  | # Define the identity of the package. | ||||||
|  | dnl Distinguish between old-style and new-style calls. | ||||||
|  | m4_ifval([$2], | ||||||
|  | [AC_DIAGNOSE([obsolete], | ||||||
|  |              [$0: two- and three-arguments forms are deprecated.]) | ||||||
|  | m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl | ||||||
|  |  AC_SUBST([PACKAGE], [$1])dnl | ||||||
|  |  AC_SUBST([VERSION], [$2])], | ||||||
|  | [_AM_SET_OPTIONS([$1])dnl | ||||||
|  | dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. | ||||||
|  | m4_if( | ||||||
|  |   m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), | ||||||
|  |   [ok:ok],, | ||||||
|  |   [m4_fatal([AC_INIT should be called with package and version arguments])])dnl | ||||||
|  |  AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl | ||||||
|  |  AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl | ||||||
|  |  | ||||||
|  | _AM_IF_OPTION([no-define],, | ||||||
|  | [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) | ||||||
|  |  AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl | ||||||
|  |  | ||||||
|  | # Some tools Automake needs. | ||||||
|  | AC_REQUIRE([AM_SANITY_CHECK])dnl | ||||||
|  | AC_REQUIRE([AC_ARG_PROGRAM])dnl | ||||||
|  | AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) | ||||||
|  | AM_MISSING_PROG([AUTOCONF], [autoconf]) | ||||||
|  | AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) | ||||||
|  | AM_MISSING_PROG([AUTOHEADER], [autoheader]) | ||||||
|  | AM_MISSING_PROG([MAKEINFO], [makeinfo]) | ||||||
|  | AC_REQUIRE([AM_PROG_INSTALL_SH])dnl | ||||||
|  | AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl | ||||||
|  | AC_REQUIRE([AC_PROG_MKDIR_P])dnl | ||||||
|  | # For better backward compatibility.  To be removed once Automake 1.9.x | ||||||
|  | # dies out for good.  For more background, see: | ||||||
|  | # <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html> | ||||||
|  | # <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html> | ||||||
|  | AC_SUBST([mkdir_p], ['$(MKDIR_P)']) | ||||||
|  | # We need awk for the "check" target (and possibly the TAP driver).  The | ||||||
|  | # system "awk" is bad on some platforms. | ||||||
|  | AC_REQUIRE([AC_PROG_AWK])dnl | ||||||
|  | AC_REQUIRE([AC_PROG_MAKE_SET])dnl | ||||||
|  | AC_REQUIRE([AM_SET_LEADING_DOT])dnl | ||||||
|  | _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], | ||||||
|  | 	      [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], | ||||||
|  | 			     [_AM_PROG_TAR([v7])])]) | ||||||
|  | _AM_IF_OPTION([no-dependencies],, | ||||||
|  | [AC_PROVIDE_IFELSE([AC_PROG_CC], | ||||||
|  | 		  [_AM_DEPENDENCIES([CC])], | ||||||
|  | 		  [m4_define([AC_PROG_CC], | ||||||
|  | 			     m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl | ||||||
|  | AC_PROVIDE_IFELSE([AC_PROG_CXX], | ||||||
|  | 		  [_AM_DEPENDENCIES([CXX])], | ||||||
|  | 		  [m4_define([AC_PROG_CXX], | ||||||
|  | 			     m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl | ||||||
|  | AC_PROVIDE_IFELSE([AC_PROG_OBJC], | ||||||
|  | 		  [_AM_DEPENDENCIES([OBJC])], | ||||||
|  | 		  [m4_define([AC_PROG_OBJC], | ||||||
|  | 			     m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl | ||||||
|  | AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], | ||||||
|  | 		  [_AM_DEPENDENCIES([OBJCXX])], | ||||||
|  | 		  [m4_define([AC_PROG_OBJCXX], | ||||||
|  | 			     m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl | ||||||
|  | ]) | ||||||
|  | AC_REQUIRE([AM_SILENT_RULES])dnl | ||||||
|  | dnl The testsuite driver may need to know about EXEEXT, so add the | ||||||
|  | dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This | ||||||
|  | dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. | ||||||
|  | AC_CONFIG_COMMANDS_PRE(dnl | ||||||
|  | [m4_provide_if([_AM_COMPILER_EXEEXT], | ||||||
|  |   [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl | ||||||
|  |  | ||||||
|  | # POSIX will say in a future version that running "rm -f" with no argument | ||||||
|  | # is OK; and we want to be able to make that assumption in our Makefile | ||||||
|  | # recipes.  So use an aggressive probe to check that the usage we want is | ||||||
|  | # actually supported "in the wild" to an acceptable degree. | ||||||
|  | # See automake bug#10828. | ||||||
|  | # To make any issue more visible, cause the running configure to be aborted | ||||||
|  | # by default if the 'rm' program in use doesn't match our expectations; the | ||||||
|  | # user can still override this though. | ||||||
|  | if rm -f && rm -fr && rm -rf; then : OK; else | ||||||
|  |   cat >&2 <<'END' | ||||||
|  | Oops! | ||||||
|  |  | ||||||
|  | Your 'rm' program seems unable to run without file operands specified | ||||||
|  | on the command line, even when the '-f' option is present.  This is contrary | ||||||
|  | to the behaviour of most rm programs out there, and not conforming with | ||||||
|  | the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542> | ||||||
|  |  | ||||||
|  | Please tell bug-automake@gnu.org about your system, including the value | ||||||
|  | of your $PATH and any error possibly output before this message.  This | ||||||
|  | can help us improve future automake versions. | ||||||
|  |  | ||||||
|  | END | ||||||
|  |   if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then | ||||||
|  |     echo 'Configuration will proceed anyway, since you have set the' >&2 | ||||||
|  |     echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 | ||||||
|  |     echo >&2 | ||||||
|  |   else | ||||||
|  |     cat >&2 <<'END' | ||||||
|  | Aborting the configuration process, to ensure you take notice of the issue. | ||||||
|  |  | ||||||
|  | You can download and install GNU coreutils to get an 'rm' implementation | ||||||
|  | that behaves properly: <http://www.gnu.org/software/coreutils/>. | ||||||
|  |  | ||||||
|  | If you want to complete the configuration process using your problematic | ||||||
|  | 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM | ||||||
|  | to "yes", and re-run configure. | ||||||
|  |  | ||||||
|  | END | ||||||
|  |     AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) | ||||||
|  |   fi | ||||||
|  | fi | ||||||
|  | dnl The trailing newline in this macro's definition is deliberate, for | ||||||
|  | dnl backward compatibility and to allow trailing 'dnl'-style comments | ||||||
|  | dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. | ||||||
|  | ]) | ||||||
|  |  | ||||||
|  | dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not | ||||||
|  | dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further | ||||||
|  | dnl mangled by Autoconf and run in a shell conditional statement. | ||||||
|  | m4_define([_AC_COMPILER_EXEEXT], | ||||||
|  | m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) | ||||||
|  |  | ||||||
|  | # When config.status generates a header, we must update the stamp-h file. | ||||||
|  | # This file resides in the same directory as the config header | ||||||
|  | # that is generated.  The stamp files are numbered to have different names. | ||||||
|  |  | ||||||
|  | # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the | ||||||
|  | # loop where config.status creates the headers, so we can generate | ||||||
|  | # our stamp files there. | ||||||
|  | AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], | ||||||
|  | [# Compute $1's index in $config_headers. | ||||||
|  | _am_arg=$1 | ||||||
|  | _am_stamp_count=1 | ||||||
|  | for _am_header in $config_headers :; do | ||||||
|  |   case $_am_header in | ||||||
|  |     $_am_arg | $_am_arg:* ) | ||||||
|  |       break ;; | ||||||
|  |     * ) | ||||||
|  |       _am_stamp_count=`expr $_am_stamp_count + 1` ;; | ||||||
|  |   esac | ||||||
|  | done | ||||||
|  | echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) | ||||||
|  |  | ||||||
|  | # Copyright (C) 2001-2017 Free Software Foundation, Inc. | ||||||
|  | # | ||||||
|  | # This file is free software; the Free Software Foundation | ||||||
|  | # gives unlimited permission to copy and/or distribute it, | ||||||
|  | # with or without modifications, as long as this notice is preserved. | ||||||
|  |  | ||||||
|  | # AM_PROG_INSTALL_SH | ||||||
|  | # ------------------ | ||||||
|  | # Define $install_sh. | ||||||
|  | AC_DEFUN([AM_PROG_INSTALL_SH], | ||||||
|  | [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl | ||||||
|  | if test x"${install_sh+set}" != xset; then | ||||||
|  |   case $am_aux_dir in | ||||||
|  |   *\ * | *\	*) | ||||||
|  |     install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; | ||||||
|  |   *) | ||||||
|  |     install_sh="\${SHELL} $am_aux_dir/install-sh" | ||||||
|  |   esac | ||||||
|  | fi | ||||||
|  | AC_SUBST([install_sh])]) | ||||||
|  |  | ||||||
|  | # Add --enable-maintainer-mode option to configure.         -*- Autoconf -*- | ||||||
|  | # From Jim Meyering | ||||||
|  |  | ||||||
|  | # Copyright (C) 1996-2017 Free Software Foundation, Inc. | ||||||
|  | # | ||||||
|  | # This file is free software; the Free Software Foundation | ||||||
|  | # gives unlimited permission to copy and/or distribute it, | ||||||
|  | # with or without modifications, as long as this notice is preserved. | ||||||
|  |  | ||||||
|  | # AM_MAINTAINER_MODE([DEFAULT-MODE]) | ||||||
|  | # ---------------------------------- | ||||||
|  | # Control maintainer-specific portions of Makefiles. | ||||||
|  | # Default is to disable them, unless 'enable' is passed literally. | ||||||
|  | # For symmetry, 'disable' may be passed as well.  Anyway, the user | ||||||
|  | # can override the default with the --enable/--disable switch. | ||||||
|  | AC_DEFUN([AM_MAINTAINER_MODE], | ||||||
|  | [m4_case(m4_default([$1], [disable]), | ||||||
|  |        [enable], [m4_define([am_maintainer_other], [disable])], | ||||||
|  |        [disable], [m4_define([am_maintainer_other], [enable])], | ||||||
|  |        [m4_define([am_maintainer_other], [enable]) | ||||||
|  |         m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) | ||||||
|  | AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) | ||||||
|  |   dnl maintainer-mode's default is 'disable' unless 'enable' is passed | ||||||
|  |   AC_ARG_ENABLE([maintainer-mode], | ||||||
|  |     [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], | ||||||
|  |       am_maintainer_other[ make rules and dependencies not useful | ||||||
|  |       (and sometimes confusing) to the casual installer])], | ||||||
|  |     [USE_MAINTAINER_MODE=$enableval], | ||||||
|  |     [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) | ||||||
|  |   AC_MSG_RESULT([$USE_MAINTAINER_MODE]) | ||||||
|  |   AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) | ||||||
|  |   MAINT=$MAINTAINER_MODE_TRUE | ||||||
|  |   AC_SUBST([MAINT])dnl | ||||||
|  | ] | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | # Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*- | ||||||
|  |  | ||||||
|  | # Copyright (C) 1997-2017 Free Software Foundation, Inc. | ||||||
|  | # | ||||||
|  | # This file is free software; the Free Software Foundation | ||||||
|  | # gives unlimited permission to copy and/or distribute it, | ||||||
|  | # with or without modifications, as long as this notice is preserved. | ||||||
|  |  | ||||||
|  | # AM_MISSING_PROG(NAME, PROGRAM) | ||||||
|  | # ------------------------------ | ||||||
|  | AC_DEFUN([AM_MISSING_PROG], | ||||||
|  | [AC_REQUIRE([AM_MISSING_HAS_RUN]) | ||||||
|  | $1=${$1-"${am_missing_run}$2"} | ||||||
|  | AC_SUBST($1)]) | ||||||
|  |  | ||||||
|  | # AM_MISSING_HAS_RUN | ||||||
|  | # ------------------ | ||||||
|  | # Define MISSING if not defined so far and test if it is modern enough. | ||||||
|  | # If it is, set am_missing_run to use it, otherwise, to nothing. | ||||||
|  | AC_DEFUN([AM_MISSING_HAS_RUN], | ||||||
|  | [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl | ||||||
|  | AC_REQUIRE_AUX_FILE([missing])dnl | ||||||
|  | if test x"${MISSING+set}" != xset; then | ||||||
|  |   case $am_aux_dir in | ||||||
|  |   *\ * | *\	*) | ||||||
|  |     MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; | ||||||
|  |   *) | ||||||
|  |     MISSING="\${SHELL} $am_aux_dir/missing" ;; | ||||||
|  |   esac | ||||||
|  | fi | ||||||
|  | # Use eval to expand $SHELL | ||||||
|  | if eval "$MISSING --is-lightweight"; then | ||||||
|  |   am_missing_run="$MISSING " | ||||||
|  | else | ||||||
|  |   am_missing_run= | ||||||
|  |   AC_MSG_WARN(['missing' script is too old or missing]) | ||||||
|  | fi | ||||||
|  | ]) | ||||||
|  |  | ||||||
|  | # Helper functions for option handling.                     -*- Autoconf -*- | ||||||
|  |  | ||||||
|  | # Copyright (C) 2001-2017 Free Software Foundation, Inc. | ||||||
|  | # | ||||||
|  | # This file is free software; the Free Software Foundation | ||||||
|  | # gives unlimited permission to copy and/or distribute it, | ||||||
|  | # with or without modifications, as long as this notice is preserved. | ||||||
|  |  | ||||||
|  | # _AM_MANGLE_OPTION(NAME) | ||||||
|  | # ----------------------- | ||||||
|  | AC_DEFUN([_AM_MANGLE_OPTION], | ||||||
|  | [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) | ||||||
|  |  | ||||||
|  | # _AM_SET_OPTION(NAME) | ||||||
|  | # -------------------- | ||||||
|  | # Set option NAME.  Presently that only means defining a flag for this option. | ||||||
|  | AC_DEFUN([_AM_SET_OPTION], | ||||||
|  | [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) | ||||||
|  |  | ||||||
|  | # _AM_SET_OPTIONS(OPTIONS) | ||||||
|  | # ------------------------ | ||||||
|  | # OPTIONS is a space-separated list of Automake options. | ||||||
|  | AC_DEFUN([_AM_SET_OPTIONS], | ||||||
|  | [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) | ||||||
|  |  | ||||||
|  | # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) | ||||||
|  | # ------------------------------------------- | ||||||
|  | # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. | ||||||
|  | AC_DEFUN([_AM_IF_OPTION], | ||||||
|  | [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) | ||||||
|  |  | ||||||
|  | # Copyright (C) 1999-2017 Free Software Foundation, Inc. | ||||||
|  | # | ||||||
|  | # This file is free software; the Free Software Foundation | ||||||
|  | # gives unlimited permission to copy and/or distribute it, | ||||||
|  | # with or without modifications, as long as this notice is preserved. | ||||||
|  |  | ||||||
|  | # _AM_PROG_CC_C_O | ||||||
|  | # --------------- | ||||||
|  | # Like AC_PROG_CC_C_O, but changed for automake.  We rewrite AC_PROG_CC | ||||||
|  | # to automatically call this. | ||||||
|  | AC_DEFUN([_AM_PROG_CC_C_O], | ||||||
|  | [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl | ||||||
|  | AC_REQUIRE_AUX_FILE([compile])dnl | ||||||
|  | AC_LANG_PUSH([C])dnl | ||||||
|  | AC_CACHE_CHECK( | ||||||
|  |   [whether $CC understands -c and -o together], | ||||||
|  |   [am_cv_prog_cc_c_o], | ||||||
|  |   [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) | ||||||
|  |   # Make sure it works both with $CC and with simple cc. | ||||||
|  |   # Following AC_PROG_CC_C_O, we do the test twice because some | ||||||
|  |   # compilers refuse to overwrite an existing .o file with -o, | ||||||
|  |   # though they will create one. | ||||||
|  |   am_cv_prog_cc_c_o=yes | ||||||
|  |   for am_i in 1 2; do | ||||||
|  |     if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ | ||||||
|  |          && test -f conftest2.$ac_objext; then | ||||||
|  |       : OK | ||||||
|  |     else | ||||||
|  |       am_cv_prog_cc_c_o=no | ||||||
|  |       break | ||||||
|  |     fi | ||||||
|  |   done | ||||||
|  |   rm -f core conftest* | ||||||
|  |   unset am_i]) | ||||||
|  | if test "$am_cv_prog_cc_c_o" != yes; then | ||||||
|  |    # Losing compiler, so override with the script. | ||||||
|  |    # FIXME: It is wrong to rewrite CC. | ||||||
|  |    # But if we don't then we get into trouble of one sort or another. | ||||||
|  |    # A longer-term fix would be to have automake use am__CC in this case, | ||||||
|  |    # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" | ||||||
|  |    CC="$am_aux_dir/compile $CC" | ||||||
|  | fi | ||||||
|  | AC_LANG_POP([C])]) | ||||||
|  |  | ||||||
|  | # For backward compatibility. | ||||||
|  | AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) | ||||||
|  |  | ||||||
|  | # Copyright (C) 2001-2017 Free Software Foundation, Inc. | ||||||
|  | # | ||||||
|  | # This file is free software; the Free Software Foundation | ||||||
|  | # gives unlimited permission to copy and/or distribute it, | ||||||
|  | # with or without modifications, as long as this notice is preserved. | ||||||
|  |  | ||||||
|  | # AM_RUN_LOG(COMMAND) | ||||||
|  | # ------------------- | ||||||
|  | # Run COMMAND, save the exit status in ac_status, and log it. | ||||||
|  | # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) | ||||||
|  | AC_DEFUN([AM_RUN_LOG], | ||||||
|  | [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD | ||||||
|  |    ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD | ||||||
|  |    ac_status=$? | ||||||
|  |    echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD | ||||||
|  |    (exit $ac_status); }]) | ||||||
|  |  | ||||||
|  | # Check to make sure that the build environment is sane.    -*- Autoconf -*- | ||||||
|  |  | ||||||
|  | # Copyright (C) 1996-2017 Free Software Foundation, Inc. | ||||||
|  | # | ||||||
|  | # This file is free software; the Free Software Foundation | ||||||
|  | # gives unlimited permission to copy and/or distribute it, | ||||||
|  | # with or without modifications, as long as this notice is preserved. | ||||||
|  |  | ||||||
|  | # AM_SANITY_CHECK | ||||||
|  | # --------------- | ||||||
|  | AC_DEFUN([AM_SANITY_CHECK], | ||||||
|  | [AC_MSG_CHECKING([whether build environment is sane]) | ||||||
|  | # Reject unsafe characters in $srcdir or the absolute working directory | ||||||
|  | # name.  Accept space and tab only in the latter. | ||||||
|  | am_lf=' | ||||||
|  | ' | ||||||
|  | case `pwd` in | ||||||
|  |   *[[\\\"\#\$\&\'\`$am_lf]]*) | ||||||
|  |     AC_MSG_ERROR([unsafe absolute working directory name]);; | ||||||
|  | esac | ||||||
|  | case $srcdir in | ||||||
|  |   *[[\\\"\#\$\&\'\`$am_lf\ \	]]*) | ||||||
|  |     AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; | ||||||
|  | esac | ||||||
|  |  | ||||||
|  | # Do 'set' in a subshell so we don't clobber the current shell's | ||||||
|  | # arguments.  Must try -L first in case configure is actually a | ||||||
|  | # symlink; some systems play weird games with the mod time of symlinks | ||||||
|  | # (eg FreeBSD returns the mod time of the symlink's containing | ||||||
|  | # directory). | ||||||
|  | if ( | ||||||
|  |    am_has_slept=no | ||||||
|  |    for am_try in 1 2; do | ||||||
|  |      echo "timestamp, slept: $am_has_slept" > conftest.file | ||||||
|  |      set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` | ||||||
|  |      if test "$[*]" = "X"; then | ||||||
|  | 	# -L didn't work. | ||||||
|  | 	set X `ls -t "$srcdir/configure" conftest.file` | ||||||
|  |      fi | ||||||
|  |      if test "$[*]" != "X $srcdir/configure conftest.file" \ | ||||||
|  | 	&& test "$[*]" != "X conftest.file $srcdir/configure"; then | ||||||
|  |  | ||||||
|  | 	# If neither matched, then we have a broken ls.  This can happen | ||||||
|  | 	# if, for instance, CONFIG_SHELL is bash and it inherits a | ||||||
|  | 	# broken ls alias from the environment.  This has actually | ||||||
|  | 	# happened.  Such a system could not be considered "sane". | ||||||
|  | 	AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken | ||||||
|  |   alias in your environment]) | ||||||
|  |      fi | ||||||
|  |      if test "$[2]" = conftest.file || test $am_try -eq 2; then | ||||||
|  |        break | ||||||
|  |      fi | ||||||
|  |      # Just in case. | ||||||
|  |      sleep 1 | ||||||
|  |      am_has_slept=yes | ||||||
|  |    done | ||||||
|  |    test "$[2]" = conftest.file | ||||||
|  |    ) | ||||||
|  | then | ||||||
|  |    # Ok. | ||||||
|  |    : | ||||||
|  | else | ||||||
|  |    AC_MSG_ERROR([newly created file is older than distributed files! | ||||||
|  | Check your system clock]) | ||||||
|  | fi | ||||||
|  | AC_MSG_RESULT([yes]) | ||||||
|  | # If we didn't sleep, we still need to ensure time stamps of config.status and | ||||||
|  | # generated files are strictly newer. | ||||||
|  | am_sleep_pid= | ||||||
|  | if grep 'slept: no' conftest.file >/dev/null 2>&1; then | ||||||
|  |   ( sleep 1 ) & | ||||||
|  |   am_sleep_pid=$! | ||||||
|  | fi | ||||||
|  | AC_CONFIG_COMMANDS_PRE( | ||||||
|  |   [AC_MSG_CHECKING([that generated files are newer than configure]) | ||||||
|  |    if test -n "$am_sleep_pid"; then | ||||||
|  |      # Hide warnings about reused PIDs. | ||||||
|  |      wait $am_sleep_pid 2>/dev/null | ||||||
|  |    fi | ||||||
|  |    AC_MSG_RESULT([done])]) | ||||||
|  | rm -f conftest.file | ||||||
|  | ]) | ||||||
|  |  | ||||||
|  | # Copyright (C) 2009-2017 Free Software Foundation, Inc. | ||||||
|  | # | ||||||
|  | # This file is free software; the Free Software Foundation | ||||||
|  | # gives unlimited permission to copy and/or distribute it, | ||||||
|  | # with or without modifications, as long as this notice is preserved. | ||||||
|  |  | ||||||
|  | # AM_SILENT_RULES([DEFAULT]) | ||||||
|  | # -------------------------- | ||||||
|  | # Enable less verbose build rules; with the default set to DEFAULT | ||||||
|  | # ("yes" being less verbose, "no" or empty being verbose). | ||||||
|  | AC_DEFUN([AM_SILENT_RULES], | ||||||
|  | [AC_ARG_ENABLE([silent-rules], [dnl | ||||||
|  | AS_HELP_STRING( | ||||||
|  |   [--enable-silent-rules], | ||||||
|  |   [less verbose build output (undo: "make V=1")]) | ||||||
|  | AS_HELP_STRING( | ||||||
|  |   [--disable-silent-rules], | ||||||
|  |   [verbose build output (undo: "make V=0")])dnl | ||||||
|  | ]) | ||||||
|  | case $enable_silent_rules in @%:@ ((( | ||||||
|  |   yes) AM_DEFAULT_VERBOSITY=0;; | ||||||
|  |    no) AM_DEFAULT_VERBOSITY=1;; | ||||||
|  |     *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; | ||||||
|  | esac | ||||||
|  | dnl | ||||||
|  | dnl A few 'make' implementations (e.g., NonStop OS and NextStep) | ||||||
|  | dnl do not support nested variable expansions. | ||||||
|  | dnl See automake bug#9928 and bug#10237. | ||||||
|  | am_make=${MAKE-make} | ||||||
|  | AC_CACHE_CHECK([whether $am_make supports nested variables], | ||||||
|  |    [am_cv_make_support_nested_variables], | ||||||
|  |    [if AS_ECHO([['TRUE=$(BAR$(V)) | ||||||
|  | BAR0=false | ||||||
|  | BAR1=true | ||||||
|  | V=1 | ||||||
|  | am__doit: | ||||||
|  | 	@$(TRUE) | ||||||
|  | .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then | ||||||
|  |   am_cv_make_support_nested_variables=yes | ||||||
|  | else | ||||||
|  |   am_cv_make_support_nested_variables=no | ||||||
|  | fi]) | ||||||
|  | if test $am_cv_make_support_nested_variables = yes; then | ||||||
|  |   dnl Using '$V' instead of '$(V)' breaks IRIX make. | ||||||
|  |   AM_V='$(V)' | ||||||
|  |   AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' | ||||||
|  | else | ||||||
|  |   AM_V=$AM_DEFAULT_VERBOSITY | ||||||
|  |   AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY | ||||||
|  | fi | ||||||
|  | AC_SUBST([AM_V])dnl | ||||||
|  | AM_SUBST_NOTMAKE([AM_V])dnl | ||||||
|  | AC_SUBST([AM_DEFAULT_V])dnl | ||||||
|  | AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl | ||||||
|  | AC_SUBST([AM_DEFAULT_VERBOSITY])dnl | ||||||
|  | AM_BACKSLASH='\' | ||||||
|  | AC_SUBST([AM_BACKSLASH])dnl | ||||||
|  | _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl | ||||||
|  | ]) | ||||||
|  |  | ||||||
|  | # Copyright (C) 2001-2017 Free Software Foundation, Inc. | ||||||
|  | # | ||||||
|  | # This file is free software; the Free Software Foundation | ||||||
|  | # gives unlimited permission to copy and/or distribute it, | ||||||
|  | # with or without modifications, as long as this notice is preserved. | ||||||
|  |  | ||||||
|  | # AM_PROG_INSTALL_STRIP | ||||||
|  | # --------------------- | ||||||
|  | # One issue with vendor 'install' (even GNU) is that you can't | ||||||
|  | # specify the program used to strip binaries.  This is especially | ||||||
|  | # annoying in cross-compiling environments, where the build's strip | ||||||
|  | # is unlikely to handle the host's binaries. | ||||||
|  | # Fortunately install-sh will honor a STRIPPROG variable, so we | ||||||
|  | # always use install-sh in "make install-strip", and initialize | ||||||
|  | # STRIPPROG with the value of the STRIP variable (set by the user). | ||||||
|  | AC_DEFUN([AM_PROG_INSTALL_STRIP], | ||||||
|  | [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl | ||||||
|  | # Installed binaries are usually stripped using 'strip' when the user | ||||||
|  | # run "make install-strip".  However 'strip' might not be the right | ||||||
|  | # tool to use in cross-compilation environments, therefore Automake | ||||||
|  | # will honor the 'STRIP' environment variable to overrule this program. | ||||||
|  | dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. | ||||||
|  | if test "$cross_compiling" != no; then | ||||||
|  |   AC_CHECK_TOOL([STRIP], [strip], :) | ||||||
|  | fi | ||||||
|  | INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" | ||||||
|  | AC_SUBST([INSTALL_STRIP_PROGRAM])]) | ||||||
|  |  | ||||||
|  | # Copyright (C) 2006-2017 Free Software Foundation, Inc. | ||||||
|  | # | ||||||
|  | # This file is free software; the Free Software Foundation | ||||||
|  | # gives unlimited permission to copy and/or distribute it, | ||||||
|  | # with or without modifications, as long as this notice is preserved. | ||||||
|  |  | ||||||
|  | # _AM_SUBST_NOTMAKE(VARIABLE) | ||||||
|  | # --------------------------- | ||||||
|  | # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. | ||||||
|  | # This macro is traced by Automake. | ||||||
|  | AC_DEFUN([_AM_SUBST_NOTMAKE]) | ||||||
|  |  | ||||||
|  | # AM_SUBST_NOTMAKE(VARIABLE) | ||||||
|  | # -------------------------- | ||||||
|  | # Public sister of _AM_SUBST_NOTMAKE. | ||||||
|  | AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) | ||||||
|  |  | ||||||
|  | # Check how to create a tarball.                            -*- Autoconf -*- | ||||||
|  |  | ||||||
|  | # Copyright (C) 2004-2017 Free Software Foundation, Inc. | ||||||
|  | # | ||||||
|  | # This file is free software; the Free Software Foundation | ||||||
|  | # gives unlimited permission to copy and/or distribute it, | ||||||
|  | # with or without modifications, as long as this notice is preserved. | ||||||
|  |  | ||||||
|  | # _AM_PROG_TAR(FORMAT) | ||||||
|  | # -------------------- | ||||||
|  | # Check how to create a tarball in format FORMAT. | ||||||
|  | # FORMAT should be one of 'v7', 'ustar', or 'pax'. | ||||||
|  | # | ||||||
|  | # Substitute a variable $(am__tar) that is a command | ||||||
|  | # writing to stdout a FORMAT-tarball containing the directory | ||||||
|  | # $tardir. | ||||||
|  | #     tardir=directory && $(am__tar) > result.tar | ||||||
|  | # | ||||||
|  | # Substitute a variable $(am__untar) that extract such | ||||||
|  | # a tarball read from stdin. | ||||||
|  | #     $(am__untar) < result.tar | ||||||
|  | # | ||||||
|  | AC_DEFUN([_AM_PROG_TAR], | ||||||
|  | [# Always define AMTAR for backward compatibility.  Yes, it's still used | ||||||
|  | # in the wild :-(  We should find a proper way to deprecate it ... | ||||||
|  | AC_SUBST([AMTAR], ['$${TAR-tar}']) | ||||||
|  |  | ||||||
|  | # We'll loop over all known methods to create a tar archive until one works. | ||||||
|  | _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' | ||||||
|  |  | ||||||
|  | m4_if([$1], [v7], | ||||||
|  |   [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], | ||||||
|  |  | ||||||
|  |   [m4_case([$1], | ||||||
|  |     [ustar], | ||||||
|  |      [# The POSIX 1988 'ustar' format is defined with fixed-size fields. | ||||||
|  |       # There is notably a 21 bits limit for the UID and the GID.  In fact, | ||||||
|  |       # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 | ||||||
|  |       # and bug#13588). | ||||||
|  |       am_max_uid=2097151 # 2^21 - 1 | ||||||
|  |       am_max_gid=$am_max_uid | ||||||
|  |       # The $UID and $GID variables are not portable, so we need to resort | ||||||
|  |       # to the POSIX-mandated id(1) utility.  Errors in the 'id' calls | ||||||
|  |       # below are definitely unexpected, so allow the users to see them | ||||||
|  |       # (that is, avoid stderr redirection). | ||||||
|  |       am_uid=`id -u || echo unknown` | ||||||
|  |       am_gid=`id -g || echo unknown` | ||||||
|  |       AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) | ||||||
|  |       if test $am_uid -le $am_max_uid; then | ||||||
|  |          AC_MSG_RESULT([yes]) | ||||||
|  |       else | ||||||
|  |          AC_MSG_RESULT([no]) | ||||||
|  |          _am_tools=none | ||||||
|  |       fi | ||||||
|  |       AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) | ||||||
|  |       if test $am_gid -le $am_max_gid; then | ||||||
|  |          AC_MSG_RESULT([yes]) | ||||||
|  |       else | ||||||
|  |         AC_MSG_RESULT([no]) | ||||||
|  |         _am_tools=none | ||||||
|  |       fi], | ||||||
|  |  | ||||||
|  |   [pax], | ||||||
|  |     [], | ||||||
|  |  | ||||||
|  |   [m4_fatal([Unknown tar format])]) | ||||||
|  |  | ||||||
|  |   AC_MSG_CHECKING([how to create a $1 tar archive]) | ||||||
|  |  | ||||||
|  |   # Go ahead even if we have the value already cached.  We do so because we | ||||||
|  |   # need to set the values for the 'am__tar' and 'am__untar' variables. | ||||||
|  |   _am_tools=${am_cv_prog_tar_$1-$_am_tools} | ||||||
|  |  | ||||||
|  |   for _am_tool in $_am_tools; do | ||||||
|  |     case $_am_tool in | ||||||
|  |     gnutar) | ||||||
|  |       for _am_tar in tar gnutar gtar; do | ||||||
|  |         AM_RUN_LOG([$_am_tar --version]) && break | ||||||
|  |       done | ||||||
|  |       am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' | ||||||
|  |       am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' | ||||||
|  |       am__untar="$_am_tar -xf -" | ||||||
|  |       ;; | ||||||
|  |     plaintar) | ||||||
|  |       # Must skip GNU tar: if it does not support --format= it doesn't create | ||||||
|  |       # ustar tarball either. | ||||||
|  |       (tar --version) >/dev/null 2>&1 && continue | ||||||
|  |       am__tar='tar chf - "$$tardir"' | ||||||
|  |       am__tar_='tar chf - "$tardir"' | ||||||
|  |       am__untar='tar xf -' | ||||||
|  |       ;; | ||||||
|  |     pax) | ||||||
|  |       am__tar='pax -L -x $1 -w "$$tardir"' | ||||||
|  |       am__tar_='pax -L -x $1 -w "$tardir"' | ||||||
|  |       am__untar='pax -r' | ||||||
|  |       ;; | ||||||
|  |     cpio) | ||||||
|  |       am__tar='find "$$tardir" -print | cpio -o -H $1 -L' | ||||||
|  |       am__tar_='find "$tardir" -print | cpio -o -H $1 -L' | ||||||
|  |       am__untar='cpio -i -H $1 -d' | ||||||
|  |       ;; | ||||||
|  |     none) | ||||||
|  |       am__tar=false | ||||||
|  |       am__tar_=false | ||||||
|  |       am__untar=false | ||||||
|  |       ;; | ||||||
|  |     esac | ||||||
|  |  | ||||||
|  |     # If the value was cached, stop now.  We just wanted to have am__tar | ||||||
|  |     # and am__untar set. | ||||||
|  |     test -n "${am_cv_prog_tar_$1}" && break | ||||||
|  |  | ||||||
|  |     # tar/untar a dummy directory, and stop if the command works. | ||||||
|  |     rm -rf conftest.dir | ||||||
|  |     mkdir conftest.dir | ||||||
|  |     echo GrepMe > conftest.dir/file | ||||||
|  |     AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) | ||||||
|  |     rm -rf conftest.dir | ||||||
|  |     if test -s conftest.tar; then | ||||||
|  |       AM_RUN_LOG([$am__untar <conftest.tar]) | ||||||
|  |       AM_RUN_LOG([cat conftest.dir/file]) | ||||||
|  |       grep GrepMe conftest.dir/file >/dev/null 2>&1 && break | ||||||
|  |     fi | ||||||
|  |   done | ||||||
|  |   rm -rf conftest.dir | ||||||
|  |  | ||||||
|  |   AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) | ||||||
|  |   AC_MSG_RESULT([$am_cv_prog_tar_$1])]) | ||||||
|  |  | ||||||
|  | AC_SUBST([am__tar]) | ||||||
|  | AC_SUBST([am__untar]) | ||||||
|  | ]) # _AM_PROG_TAR | ||||||
|  |  | ||||||
|  | m4_include([config/lead-dot.m4]) | ||||||
|  | m4_include([config/libtool.m4]) | ||||||
|  | m4_include([config/ltoptions.m4]) | ||||||
|  | m4_include([config/ltsugar.m4]) | ||||||
|  | m4_include([config/ltversion.m4]) | ||||||
|  | m4_include([config/lt~obsolete.m4]) | ||||||
|  | m4_include([config/multi.m4]) | ||||||
|  | m4_include([config/override.m4]) | ||||||
|  | m4_include([config/unwind_ipinfo.m4]) | ||||||
|  | m4_include([config/warnings.m4]) | ||||||
							
								
								
									
										167
									
								
								deps/libbacktrace/alloc.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								deps/libbacktrace/alloc.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,167 @@ | |||||||
|  | /* alloc.c -- Memory allocation without mmap. | ||||||
|  |    Copyright (C) 2012-2021 Free Software Foundation, Inc. | ||||||
|  |    Written by Ian Lance Taylor, Google. | ||||||
|  |  | ||||||
|  | Redistribution and use in source and binary forms, with or without | ||||||
|  | modification, are permitted provided that the following conditions are | ||||||
|  | met: | ||||||
|  |  | ||||||
|  |     (1) Redistributions of source code must retain the above copyright | ||||||
|  |     notice, this list of conditions and the following disclaimer. | ||||||
|  |  | ||||||
|  |     (2) Redistributions in binary form must reproduce the above copyright | ||||||
|  |     notice, this list of conditions and the following disclaimer in | ||||||
|  |     the documentation and/or other materials provided with the | ||||||
|  |     distribution. | ||||||
|  |  | ||||||
|  |     (3) The name of the author may not be used to | ||||||
|  |     endorse or promote products derived from this software without | ||||||
|  |     specific prior written permission. | ||||||
|  |  | ||||||
|  | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||||||
|  | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||||
|  | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||||
|  | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, | ||||||
|  | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||||
|  | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||||
|  | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||||
|  | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||||||
|  | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||||||
|  | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||||
|  | POSSIBILITY OF SUCH DAMAGE.  */ | ||||||
|  |  | ||||||
|  | #include "config.h" | ||||||
|  |  | ||||||
|  | #include <errno.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <sys/types.h> | ||||||
|  |  | ||||||
|  | #include "backtrace.h" | ||||||
|  | #include "internal.h" | ||||||
|  |  | ||||||
|  | /* Allocation routines to use on systems that do not support anonymous | ||||||
|  |    mmap.  This implementation just uses malloc, which means that the | ||||||
|  |    backtrace functions may not be safely invoked from a signal | ||||||
|  |    handler.  */ | ||||||
|  |  | ||||||
|  | /* Allocate memory like malloc.  If ERROR_CALLBACK is NULL, don't | ||||||
|  |    report an error.  */ | ||||||
|  |  | ||||||
|  | void * | ||||||
|  | backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED, | ||||||
|  | 		 size_t size, backtrace_error_callback error_callback, | ||||||
|  | 		 void *data) | ||||||
|  | { | ||||||
|  |   void *ret; | ||||||
|  |  | ||||||
|  |   ret = malloc (size); | ||||||
|  |   if (ret == NULL) | ||||||
|  |     { | ||||||
|  |       if (error_callback) | ||||||
|  | 	error_callback (data, "malloc", errno); | ||||||
|  |     } | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Free memory.  */ | ||||||
|  |  | ||||||
|  | void | ||||||
|  | backtrace_free (struct backtrace_state *state ATTRIBUTE_UNUSED, | ||||||
|  | 		void *p, size_t size ATTRIBUTE_UNUSED, | ||||||
|  | 		backtrace_error_callback error_callback ATTRIBUTE_UNUSED, | ||||||
|  | 		void *data ATTRIBUTE_UNUSED) | ||||||
|  | { | ||||||
|  |   free (p); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Grow VEC by SIZE bytes.  */ | ||||||
|  |  | ||||||
|  | void * | ||||||
|  | backtrace_vector_grow (struct backtrace_state *state ATTRIBUTE_UNUSED, | ||||||
|  | 		       size_t size, backtrace_error_callback error_callback, | ||||||
|  | 		       void *data, struct backtrace_vector *vec) | ||||||
|  | { | ||||||
|  |   void *ret; | ||||||
|  |  | ||||||
|  |   if (size > vec->alc) | ||||||
|  |     { | ||||||
|  |       size_t alc; | ||||||
|  |       void *base; | ||||||
|  |  | ||||||
|  |       if (vec->size == 0) | ||||||
|  | 	alc = 32 * size; | ||||||
|  |       else if (vec->size >= 4096) | ||||||
|  | 	alc = vec->size + 4096; | ||||||
|  |       else | ||||||
|  | 	alc = 2 * vec->size; | ||||||
|  |  | ||||||
|  |       if (alc < vec->size + size) | ||||||
|  | 	alc = vec->size + size; | ||||||
|  |  | ||||||
|  |       base = realloc (vec->base, alc); | ||||||
|  |       if (base == NULL) | ||||||
|  | 	{ | ||||||
|  | 	  error_callback (data, "realloc", errno); | ||||||
|  | 	  return NULL; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  |       vec->base = base; | ||||||
|  |       vec->alc = alc - vec->size; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   ret = (char *) vec->base + vec->size; | ||||||
|  |   vec->size += size; | ||||||
|  |   vec->alc -= size; | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Finish the current allocation on VEC.  */ | ||||||
|  |  | ||||||
|  | void * | ||||||
|  | backtrace_vector_finish (struct backtrace_state *state, | ||||||
|  | 			 struct backtrace_vector *vec, | ||||||
|  | 			 backtrace_error_callback error_callback, | ||||||
|  | 			 void *data) | ||||||
|  | { | ||||||
|  |   void *ret; | ||||||
|  |  | ||||||
|  |   /* With this allocator we call realloc in backtrace_vector_grow, | ||||||
|  |      which means we can't easily reuse the memory here.  So just | ||||||
|  |      release it.  */ | ||||||
|  |   if (!backtrace_vector_release (state, vec, error_callback, data)) | ||||||
|  |     return NULL; | ||||||
|  |   ret = vec->base; | ||||||
|  |   vec->base = NULL; | ||||||
|  |   vec->size = 0; | ||||||
|  |   vec->alc = 0; | ||||||
|  |   return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Release any extra space allocated for VEC.  */ | ||||||
|  |  | ||||||
|  | int | ||||||
|  | backtrace_vector_release (struct backtrace_state *state ATTRIBUTE_UNUSED, | ||||||
|  | 			  struct backtrace_vector *vec, | ||||||
|  | 			  backtrace_error_callback error_callback, | ||||||
|  | 			  void *data) | ||||||
|  | { | ||||||
|  |   vec->alc = 0; | ||||||
|  |  | ||||||
|  |   if (vec->size == 0) | ||||||
|  |     { | ||||||
|  |       /* As of C17, realloc with size 0 is marked as an obsolescent feature, use | ||||||
|  | 	 free instead.  */ | ||||||
|  |       free (vec->base); | ||||||
|  |       vec->base = NULL; | ||||||
|  |       return 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   vec->base = realloc (vec->base, vec->size); | ||||||
|  |   if (vec->base == NULL) | ||||||
|  |     { | ||||||
|  |       error_callback (data, "realloc", errno); | ||||||
|  |       return 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   return 1; | ||||||
|  | } | ||||||
							
								
								
									
										136
									
								
								deps/libbacktrace/allocfail.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								deps/libbacktrace/allocfail.c
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,136 @@ | |||||||
|  | /* allocfail.c -- Test for libbacktrace library | ||||||
|  |    Copyright (C) 2018-2021 Free Software Foundation, Inc. | ||||||
|  |  | ||||||
|  | Redistribution and use in source and binary forms, with or without | ||||||
|  | modification, are permitted provided that the following conditions are | ||||||
|  | met: | ||||||
|  |  | ||||||
|  |     (1) Redistributions of source code must retain the above copyright | ||||||
|  |     notice, this list of conditions and the following disclaimer. | ||||||
|  |  | ||||||
|  |     (2) Redistributions in binary form must reproduce the above copyright | ||||||
|  |     notice, this list of conditions and the following disclaimer in | ||||||
|  |     the documentation and/or other materials provided with the | ||||||
|  |     distribution. | ||||||
|  |  | ||||||
|  |     (3) The name of the author may not be used to | ||||||
|  |     endorse or promote products derived from this software without | ||||||
|  |     specific prior written permission. | ||||||
|  |  | ||||||
|  | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||||||
|  | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||||
|  | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||||
|  | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, | ||||||
|  | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||||
|  | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||||
|  | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||||
|  | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||||||
|  | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||||||
|  | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||||
|  | POSSIBILITY OF SUCH DAMAGE.  */ | ||||||
|  |  | ||||||
|  | #include <assert.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <unistd.h> | ||||||
|  |  | ||||||
|  | #include "filenames.h" | ||||||
|  |  | ||||||
|  | #include "backtrace.h" | ||||||
|  | #include "backtrace-supported.h" | ||||||
|  |  | ||||||
|  | #include "testlib.h" | ||||||
|  |  | ||||||
|  | extern uint64_t get_nr_allocs (void); | ||||||
|  | extern void set_fail_at_alloc (uint64_t); | ||||||
|  | extern int at_fail_alloc_p (void); | ||||||
|  |  | ||||||
|  | static int test1 (void) __attribute__ ((noinline, unused)); | ||||||
|  | static int f2 (int) __attribute__ ((noinline)); | ||||||
|  | static int f3 (int, int) __attribute__ ((noinline)); | ||||||
|  |  | ||||||
|  | static unsigned callback_errors = 0; | ||||||
|  |  | ||||||
|  | static void | ||||||
|  | error_callback_full (void *vdata ATTRIBUTE_UNUSED, | ||||||
|  | 		     const char *msg ATTRIBUTE_UNUSED, | ||||||
|  | 		     int errnum ATTRIBUTE_UNUSED) | ||||||
|  | { | ||||||
|  |   if (at_fail_alloc_p ()) | ||||||
|  |     { | ||||||
|  |       set_fail_at_alloc (0); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   callback_errors++; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int | ||||||
|  | callback_full (void *vdata ATTRIBUTE_UNUSED, uintptr_t pc ATTRIBUTE_UNUSED, | ||||||
|  | 	      const char *filename ATTRIBUTE_UNUSED, | ||||||
|  | 	      int lineno ATTRIBUTE_UNUSED, | ||||||
|  | 	      const char *function ATTRIBUTE_UNUSED) | ||||||
|  | { | ||||||
|  |  | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int | ||||||
|  | test1 (void) | ||||||
|  | { | ||||||
|  |   return f2 (__LINE__) + 1; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int | ||||||
|  | f2 (int f1line) | ||||||
|  | { | ||||||
|  |   return f3 (f1line, __LINE__) + 2; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int | ||||||
|  | f3 (int f1line ATTRIBUTE_UNUSED, int f2line ATTRIBUTE_UNUSED) | ||||||
|  | { | ||||||
|  |   int i; | ||||||
|  |  | ||||||
|  |   i = backtrace_full (state, 0, callback_full, error_callback_full, NULL); | ||||||
|  |  | ||||||
|  |   if (i != 0) | ||||||
|  |     { | ||||||
|  |       fprintf (stderr, "test1: unexpected return value %d\n", i); | ||||||
|  |       ++failures; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   if (callback_errors) | ||||||
|  |       ++failures; | ||||||
|  |  | ||||||
|  |   return failures; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Run all the tests.  */ | ||||||
|  |  | ||||||
|  | int | ||||||
|  | main (int argc, char **argv) | ||||||
|  | { | ||||||
|  |   uint64_t fail_at = 0; | ||||||
|  |  | ||||||
|  |   if (argc == 2) | ||||||
|  |     { | ||||||
|  |       fail_at = atoi (argv[1]); | ||||||
|  |       set_fail_at_alloc (fail_at); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS, | ||||||
|  | 				  error_callback_full, NULL); | ||||||
|  |   if (state == NULL) | ||||||
|  |     exit (failures ? EXIT_FAILURE : EXIT_SUCCESS); | ||||||
|  |  | ||||||
|  | #if BACKTRACE_SUPPORTED | ||||||
|  |   test1 (); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |   if (argc == 1) | ||||||
|  |     fprintf (stderr, "%llu\n", (long long unsigned) get_nr_allocs ()); | ||||||
|  |  | ||||||
|  |   exit (failures ? EXIT_FAILURE : EXIT_SUCCESS); | ||||||
|  | } | ||||||
							
								
								
									
										104
									
								
								deps/libbacktrace/allocfail.sh
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										104
									
								
								deps/libbacktrace/allocfail.sh
									
									
									
									
										vendored
									
									
										Executable file
									
								
							| @@ -0,0 +1,104 @@ | |||||||
|  | #!/bin/sh | ||||||
|  |  | ||||||
|  | # allocfail.sh -- Test for libbacktrace library. | ||||||
|  | # Copyright (C) 2018-2021 Free Software Foundation, Inc. | ||||||
|  |  | ||||||
|  | # Redistribution and use in source and binary forms, with or without | ||||||
|  | # modification, are permitted provided that the following conditions are | ||||||
|  | # met: | ||||||
|  |  | ||||||
|  | #     (1) Redistributions of source code must retain the above copyright | ||||||
|  | #     notice, this list of conditions and the following disclaimer. | ||||||
|  |  | ||||||
|  | #     (2) Redistributions in binary form must reproduce the above copyright | ||||||
|  | #     notice, this list of conditions and the following disclaimer in | ||||||
|  | #     the documentation and/or other materials provided with the | ||||||
|  | #     distribution. | ||||||
|  |  | ||||||
|  | #     (3) The name of the author may not be used to | ||||||
|  | #     endorse or promote products derived from this software without | ||||||
|  | #     specific prior written permission. | ||||||
|  |  | ||||||
|  | # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||||||
|  | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||||
|  | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||||
|  | # DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, | ||||||
|  | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||||
|  | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||||
|  | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||||
|  | # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||||||
|  | # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||||||
|  | # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||||
|  | # POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  | ||||||
|  | set -e | ||||||
|  |  | ||||||
|  | if [ ! -f ./allocfail ]; then | ||||||
|  |     # Hard failure. | ||||||
|  |     exit 99 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | allocs=$(./allocfail 2>&1) | ||||||
|  | if [ "$allocs" = "" ]; then | ||||||
|  |     # Hard failure. | ||||||
|  |     exit 99 | ||||||
|  | fi | ||||||
|  |  | ||||||
|  | # This generates the following output: | ||||||
|  | # ... | ||||||
|  | # $ allocfail.sh | ||||||
|  | # allocs: 80495 | ||||||
|  | # Status changed to 0 at 1 | ||||||
|  | # Status changed to 1 at 3 | ||||||
|  | # Status changed to 0 at 11 | ||||||
|  | # Status changed to 1 at 12 | ||||||
|  | # Status changed to 0 at 845 | ||||||
|  | # ... | ||||||
|  | # | ||||||
|  | # We have status 0 for an allocation failure at: | ||||||
|  | # - 1 because backtrace_create_state handles failure robustly | ||||||
|  | # - 2 because the fail switches backtrace_full to !can_alloc mode. | ||||||
|  | # - 11 because failure of elf_open_debugfile_by_buildid does not generate an | ||||||
|  | #   error callback beyond the one for the allocation failure itself. | ||||||
|  |  | ||||||
|  | echo "allocs: $allocs" | ||||||
|  |  | ||||||
|  | step=1 | ||||||
|  | i=1 | ||||||
|  | passes=0 | ||||||
|  | prev_status=-1 | ||||||
|  | while [ $i -le $allocs ]; do | ||||||
|  |     if ./allocfail $i >/dev/null 2>&1; status=$?; then | ||||||
|  | 	true | ||||||
|  |     fi | ||||||
|  |     if [ $status -gt 1 ]; then | ||||||
|  | 	echo "Unallowed fail found: $i" | ||||||
|  | 	# Failure. | ||||||
|  | 	exit 1 | ||||||
|  |     fi | ||||||
|  |  | ||||||
|  |     # The test-case would run too long if we would excercise all allocs. | ||||||
|  |     # So, run with step 1 initially, and increase the step once we have 10 | ||||||
|  |     # subsequent passes, and drop back to step 1 once we encounter another | ||||||
|  |     # failure.  This takes ~2.6 seconds on an i7-6600U CPU @ 2.60GHz. | ||||||
|  |     if [ $status -eq 0 ]; then | ||||||
|  | 	passes=$(($passes + 1)) | ||||||
|  | 	if [ $passes -ge 10 ]; then | ||||||
|  | 	    step=$((step * 10)) | ||||||
|  | 	    passes=0 | ||||||
|  | 	fi | ||||||
|  |     elif [ $status -eq 1 ]; then | ||||||
|  | 	passes=0 | ||||||
|  | 	step=1 | ||||||
|  |     fi | ||||||
|  |  | ||||||
|  |     if [ $status -ne $prev_status ]; then | ||||||
|  | 	echo "Status changed to $status at $i" | ||||||
|  |     fi | ||||||
|  |     prev_status=$status | ||||||
|  |  | ||||||
|  |     i=$(($i + $step)) | ||||||
|  | done | ||||||
|  |  | ||||||
|  | # Success. | ||||||
|  | exit 0 | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user