Compare commits
	
		
			99 Commits
		
	
	
		
			v0.0.17
			...
			fae2771645
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						fae2771645
	
				 | 
					
					
						|||
| 
						
						
							
						
						2bb6d68122
	
				 | 
					
					
						|||
| 
						
						
							
						
						5c8c6e8760
	
				 | 
					
					
						|||
| 
						
						
							
						
						85ac8080f4
	
				 | 
					
					
						|||
| 
						
						
							
						
						0751699bc8
	
				 | 
					
					
						|||
| 
						
						
							
						
						5551fd2dea
	
				 | 
					
					
						|||
| 
						
						
							
						
						69b2e2a955
	
				 | 
					
					
						|||
| 
						
						
							
						
						34c7fa8312
	
				 | 
					
					
						|||
| 
						
						
							
						
						396f37ee3b
	
				 | 
					
					
						|||
| 7caf4a0173 | |||
| 385524352c | |||
| 5ca5323782 | |||
| ba6da856bb | |||
| c0e72246cc | |||
| c7ab5447ea | |||
| 5fdd461159 | |||
| 421955f2a0 | |||
| a28f6985ed | |||
| 8244dddab7 | |||
| a5ca436eaa | |||
| d7fc1c2c88 | |||
| 382627ef8d | |||
| 17667b4cf8 | |||
| 5231ec22e7 | |||
| 929ae1b709 | |||
| f01f7a5ab9 | |||
| a2dce833f8 | |||
| de6c7a4fd4 | |||
| 4edee0f7f6 | |||
| 988a807fa4 | |||
| 5258e4253d | |||
| 09ba86dec5 | |||
| 78d8a1aa23 | |||
| 22def15209 | |||
| 4cbda7a849 | |||
| be85a620ef | |||
| 0b07b678b4 | |||
| 4733ce9287 | |||
| 48d6bf4c15 | |||
| 8c759bcbac | |||
| b5ed7014f6 | |||
| 6cd9dea186 | |||
| 202b416acf | |||
| 93d46f5610 | |||
| c5ddf3ac99 | |||
| a9cb913a47 | |||
| b7b5d4f1a5 | |||
| a947396bad | |||
| d528bc808e | |||
| c6fd05c2cf | |||
| d6bb9d311a | |||
| 53b4cbbf8c | |||
| 628716ec28 | |||
| bd14168627 | |||
| 96037d4da6 | |||
| 5448e773d8 | |||
| 848ef21c7c | |||
| 2ecae7da93 | |||
| d9ce569eb9 | |||
| eacaf392b1 | |||
| ce16592b6a | |||
| 295d76d354 | |||
| 23b3c998bd | |||
| b5e966c9a1 | |||
| 96cb6f4b12 | |||
| e2c0f82ec0 | |||
| dbf28c03e6 | |||
| 26165e30de | |||
| c52331a23a | |||
| 8007e71e1d | |||
| 28d08e013f | |||
| 64bbd383de | |||
| 8a9f53102b | |||
| 0412b97170 | |||
| c8b8a8fc03 | |||
| 95d3090b9b | |||
| 49129ee6dd | |||
| 6a7ecb0d4a | |||
| 1ceeed1007 | |||
| a7922ff44e | |||
| a421604ed5 | |||
| 7d182db32f | |||
| c5cb9979d3 | |||
| b9a73106ed | |||
| c674cca482 | |||
| 81d1228b92 | |||
| 6ae61d5b81 | |||
| 9cb872eec2 | |||
| 68e8c010b7 | |||
| 9671413906 | |||
| 4c8d24c319 | |||
| e50144bd34 | |||
| 9f3171e3f1 | |||
| cc92748747 | |||
| 0a0b0c1adb | |||
| 92a74026a6 | |||
| 3fa1c6c420 | |||
| b04eccdbda | |||
| 9ce30dee70 | 
@@ -1,4 +1,5 @@
 | 
			
		||||
.svn
 | 
			
		||||
db.sqlite
 | 
			
		||||
db.*
 | 
			
		||||
out/**/*.o
 | 
			
		||||
out/**/*.d
 | 
			
		||||
NOTES.md
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -8,3 +8,4 @@ out
 | 
			
		||||
*.swo
 | 
			
		||||
*.swp
 | 
			
		||||
.zsign_cache/
 | 
			
		||||
NOTES.md
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
[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
 | 
			
		||||
							
								
								
									
										5
									
								
								.markdownlint.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.markdownlint.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
default: true
 | 
			
		||||
MD010: false # Ignore tabs in code blocks
 | 
			
		||||
MD013: false # Don't wrap lines by default
 | 
			
		||||
MD046: 
 | 
			
		||||
  style: "fenced" # Force fenced code blocks
 | 
			
		||||
@@ -12,3 +12,8 @@ deps
 | 
			
		||||
apps/ssb/tribute.esm.js
 | 
			
		||||
apps/api/app.js
 | 
			
		||||
**/emojis.json
 | 
			
		||||
 | 
			
		||||
# only markdownlint should deal with the documentation
 | 
			
		||||
docs/**/*.md
 | 
			
		||||
 | 
			
		||||
NOTES.md
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										31
									
								
								GNUmakefile
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								GNUmakefile
									
									
									
									
									
								
							@@ -3,11 +3,11 @@
 | 
			
		||||
MAKEFLAGS += --warn-undefined-variables
 | 
			
		||||
MAKEFLAGS += --no-builtin-rules
 | 
			
		||||
 | 
			
		||||
VERSION_CODE := 17
 | 
			
		||||
VERSION_NUMBER := 0.0.17
 | 
			
		||||
VERSION_NAME := Please enjoy responsibly.
 | 
			
		||||
VERSION_CODE := 19
 | 
			
		||||
VERSION_NUMBER := 0.0.19-wip
 | 
			
		||||
VERSION_NAME := Don't let your loyalty become a burden.
 | 
			
		||||
 | 
			
		||||
SQLITE_URL := https://www.sqlite.org/2024/sqlite-amalgamation-3450200.zip
 | 
			
		||||
SQLITE_URL := https://www.sqlite.org/2024/sqlite-amalgamation-3450300.zip
 | 
			
		||||
LIBUV_URL := https://dist.libuv.org/dist/v1.48.0/libuv-v1.48.0.tar.gz
 | 
			
		||||
 | 
			
		||||
PROJECT = tildefriends
 | 
			
		||||
@@ -17,6 +17,8 @@ UNAME_M := $(shell uname -m)
 | 
			
		||||
 | 
			
		||||
ANDROID_SDK ?= ~/Android/Sdk
 | 
			
		||||
 | 
			
		||||
HAVE_WIN := 0
 | 
			
		||||
 | 
			
		||||
ifeq ($(UNAME_S),Darwin)
 | 
			
		||||
BUILD_TYPES := macosdebug macosrelease iosdebug iosrelease iossimdebug iossimrelease
 | 
			
		||||
else ifeq ($(UNAME_S),Linux)
 | 
			
		||||
@@ -39,7 +41,6 @@ LDFLAGS += \
 | 
			
		||||
	-lc++abi
 | 
			
		||||
HAVE_ANDROID := 0
 | 
			
		||||
HAVE_LINUX_IOS := 0
 | 
			
		||||
HAVE_WIN := 0
 | 
			
		||||
else
 | 
			
		||||
$(error Unexpected host platform $(UNAME_S).)
 | 
			
		||||
endif
 | 
			
		||||
@@ -56,11 +57,11 @@ CFLAGS += \
 | 
			
		||||
	-fno-exceptions \
 | 
			
		||||
	-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_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 := \
 | 
			
		||||
	out/androiddebug-armv7a/tildefriends \
 | 
			
		||||
@@ -692,7 +693,7 @@ CLASS_FILES := $(foreach src,$(JAVA_FILES),out/classes/com/unprompted/tildefrien
 | 
			
		||||
 | 
			
		||||
$(CLASS_FILES) &: $(JAVA_FILES)
 | 
			
		||||
	@echo "[javac] $(CLASS_FILES)"
 | 
			
		||||
	@javac --release 8 -Xlint:deprecation -classpath $(ANDROID_PLATFORM)/android.jar -d out/classes $(JAVA_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)
 | 
			
		||||
 | 
			
		||||
out/apk/classes.dex: $(CLASS_FILES)
 | 
			
		||||
	@mkdir -p $(dir $@)
 | 
			
		||||
@@ -758,7 +759,7 @@ release-apk: out/TildeFriends-arm-release.zopfli.apk out/TildeFriends-x86-releas
 | 
			
		||||
 | 
			
		||||
releaseapkgo: out/TildeFriends-arm-release.apk
 | 
			
		||||
	@adb install -r $<
 | 
			
		||||
	@adb shell am start com.unprompted.tildefriends/.MainActivity
 | 
			
		||||
	@adb shell am start com.unprompted.tildefriends/.TildeFriendsActivity
 | 
			
		||||
.PHONY: releaseapkgo
 | 
			
		||||
 | 
			
		||||
# iOS Support
 | 
			
		||||
@@ -792,6 +793,10 @@ 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
 | 
			
		||||
iossimrelease-app: out/tildefriends-iossimrelease.app/tildefriends
 | 
			
		||||
@@ -853,11 +858,11 @@ clean:
 | 
			
		||||
	rm -rf $(BUILD_DIR)
 | 
			
		||||
.PHONY: clean
 | 
			
		||||
 | 
			
		||||
dist: release-apk iosrelease-ipa
 | 
			
		||||
dist: release-apk iosrelease-ipa $(if $(HAVE_WIN), out/winrelease/tildefriends.standalone.exe)
 | 
			
		||||
	@echo [archive] dist/tildefriends-$(VERSION_NUMBER).tar.xz
 | 
			
		||||
	@rm -rf out/tildefriends-$(VERSION_NUMBER)
 | 
			
		||||
	@mkdir -p dist/ out/tildefriends-$(VERSION_NUMBER)
 | 
			
		||||
	@git archive HEAD | tar -x -C out/tildefriends-$(VERSION_NUMBER)
 | 
			
		||||
	@git ls-files --recurse-submodules | tar -c -T- | tar -x -C out/tildefriends-$(VERSION_NUMBER)
 | 
			
		||||
	@tar \
 | 
			
		||||
		--exclude=apps/welcome* \
 | 
			
		||||
		--exclude=deps/libbacktrace/Isaac.Newton-Opticks.txt \
 | 
			
		||||
@@ -882,6 +887,8 @@ dist: release-apk iosrelease-ipa
 | 
			
		||||
	@cp out/TildeFriends-arm-release.zopfli.apk dist/TildeFriends-arm-$(VERSION_NUMBER).apk
 | 
			
		||||
	@echo "[cp] 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
 | 
			
		||||
 | 
			
		||||
dist-test: dist
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
Copyright 2014 Cory McWilliams
 | 
			
		||||
Copyright 2014-2024 Cory McWilliams
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
 | 
			
		||||
this software and associated documentation files (the "Software"), to deal in
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								README.md
									
									
									
									
									
								
							@@ -4,46 +4,19 @@ Tilde Friends is a tool for making and sharing.
 | 
			
		||||
 | 
			
		||||
A public instance lives at https://www.tildefriends.net/.
 | 
			
		||||
 | 
			
		||||
It is both a peer-to-peer social network client, participating in Secure
 | 
			
		||||
Scuttlebutt, as well as a platform for writing and running web applications.
 | 
			
		||||
It is both a peer-to-peer social network client, participating in Secure Scuttlebutt, as well as a platform for writing and running web applications.
 | 
			
		||||
 | 
			
		||||
## Goals
 | 
			
		||||
 | 
			
		||||
1. Make it easy and fun to run all sorts of web applications.
 | 
			
		||||
2. Provide security that is easy to understand and protects your data.
 | 
			
		||||
3. Make creating and sharing web applications accessible to anyone with a
 | 
			
		||||
   browser.
 | 
			
		||||
 | 
			
		||||
## Building
 | 
			
		||||
 | 
			
		||||
Builds on Linux (x86_64 and aarch64), MacOS, OpenBSD, and Haiku. Builds for
 | 
			
		||||
all of those host platforms plus mingw64, iOS, and android.
 | 
			
		||||
 | 
			
		||||
1. Requires openssl (`libssl-dev`, in debian-speak). All other dependencies
 | 
			
		||||
   are kept up to date in the tree.
 | 
			
		||||
2. To build, run `make debug` or `make release`. An executable will be
 | 
			
		||||
   generated in a subdirectory of `out/`.
 | 
			
		||||
3. It's possible to build for Android, iOS, and Windows on Linux, if you have
 | 
			
		||||
   the right dependencies in the right places. `make windebug winrelease
 | 
			
		||||
iosdebug-ipa iosrelease-ipa release-apk`.
 | 
			
		||||
4. To build in docker, `docker build .`.
 | 
			
		||||
5. `make format` will normalize formatting to the coding standard.
 | 
			
		||||
 | 
			
		||||
## Running
 | 
			
		||||
 | 
			
		||||
By default, running the built `tildefriends` executable will start a web server
 | 
			
		||||
at <http://localhost:12345/>. `tildefriends -h` lists further options.
 | 
			
		||||
 | 
			
		||||
The first user to create an account and log in will be granted administrative
 | 
			
		||||
privileges. Further administration can be done at
 | 
			
		||||
<http://localhost:12345/~core/admin/>.
 | 
			
		||||
3. Make creating and sharing web applications accessible to anyone with a browser.
 | 
			
		||||
 | 
			
		||||
## Documentation
 | 
			
		||||
 | 
			
		||||
Docs are a work in progress:
 | 
			
		||||
<https://www.tildefriends.net/~cory/wiki/#test-wiki/tf-app-quick-reference>.
 | 
			
		||||
Docs are a work in progress in the `docs` folder, or alternatively in Tilde Friends: <https://www.tildefriends.net/~cory/wiki/#test-wiki/tf-app-quick-reference>.
 | 
			
		||||
 | 
			
		||||
## License
 | 
			
		||||
 | 
			
		||||
All code unless otherwise noted in is provided under the
 | 
			
		||||
[MIT](https://opensource.org/licenses/MIT) license.
 | 
			
		||||
All code, documentation and assets unless otherwise noted in is provided under the
 | 
			
		||||
[MIT](https://opensource.org/licenses/MIT/) license.
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
	"type": "tildefriends-app",
 | 
			
		||||
	"emoji": "🎛"
 | 
			
		||||
	"emoji": "🎛",
 | 
			
		||||
	"previous": "&vrpS/vE7n588iYv1p8HafDxHB+YDHTrtUbJiu9nGA9I=.sha256"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,9 +4,37 @@
 | 
			
		||||
		<script>
 | 
			
		||||
			const g_data = $data;
 | 
			
		||||
		</script>
 | 
			
		||||
		<link rel="stylesheet" href="w3.css"></link>
 | 
			
		||||
		<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>
 | 
			
		||||
	<body style="color: #fff; width: 100%">
 | 
			
		||||
		<h1>Tilde Friends Administration</h1>
 | 
			
		||||
	<body class="w3-theme-l4">
 | 
			
		||||
		<header class="w3-row w3-padding w3-header w3-theme-l1">
 | 
			
		||||
			<h1>Tilde Friends Administration</h1>
 | 
			
		||||
		</header>
 | 
			
		||||
	</body>
 | 
			
		||||
	<script type="module" src="script.js"></script>
 | 
			
		||||
</html>
 | 
			
		||||
 
 | 
			
		||||
@@ -32,59 +32,54 @@ window.addEventListener('load', function () {
 | 
			
		||||
	function input_template(key, description) {
 | 
			
		||||
		if (description.type === 'boolean') {
 | 
			
		||||
			return html`
 | 
			
		||||
				<div style="margin-top: 1em">
 | 
			
		||||
					<label for=${'gs_' + key} style="font-weight: bold">${key}: </label>
 | 
			
		||||
					<div>
 | 
			
		||||
						<input type="checkbox" ?checked=${description.value} id=${'gs_' + key}></input>
 | 
			
		||||
						<button @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.checked)}>Set</button>
 | 
			
		||||
						<div>${description.description}</div>
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
				<li class="w3-row">
 | 
			
		||||
					<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold">${key}</label>
 | 
			
		||||
					<div class="w3-quarter w3-padding">${description.description}</div>
 | 
			
		||||
					<input class="w3-quarter w3-check" type="checkbox" ?checked=${description.value} id=${'gs_' + key}></input>
 | 
			
		||||
					<button class="w3-quarter w3-button w3-theme-action" @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.checked)}>Set</button>
 | 
			
		||||
				</li>
 | 
			
		||||
			`;
 | 
			
		||||
		} else if (description.type === 'textarea') {
 | 
			
		||||
			return html`
 | 
			
		||||
				<div style="margin-top: 1em"">
 | 
			
		||||
					<label for=${'gs_' + key} style="font-weight: bold">${key}: </label>
 | 
			
		||||
					<div style="width: 100%; padding: 0; margin: 0">
 | 
			
		||||
						<div style="width: 90%; padding: 0 margin: 0">
 | 
			
		||||
							<textarea style="vertical-align: top; width: 100%" rows=20 cols=80 id=${'gs_' + key}>${description.value}</textarea>
 | 
			
		||||
						</div>
 | 
			
		||||
						<button @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.firstElementChild.value)}>Set</button>
 | 
			
		||||
						<div>${description.description}</div>
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
				<li class="w3-row">
 | 
			
		||||
					<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold">${key}</label>
 | 
			
		||||
					<div class="w3-rest w3-padding">${description.description}</div>
 | 
			
		||||
					<textarea class="w3-input" style="vertical-align: top; resize: vertical" id=${'gs_' + key}>${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 {
 | 
			
		||||
			return html`
 | 
			
		||||
				<div style="margin-top: 1em">
 | 
			
		||||
					<label for=${'gs_' + key} style="font-weight: bold">${key}: </label>
 | 
			
		||||
					<div>
 | 
			
		||||
						<input type="text" value="${description.value}" id=${'gs_' + key}></input>
 | 
			
		||||
						<button @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.value)}>Set</button>
 | 
			
		||||
						<div>${description.description}</div>
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
				<li class="w3-row">
 | 
			
		||||
					<label class="w3-quarter" for=${'gs_' + key} style="font-weight: bold">${key}</label>
 | 
			
		||||
					<div class="w3-quarter w3-padding">${description.description}</div>
 | 
			
		||||
					<input class="w3-input w3-quarter" type="text" value="${description.value}" id=${'gs_' + key}></input>
 | 
			
		||||
					<button class="w3-button w3-quarter w3-theme-action" @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.value)}>Set</button>
 | 
			
		||||
				</li>
 | 
			
		||||
			`;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	const user_template = (user, permissions) => html`
 | 
			
		||||
		<li>
 | 
			
		||||
			<button @click=${(e) => delete_user(user)}>Delete</button>
 | 
			
		||||
		<li class="w3-card w3-margin">
 | 
			
		||||
			<button class="w3-button w3-theme-action" @click=${(e) => delete_user(user)}>Delete</button>
 | 
			
		||||
			${user}: ${permissions.map((x) => permission_template(x))}
 | 
			
		||||
		</li>
 | 
			
		||||
	`;
 | 
			
		||||
	const users_template = (users) =>
 | 
			
		||||
		html`<h2>Users</h2>
 | 
			
		||||
			<ul>
 | 
			
		||||
		html`
 | 
			
		||||
			<header class="w3-container w3-theme-l2"><h2>Users</h2></header>
 | 
			
		||||
			<ul class="w3-ul">
 | 
			
		||||
				${Object.entries(users).map((u) => user_template(u[0], u[1]))}
 | 
			
		||||
			</ul>`;
 | 
			
		||||
	const page_template = (data) =>
 | 
			
		||||
		html`<div style="padding: 0; margin: 0; width: 100%; max-width: 100%">
 | 
			
		||||
			<h2>Global Settings</h2>
 | 
			
		||||
			<div>
 | 
			
		||||
				${Object.keys(data.settings)
 | 
			
		||||
					.sort()
 | 
			
		||||
					.map((x) => html`${input_template(x, data.settings[x])}`)}
 | 
			
		||||
			<header class="w3-container w3-theme-l2"><h2>Global Settings</h2></header>
 | 
			
		||||
			<div class="w3-container">
 | 
			
		||||
				<ul class="w3-ul">
 | 
			
		||||
					${Object.keys(data.settings)
 | 
			
		||||
						.sort()
 | 
			
		||||
						.map((x) => html`${input_template(x, data.settings[x])}`)}
 | 
			
		||||
				</ul>
 | 
			
		||||
			</div>
 | 
			
		||||
			${users_template(data.users)}
 | 
			
		||||
		</div> `;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										235
									
								
								apps/admin/w3.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								apps/admin/w3.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,235 @@
 | 
			
		||||
/* 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 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
	"type": "tildefriends-app",
 | 
			
		||||
	"emoji": "🪪",
 | 
			
		||||
	"previous": "&kgukkyDk1RxgfzgMH6H/0QeDPIuwPZypLuAFax21ljk=.sha256"
 | 
			
		||||
	"previous": "&de7q4A59auHP/34bXgeNH05JZoxsGr5TjwXPvehWH30=.sha256"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,36 @@ tfrpc.register(async function reload() {
 | 
			
		||||
async function main() {
 | 
			
		||||
	let ids = await ssb.getIdentities();
 | 
			
		||||
	await app.setDocument(
 | 
			
		||||
		`<body style="color: #fff">
 | 
			
		||||
		`
 | 
			
		||||
		<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';
 | 
			
		||||
@@ -27,7 +56,8 @@ async function main() {
 | 
			
		||||
				let id = event.srcElement.dataset.id;
 | 
			
		||||
				let element = document.createElement('textarea');
 | 
			
		||||
				element.value = await tfrpc.rpc.get_private_key(id);
 | 
			
		||||
				element.style = 'width: 100%; read-only: true';
 | 
			
		||||
				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);
 | 
			
		||||
@@ -69,23 +99,34 @@ async function main() {
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		</script>
 | 
			
		||||
		<h1>SSB Identity Management</h1>
 | 
			
		||||
		<h2>Create a new identity</h2>
 | 
			
		||||
		<button id="create_id" onclick="handler.create_id()">Create Identity</button>
 | 
			
		||||
		<h2>Import an SSB Identity from 12 BIP39 English Words</h2>
 | 
			
		||||
		<textarea id="add_id" style="width: 100%" rows="4"></textarea><button id="add" onclick="handler.add_id(event)">Import Identity</button>
 | 
			
		||||
		<h2>Identities</h2>
 | 
			
		||||
		<ul>` +
 | 
			
		||||
			ids
 | 
			
		||||
				.map(
 | 
			
		||||
					(id) => `<li>
 | 
			
		||||
			<button onclick="handler.export_id(event)" data-id="${id}">Export Identity</button>
 | 
			
		||||
			<button onclick="handler.delete_id(event)" data-id="${id}">Delete Identity</button>
 | 
			
		||||
			${id}
 | 
			
		||||
		</li>`
 | 
			
		||||
				)
 | 
			
		||||
				.join('\n') +
 | 
			
		||||
			`	</ul>
 | 
			
		||||
		<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>`
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										235
									
								
								apps/identity/w3.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								apps/identity/w3.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,235 @@
 | 
			
		||||
/* 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",
 | 
			
		||||
	"emoji": "🦟",
 | 
			
		||||
	"previous": "&TegdzvFE+im94shygaHkgDYSaSrwY2h0OKUXSRPBQDM=.sha256"
 | 
			
		||||
	"previous": "&cUqvSDUls3jn0haD85LPFAGdkc8wFuy347TtATNcJgg=.sha256"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -85,6 +85,9 @@ tfrpc.register(async function store_message(message) {
 | 
			
		||||
tfrpc.register(function apps() {
 | 
			
		||||
	return core.apps();
 | 
			
		||||
});
 | 
			
		||||
tfrpc.register(function getActiveIdentity() {
 | 
			
		||||
	return ssb.getActiveIdentity();
 | 
			
		||||
});
 | 
			
		||||
tfrpc.register(async function try_decrypt(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,48 +4,6 @@ import * as tfutils from './tf-utils.js';
 | 
			
		||||
 | 
			
		||||
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 {
 | 
			
		||||
	static get properties() {
 | 
			
		||||
		return {
 | 
			
		||||
@@ -105,10 +63,10 @@ class TfIssuesAppElement extends LitElement {
 | 
			
		||||
		let issues = {};
 | 
			
		||||
		let messages = await tfrpc.rpc.query(
 | 
			
		||||
			`
 | 
			
		||||
			WITH issues AS (SELECT messages.* FROM messages_refs JOIN messages ON
 | 
			
		||||
			WITH issues AS (SELECT messages.id, json(messages.content) AS content, messages.author, messages.timestamp FROM messages_refs JOIN messages ON
 | 
			
		||||
				messages.id = messages_refs.message
 | 
			
		||||
				WHERE messages_refs.ref = ? AND json_extract(messages.content, '$.type') = 'issue'),
 | 
			
		||||
			edits AS (SELECT messages.* FROM issues JOIN messages_refs ON
 | 
			
		||||
			edits AS (SELECT messages.id, json(messages.content) AS content, messages.author, messages.timestamp FROM issues JOIN messages_refs ON
 | 
			
		||||
				issues.id = messages_refs.ref JOIN messages ON
 | 
			
		||||
				messages.id = messages_refs.message
 | 
			
		||||
				WHERE json_extract(messages.content, '$.type') IN ('issue-edit', 'post'))
 | 
			
		||||
@@ -206,7 +164,7 @@ class TfIssuesAppElement extends LitElement {
 | 
			
		||||
		if (
 | 
			
		||||
			confirm(`Are you sure you want to ${open ? 'open' : 'close'} this issue?`)
 | 
			
		||||
		) {
 | 
			
		||||
			let whoami = this.shadowRoot.getElementById('picker').selected;
 | 
			
		||||
			let whoami = await tfrpc.rpc.getActiveIdentity();
 | 
			
		||||
			await tfrpc.rpc.appendMessage(whoami, {
 | 
			
		||||
				type: 'issue-edit',
 | 
			
		||||
				issues: [
 | 
			
		||||
@@ -221,7 +179,7 @@ class TfIssuesAppElement extends LitElement {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async create_issue(event) {
 | 
			
		||||
		let whoami = this.shadowRoot.getElementById('picker').selected;
 | 
			
		||||
		let whoami = await tfrpc.rpc.getActiveIdentity();
 | 
			
		||||
		await tfrpc.rpc.appendMessage(whoami, {
 | 
			
		||||
			type: 'issue',
 | 
			
		||||
			project: k_project,
 | 
			
		||||
@@ -231,7 +189,7 @@ class TfIssuesAppElement extends LitElement {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async reply_to_issue(event) {
 | 
			
		||||
		let whoami = this.shadowRoot.getElementById('picker').selected;
 | 
			
		||||
		let whoami = await tfrpc.rpc.getActiveIdentity();
 | 
			
		||||
		await tfrpc.rpc.appendMessage(whoami, {
 | 
			
		||||
			type: 'post',
 | 
			
		||||
			text: event.detail.value,
 | 
			
		||||
@@ -249,10 +207,7 @@ class TfIssuesAppElement extends LitElement {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	render() {
 | 
			
		||||
		let header = html`
 | 
			
		||||
			<h1>Tilde Friends Issues</h1>
 | 
			
		||||
			<tf-id-picker id="picker"></tf-id-picker>
 | 
			
		||||
		`;
 | 
			
		||||
		let header = html` <h1>Tilde Friends Issues</h1> `;
 | 
			
		||||
		if (this.selected) {
 | 
			
		||||
			return html`
 | 
			
		||||
				${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",
 | 
			
		||||
	"emoji": "📦",
 | 
			
		||||
	"previous": "&IU+TwyM7TznD8NBfnw7tgW2zxVlMqTVxSqWFjuosLwo=.sha256"
 | 
			
		||||
	"emoji": "🚪",
 | 
			
		||||
	"previous": "&HXCdDG8gGYXElTyEFbg85jqa6lDXNL2ENPIA9UoJNbI=.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",
 | 
			
		||||
	"emoji": "🐌",
 | 
			
		||||
	"previous": "&Xs1X5TzLCk6KVr+5IDc80JAHYxJyoD10cXKBUYpFqWQ=.sha256"
 | 
			
		||||
	"previous": "&vEaOZjrNb0u9rhNqrQ8eU9TlOFlo4HsgW6hbI7VdIT0=.sha256"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -100,6 +100,9 @@ tfrpc.register(async function try_decrypt(id, content) {
 | 
			
		||||
tfrpc.register(async function encrypt(id, recipients, content) {
 | 
			
		||||
	return await ssb.privateMessageEncrypt(id, recipients, content);
 | 
			
		||||
});
 | 
			
		||||
tfrpc.register(async function getActiveIdentity() {
 | 
			
		||||
	return await ssb.getActiveIdentity();
 | 
			
		||||
});
 | 
			
		||||
ssb.addEventListener('broadcasts', async function () {
 | 
			
		||||
	await tfrpc.rpc.set('broadcasts', await ssb.getBroadcasts());
 | 
			
		||||
});
 | 
			
		||||
@@ -107,6 +110,9 @@ ssb.addEventListener('broadcasts', async function () {
 | 
			
		||||
core.register('onConnectionsChanged', async function () {
 | 
			
		||||
	await tfrpc.rpc.set('connections', await ssb.connections());
 | 
			
		||||
});
 | 
			
		||||
core.register('setActiveIdentity', async function (id) {
 | 
			
		||||
	await tfrpc.rpc.set('identity', id);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
async function main() {
 | 
			
		||||
	if (typeof database !== 'undefined') {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,90 +1,94 @@
 | 
			
		||||
function textNode(text) {
 | 
			
		||||
  const node = new commonmark.Node("text", undefined);
 | 
			
		||||
  node.literal = text;
 | 
			
		||||
  return node;
 | 
			
		||||
	const node = new commonmark.Node('text', undefined);
 | 
			
		||||
	node.literal = text;
 | 
			
		||||
	return node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function linkNode(text, link) {
 | 
			
		||||
  const linkNode = new commonmark.Node("link", undefined);
 | 
			
		||||
  linkNode.destination = `#q=${encodeURIComponent(link)}`;
 | 
			
		||||
  linkNode.appendChild(textNode(text));
 | 
			
		||||
  return linkNode;
 | 
			
		||||
	const linkNode = new commonmark.Node('link', undefined);
 | 
			
		||||
	if (link.startsWith('#')) {
 | 
			
		||||
		linkNode.destination = `#q=${encodeURIComponent(link)}`;
 | 
			
		||||
	} else {
 | 
			
		||||
		linkNode.destination = link;
 | 
			
		||||
	}
 | 
			
		||||
	linkNode.appendChild(textNode(text));
 | 
			
		||||
	return linkNode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function splitMatches(text, regexp) {
 | 
			
		||||
  // Regexp must be sticky.
 | 
			
		||||
  regexp = new RegExp(regexp, "gm");
 | 
			
		||||
	// Regexp must be sticky.
 | 
			
		||||
	regexp = new RegExp(regexp, 'gm');
 | 
			
		||||
 | 
			
		||||
  let i = 0;
 | 
			
		||||
  const result = [];
 | 
			
		||||
	let i = 0;
 | 
			
		||||
	const result = [];
 | 
			
		||||
 | 
			
		||||
  let match = regexp.exec(text);
 | 
			
		||||
  while (match) {
 | 
			
		||||
    const matchText = match[0];
 | 
			
		||||
	let match = regexp.exec(text);
 | 
			
		||||
	while (match) {
 | 
			
		||||
		const matchText = match[0];
 | 
			
		||||
 | 
			
		||||
    if (match.index > i) {
 | 
			
		||||
      result.push([text.substring(i, match.index), false]);
 | 
			
		||||
    }
 | 
			
		||||
		if (match.index > i) {
 | 
			
		||||
			result.push([text.substring(i, match.index), false]);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
    result.push([matchText, true]);
 | 
			
		||||
    i = match.index + matchText.length;
 | 
			
		||||
		result.push([matchText, true]);
 | 
			
		||||
		i = match.index + matchText.length;
 | 
			
		||||
 | 
			
		||||
    match = regexp.exec(text);
 | 
			
		||||
  }
 | 
			
		||||
		match = regexp.exec(text);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  if (i < text.length) {
 | 
			
		||||
    result.push([text.substring(i, text.length), false]);
 | 
			
		||||
  }
 | 
			
		||||
	if (i < text.length) {
 | 
			
		||||
		result.push([text.substring(i, text.length), false]);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  return result;
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const regex = new RegExp("(?<!\\w)#[\\w-]+");
 | 
			
		||||
const regex = new RegExp('(?:https?://[^ ]+[^ .,])|(?:(?<!\\w)#[\\w-]+)|(?:@[A-Za-z0-9+/]+=.ed25519)|(?:[%&][A-Za-z0-9+/]+=.sha256)');
 | 
			
		||||
 | 
			
		||||
function split(textNodes) {
 | 
			
		||||
  const text = textNodes.map(n => n.literal).join("");
 | 
			
		||||
  const parts = splitMatches(text, regex);
 | 
			
		||||
	const text = textNodes.map((n) => n.literal).join('');
 | 
			
		||||
	const parts = splitMatches(text, regex);
 | 
			
		||||
 | 
			
		||||
  return parts.map(part => {
 | 
			
		||||
    if (part[1]) {
 | 
			
		||||
      return linkNode(part[0], part[0]);
 | 
			
		||||
    } else {
 | 
			
		||||
      return textNode(part[0]);
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
	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;
 | 
			
		||||
	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) {
 | 
			
		||||
        split(nodes)
 | 
			
		||||
          .reverse()
 | 
			
		||||
          .forEach(newNode => {
 | 
			
		||||
            nodes[0].insertAfter(newNode);
 | 
			
		||||
          });
 | 
			
		||||
	let nodes = [];
 | 
			
		||||
	while ((event = walker.next())) {
 | 
			
		||||
		const node = event.node;
 | 
			
		||||
		if (event.entering && node.type === 'text') {
 | 
			
		||||
			nodes.push(node);
 | 
			
		||||
		} else {
 | 
			
		||||
			if (nodes.length > 0) {
 | 
			
		||||
				split(nodes)
 | 
			
		||||
					.reverse()
 | 
			
		||||
					.forEach((newNode) => {
 | 
			
		||||
						nodes[0].insertAfter(newNode);
 | 
			
		||||
					});
 | 
			
		||||
 | 
			
		||||
        nodes.forEach(n => n.unlink());
 | 
			
		||||
        nodes = [];
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
				nodes.forEach((n) => n.unlink());
 | 
			
		||||
				nodes = [];
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  if (nodes.length > 0) {
 | 
			
		||||
    split(nodes)
 | 
			
		||||
      .reverse()
 | 
			
		||||
      .forEach(newNode => {
 | 
			
		||||
        nodes[0].insertAfter(newNode);
 | 
			
		||||
      });
 | 
			
		||||
    nodes.forEach(n => n.unlink());
 | 
			
		||||
  }
 | 
			
		||||
	if (nodes.length > 0) {
 | 
			
		||||
		split(nodes)
 | 
			
		||||
			.reverse()
 | 
			
		||||
			.forEach((newNode) => {
 | 
			
		||||
				nodes[0].insertAfter(newNode);
 | 
			
		||||
			});
 | 
			
		||||
		nodes.forEach((n) => n.unlink());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  return parsed;
 | 
			
		||||
	return parsed;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,91 +0,0 @@
 | 
			
		||||
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,3 +1,5 @@
 | 
			
		||||
import * as tfrpc from '/static/tfrpc.js';
 | 
			
		||||
 | 
			
		||||
let g_emojis;
 | 
			
		||||
 | 
			
		||||
function get_emojis() {
 | 
			
		||||
@@ -10,105 +12,154 @@ function get_emojis() {
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function picker(callback, anchor) {
 | 
			
		||||
	get_emojis().then(function (json) {
 | 
			
		||||
		let div = document.createElement('div');
 | 
			
		||||
		div.id = 'emoji_picker';
 | 
			
		||||
		div.style.color = '#000';
 | 
			
		||||
		div.style.background = '#fff';
 | 
			
		||||
		div.style.border = '1px solid #000';
 | 
			
		||||
		div.style.display = 'block';
 | 
			
		||||
		div.style.position = 'absolute';
 | 
			
		||||
		div.style.minWidth = 'min(16em, 90vw)';
 | 
			
		||||
		div.style.width = 'min(16em, 90vw)';
 | 
			
		||||
		div.style.maxWidth = 'min(16em, 90vw)';
 | 
			
		||||
		div.style.maxHeight = '16em';
 | 
			
		||||
		div.style.overflow = 'scroll';
 | 
			
		||||
		div.style.fontWeight = 'bold';
 | 
			
		||||
		div.style.fontSize = 'xx-large';
 | 
			
		||||
		let input = document.createElement('input');
 | 
			
		||||
		input.type = 'text';
 | 
			
		||||
		input.style.display = 'block';
 | 
			
		||||
		input.style.boxSizing = 'border-box';
 | 
			
		||||
		input.style.width = '100%';
 | 
			
		||||
		input.style.margin = '0';
 | 
			
		||||
		input.style.position = 'relative';
 | 
			
		||||
		div.appendChild(input);
 | 
			
		||||
		let list = document.createElement('div');
 | 
			
		||||
		div.appendChild(list);
 | 
			
		||||
		div.addEventListener('mousedown', function (event) {
 | 
			
		||||
			event.stopPropagation();
 | 
			
		||||
		});
 | 
			
		||||
async function get_recent(author) {
 | 
			
		||||
	let recent = await tfrpc.rpc.query(
 | 
			
		||||
		`
 | 
			
		||||
		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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		function cleanup() {
 | 
			
		||||
			console.log('emoji cleanup');
 | 
			
		||||
			div.parentElement.removeChild(div);
 | 
			
		||||
			window.removeEventListener('keydown', key_down);
 | 
			
		||||
			console.log('removing click');
 | 
			
		||||
			document.body.removeEventListener('mousedown', cleanup);
 | 
			
		||||
		}
 | 
			
		||||
export async function picker(callback, anchor, author) {
 | 
			
		||||
	let json = await get_emojis();
 | 
			
		||||
	let recent = await get_recent(author);
 | 
			
		||||
 | 
			
		||||
		function key_down(event) {
 | 
			
		||||
			if (event.key == 'Escape') {
 | 
			
		||||
				cleanup();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	let div = document.createElement('div');
 | 
			
		||||
	div.id = 'emoji_picker';
 | 
			
		||||
	div.style.color = '#000';
 | 
			
		||||
	div.style.background = '#fff';
 | 
			
		||||
	div.style.border = '1px solid #000';
 | 
			
		||||
	div.style.display = 'block';
 | 
			
		||||
	div.style.position = 'absolute';
 | 
			
		||||
	div.style.minWidth = 'min(16em, 90vw)';
 | 
			
		||||
	div.style.width = 'min(16em, 90vw)';
 | 
			
		||||
	div.style.maxWidth = 'min(16em, 90vw)';
 | 
			
		||||
	div.style.maxHeight = '16em';
 | 
			
		||||
	div.style.overflow = 'scroll';
 | 
			
		||||
	div.style.fontWeight = 'bold';
 | 
			
		||||
	div.style.fontSize = 'xx-large';
 | 
			
		||||
	let input = document.createElement('input');
 | 
			
		||||
	input.type = 'text';
 | 
			
		||||
	input.style.display = 'block';
 | 
			
		||||
	input.style.boxSizing = 'border-box';
 | 
			
		||||
	input.style.width = '100%';
 | 
			
		||||
	input.style.margin = '0';
 | 
			
		||||
	input.style.position = 'relative';
 | 
			
		||||
	div.appendChild(input);
 | 
			
		||||
	let list = document.createElement('div');
 | 
			
		||||
	div.appendChild(list);
 | 
			
		||||
	div.addEventListener('mousedown', function (event) {
 | 
			
		||||
		event.stopPropagation();
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
		function chosen(event) {
 | 
			
		||||
			console.log(event.srcElement.innerText);
 | 
			
		||||
			callback(event.srcElement.innerText);
 | 
			
		||||
	function cleanup() {
 | 
			
		||||
		console.log('emoji cleanup');
 | 
			
		||||
		div.parentElement.removeChild(div);
 | 
			
		||||
		window.removeEventListener('keydown', key_down);
 | 
			
		||||
		console.log('removing click');
 | 
			
		||||
		document.body.removeEventListener('mousedown', cleanup);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function key_down(event) {
 | 
			
		||||
		if (event.key == 'Escape') {
 | 
			
		||||
			cleanup();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
		function refresh() {
 | 
			
		||||
			while (list.firstChild) {
 | 
			
		||||
				list.removeChild(list.firstChild);
 | 
			
		||||
			}
 | 
			
		||||
			let search = input.value.toLowerCase();
 | 
			
		||||
			let any_at_all = false;
 | 
			
		||||
			for (let row of Object.entries(json)) {
 | 
			
		||||
				let header = document.createElement('div');
 | 
			
		||||
				header.appendChild(document.createTextNode(row[0]));
 | 
			
		||||
				list.appendChild(header);
 | 
			
		||||
				let any = false;
 | 
			
		||||
				for (let entry of Object.entries(row[1])) {
 | 
			
		||||
					if (
 | 
			
		||||
						search &&
 | 
			
		||||
						search.length &&
 | 
			
		||||
						entry[0].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 = entry[0];
 | 
			
		||||
					emoji.appendChild(document.createTextNode(entry[1]));
 | 
			
		||||
					list.appendChild(emoji);
 | 
			
		||||
					any = true;
 | 
			
		||||
					any_at_all = true;
 | 
			
		||||
				}
 | 
			
		||||
				if (!any) {
 | 
			
		||||
					list.removeChild(header);
 | 
			
		||||
	function chosen(event) {
 | 
			
		||||
		console.log(event.srcElement.innerText);
 | 
			
		||||
		callback(event.srcElement.innerText);
 | 
			
		||||
		cleanup();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function refresh() {
 | 
			
		||||
		while (list.firstChild) {
 | 
			
		||||
			list.removeChild(list.firstChild);
 | 
			
		||||
		}
 | 
			
		||||
		let search = input.value.toLowerCase();
 | 
			
		||||
		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];
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if (!any_at_all) {
 | 
			
		||||
				list.appendChild(document.createTextNode('No matches found.'));
 | 
			
		||||
			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);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		refresh();
 | 
			
		||||
		input.oninput = refresh;
 | 
			
		||||
		document.body.appendChild(div);
 | 
			
		||||
		div.style.position = 'fixed';
 | 
			
		||||
		div.style.top = '50%';
 | 
			
		||||
		div.style.left = '50%';
 | 
			
		||||
		div.style.transform = 'translate(-50%, -50%)';
 | 
			
		||||
		input.focus();
 | 
			
		||||
		console.log('adding click');
 | 
			
		||||
		document.body.addEventListener('mousedown', cleanup);
 | 
			
		||||
		window.addEventListener('keydown', key_down);
 | 
			
		||||
	});
 | 
			
		||||
		for (let row of Object.entries(json)) {
 | 
			
		||||
			let header = document.createElement('div');
 | 
			
		||||
			header.appendChild(document.createTextNode(row[0]));
 | 
			
		||||
			list.appendChild(header);
 | 
			
		||||
			let any = false;
 | 
			
		||||
			for (let entry of Object.entries(row[1])) {
 | 
			
		||||
				if (
 | 
			
		||||
					search &&
 | 
			
		||||
					search.length &&
 | 
			
		||||
					entry[0].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 = entry[0];
 | 
			
		||||
				emoji.appendChild(document.createTextNode(entry[1]));
 | 
			
		||||
				list.appendChild(emoji);
 | 
			
		||||
				any = true;
 | 
			
		||||
				any_at_all = true;
 | 
			
		||||
			}
 | 
			
		||||
			if (!any) {
 | 
			
		||||
				list.removeChild(header);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (!any_at_all) {
 | 
			
		||||
			list.appendChild(document.createTextNode('No matches found.'));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	refresh();
 | 
			
		||||
	input.oninput = refresh;
 | 
			
		||||
	document.body.appendChild(div);
 | 
			
		||||
	div.style.position = 'fixed';
 | 
			
		||||
	div.style.top = '50%';
 | 
			
		||||
	div.style.left = '50%';
 | 
			
		||||
	div.style.transform = 'translate(-50%, -50%)';
 | 
			
		||||
	input.focus();
 | 
			
		||||
	console.log('adding click');
 | 
			
		||||
	document.body.addEventListener('mousedown', cleanup);
 | 
			
		||||
	window.addEventListener('keydown', key_down);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<!doctype html>
 | 
			
		||||
<html style="color: #fff">
 | 
			
		||||
<html>
 | 
			
		||||
	<head>
 | 
			
		||||
		<title>Tilde Friends</title>
 | 
			
		||||
		<base target="_top" />
 | 
			
		||||
@@ -10,14 +10,14 @@
 | 
			
		||||
			}
 | 
			
		||||
		</style>
 | 
			
		||||
	</head>
 | 
			
		||||
	<body style="background-color: #223a5e">
 | 
			
		||||
		<tf-app class="w3-deep-purple" />
 | 
			
		||||
	<body style="margin: 0; padding: 0">
 | 
			
		||||
		<tf-app></tf-app>
 | 
			
		||||
		<tf-reactions-modal id="reactions_modal"></tf-reactions-modal>
 | 
			
		||||
		<script>
 | 
			
		||||
			window.litDisableBundleWarning = true;
 | 
			
		||||
		</script>
 | 
			
		||||
		<script src="filesaver.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="script.js" type="module"></script>
 | 
			
		||||
	</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 * 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_message from './tf-message.js';
 | 
			
		||||
import * as tf_user from './tf-user.js';
 | 
			
		||||
import * as tf_compose from './tf-compose.js';
 | 
			
		||||
import * as tf_news from './tf-news.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_news from './tf-tab-news.js';
 | 
			
		||||
import * as tf_tab_news_feed from './tf-tab-news-feed.js';
 | 
			
		||||
 
 | 
			
		||||
@@ -52,13 +52,15 @@ class TfElement extends LitElement {
 | 
			
		||||
				self.broadcasts = value;
 | 
			
		||||
			} else if (name === 'connections') {
 | 
			
		||||
				self.connections = value;
 | 
			
		||||
			} else if (name === 'identity') {
 | 
			
		||||
				self.whoami = value;
 | 
			
		||||
			}
 | 
			
		||||
		});
 | 
			
		||||
		this.initial_load();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async initial_load() {
 | 
			
		||||
		let whoami = await tfrpc.rpc.localStorageGet('whoami');
 | 
			
		||||
		let whoami = await tfrpc.rpc.getActiveIdentity();
 | 
			
		||||
		let ids = (await tfrpc.rpc.getIdentities()) || [];
 | 
			
		||||
		this.whoami = whoami ?? (ids.length ? ids[0] : undefined);
 | 
			
		||||
		this.ids = ids;
 | 
			
		||||
@@ -193,29 +195,6 @@ 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() {
 | 
			
		||||
		let start = new Date();
 | 
			
		||||
		this.tags = await tfrpc.rpc.query(
 | 
			
		||||
@@ -255,7 +234,15 @@ class TfElement extends LitElement {
 | 
			
		||||
			by_count.push({count: v.of, id: id});
 | 
			
		||||
		}
 | 
			
		||||
		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);
 | 
			
		||||
		console.log(
 | 
			
		||||
			'about took',
 | 
			
		||||
			(new Date() - start_time) / 1000.0,
 | 
			
		||||
			'seconds for',
 | 
			
		||||
			Object.keys(users).length,
 | 
			
		||||
			'users'
 | 
			
		||||
		);
 | 
			
		||||
		this.following = Object.keys(following);
 | 
			
		||||
		this.users = users;
 | 
			
		||||
		await tags;
 | 
			
		||||
@@ -352,15 +339,15 @@ class TfElement extends LitElement {
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		let tabs = html`
 | 
			
		||||
			<div class="w3-bar w3-black">
 | 
			
		||||
			<div class="w3-bar w3-theme-l1">
 | 
			
		||||
				${Object.entries(k_tabs).map(
 | 
			
		||||
					([k, v]) => html`
 | 
			
		||||
						<button
 | 
			
		||||
							title=${v}
 | 
			
		||||
							class="w3-bar-item w3-padding-large w3-hover-gray tab ${self.tab ==
 | 
			
		||||
							class="w3-bar-item w3-padding-large w3-hover-theme tab ${self.tab ==
 | 
			
		||||
							v
 | 
			
		||||
								? 'w3-red'
 | 
			
		||||
								: 'w3-black'}"
 | 
			
		||||
								? 'w3-theme-l2'
 | 
			
		||||
								: 'w3-theme-l1'}"
 | 
			
		||||
							@click=${() => self.set_tab(v)}
 | 
			
		||||
						>
 | 
			
		||||
							${k}
 | 
			
		||||
@@ -371,15 +358,25 @@ class TfElement extends LitElement {
 | 
			
		||||
		`;
 | 
			
		||||
		let contents = !this.loaded
 | 
			
		||||
			? this.loading
 | 
			
		||||
				? html`<div>Loading...</div>`
 | 
			
		||||
				? html`<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>`
 | 
			
		||||
			: this.render_tab();
 | 
			
		||||
		return html`
 | 
			
		||||
			${this.render_id_picker()} ${tabs}
 | 
			
		||||
			${this.tags.map(
 | 
			
		||||
				(x) => html`<tf-tag tag=${x.tag} count=${x.count}></tf-tag>`
 | 
			
		||||
			)}
 | 
			
		||||
			${contents}
 | 
			
		||||
			<div
 | 
			
		||||
				style="width: 100vw; min-height: 100vh; height: 100%"
 | 
			
		||||
				class="w3-theme-dark"
 | 
			
		||||
			>
 | 
			
		||||
				${tabs}
 | 
			
		||||
				<div style="padding: 8px">
 | 
			
		||||
					${this.tags.map(
 | 
			
		||||
						(x) => html`<tf-tag tag=${x.tag} count=${x.count}></tf-tag>`
 | 
			
		||||
					)}
 | 
			
		||||
					${contents}
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		`;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import {LitElement, html, unsafeHTML} from './lit-all.min.js';
 | 
			
		||||
import {LitElement, html, unsafeHTML, live} from './lit-all.min.js';
 | 
			
		||||
import * as tfutils from './tf-utils.js';
 | 
			
		||||
import * as tfrpc from '/static/tfrpc.js';
 | 
			
		||||
import {styles} from './tf-styles.js';
 | 
			
		||||
@@ -13,6 +13,7 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
			branch: {type: String},
 | 
			
		||||
			apps: {type: Object},
 | 
			
		||||
			drafts: {type: Object},
 | 
			
		||||
			author: {type: String},
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -25,6 +26,7 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
		this.branch = undefined;
 | 
			
		||||
		this.apps = undefined;
 | 
			
		||||
		this.drafts = {};
 | 
			
		||||
		this.author = undefined;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	process_text(text) {
 | 
			
		||||
@@ -64,7 +66,7 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
			updated = true;
 | 
			
		||||
		}
 | 
			
		||||
		if (updated) {
 | 
			
		||||
			this.requestUpdate();
 | 
			
		||||
			setTimeout(() => this.notify(draft), 0);
 | 
			
		||||
		}
 | 
			
		||||
		return tfutils.markdown(text);
 | 
			
		||||
	}
 | 
			
		||||
@@ -72,7 +74,7 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
	input(event) {
 | 
			
		||||
		let edit = this.renderRoot.getElementById('edit');
 | 
			
		||||
		let preview = this.renderRoot.getElementById('preview');
 | 
			
		||||
		preview.innerHTML = this.process_text(edit.value);
 | 
			
		||||
		preview.innerHTML = this.process_text(edit.innerText);
 | 
			
		||||
		let content_warning = this.renderRoot.getElementById('content_warning');
 | 
			
		||||
		let content_warning_preview = this.renderRoot.getElementById(
 | 
			
		||||
			'content_warning_preview'
 | 
			
		||||
@@ -80,6 +82,10 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
		if (content_warning && content_warning_preview) {
 | 
			
		||||
			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) {
 | 
			
		||||
@@ -95,14 +101,6 @@ 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) {
 | 
			
		||||
		return new Promise(function (resolve, reject) {
 | 
			
		||||
			let img = new Image();
 | 
			
		||||
@@ -169,8 +167,7 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
				size: buffer.length ?? buffer.byteLength,
 | 
			
		||||
			};
 | 
			
		||||
			let edit = self.renderRoot.getElementById('edit');
 | 
			
		||||
			edit.value += `\n`;
 | 
			
		||||
			self.change();
 | 
			
		||||
			edit.innerText += `\n`;
 | 
			
		||||
			self.input();
 | 
			
		||||
		} catch (e) {
 | 
			
		||||
			alert(e?.message);
 | 
			
		||||
@@ -197,7 +194,7 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
		let edit = this.renderRoot.getElementById('edit');
 | 
			
		||||
		let message = {
 | 
			
		||||
			type: 'post',
 | 
			
		||||
			text: edit.value,
 | 
			
		||||
			text: edit.innerText,
 | 
			
		||||
		};
 | 
			
		||||
		if (this.root || this.branch) {
 | 
			
		||||
			message.root = this.root;
 | 
			
		||||
@@ -225,8 +222,8 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
		}
 | 
			
		||||
		try {
 | 
			
		||||
			await tfrpc.rpc.appendMessage(this.whoami, message).then(function () {
 | 
			
		||||
				edit.value = '';
 | 
			
		||||
				self.change();
 | 
			
		||||
				edit.innerText = '';
 | 
			
		||||
				self.input();
 | 
			
		||||
				self.notify(undefined);
 | 
			
		||||
				self.requestUpdate();
 | 
			
		||||
			});
 | 
			
		||||
@@ -236,17 +233,11 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	discard() {
 | 
			
		||||
		let edit = this.renderRoot.getElementById('edit');
 | 
			
		||||
		edit.value = '';
 | 
			
		||||
		this.change();
 | 
			
		||||
		let preview = this.renderRoot.getElementById('preview');
 | 
			
		||||
		preview.innerHTML = '';
 | 
			
		||||
		this.notify(undefined);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	attach() {
 | 
			
		||||
		let self = this;
 | 
			
		||||
		let edit = this.renderRoot.getElementById('edit');
 | 
			
		||||
		let input = document.createElement('input');
 | 
			
		||||
		input.type = 'file';
 | 
			
		||||
		input.onchange = function (event) {
 | 
			
		||||
@@ -284,22 +275,34 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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({
 | 
			
		||||
			collection: [
 | 
			
		||||
				{
 | 
			
		||||
					values: Object.entries(this.users).map((x) => ({
 | 
			
		||||
						key: x[1].name,
 | 
			
		||||
						value: x[0],
 | 
			
		||||
					})),
 | 
			
		||||
					values: values,
 | 
			
		||||
					selectTemplate: function (item) {
 | 
			
		||||
						return `[@${item.original.key}](${item.original.value})`;
 | 
			
		||||
						return item ? `[@${item.original.key}](${item.original.value})` : undefined;
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					trigger: '&',
 | 
			
		||||
					values: this.autocomplete,
 | 
			
		||||
					selectTemplate: function (item) {
 | 
			
		||||
						return ``;
 | 
			
		||||
						return item ? `` : undefined;
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			],
 | 
			
		||||
@@ -310,10 +313,10 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
	updated() {
 | 
			
		||||
		super.updated();
 | 
			
		||||
		let edit = this.renderRoot.getElementById('edit');
 | 
			
		||||
		if (this.last_updated_text !== edit.value) {
 | 
			
		||||
		if (this.last_updated_text !== edit.innerText) {
 | 
			
		||||
			let preview = this.renderRoot.getElementById('preview');
 | 
			
		||||
			preview.innerHTML = this.process_text(edit.value);
 | 
			
		||||
			this.last_updated_text = edit.value;
 | 
			
		||||
			preview.innerHTML = this.process_text(edit.innerText);
 | 
			
		||||
			this.last_updated_text = edit.innerText;
 | 
			
		||||
		}
 | 
			
		||||
		let encrypt = this.renderRoot.getElementById('encrypt_to');
 | 
			
		||||
		if (encrypt) {
 | 
			
		||||
@@ -333,8 +336,7 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
	remove_mention(id) {
 | 
			
		||||
		let draft = this.get_draft();
 | 
			
		||||
		delete draft.mentions[id];
 | 
			
		||||
		this.notify(draft);
 | 
			
		||||
		this.requestUpdate();
 | 
			
		||||
		setTimeout(() => this.notify(), 0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	render_mention(mention) {
 | 
			
		||||
@@ -342,7 +344,7 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
		return html` <div style="display: flex; flex-direction: row">
 | 
			
		||||
			<div style="align-self: center; margin: 0.5em">
 | 
			
		||||
				<button
 | 
			
		||||
					class="w3-button w3-dark-grey"
 | 
			
		||||
					class="w3-button w3-theme-d1"
 | 
			
		||||
					title="Remove ${mention.name} mention"
 | 
			
		||||
					@click=${() => self.remove_mention(mention.link)}
 | 
			
		||||
				>
 | 
			
		||||
@@ -396,16 +398,16 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
		if (this.apps) {
 | 
			
		||||
			return html`
 | 
			
		||||
				<div class="w3-card-4 w3-margin w3-padding">
 | 
			
		||||
					<select id="select" class="w3-select w3-dark-grey">
 | 
			
		||||
					<select id="select" class="w3-select w3-theme-d1">
 | 
			
		||||
						${Object.keys(self.apps).map(
 | 
			
		||||
							(app) => html`<option value=${app}>${app}</option>`
 | 
			
		||||
						)}
 | 
			
		||||
					</select>
 | 
			
		||||
					<button class="w3-button w3-dark-grey" @click=${attach_selected_app}>
 | 
			
		||||
					<button class="w3-button w3-theme-d1" @click=${attach_selected_app}>
 | 
			
		||||
						Attach
 | 
			
		||||
					</button>
 | 
			
		||||
					<button
 | 
			
		||||
						class="w3-button w3-dark-grey"
 | 
			
		||||
						class="w3-button w3-theme-d1"
 | 
			
		||||
						@click=${() => (this.apps = null)}
 | 
			
		||||
					>
 | 
			
		||||
						Cancel
 | 
			
		||||
@@ -421,12 +423,12 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
			self.apps = await tfrpc.rpc.apps();
 | 
			
		||||
		}
 | 
			
		||||
		if (!this.apps) {
 | 
			
		||||
			return html`<button class="w3-button w3-dark-grey" @click=${attach_app}>
 | 
			
		||||
			return html`<button class="w3-button w3-theme-d1" @click=${attach_app}>
 | 
			
		||||
				Attach App
 | 
			
		||||
			</button>`;
 | 
			
		||||
		} else {
 | 
			
		||||
			return html`<button
 | 
			
		||||
				class="w3-button w3-dark-grey"
 | 
			
		||||
				class="w3-button w3-theme-d1"
 | 
			
		||||
				@click=${() => (this.apps = null)}
 | 
			
		||||
			>
 | 
			
		||||
				Discard App
 | 
			
		||||
@@ -448,15 +450,15 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
			return html`
 | 
			
		||||
				<div class="w3-container w3-padding">
 | 
			
		||||
					<p>
 | 
			
		||||
						<input type="checkbox" class="w3-check w3-dark-grey" id="cw" @change=${() => self.set_content_warning(undefined)} checked="checked"></input>
 | 
			
		||||
						<input type="checkbox" class="w3-check w3-theme-d1" id="cw" @change=${() => self.set_content_warning(undefined)} checked="checked"></input>
 | 
			
		||||
						<label for="cw">CW</label>
 | 
			
		||||
					</p>
 | 
			
		||||
					<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>
 | 
			
		||||
					<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>
 | 
			
		||||
				</div>
 | 
			
		||||
			`;
 | 
			
		||||
		} else {
 | 
			
		||||
			return html`
 | 
			
		||||
				<input type="checkbox" class="w3-check w3-dark-grey" id="cw" @change=${() => self.set_content_warning('')}></input>
 | 
			
		||||
				<input type="checkbox" class="w3-check w3-theme-d1" id="cw" @change=${() => self.set_content_warning('')}></input>
 | 
			
		||||
				<label for="cw">CW</label>
 | 
			
		||||
			`;
 | 
			
		||||
		}
 | 
			
		||||
@@ -486,14 +488,14 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
			<div style="display: flex; flex-direction: row; width: 100%">
 | 
			
		||||
				<label for="encrypt_to">🔐 To:</label>
 | 
			
		||||
				<input type="text" id="encrypt_to" style="display: flex; flex: 1 1" @input=${this.update_encrypt}></input>
 | 
			
		||||
				<button class="w3-button w3-dark-grey" @click=${() => this.set_encrypt(undefined)}>🚮</button>
 | 
			
		||||
				<button class="w3-button w3-theme-d1" @click=${() => this.set_encrypt(undefined)}>🚮</button>
 | 
			
		||||
			</div>
 | 
			
		||||
			<ul>
 | 
			
		||||
				${draft.encrypt_to.map(
 | 
			
		||||
					(x) => html`
 | 
			
		||||
					<li>
 | 
			
		||||
						<tf-user id=${x} .users=${this.users}></tf-user>
 | 
			
		||||
						<input type="button" class="w3-button w3-dark-grey" value="🚮" @click=${() => this.set_encrypt(draft.encrypt_to.filter((id) => id != x))}></input>
 | 
			
		||||
						<input type="button" class="w3-button w3-theme-d1" value="🚮" @click=${() => this.set_encrypt(draft.encrypt_to.filter((id) => id != x))}></input>
 | 
			
		||||
					</li>`
 | 
			
		||||
				)}
 | 
			
		||||
			</ul>
 | 
			
		||||
@@ -512,7 +514,7 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
		let draft = self.get_draft();
 | 
			
		||||
		let content_warning =
 | 
			
		||||
			draft.content_warning !== undefined
 | 
			
		||||
				? html`<div class="w3-panel w3-round-xlarge w3-blue">
 | 
			
		||||
				? html`<div class="w3-panel w3-round-xlarge w3-theme-d2">
 | 
			
		||||
						<p id="content_warning_preview">${draft.content_warning}</p>
 | 
			
		||||
					</div>`
 | 
			
		||||
				: undefined;
 | 
			
		||||
@@ -520,34 +522,31 @@ class TfComposeElement extends LitElement {
 | 
			
		||||
			draft.encrypt_to !== undefined
 | 
			
		||||
				? undefined
 | 
			
		||||
				: html`<button
 | 
			
		||||
						class="w3-button w3-dark-grey"
 | 
			
		||||
						class="w3-button w3-theme-d1"
 | 
			
		||||
						@click=${() => this.set_encrypt([])}
 | 
			
		||||
					>
 | 
			
		||||
						🔐
 | 
			
		||||
					</button>`;
 | 
			
		||||
		let result = html`
 | 
			
		||||
			<div
 | 
			
		||||
				class="w3-card-4 w3-blue-grey w3-padding"
 | 
			
		||||
				class="w3-card-4 w3-theme-d4 w3-padding-small"
 | 
			
		||||
				style="box-sizing: border-box"
 | 
			
		||||
			>
 | 
			
		||||
				${this.render_encrypt()}
 | 
			
		||||
				<div style="display: flex; flex-direction: row; width: 100%; gap: 4px">
 | 
			
		||||
					<div style="flex: 1 0 50%">
 | 
			
		||||
						<p>
 | 
			
		||||
							<textarea
 | 
			
		||||
								class="w3-input w3-dark-grey w3-border"
 | 
			
		||||
								style="resize: vertical"
 | 
			
		||||
								placeholder="Write a post here."
 | 
			
		||||
								id="edit"
 | 
			
		||||
								@input=${this.input}
 | 
			
		||||
								@change=${this.change}
 | 
			
		||||
								@paste=${this.paste}
 | 
			
		||||
							>
 | 
			
		||||
${draft.text}</textarea
 | 
			
		||||
							>
 | 
			
		||||
						</p>
 | 
			
		||||
				<div class="w3-container w3-padding-small">
 | 
			
		||||
					<div class="w3-half">
 | 
			
		||||
						<span
 | 
			
		||||
							class="w3-input w3-theme-d1 w3-border"
 | 
			
		||||
							style="resize: vertical; width: 100%; overflow: hidden; white-space: pre-wrap"
 | 
			
		||||
							placeholder="Write a post here."
 | 
			
		||||
							id="edit"
 | 
			
		||||
							@input=${this.input}
 | 
			
		||||
							@paste=${this.paste}
 | 
			
		||||
							contenteditable
 | 
			
		||||
							.innerText=${live(draft.text ?? '')}
 | 
			
		||||
							></span>
 | 
			
		||||
					</div>
 | 
			
		||||
					<div style="flex: 1 0 50%">
 | 
			
		||||
					<div class="w3-half w3-padding">
 | 
			
		||||
						${content_warning}
 | 
			
		||||
						<div id="preview"></div>
 | 
			
		||||
					</div>
 | 
			
		||||
@@ -556,18 +555,14 @@ ${draft.text}</textarea
 | 
			
		||||
					self.render_mention(x)
 | 
			
		||||
				)}
 | 
			
		||||
				${this.render_attach_app()} ${this.render_content_warning()}
 | 
			
		||||
				<button
 | 
			
		||||
					class="w3-button w3-dark-grey"
 | 
			
		||||
					id="submit"
 | 
			
		||||
					@click=${this.submit}
 | 
			
		||||
				>
 | 
			
		||||
				<button class="w3-button w3-theme-d1" id="submit" @click=${this.submit}>
 | 
			
		||||
					Submit
 | 
			
		||||
				</button>
 | 
			
		||||
				<button class="w3-button w3-dark-grey" @click=${this.attach}>
 | 
			
		||||
				<button class="w3-button w3-theme-d1" @click=${this.attach}>
 | 
			
		||||
					Attach
 | 
			
		||||
				</button>
 | 
			
		||||
				${this.render_attach_app_button()} ${encrypt}
 | 
			
		||||
				<button class="w3-button w3-dark-grey" @click=${this.discard}>
 | 
			
		||||
				<button class="w3-button w3-theme-d1" @click=${this.discard}>
 | 
			
		||||
					Discard
 | 
			
		||||
				</button>
 | 
			
		||||
			</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,54 +0,0 @@
 | 
			
		||||
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, unsafeHTML} from './lit-all.min.js';
 | 
			
		||||
import {LitElement, html, render, unsafeHTML} from './lit-all.min.js';
 | 
			
		||||
import * as tfrpc from '/static/tfrpc.js';
 | 
			
		||||
import * as tfutils from './tf-utils.js';
 | 
			
		||||
import * as emojis from './emojis.js';
 | 
			
		||||
@@ -54,6 +54,12 @@ class TfMessageElement extends LitElement {
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	show_reactions() {
 | 
			
		||||
		let modal = document.getElementById('reactions_modal');
 | 
			
		||||
		modal.users = this.users;
 | 
			
		||||
		modal.votes = this.message?.votes || [];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	render_votes() {
 | 
			
		||||
		function normalize_expression(expression) {
 | 
			
		||||
			if (expression === 'Like' || !expression) {
 | 
			
		||||
@@ -66,19 +72,21 @@ class TfMessageElement extends LitElement {
 | 
			
		||||
				return expression;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return html`<div>
 | 
			
		||||
			${(this.message.votes || []).map(
 | 
			
		||||
				(vote) => html`
 | 
			
		||||
					<span
 | 
			
		||||
						title="${this.users[vote.author]?.name ?? vote.author} ${new Date(
 | 
			
		||||
							vote.timestamp
 | 
			
		||||
						)}"
 | 
			
		||||
					>
 | 
			
		||||
						${normalize_expression(vote.content.vote.expression)}
 | 
			
		||||
					</span>
 | 
			
		||||
				`
 | 
			
		||||
			)}
 | 
			
		||||
		</div>`;
 | 
			
		||||
		if (this.message?.votes?.length) {
 | 
			
		||||
			return html`<div class="w3-button" @click=${this.show_reactions}>
 | 
			
		||||
				${(this.message.votes || []).map(
 | 
			
		||||
					(vote) => html`
 | 
			
		||||
						<span
 | 
			
		||||
							title="${this.users[vote.author]?.name ?? vote.author} ${new Date(
 | 
			
		||||
								vote.timestamp
 | 
			
		||||
							)}"
 | 
			
		||||
						>
 | 
			
		||||
							${normalize_expression(vote.content.vote.expression)}
 | 
			
		||||
						</span>
 | 
			
		||||
					`
 | 
			
		||||
				)}
 | 
			
		||||
			</div>`;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	render_raw() {
 | 
			
		||||
@@ -125,7 +133,7 @@ class TfMessageElement extends LitElement {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	react(event) {
 | 
			
		||||
		emojis.picker((x) => this.vote(x));
 | 
			
		||||
		emojis.picker((x) => this.vote(x), null, this.whoami);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	show_image(link) {
 | 
			
		||||
@@ -240,7 +248,7 @@ ${JSON.stringify(mention, null, 2)}</pre
 | 
			
		||||
			let self = this;
 | 
			
		||||
			return html`
 | 
			
		||||
				<fieldset
 | 
			
		||||
					style="background-color: rgba(0, 0, 0, 0.1); padding: 0.5em; border: 1px solid black"
 | 
			
		||||
					style="padding: 0.5em; border: 1px solid black"
 | 
			
		||||
				>
 | 
			
		||||
					<legend>Mentions</legend>
 | 
			
		||||
					${mentions.map((x) => self.render_mention(x))}
 | 
			
		||||
@@ -282,14 +290,14 @@ ${JSON.stringify(mention, null, 2)}</pre
 | 
			
		||||
		if (this.message.child_messages?.length) {
 | 
			
		||||
			if (!this.expanded[this.message.id]) {
 | 
			
		||||
				return html`<button
 | 
			
		||||
					class="w3-button w3-dark-grey"
 | 
			
		||||
					class="w3-button w3-theme-d1"
 | 
			
		||||
					@click=${() => self.set_expanded(true)}
 | 
			
		||||
				>
 | 
			
		||||
					+ ${this.total_child_messages(this.message) + ' More'}
 | 
			
		||||
				</button>`;
 | 
			
		||||
			} else {
 | 
			
		||||
				return html`<button
 | 
			
		||||
						class="w3-button w3-dark-grey"
 | 
			
		||||
						class="w3-button w3-theme-d1"
 | 
			
		||||
						@click=${() => self.set_expanded(false)}
 | 
			
		||||
					>
 | 
			
		||||
						Collapse</button
 | 
			
		||||
@@ -331,20 +339,23 @@ ${JSON.stringify(mention, null, 2)}</pre
 | 
			
		||||
		if (this.message?.decrypted?.type == 'post') {
 | 
			
		||||
			content = this.message.decrypted;
 | 
			
		||||
		}
 | 
			
		||||
		let class_background = this.message?.decrypted
 | 
			
		||||
			? 'w3-pale-red'
 | 
			
		||||
			: 'w3-theme-d4';
 | 
			
		||||
		let self = this;
 | 
			
		||||
		let raw_button;
 | 
			
		||||
		switch (this.format) {
 | 
			
		||||
			case 'raw':
 | 
			
		||||
				if (content?.type == 'post' || content?.type == 'blog') {
 | 
			
		||||
					raw_button = html`<button
 | 
			
		||||
						class="w3-button w3-dark-grey"
 | 
			
		||||
						class="w3-button w3-theme-d1"
 | 
			
		||||
						@click=${() => (self.format = 'md')}
 | 
			
		||||
					>
 | 
			
		||||
						Markdown
 | 
			
		||||
					</button>`;
 | 
			
		||||
				} else {
 | 
			
		||||
					raw_button = html`<button
 | 
			
		||||
						class="w3-button w3-dark-grey"
 | 
			
		||||
						class="w3-button w3-theme-d1"
 | 
			
		||||
						@click=${() => (self.format = 'message')}
 | 
			
		||||
					>
 | 
			
		||||
						Message
 | 
			
		||||
@@ -353,7 +364,7 @@ ${JSON.stringify(mention, null, 2)}</pre
 | 
			
		||||
				break;
 | 
			
		||||
			case 'md':
 | 
			
		||||
				raw_button = html`<button
 | 
			
		||||
					class="w3-button w3-dark-grey"
 | 
			
		||||
					class="w3-button w3-theme-d1"
 | 
			
		||||
					@click=${() => (self.format = 'message')}
 | 
			
		||||
				>
 | 
			
		||||
					Message
 | 
			
		||||
@@ -361,7 +372,7 @@ ${JSON.stringify(mention, null, 2)}</pre
 | 
			
		||||
				break;
 | 
			
		||||
			case 'decrypted':
 | 
			
		||||
				raw_button = html`<button
 | 
			
		||||
					class="w3-button w3-dark-grey"
 | 
			
		||||
					class="w3-button w3-theme-d1"
 | 
			
		||||
					@click=${() => (self.format = 'raw')}
 | 
			
		||||
				>
 | 
			
		||||
					Raw
 | 
			
		||||
@@ -370,14 +381,14 @@ ${JSON.stringify(mention, null, 2)}</pre
 | 
			
		||||
			default:
 | 
			
		||||
				if (this.message.decrypted) {
 | 
			
		||||
					raw_button = html`<button
 | 
			
		||||
						class="w3-button w3-dark-grey"
 | 
			
		||||
						class="w3-button w3-theme-d1"
 | 
			
		||||
						@click=${() => (self.format = 'decrypted')}
 | 
			
		||||
					>
 | 
			
		||||
						Decrypted
 | 
			
		||||
					</button>`;
 | 
			
		||||
				} else {
 | 
			
		||||
					raw_button = html`<button
 | 
			
		||||
						class="w3-button w3-dark-grey"
 | 
			
		||||
						class="w3-button w3-theme-d1"
 | 
			
		||||
						@click=${() => (self.format = 'raw')}
 | 
			
		||||
					>
 | 
			
		||||
						Raw
 | 
			
		||||
@@ -389,8 +400,8 @@ ${JSON.stringify(mention, null, 2)}</pre
 | 
			
		||||
			let body;
 | 
			
		||||
			return html`
 | 
			
		||||
				<div
 | 
			
		||||
					class="w3-card-4"
 | 
			
		||||
					style="background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px; display: inline-block; overflow-wrap: anywhere"
 | 
			
		||||
					class="w3-card-4 w3-theme-d4 w3-border-theme"
 | 
			
		||||
					style="margin-top: 8px; padding: 16px; display: inline-block; overflow-wrap: anywhere"
 | 
			
		||||
				>
 | 
			
		||||
					<tf-user id=${self.message.author} .users=${self.users}></tf-user>
 | 
			
		||||
					<span style="padding-right: 8px"
 | 
			
		||||
@@ -400,13 +411,24 @@ ${JSON.stringify(mention, null, 2)}</pre
 | 
			
		||||
					>
 | 
			
		||||
					${raw_button} ${self.format == 'raw' ? self.render_raw() : inner}
 | 
			
		||||
					${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>
 | 
			
		||||
			`;
 | 
			
		||||
		}
 | 
			
		||||
		if (this.message?.type === 'contact_group') {
 | 
			
		||||
			return html` <div
 | 
			
		||||
				class="w3-card-4"
 | 
			
		||||
				style="border: 1px solid black; background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px; overflow-wrap: anywhere"
 | 
			
		||||
				class="w3-card-4 w3-theme-d4 w3-border-theme"
 | 
			
		||||
				style="margin-top: 8px; padding: 16px; overflow-wrap: anywhere"
 | 
			
		||||
			>
 | 
			
		||||
				${this.message.messages.map(
 | 
			
		||||
					(x) =>
 | 
			
		||||
@@ -421,8 +443,8 @@ ${JSON.stringify(mention, null, 2)}</pre
 | 
			
		||||
			</div>`;
 | 
			
		||||
		} else if (this.message.placeholder) {
 | 
			
		||||
			return html` <div
 | 
			
		||||
				class="w3-card-4"
 | 
			
		||||
				style="border: 1px solid black; background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px; overflow-wrap: anywhere"
 | 
			
		||||
				class="w3-card-4 w3-theme-d4 w3-border-theme"
 | 
			
		||||
				style="margin-top: 8px; padding: 16px; overflow-wrap: anywhere"
 | 
			
		||||
			>
 | 
			
		||||
				<a target="_top" href=${'#' + this.message.id}>${this.message.id}</a>
 | 
			
		||||
				(placeholder)
 | 
			
		||||
@@ -498,13 +520,11 @@ ${JSON.stringify(mention, null, 2)}</pre
 | 
			
		||||
									branch=${this.message.id}
 | 
			
		||||
									.drafts=${this.drafts}
 | 
			
		||||
									@tf-discard=${this.discard_reply}
 | 
			
		||||
									author=${this.message.author}
 | 
			
		||||
								></tf-compose>
 | 
			
		||||
							`
 | 
			
		||||
						: html`
 | 
			
		||||
								<button
 | 
			
		||||
									class="w3-button w3-dark-grey"
 | 
			
		||||
									@click=${this.show_reply}
 | 
			
		||||
								>
 | 
			
		||||
								<button class="w3-button w3-theme-d1" @click=${this.show_reply}>
 | 
			
		||||
									Reply
 | 
			
		||||
								</button>
 | 
			
		||||
							`;
 | 
			
		||||
@@ -533,7 +553,7 @@ ${JSON.stringify(content, null, 2)}</pre
 | 
			
		||||
				}
 | 
			
		||||
				let content_warning = html`
 | 
			
		||||
					<div
 | 
			
		||||
						class="w3-panel w3-round-xlarge w3-blue"
 | 
			
		||||
						class="w3-panel w3-round-xlarge w3-theme-l4"
 | 
			
		||||
						style="cursor: pointer"
 | 
			
		||||
						@click=${(x) => this.toggle_expanded(':cw')}
 | 
			
		||||
					>
 | 
			
		||||
@@ -553,9 +573,6 @@ ${JSON.stringify(content, null, 2)}</pre
 | 
			
		||||
				let is_encrypted = this.message?.decrypted
 | 
			
		||||
					? html`<span style="align-self: center">🔓</span>`
 | 
			
		||||
					: undefined;
 | 
			
		||||
				let style_background = this.message?.decrypted
 | 
			
		||||
					? 'rgba(255, 0, 0, 0.2)'
 | 
			
		||||
					: 'rgba(255, 255, 255, 0.1)';
 | 
			
		||||
				return html`
 | 
			
		||||
					<style>
 | 
			
		||||
						code {
 | 
			
		||||
@@ -572,8 +589,8 @@ ${JSON.stringify(content, null, 2)}</pre
 | 
			
		||||
						}
 | 
			
		||||
					</style>
 | 
			
		||||
					<div
 | 
			
		||||
						class="w3-card-4"
 | 
			
		||||
						style="border: 1px solid black; background-color: ${style_background}; margin-top: 8px; padding: 16px"
 | 
			
		||||
						class="w3-card-4 ${class_background} w3-border-theme"
 | 
			
		||||
						style="margin-top: 8px; padding: 16px"
 | 
			
		||||
					>
 | 
			
		||||
						<div style="display: flex; flex-direction: row">
 | 
			
		||||
							<tf-user id=${this.message.author} .users=${this.users}></tf-user>
 | 
			
		||||
@@ -588,7 +605,7 @@ ${JSON.stringify(content, null, 2)}</pre
 | 
			
		||||
						${payload} ${this.render_votes()}
 | 
			
		||||
						<p>
 | 
			
		||||
							${reply}
 | 
			
		||||
							<button class="w3-button w3-dark-grey" @click=${this.react}>
 | 
			
		||||
							<button class="w3-button w3-theme-d1" @click=${this.react}>
 | 
			
		||||
								React
 | 
			
		||||
							</button>
 | 
			
		||||
						</p>
 | 
			
		||||
@@ -599,9 +616,6 @@ ${JSON.stringify(content, null, 2)}</pre
 | 
			
		||||
				let is_encrypted = this.message?.decrypted
 | 
			
		||||
					? html`<span style="align-self: center">🔓</span>`
 | 
			
		||||
					: undefined;
 | 
			
		||||
				let style_background = this.message?.decrypted
 | 
			
		||||
					? 'rgba(255, 0, 0, 0.2)'
 | 
			
		||||
					: 'rgba(255, 255, 255, 0.1)';
 | 
			
		||||
				return html`
 | 
			
		||||
					<style>
 | 
			
		||||
						code {
 | 
			
		||||
@@ -618,8 +632,8 @@ ${JSON.stringify(content, null, 2)}</pre
 | 
			
		||||
						}
 | 
			
		||||
					</style>
 | 
			
		||||
					<div
 | 
			
		||||
						class="w3-card-4"
 | 
			
		||||
						style="border: 1px solid black; background-color: ${style_background}; margin-top: 8px; padding: 16px"
 | 
			
		||||
						class="w3-card-4 ${class_background} w3-border-theme"
 | 
			
		||||
						style="margin-top: 8px; padding: 16px"
 | 
			
		||||
					>
 | 
			
		||||
						<div style="display: flex; flex-direction: row">
 | 
			
		||||
							<tf-user id=${this.message.author} .users=${this.users}></tf-user>
 | 
			
		||||
@@ -633,7 +647,7 @@ ${JSON.stringify(content, null, 2)}</pre
 | 
			
		||||
						</div>
 | 
			
		||||
						${content.text} ${this.render_votes()}
 | 
			
		||||
						<p>
 | 
			
		||||
							<button class="w3-button w3-dark-grey" @click=${this.react}>
 | 
			
		||||
							<button class="w3-button w3-theme-d1" @click=${this.react}>
 | 
			
		||||
								React
 | 
			
		||||
							</button>
 | 
			
		||||
						</p>
 | 
			
		||||
@@ -685,13 +699,11 @@ ${JSON.stringify(content, null, 2)}</pre
 | 
			
		||||
									branch=${this.message.id}
 | 
			
		||||
									.drafts=${this.drafts}
 | 
			
		||||
									@tf-discard=${this.discard_reply}
 | 
			
		||||
									author=${this.message.author}
 | 
			
		||||
								></tf-compose>
 | 
			
		||||
							`
 | 
			
		||||
						: html`
 | 
			
		||||
								<button
 | 
			
		||||
									class="w3-button w3-dark-grey"
 | 
			
		||||
									@click=${this.show_reply}
 | 
			
		||||
								>
 | 
			
		||||
								<button class="w3-button w3-theme-d1" @click=${this.show_reply}>
 | 
			
		||||
									Reply
 | 
			
		||||
								</button>
 | 
			
		||||
							`;
 | 
			
		||||
@@ -711,8 +723,8 @@ ${JSON.stringify(content, null, 2)}</pre
 | 
			
		||||
						}
 | 
			
		||||
					</style>
 | 
			
		||||
					<div
 | 
			
		||||
						class="w3-card-4"
 | 
			
		||||
						style="border: 1px solid black; background-color: rgba(255, 255, 255, 0.1); margin-top: 8px; padding: 16px"
 | 
			
		||||
						class="w3-card-4 w3-theme-d4 w3-border-theme"
 | 
			
		||||
						style="margin-top: 8px; padding: 16px"
 | 
			
		||||
					>
 | 
			
		||||
						<div style="display: flex; flex-direction: row">
 | 
			
		||||
							<tf-user id=${this.message.author} .users=${this.users}></tf-user>
 | 
			
		||||
@@ -728,7 +740,7 @@ ${JSON.stringify(content, null, 2)}</pre
 | 
			
		||||
						${this.render_mentions()}
 | 
			
		||||
						<div>
 | 
			
		||||
							${reply}
 | 
			
		||||
							<button class="w3-button w3-dark-grey" @click=${this.react}>
 | 
			
		||||
							<button class="w3-button w3-theme-d1" @click=${this.react}>
 | 
			
		||||
								React
 | 
			
		||||
							</button>
 | 
			
		||||
						</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -215,49 +215,49 @@ class TfProfileElement extends LitElement {
 | 
			
		||||
				let server_follow;
 | 
			
		||||
				if (this.server_follows_me === true) {
 | 
			
		||||
					server_follow = html`<button
 | 
			
		||||
						class="w3-button w3-dark-grey"
 | 
			
		||||
						class="w3-button w3-theme-d1"
 | 
			
		||||
						@click=${() => this.server_follow_me(false)}
 | 
			
		||||
					>
 | 
			
		||||
						Server, Stop Following Me
 | 
			
		||||
					</button>`;
 | 
			
		||||
				} else if (this.server_follows_me === false) {
 | 
			
		||||
					server_follow = html`<button
 | 
			
		||||
						class="w3-button w3-dark-grey"
 | 
			
		||||
						class="w3-button w3-theme-d1"
 | 
			
		||||
						@click=${() => this.server_follow_me(true)}
 | 
			
		||||
					>
 | 
			
		||||
						Server, Follow Me
 | 
			
		||||
					</button>`;
 | 
			
		||||
				}
 | 
			
		||||
				edit = html`
 | 
			
		||||
					<button class="w3-button w3-dark-grey" @click=${this.save_edits}>
 | 
			
		||||
					<button class="w3-button w3-theme-d1" @click=${this.save_edits}>
 | 
			
		||||
						Save Profile
 | 
			
		||||
					</button>
 | 
			
		||||
					<button class="w3-button w3-dark-grey" @click=${this.discard_edits}>
 | 
			
		||||
					<button class="w3-button w3-theme-d1" @click=${this.discard_edits}>
 | 
			
		||||
						Discard
 | 
			
		||||
					</button>
 | 
			
		||||
					${server_follow}
 | 
			
		||||
				`;
 | 
			
		||||
			} else {
 | 
			
		||||
				edit = html`<button class="w3-button w3-dark-grey" @click=${this.edit}>
 | 
			
		||||
				edit = html`<button class="w3-button w3-theme-d1" @click=${this.edit}>
 | 
			
		||||
					Edit Profile
 | 
			
		||||
				</button>`;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (this.id !== this.whoami && this.following !== undefined) {
 | 
			
		||||
			follow = this.following
 | 
			
		||||
				? html`<button class="w3-button w3-dark-grey" @click=${this.unfollow}>
 | 
			
		||||
				? html`<button class="w3-button w3-theme-d1" @click=${this.unfollow}>
 | 
			
		||||
						Unfollow
 | 
			
		||||
					</button>`
 | 
			
		||||
				: html`<button class="w3-button w3-dark-grey" @click=${this.follow}>
 | 
			
		||||
				: html`<button class="w3-button w3-theme-d1" @click=${this.follow}>
 | 
			
		||||
						Follow
 | 
			
		||||
					</button>`;
 | 
			
		||||
		}
 | 
			
		||||
		if (this.id !== this.whoami && this.blocking !== undefined) {
 | 
			
		||||
			block = this.blocking
 | 
			
		||||
				? html`<button class="w3-button w3-dark-grey" @click=${this.unblock}>
 | 
			
		||||
				? html`<button class="w3-button w3-theme-d1" @click=${this.unblock}>
 | 
			
		||||
						Unblock
 | 
			
		||||
					</button>`
 | 
			
		||||
				: html`<button class="w3-button w3-dark-grey" @click=${this.block}>
 | 
			
		||||
				: html`<button class="w3-button w3-theme-d1" @click=${this.block}>
 | 
			
		||||
						Block
 | 
			
		||||
					</button>`;
 | 
			
		||||
		}
 | 
			
		||||
@@ -267,16 +267,16 @@ class TfProfileElement extends LitElement {
 | 
			
		||||
				<div class="w3-container">
 | 
			
		||||
					<div>
 | 
			
		||||
						<label for="name">Name:</label>
 | 
			
		||||
						<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>
 | 
			
		||||
						<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>
 | 
			
		||||
					</div>
 | 
			
		||||
					<div><label for="description">Description:</label></div>
 | 
			
		||||
					<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>
 | 
			
		||||
					<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>
 | 
			
		||||
					<div>
 | 
			
		||||
						<label for="public_web_hosting">Public Web Hosting:</label>
 | 
			
		||||
						<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>
 | 
			
		||||
						<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>
 | 
			
		||||
					</div>
 | 
			
		||||
					<div>
 | 
			
		||||
						<button class="w3-button w3-dark-grey" @click=${this.attach_image}>Attach Image</button>
 | 
			
		||||
						<button class="w3-button w3-theme-d1" @click=${this.attach_image}>Attach Image</button>
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>`
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										68
									
								
								apps/ssb/tf-reactions-modal.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								apps/ssb/tf-reactions-modal.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
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,9 +33,11 @@ class TfTabConnectionsElement extends LitElement {
 | 
			
		||||
 | 
			
		||||
	render_connection_summary(connection) {
 | 
			
		||||
		if (connection.address && connection.port) {
 | 
			
		||||
			return html`(<small>${connection.address}:${connection.port}</small>)`;
 | 
			
		||||
			return html`<div>
 | 
			
		||||
				<small>${connection.address}:${connection.port}</small>
 | 
			
		||||
			</div>`;
 | 
			
		||||
		} else if (connection.tunnel) {
 | 
			
		||||
			return html`(room peer)`;
 | 
			
		||||
			return html`<div>room peer</div>`;
 | 
			
		||||
		} else {
 | 
			
		||||
			return JSON.stringify(connection);
 | 
			
		||||
		}
 | 
			
		||||
@@ -61,7 +63,7 @@ class TfTabConnectionsElement extends LitElement {
 | 
			
		||||
		return html`
 | 
			
		||||
			<li>
 | 
			
		||||
				<button
 | 
			
		||||
					class="w3-button w3-dark-grey"
 | 
			
		||||
					class="w3-button w3-theme-d1"
 | 
			
		||||
					@click=${() => self._tunnel(connection.tunnel.id, connection.pubkey)}
 | 
			
		||||
				>
 | 
			
		||||
					Connect
 | 
			
		||||
@@ -73,15 +75,17 @@ class TfTabConnectionsElement extends LitElement {
 | 
			
		||||
 | 
			
		||||
	render_broadcast(connection) {
 | 
			
		||||
		return html`
 | 
			
		||||
			<li>
 | 
			
		||||
			<li class="w3-bar" style="overflow: hidden; overflow-wrap: nowrap">
 | 
			
		||||
				<button
 | 
			
		||||
					class="w3-button w3-dark-grey"
 | 
			
		||||
					class="w3-bar-item w3-button w3-theme-d1"
 | 
			
		||||
					@click=${() => tfrpc.rpc.connect(connection)}
 | 
			
		||||
				>
 | 
			
		||||
					Connect
 | 
			
		||||
				</button>
 | 
			
		||||
				<tf-user id=${connection.pubkey} .users=${this.users}></tf-user>
 | 
			
		||||
				${this.render_connection_summary(connection)}
 | 
			
		||||
				<div class="w3-bar-item">
 | 
			
		||||
					<tf-user id=${connection.pubkey} .users=${this.users}></tf-user>
 | 
			
		||||
					${this.render_connection_summary(connection)}
 | 
			
		||||
				</div>
 | 
			
		||||
			</li>
 | 
			
		||||
		`;
 | 
			
		||||
	}
 | 
			
		||||
@@ -94,7 +98,7 @@ class TfTabConnectionsElement extends LitElement {
 | 
			
		||||
	render_connection(connection) {
 | 
			
		||||
		return html`
 | 
			
		||||
			<button
 | 
			
		||||
				class="w3-button w3-dark-grey"
 | 
			
		||||
				class="w3-button w3-theme-d1"
 | 
			
		||||
				@click=${() => tfrpc.rpc.closeConnection(connection.id)}
 | 
			
		||||
			>
 | 
			
		||||
				Close
 | 
			
		||||
@@ -103,6 +107,9 @@ class TfTabConnectionsElement extends LitElement {
 | 
			
		||||
			${connection.tunnel !== undefined
 | 
			
		||||
				? '🚇'
 | 
			
		||||
				: 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>
 | 
			
		||||
				${this.connections
 | 
			
		||||
					.filter((x) => x.tunnel === this.connections.indexOf(connection))
 | 
			
		||||
@@ -115,56 +122,64 @@ class TfTabConnectionsElement extends LitElement {
 | 
			
		||||
	render() {
 | 
			
		||||
		let self = this;
 | 
			
		||||
		return html`
 | 
			
		||||
			<div class="w3-container">
 | 
			
		||||
			<div class="w3-container" style="box-sizing: border-box">
 | 
			
		||||
				<h2>New Connection</h2>
 | 
			
		||||
				<textarea class="w3-input w3-dark-grey" id="code"></textarea>
 | 
			
		||||
				<textarea class="w3-input w3-theme-d1" id="code"></textarea>
 | 
			
		||||
				<button
 | 
			
		||||
					class="w3-button w3-dark-grey"
 | 
			
		||||
					class="w3-button w3-theme-d1"
 | 
			
		||||
					@click=${() =>
 | 
			
		||||
						tfrpc.rpc.connect(self.renderRoot.getElementById('code').value)}
 | 
			
		||||
				>
 | 
			
		||||
					Connect
 | 
			
		||||
				</button>
 | 
			
		||||
				<h2>Broadcasts</h2>
 | 
			
		||||
				<ul>
 | 
			
		||||
				<ul class="w3-ul w3-border">
 | 
			
		||||
					${this.broadcasts
 | 
			
		||||
						.filter((x) => x.address)
 | 
			
		||||
						.map((x) => self.render_broadcast(x))}
 | 
			
		||||
				</ul>
 | 
			
		||||
				<h2>Connections</h2>
 | 
			
		||||
				<ul>
 | 
			
		||||
				<ul class="w3-ul w3-border">
 | 
			
		||||
					${this.connections
 | 
			
		||||
						.filter((x) => x.tunnel === undefined)
 | 
			
		||||
						.map((x) => html` <li>${this.render_connection(x)}</li> `)}
 | 
			
		||||
						.map(
 | 
			
		||||
							(x) => html`
 | 
			
		||||
								<li class="w3-bar">${this.render_connection(x)}</li>
 | 
			
		||||
							`
 | 
			
		||||
						)}
 | 
			
		||||
				</ul>
 | 
			
		||||
				<h2>Stored Connections (WIP)</h2>
 | 
			
		||||
				<ul>
 | 
			
		||||
				<h2>Stored Connections</h2>
 | 
			
		||||
				<ul class="w3-ul w3-border">
 | 
			
		||||
					${this.stored_connections.map(
 | 
			
		||||
						(x) => html`
 | 
			
		||||
							<li>
 | 
			
		||||
							<li class="w3-bar">
 | 
			
		||||
								<button
 | 
			
		||||
									class="w3-button w3-dark-grey"
 | 
			
		||||
									class="w3-bar-item w3-button w3-theme-d1"
 | 
			
		||||
									@click=${() => self.forget_stored_connection(x)}
 | 
			
		||||
								>
 | 
			
		||||
									Forget
 | 
			
		||||
								</button>
 | 
			
		||||
								<button
 | 
			
		||||
									class="w3-button w3-dark-grey"
 | 
			
		||||
									class="w3-bar-item w3-button w3-theme-d1"
 | 
			
		||||
									@click=${() => tfrpc.rpc.connect(x)}
 | 
			
		||||
								>
 | 
			
		||||
									Connect
 | 
			
		||||
								</button>
 | 
			
		||||
								${x.address}:${x.port}
 | 
			
		||||
								<tf-user id=${x.pubkey} .users=${self.users}></tf-user>
 | 
			
		||||
								<div class="w3-bar-item">
 | 
			
		||||
									<tf-user id=${x.pubkey} .users=${self.users}></tf-user>
 | 
			
		||||
									<div><small>${x.address}:${x.port}</small></div>
 | 
			
		||||
								</div>
 | 
			
		||||
							</li>
 | 
			
		||||
						`
 | 
			
		||||
					)}
 | 
			
		||||
				</ul>
 | 
			
		||||
				<h2>Local Accounts</h2>
 | 
			
		||||
				<ul>
 | 
			
		||||
				<ul class="w3-ul w3-border">
 | 
			
		||||
					${this.identities.map(
 | 
			
		||||
						(x) =>
 | 
			
		||||
							html`<li><tf-user id=${x} .users=${this.users}></tf-user></li>`
 | 
			
		||||
							html`<li class="w3-bar">
 | 
			
		||||
								<tf-user id=${x} .users=${this.users}></tf-user>
 | 
			
		||||
							</li>`
 | 
			
		||||
					)}
 | 
			
		||||
				</ul>
 | 
			
		||||
			</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -187,7 +187,7 @@ class TfTabNewsFeedElement extends LitElement {
 | 
			
		||||
		if (!this.hash.startsWith('#@') && !this.hash.startsWith('#%')) {
 | 
			
		||||
			more = html`
 | 
			
		||||
				<p>
 | 
			
		||||
					<button class="w3-button w3-dark-grey" @click=${this.load_more}>
 | 
			
		||||
					<button class="w3-button w3-theme-d1" @click=${this.load_more}>
 | 
			
		||||
						Load More
 | 
			
		||||
					</button>
 | 
			
		||||
				</p>
 | 
			
		||||
 
 | 
			
		||||
@@ -84,10 +84,7 @@ class TfTabNewsElement extends LitElement {
 | 
			
		||||
		} else {
 | 
			
		||||
			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));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -119,7 +116,7 @@ class TfTabNewsElement extends LitElement {
 | 
			
		||||
		return html`
 | 
			
		||||
			<p class="w3-bar">
 | 
			
		||||
				<button
 | 
			
		||||
					class="w3-bar-item w3-button w3-dark-grey"
 | 
			
		||||
					class="w3-bar-item w3-button w3-theme-d1"
 | 
			
		||||
					@click=${this.show_more}
 | 
			
		||||
				>
 | 
			
		||||
					${this.new_messages_text()}
 | 
			
		||||
 
 | 
			
		||||
@@ -110,14 +110,14 @@ class TfTabQueryElement extends LitElement {
 | 
			
		||||
				<textarea
 | 
			
		||||
					id="search"
 | 
			
		||||
					rows="8"
 | 
			
		||||
					class="w3-input w3-dark-grey"
 | 
			
		||||
					class="w3-input w3-theme-d1"
 | 
			
		||||
					style="flex: 1; resize: vertical"
 | 
			
		||||
					@keydown=${this.search_keydown}
 | 
			
		||||
				>
 | 
			
		||||
${this.query}</textarea
 | 
			
		||||
				>
 | 
			
		||||
				<button
 | 
			
		||||
					class="w3-button w3-dark-grey"
 | 
			
		||||
					class="w3-button w3-theme-d1"
 | 
			
		||||
					@click=${(event) =>
 | 
			
		||||
						self.search(self.renderRoot.getElementById('search').value)}
 | 
			
		||||
				>
 | 
			
		||||
 
 | 
			
		||||
@@ -78,8 +78,8 @@ class TfTabSearchElement extends LitElement {
 | 
			
		||||
		let self = this;
 | 
			
		||||
		return html`
 | 
			
		||||
			<div style="display: flex; flex-direction: row; gap: 4px">
 | 
			
		||||
				<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-dark-grey" @click=${(event) => self.search(self.renderRoot.getElementById('search').value)}>Search</button>
 | 
			
		||||
				<input type="text" class="w3-input w3-theme-d1" 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>
 | 
			
		||||
			</div>
 | 
			
		||||
			<tf-news id="news" whoami=${this.whoami} .messages=${this.messages} .users=${this.users} .expanded=${this.expanded} @tf-expand=${this.on_expand}></tf-news>
 | 
			
		||||
		`;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
import * as linkify from './commonmark-linkify.js';
 | 
			
		||||
import * as hashtagify from './commonmark-hashtag.js';
 | 
			
		||||
 | 
			
		||||
const k_code_classes = 'w3-theme-l4 w3-theme-border w3-round';
 | 
			
		||||
 | 
			
		||||
function image(node, entering) {
 | 
			
		||||
	if (
 | 
			
		||||
		node.firstChild?.type === 'text' &&
 | 
			
		||||
@@ -61,13 +62,32 @@ 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) {
 | 
			
		||||
	let reader = new commonmark.Parser({safe: true});
 | 
			
		||||
	let writer = new commonmark.HtmlRenderer();
 | 
			
		||||
	writer.image = image;
 | 
			
		||||
	writer.code = code;
 | 
			
		||||
	writer.attrs = attrs;
 | 
			
		||||
	let parsed = reader.parse(md || '');
 | 
			
		||||
	parsed = hashtagify.transform(parsed);
 | 
			
		||||
	parsed = linkify.transform(parsed);
 | 
			
		||||
	let walker = parsed.walker();
 | 
			
		||||
	let event, node;
 | 
			
		||||
	while ((event = walker.next())) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
	"type": "tildefriends-app",
 | 
			
		||||
	"emoji": "👋",
 | 
			
		||||
	"previous": "&zFISmRDAv+SXFonfZ9/sHNhrmMe+poTU22gwZzuSkT4=.sha256"
 | 
			
		||||
	"previous": "&W5aJp2DgOW5rQ0AOIC9Ut3DpsahPrO6PjkJ1PQbNRdM=.sha256"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -55,7 +55,7 @@
 | 
			
		||||
					</p>
 | 
			
		||||
					<a
 | 
			
		||||
						class="w3-button w3-black w3-padding-large"
 | 
			
		||||
						href="https://www.tildefriends.net/~cory/releases/"
 | 
			
		||||
						href="https://dev.tildefriends.net/cory/tildefriends/releases"
 | 
			
		||||
						><i class="fa fa-download"></i> Download</a
 | 
			
		||||
					>
 | 
			
		||||
					<a
 | 
			
		||||
@@ -63,6 +63,11 @@
 | 
			
		||||
						href="https://www.tildefriends.net/~cory/apps/"
 | 
			
		||||
						><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 class="w3-col l4 m6">
 | 
			
		||||
					<img src="tildefriends.png" class="w3-image w3-right w3-hide-small" />
 | 
			
		||||
@@ -70,6 +75,60 @@
 | 
			
		||||
			</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 -->
 | 
			
		||||
		<div class="w3-light-grey">
 | 
			
		||||
			<div class="w3-row-padding w3-padding-64">
 | 
			
		||||
@@ -199,7 +258,7 @@
 | 
			
		||||
			</div>
 | 
			
		||||
 | 
			
		||||
			<div class="w3-row" style="margin-top: 64px">
 | 
			
		||||
				<a href="https://codemirror.net/5/" class="w3-col s3">
 | 
			
		||||
				<a href="https://codemirror.net/docs/changelog/" class="w3-col s3">
 | 
			
		||||
					<i class="fa fa-keyboard w3-text-indigo w3-jumbo"></i>
 | 
			
		||||
					<p>CodeMirror</p>
 | 
			
		||||
				</a>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
	"type": "tildefriends-app",
 | 
			
		||||
	"emoji": "📝",
 | 
			
		||||
	"previous": "&DnfuAUGzzalSh9NgZXnzDc9Ru5aM0omfRJ4h27jYw4k=.sha256"
 | 
			
		||||
	"previous": "&DaYqKHRBKhjFGaOzbKZ1+/pLspJeEkDJYTF2B50tH6k=.sha256"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,9 @@ import * as utils from './utils.js';
 | 
			
		||||
let g_hash;
 | 
			
		||||
let g_collection_notifies = {};
 | 
			
		||||
 | 
			
		||||
tfrpc.register(async function getActiveIdentity() {
 | 
			
		||||
	return ssb.getActiveIdentity();
 | 
			
		||||
});
 | 
			
		||||
tfrpc.register(async function getOwnerIdentities() {
 | 
			
		||||
	return ssb.getOwnerIdentities();
 | 
			
		||||
});
 | 
			
		||||
@@ -54,6 +57,9 @@ core.register('message', async function message_handler(message) {
 | 
			
		||||
		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) {
 | 
			
		||||
	if (g_hash != hash) {
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,6 @@
 | 
			
		||||
			window.litDisableBundleWarning = true;
 | 
			
		||||
		</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-app.js" type="module"></script>
 | 
			
		||||
	</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
											
										
									
								
							@@ -1,44 +0,0 @@
 | 
			
		||||
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,13 +31,16 @@ class TfCollectionsAppElement extends LitElement {
 | 
			
		||||
		tfrpc.register(function 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));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	async load() {
 | 
			
		||||
		this.ids = await tfrpc.rpc.getIdentities();
 | 
			
		||||
		this.owner_ids = await tfrpc.rpc.getOwnerIdentities();
 | 
			
		||||
		this.whoami = await tfrpc.rpc.localStorageGet('collections_whoami');
 | 
			
		||||
		this.whoami = await tfrpc.rpc.getActiveIdentity();
 | 
			
		||||
		let ids = [...new Set([...this.owner_ids, this.whoami])].sort();
 | 
			
		||||
		this.following = Object.keys(await tfrpc.rpc.following(ids, 1)).sort();
 | 
			
		||||
 | 
			
		||||
@@ -273,9 +276,6 @@ class TfCollectionsAppElement extends LitElement {
 | 
			
		||||
					margin-right: 16px;
 | 
			
		||||
				}
 | 
			
		||||
			</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>
 | 
			
		||||
				${keyed(
 | 
			
		||||
					this.whoami,
 | 
			
		||||
 
 | 
			
		||||
@@ -96,7 +96,7 @@ export async function collection(
 | 
			
		||||
		let rows = [];
 | 
			
		||||
		await ssb.sqlAsync(
 | 
			
		||||
			`
 | 
			
		||||
				SELECT messages.id, author, content, timestamp
 | 
			
		||||
				SELECT messages.id, author, json(content) AS content, timestamp
 | 
			
		||||
				FROM messages
 | 
			
		||||
				JOIN json_each(?1) AS id ON messages.author = id.value
 | 
			
		||||
				WHERE
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										38
									
								
								core/app.js
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								core/app.js
									
									
									
									
									
								
							@@ -1,4 +1,3 @@
 | 
			
		||||
import * as auth from './auth.js';
 | 
			
		||||
import * as core from './core.js';
 | 
			
		||||
 | 
			
		||||
let g_next_id = 1;
 | 
			
		||||
@@ -87,8 +86,7 @@ App.prototype.send = function (message) {
 | 
			
		||||
function socket(request, response, client) {
 | 
			
		||||
	let process;
 | 
			
		||||
	let options = {};
 | 
			
		||||
	let credentials = auth.query(request.headers);
 | 
			
		||||
	let refresh = auth.makeRefresh(credentials);
 | 
			
		||||
	let credentials = httpd.auth_query(request.headers);
 | 
			
		||||
 | 
			
		||||
	response.onClose = async function () {
 | 
			
		||||
		if (process && process.task) {
 | 
			
		||||
@@ -143,12 +141,21 @@ function socket(request, response, client) {
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				response.send(
 | 
			
		||||
					JSON.stringify({
 | 
			
		||||
						action: 'session',
 | 
			
		||||
						credentials: credentials,
 | 
			
		||||
						parentApp: parentApp,
 | 
			
		||||
						id: blobId,
 | 
			
		||||
					}),
 | 
			
		||||
					JSON.stringify(
 | 
			
		||||
						Object.assign(
 | 
			
		||||
							{
 | 
			
		||||
								action: 'session',
 | 
			
		||||
								credentials: credentials,
 | 
			
		||||
								parentApp: parentApp,
 | 
			
		||||
								id: blobId,
 | 
			
		||||
							},
 | 
			
		||||
							await ssb.getIdentityInfo(
 | 
			
		||||
								credentials?.session?.name,
 | 
			
		||||
								packageOwner,
 | 
			
		||||
								packageName
 | 
			
		||||
							)
 | 
			
		||||
						)
 | 
			
		||||
					),
 | 
			
		||||
					0x1
 | 
			
		||||
				);
 | 
			
		||||
 | 
			
		||||
@@ -212,6 +219,10 @@ function socket(request, response, client) {
 | 
			
		||||
				if (process) {
 | 
			
		||||
					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') {
 | 
			
		||||
				if (message.id && g_calls[message.id]) {
 | 
			
		||||
					if (message.error !== undefined) {
 | 
			
		||||
@@ -241,14 +252,7 @@ function socket(request, response, client) {
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	response.upgrade(
 | 
			
		||||
		100,
 | 
			
		||||
		refresh
 | 
			
		||||
			? {
 | 
			
		||||
					'Set-Cookie': `session=${refresh.token}; path=/; Max-Age=${refresh.interval}; Secure; SameSite=Strict`,
 | 
			
		||||
				}
 | 
			
		||||
			: {}
 | 
			
		||||
	);
 | 
			
		||||
	response.upgrade(100, {});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export {socket, App};
 | 
			
		||||
 
 | 
			
		||||
@@ -19,8 +19,11 @@
 | 
			
		||||
			Object.assign(app, g_data);
 | 
			
		||||
 | 
			
		||||
			class TfAuthElement extends LitElement {
 | 
			
		||||
				static get_properties() {
 | 
			
		||||
				static get properties() {
 | 
			
		||||
					return {
 | 
			
		||||
						code_of_conduct: {type: String},
 | 
			
		||||
						error: {type: String},
 | 
			
		||||
						have_administrator: {type: Boolean},
 | 
			
		||||
						name: {type: String},
 | 
			
		||||
						tab: {type: String},
 | 
			
		||||
					};
 | 
			
		||||
@@ -31,11 +34,6 @@
 | 
			
		||||
					this.tab = 'login';
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				tab_changed(name) {
 | 
			
		||||
					this.tab = name;
 | 
			
		||||
					this.requestUpdate();
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				render() {
 | 
			
		||||
					let self = this;
 | 
			
		||||
					return html`
 | 
			
		||||
@@ -83,16 +81,16 @@
 | 
			
		||||
							<h1 ?hidden=${this.name === undefined}>Welcome, ${this.name}.</h1>
 | 
			
		||||
 | 
			
		||||
							<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_changed('login')}></input>
 | 
			
		||||
								<input type="radio" name="tab" id="login" value="Login" ?checked=${this.tab == 'login'} @change=${() => (self.tab = 'login')}></input>
 | 
			
		||||
								<label for="login" id="login_label">Login</label>
 | 
			
		||||
 | 
			
		||||
								<input type="radio" name="tab" id="register" value="Register" ?checked=${this.tab == 'register'} @change=${() => self.tab_changed('register')}></input>
 | 
			
		||||
								<input type="radio" name="tab" id="register" value="Register" ?checked=${this.tab == 'register'} @change=${() => (self.tab = 'register')}></input>
 | 
			
		||||
								<label for="register" id="register_label">Register</label>
 | 
			
		||||
 | 
			
		||||
								<input type="radio" name="tab" id="guest" value="Guest" ?checked=${this.tab == 'guest'} @change=${() => self.tab_changed('guest')}></input>
 | 
			
		||||
								<input type="radio" name="tab" id="guest" value="Guest" ?checked=${this.tab == 'guest'} @change=${() => (self.tab = 'guest')}></input>
 | 
			
		||||
								<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_changed('change')}></input>
 | 
			
		||||
								<input type="radio" name="tab" id="change" value="Change Password" ?checked=${this.tab == 'change'} @change=${() => (self.tab = 'change')}></input>
 | 
			
		||||
								<label for="change" id="change_label">Change Password</label>
 | 
			
		||||
							</div>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										420
									
								
								core/auth.js
									
									
									
									
									
								
							
							
						
						
									
										420
									
								
								core/auth.js
									
									
									
									
									
								
							@@ -1,420 +0,0 @@
 | 
			
		||||
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};
 | 
			
		||||
							
								
								
									
										209
									
								
								core/client.js
									
									
									
									
									
								
							
							
						
						
									
										209
									
								
								core/client.js
									
									
									
									
									
								
							@@ -56,6 +56,9 @@ class TfNavigationElement extends LitElement {
 | 
			
		||||
			spark_lines: {type: Object},
 | 
			
		||||
			version: {type: Object},
 | 
			
		||||
			show_version: {type: Boolean},
 | 
			
		||||
			identity: {type: String},
 | 
			
		||||
			identities: {type: Array},
 | 
			
		||||
			names: {type: Object},
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -65,6 +68,8 @@ class TfNavigationElement extends LitElement {
 | 
			
		||||
		this.show_permissions = false;
 | 
			
		||||
		this.status = {};
 | 
			
		||||
		this.spark_lines = {};
 | 
			
		||||
		this.identities = [];
 | 
			
		||||
		this.names = {};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
@@ -97,10 +102,10 @@ class TfNavigationElement extends LitElement {
 | 
			
		||||
	get_spark_line(key, options) {
 | 
			
		||||
		if (!this.spark_lines[key]) {
 | 
			
		||||
			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.classList.add('w3-bar-item');
 | 
			
		||||
			spark_line.classList.add('w3-hide-small');
 | 
			
		||||
			spark_line.style.paddingRight = '0';
 | 
			
		||||
			if (options) {
 | 
			
		||||
				if (options.max) {
 | 
			
		||||
					spark_line.max = options.max;
 | 
			
		||||
@@ -118,16 +123,105 @@ class TfNavigationElement extends LitElement {
 | 
			
		||||
	 */
 | 
			
		||||
	render_login() {
 | 
			
		||||
		if (this?.credentials?.session?.name) {
 | 
			
		||||
			return html`<a id="login" href="/login/logout?return=${url() + hash()}"
 | 
			
		||||
			return html`<a
 | 
			
		||||
				class="w3-bar-item w3-right"
 | 
			
		||||
				id="login"
 | 
			
		||||
				href="/login/logout?return=${url() + hash()}"
 | 
			
		||||
				>logout ${this.credentials.session.name}</a
 | 
			
		||||
			>`;
 | 
			
		||||
		} else {
 | 
			
		||||
			return html`<a id="login" href="/login?return=${url() + hash()}"
 | 
			
		||||
			return html`<a
 | 
			
		||||
				class="w3-bar-item w3-right"
 | 
			
		||||
				id="login"
 | 
			
		||||
				href="/login?return=${url() + hash()}"
 | 
			
		||||
				>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
 | 
			
		||||
	 * @returns
 | 
			
		||||
@@ -145,11 +239,17 @@ class TfNavigationElement extends LitElement {
 | 
			
		||||
						<div>This app has the following permissions:</div>
 | 
			
		||||
						${Object.keys(this.permissions).map(
 | 
			
		||||
							(key) => html`
 | 
			
		||||
							<div>
 | 
			
		||||
								<span>${key}</span>: ${this.permissions[key] ? '✅ Allowed' : '❌ Denied'}
 | 
			
		||||
								<button @click=${() => this.reset_permission(key)} class='w3-button w3-red">Reset</button>
 | 
			
		||||
							</div>
 | 
			
		||||
						`
 | 
			
		||||
								<div>
 | 
			
		||||
									<span>${key}</span>:
 | 
			
		||||
									${this.permissions[key] ? '✅ Allowed' : '❌ Denied'}
 | 
			
		||||
									<button
 | 
			
		||||
										@click=${() => this.reset_permission(key)}
 | 
			
		||||
										class="w3-button w3-red"
 | 
			
		||||
									>
 | 
			
		||||
										Reset
 | 
			
		||||
									</button>
 | 
			
		||||
								</div>
 | 
			
		||||
							`
 | 
			
		||||
						)}
 | 
			
		||||
						<button
 | 
			
		||||
							@click=${() => (this.show_permissions = false)}
 | 
			
		||||
@@ -163,6 +263,10 @@ class TfNavigationElement extends LitElement {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	clear_error() {
 | 
			
		||||
		this.status = {};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * TODOC
 | 
			
		||||
	 * @returns
 | 
			
		||||
@@ -170,6 +274,7 @@ class TfNavigationElement extends LitElement {
 | 
			
		||||
	render() {
 | 
			
		||||
		let self = this;
 | 
			
		||||
		return html`
 | 
			
		||||
			<link type="text/css" rel="stylesheet" href="/static/w3.css" />
 | 
			
		||||
			<style>
 | 
			
		||||
				${k_global_style} .tooltip {
 | 
			
		||||
					position: absolute;
 | 
			
		||||
@@ -185,17 +290,17 @@ class TfNavigationElement extends LitElement {
 | 
			
		||||
					display: inline-block;
 | 
			
		||||
				}
 | 
			
		||||
			</style>
 | 
			
		||||
			<div
 | 
			
		||||
				style="margin: 4px; display: flex; flex-direction: row; flex-wrap: nowrap; gap: 3px; align-items: center"
 | 
			
		||||
			>
 | 
			
		||||
			<div class="w3-black w3-bar">
 | 
			
		||||
				<span
 | 
			
		||||
					class="w3-bar-item"
 | 
			
		||||
					style="cursor: pointer"
 | 
			
		||||
					@click=${() => (this.show_version = !this.show_version)}
 | 
			
		||||
					>😎</span
 | 
			
		||||
				>
 | 
			
		||||
				<span
 | 
			
		||||
					?hidden=${!this.show_version}
 | 
			
		||||
					style="flex: 0 0; white-space: nowrap"
 | 
			
		||||
					class="w3-bar-item"
 | 
			
		||||
					style=${'white-space: nowrap' +
 | 
			
		||||
					(this.show_version ? '' : '; display: none')}
 | 
			
		||||
					title=${this.version?.name +
 | 
			
		||||
					' ' +
 | 
			
		||||
					Object.entries(this.version || {})
 | 
			
		||||
@@ -204,6 +309,7 @@ class TfNavigationElement extends LitElement {
 | 
			
		||||
					>${this.version?.number}</span
 | 
			
		||||
				>
 | 
			
		||||
				<a
 | 
			
		||||
					class="w3-bar-item"
 | 
			
		||||
					accesskey="h"
 | 
			
		||||
					@mouseover=${set_access_key_title}
 | 
			
		||||
					data-tip="Open home app."
 | 
			
		||||
@@ -212,6 +318,7 @@ class TfNavigationElement extends LitElement {
 | 
			
		||||
					>TF</a
 | 
			
		||||
				>
 | 
			
		||||
				<a
 | 
			
		||||
					class="w3-bar-item"
 | 
			
		||||
					accesskey="a"
 | 
			
		||||
					@mouseover=${set_access_key_title}
 | 
			
		||||
					data-tip="Open apps list."
 | 
			
		||||
@@ -219,6 +326,7 @@ class TfNavigationElement extends LitElement {
 | 
			
		||||
					>apps</a
 | 
			
		||||
				>
 | 
			
		||||
				<a
 | 
			
		||||
					class="w3-bar-item"
 | 
			
		||||
					accesskey="e"
 | 
			
		||||
					@mouseover=${set_access_key_title}
 | 
			
		||||
					data-tip="Toggle the app editor."
 | 
			
		||||
@@ -227,6 +335,7 @@ class TfNavigationElement extends LitElement {
 | 
			
		||||
					>edit</a
 | 
			
		||||
				>
 | 
			
		||||
				<a
 | 
			
		||||
					class="w3-bar-item"
 | 
			
		||||
					accesskey="p"
 | 
			
		||||
					@mouseover=${set_access_key_title}
 | 
			
		||||
					data-tip="View and change permissions."
 | 
			
		||||
@@ -234,27 +343,34 @@ class TfNavigationElement extends LitElement {
 | 
			
		||||
					@click=${() => (self.show_permissions = !self.show_permissions)}
 | 
			
		||||
					>🎛️</a
 | 
			
		||||
				>
 | 
			
		||||
				<span
 | 
			
		||||
					style="display: inline-block; vertical-align: top; white-space: pre; color: ${this
 | 
			
		||||
						.status.color ?? kErrorColor}"
 | 
			
		||||
					>${this.status.message}</span
 | 
			
		||||
				>
 | 
			
		||||
				<span id="requests"></span>
 | 
			
		||||
				${this.render_permissions()}
 | 
			
		||||
				<span
 | 
			
		||||
					style="flex: 1 1; display: flex; flex-direction: row; white-space: nowrap; margin: 0; padding: 0"
 | 
			
		||||
					>${Object.keys(this.spark_lines)
 | 
			
		||||
						.sort()
 | 
			
		||||
						.map((x) => this.spark_lines[x])
 | 
			
		||||
						.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
 | 
			
		||||
				>
 | 
			
		||||
				${this.status?.message && !this.status.is_error
 | 
			
		||||
					? html`
 | 
			
		||||
							<link type="text/css" rel="stylesheet" href="/static/w3.css" />
 | 
			
		||||
							<div
 | 
			
		||||
								class="w3-bar-item"
 | 
			
		||||
								style="color: ${this.status.color ?? kStatusColor}"
 | 
			
		||||
							>
 | 
			
		||||
								${this.status.message}
 | 
			
		||||
							</div>
 | 
			
		||||
						`
 | 
			
		||||
					: undefined}
 | 
			
		||||
				${Object.keys(this.spark_lines)
 | 
			
		||||
					.sort()
 | 
			
		||||
					.map((x) => this.spark_lines[x])}
 | 
			
		||||
				${this.render_login()} ${this.render_identity()}
 | 
			
		||||
			</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}
 | 
			
		||||
		`;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -578,13 +694,13 @@ class TfSparkLineElement extends LitElement {
 | 
			
		||||
			) / 10.0;
 | 
			
		||||
		return html`
 | 
			
		||||
			<svg
 | 
			
		||||
				style="max-width: 7.5em; max-height: 1.5em; margin: 0; padding: 0; background: #000"
 | 
			
		||||
				style="max-width: 7.5em; margin: 0; padding: 0; background: #000; height: 1em"
 | 
			
		||||
				viewBox="0 0 50 10"
 | 
			
		||||
				xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
			>
 | 
			
		||||
				${this.lines.map((x) => this.render_line(x))}
 | 
			
		||||
				<text x="0" y="1em" style="font: 8px sans-serif; fill: #fff">
 | 
			
		||||
					${max}
 | 
			
		||||
					${this.dataset.emoji}${max}
 | 
			
		||||
				</text>
 | 
			
		||||
			</svg>
 | 
			
		||||
		`;
 | 
			
		||||
@@ -1000,9 +1116,9 @@ function api_postMessage(message) {
 | 
			
		||||
function api_error(error) {
 | 
			
		||||
	if (error) {
 | 
			
		||||
		if (typeof error == 'string') {
 | 
			
		||||
			setStatusMessage('⚠️ ' + error, '#f00');
 | 
			
		||||
			setStatusMessage('⚠️ ' + error, kErrorColor);
 | 
			
		||||
		} else {
 | 
			
		||||
			setStatusMessage('⚠️ ' + error.message + '\n' + error.stack, '#f00');
 | 
			
		||||
			setStatusMessage('⚠️ ' + error.message + '\n' + error.stack, kErrorColor);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	console.log('error', error);
 | 
			
		||||
@@ -1119,11 +1235,19 @@ function api_setHash(hash) {
 | 
			
		||||
function _receive_websocket_message(message) {
 | 
			
		||||
	if (message && message.action == 'session') {
 | 
			
		||||
		setStatusMessage('🟢 Executing...', kStatusColor);
 | 
			
		||||
		document.getElementsByTagName('tf-navigation')[0].credentials =
 | 
			
		||||
			message.credentials;
 | 
			
		||||
		let navigation = document.getElementsByTagName('tf-navigation')[0];
 | 
			
		||||
		navigation.credentials = message.credentials;
 | 
			
		||||
		navigation.identities = message.identities;
 | 
			
		||||
		navigation.identity = message.identity;
 | 
			
		||||
		navigation.names = message.names;
 | 
			
		||||
	} else if (message && message.action == 'permissions') {
 | 
			
		||||
		document.getElementsByTagName('tf-navigation')[0].permissions =
 | 
			
		||||
			message.permissions ?? {};
 | 
			
		||||
		let navigation = document.getElementsByTagName('tf-navigation')[0];
 | 
			
		||||
		navigation.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') {
 | 
			
		||||
		setStatusMessage(null);
 | 
			
		||||
		if (window.location.hash) {
 | 
			
		||||
@@ -1211,6 +1335,7 @@ function setStatusMessage(message, color) {
 | 
			
		||||
	document.getElementsByTagName('tf-navigation')[0].status = {
 | 
			
		||||
		message: message,
 | 
			
		||||
		color: color,
 | 
			
		||||
		is_error: color == kErrorColor,
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										156
									
								
								core/core.js
									
									
									
									
									
								
							
							
						
						
									
										156
									
								
								core/core.js
									
									
									
									
									
								
							@@ -1,5 +1,4 @@
 | 
			
		||||
import * as app from './app.js';
 | 
			
		||||
import * as auth from './auth.js';
 | 
			
		||||
import * as form from './form.js';
 | 
			
		||||
import * as http from './http.js';
 | 
			
		||||
 | 
			
		||||
@@ -245,6 +244,7 @@ function broadcastEvent(eventName, argv) {
 | 
			
		||||
	}
 | 
			
		||||
	return Promise.all(promises);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * TODOC
 | 
			
		||||
 * @param {*} message
 | 
			
		||||
@@ -266,6 +266,34 @@ function broadcast(message) {
 | 
			
		||||
	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
 | 
			
		||||
 * @param {*} caller
 | 
			
		||||
@@ -361,6 +389,8 @@ async function getProcessBlob(blobId, key, options) {
 | 
			
		||||
			process.key = key;
 | 
			
		||||
			process.credentials = options.credentials || {};
 | 
			
		||||
			process.task = new Task();
 | 
			
		||||
			process.packageOwner = options.packageOwner;
 | 
			
		||||
			process.packageName = options.packageName;
 | 
			
		||||
			process.eventHandlers = {};
 | 
			
		||||
			if (!options?.script || options?.script === 'app.js') {
 | 
			
		||||
				process.app = new app.App();
 | 
			
		||||
@@ -509,6 +539,64 @@ async function getProcessBlob(blobId, key, options) {
 | 
			
		||||
					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) {
 | 
			
		||||
				imports.core.globalSettingsDescriptions = function () {
 | 
			
		||||
					let settings = Object.assign({}, k_global_settings);
 | 
			
		||||
@@ -579,15 +667,7 @@ async function getProcessBlob(blobId, key, options) {
 | 
			
		||||
				Object.keys(ssb).map((key) => [key, ssb[key].bind(ssb)])
 | 
			
		||||
			);
 | 
			
		||||
			imports.ssb.port = tildefriends.ssb_port;
 | 
			
		||||
			imports.ssb.createIdentity = function () {
 | 
			
		||||
				if (
 | 
			
		||||
					process.credentials &&
 | 
			
		||||
					process.credentials.session &&
 | 
			
		||||
					process.credentials.session.name
 | 
			
		||||
				) {
 | 
			
		||||
					return ssb.createIdentity(process.credentials.session.name);
 | 
			
		||||
				}
 | 
			
		||||
			};
 | 
			
		||||
			imports.ssb.createIdentity = () => process.createIdentity();
 | 
			
		||||
			imports.ssb.addIdentity = function (id) {
 | 
			
		||||
				if (
 | 
			
		||||
					process.credentials &&
 | 
			
		||||
@@ -614,6 +694,13 @@ 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 () {
 | 
			
		||||
				if (options.packageOwner) {
 | 
			
		||||
					return ssb.getIdentities(options.packageOwner);
 | 
			
		||||
@@ -698,6 +785,7 @@ async function getProcessBlob(blobId, key, options) {
 | 
			
		||||
					);
 | 
			
		||||
				}
 | 
			
		||||
			};
 | 
			
		||||
			imports.ssb.getIdentityInfo = undefined;
 | 
			
		||||
			imports.fetch = function (url, options) {
 | 
			
		||||
				return http.fetch(url, options, gGlobalSettings.fetch_hosts);
 | 
			
		||||
			};
 | 
			
		||||
@@ -967,7 +1055,7 @@ async function useAppHandler(
 | 
			
		||||
					},
 | 
			
		||||
					respond: do_resolve,
 | 
			
		||||
				},
 | 
			
		||||
				credentials: auth.query(headers),
 | 
			
		||||
				credentials: httpd.auth_query(headers),
 | 
			
		||||
				packageOwner: packageOwner,
 | 
			
		||||
				packageName: packageName,
 | 
			
		||||
			}
 | 
			
		||||
@@ -1098,7 +1186,7 @@ async function blobHandler(request, response, blobId, uri) {
 | 
			
		||||
		if ((match = /^\/\~(\w+)\/(\w+)$/.exec(blobId))) {
 | 
			
		||||
			let user = match[1];
 | 
			
		||||
			let appName = match[2];
 | 
			
		||||
			let credentials = auth.query(request.headers);
 | 
			
		||||
			let credentials = httpd.auth_query(request.headers);
 | 
			
		||||
			if (
 | 
			
		||||
				credentials &&
 | 
			
		||||
				credentials.session &&
 | 
			
		||||
@@ -1161,7 +1249,7 @@ async function blobHandler(request, response, blobId, uri) {
 | 
			
		||||
		if ((match = /^\/\~(\w+)\/(\w+)$/.exec(blobId))) {
 | 
			
		||||
			let user = match[1];
 | 
			
		||||
			let appName = match[2];
 | 
			
		||||
			let credentials = auth.query(request.headers);
 | 
			
		||||
			let credentials = httpd.auth_query(request.headers);
 | 
			
		||||
			if (
 | 
			
		||||
				credentials &&
 | 
			
		||||
				credentials.session &&
 | 
			
		||||
@@ -1334,39 +1422,10 @@ loadSettings()
 | 
			
		||||
		if (tildefriends.https_port && 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('', function default_http_handler(request, response) {
 | 
			
		||||
			let match;
 | 
			
		||||
			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))) {
 | 
			
		||||
			if ((match = /^(\/~[^\/]+\/[^\/]+)(\/?.*)$/.exec(request.uri))) {
 | 
			
		||||
				return blobHandler(request, response, match[1], match[2]);
 | 
			
		||||
			} else if (
 | 
			
		||||
				(match = /^\/([&\%][^\.]{44}(?:\.\w+)?)(\/?.*)/.exec(request.uri))
 | 
			
		||||
@@ -1406,8 +1465,15 @@ loadSettings()
 | 
			
		||||
			async function start_tls() {
 | 
			
		||||
				const kCertificatePath = 'data/httpd/certificate.pem';
 | 
			
		||||
				const kPrivateKeyPath = 'data/httpd/privatekey.pem';
 | 
			
		||||
				let privateKey = utf8Decode(await File.readFile(kPrivateKeyPath));
 | 
			
		||||
				let certificate = utf8Decode(await File.readFile(kCertificatePath));
 | 
			
		||||
				let privateKey;
 | 
			
		||||
				let certificate;
 | 
			
		||||
				try {
 | 
			
		||||
					privateKey = utf8Decode(await File.readFile(kPrivateKeyPath));
 | 
			
		||||
					certificate = utf8Decode(await File.readFile(kCertificatePath));
 | 
			
		||||
				} catch (e) {
 | 
			
		||||
					print(`TLS disabled (${e.message}).`);
 | 
			
		||||
					return;
 | 
			
		||||
				}
 | 
			
		||||
				let context = new TlsContext();
 | 
			
		||||
				context.setPrivateKey(privateKey);
 | 
			
		||||
				context.setCertificate(certificate);
 | 
			
		||||
 
 | 
			
		||||
@@ -15,22 +15,6 @@ body {
 | 
			
		||||
	margin: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a:link {
 | 
			
		||||
	color: #268bd2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a:visited {
 | 
			
		||||
	color: #6c71c4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a:hover {
 | 
			
		||||
	color: #859900;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
a:active {
 | 
			
		||||
	color: #2aa198;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#logo {
 | 
			
		||||
	vertical-align: middle;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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": {
 | 
			
		||||
      "version": "6.15.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.15.0.tgz",
 | 
			
		||||
      "integrity": "sha512-G2Zm0mXznxz97JhaaOdoEG2cVupn4JjPaS4AcNvZzhOsnnG9YVN68VzfoUw6dYTsIxT6a/cmoFEN47KAWhXaOg==",
 | 
			
		||||
      "version": "6.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.16.0.tgz",
 | 
			
		||||
      "integrity": "sha512-P/LeCTtZHRTCU4xQsa89vSKWecYv1ZqwzOd5topheGRf+qtacFgBeIMQi3eL8Kt/BUNvxUWkx+5qP2jlGoARrg==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@codemirror/language": "^6.0.0",
 | 
			
		||||
        "@codemirror/state": "^6.0.0",
 | 
			
		||||
@@ -36,9 +36,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@codemirror/commands": {
 | 
			
		||||
      "version": "6.3.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.3.3.tgz",
 | 
			
		||||
      "integrity": "sha512-dO4hcF0fGT9tu1Pj1D2PvGvxjeGkbC6RGcZw6Qs74TH+Ed1gw98jmUgd2axWvIZEqTeTuFrg1lEB1KV6cK9h1A==",
 | 
			
		||||
      "version": "6.5.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.5.0.tgz",
 | 
			
		||||
      "integrity": "sha512-rK+sj4fCAN/QfcY9BEzYMgp4wwL/q5aj/VfNSoH1RWPF9XS/dUwBkvlL3hpWgEjOqlpdN1uLC9UkjJ4tmyjJYg==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@codemirror/language": "^6.0.0",
 | 
			
		||||
        "@codemirror/state": "^6.4.0",
 | 
			
		||||
@@ -59,9 +59,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@codemirror/lang-html": {
 | 
			
		||||
      "version": "6.4.8",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.8.tgz",
 | 
			
		||||
      "integrity": "sha512-tE2YK7wDlb9ZpAH6mpTPiYm6rhfdQKVDa5r9IwIFlwwgvVaKsCfuKKZoJGWsmMZIf3FQAuJ5CHMPLymOtg1hXw==",
 | 
			
		||||
      "version": "6.4.9",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.9.tgz",
 | 
			
		||||
      "integrity": "sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@codemirror/autocomplete": "^6.0.0",
 | 
			
		||||
        "@codemirror/lang-css": "^6.0.0",
 | 
			
		||||
@@ -111,9 +111,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@codemirror/lint": {
 | 
			
		||||
      "version": "6.5.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.5.0.tgz",
 | 
			
		||||
      "integrity": "sha512-+5YyicIaaAZKU8K43IQi8TBy6mF6giGeWAH7N96Z5LC30Wm5JMjqxOYIE9mxwMG1NbhT2mA3l9hA4uuKUM3E5g==",
 | 
			
		||||
      "version": "6.7.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.7.0.tgz",
 | 
			
		||||
      "integrity": "sha512-LTLOL2nT41ADNSCCCCw8Q/UmdAFzB23OUYSjsHTdsVaH0XEo+orhuqbDNWzrzodm14w6FOxqxpmy4LF8Lixqjw==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@codemirror/state": "^6.0.0",
 | 
			
		||||
        "@codemirror/view": "^6.0.0",
 | 
			
		||||
@@ -147,9 +147,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@codemirror/view": {
 | 
			
		||||
      "version": "6.25.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.25.1.tgz",
 | 
			
		||||
      "integrity": "sha512-2LXLxsQnHDdfGzDvjzAwZh2ZviNJm7im6tGpa0IONIDnFd8RZ80D2SNi8PDi6YjKcMoMRK20v6OmKIdsrwsyoQ==",
 | 
			
		||||
      "version": "6.26.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.26.3.tgz",
 | 
			
		||||
      "integrity": "sha512-gmqxkPALZjkgSxIeeweY/wGQXBfwTUaLs8h7OKtSwfbj9Ct3L11lD+u1sS7XHppxFQoMDiMDp07P9f3I2jWOHw==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@codemirror/state": "^6.4.0",
 | 
			
		||||
        "style-mod": "^4.1.0",
 | 
			
		||||
@@ -248,9 +248,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@lezer/javascript": {
 | 
			
		||||
      "version": "1.4.13",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.13.tgz",
 | 
			
		||||
      "integrity": "sha512-5IBr8LIO3xJdJH1e9aj/ZNLE4LSbdsx25wFmGRAZsj2zSmwAYjx26JyU/BYOCpRQlu1jcv1z3vy4NB9+UkfRow==",
 | 
			
		||||
      "version": "1.4.15",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.15.tgz",
 | 
			
		||||
      "integrity": "sha512-B082ZdjI0vo2AgLqD834GlRTE9gwRX8NzHzKq5uDwEnQ9Dq+A/CEhd3nf68tiNA2f9O+8jS1NeSTUYT9IAqcTw==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@lezer/common": "^1.2.0",
 | 
			
		||||
        "@lezer/highlight": "^1.1.3",
 | 
			
		||||
@@ -343,9 +343,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@rollup/rollup-android-arm-eabi": {
 | 
			
		||||
      "version": "4.13.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.0.tgz",
 | 
			
		||||
      "integrity": "sha512-5ZYPOuaAqEH/W3gYsRkxQATBW3Ii1MfaT4EQstTnLKViLi2gLSQmlmtTpGucNP3sXEpOiI5tdGhjdE111ekyEg==",
 | 
			
		||||
      "version": "4.17.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz",
 | 
			
		||||
      "integrity": "sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "arm"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -355,9 +355,9 @@
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@rollup/rollup-android-arm64": {
 | 
			
		||||
      "version": "4.13.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.0.tgz",
 | 
			
		||||
      "integrity": "sha512-BSbaCmn8ZadK3UAQdlauSvtaJjhlDEjS5hEVVIN3A4bbl3X+otyf/kOJV08bYiRxfejP3DXFzO2jz3G20107+Q==",
 | 
			
		||||
      "version": "4.17.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz",
 | 
			
		||||
      "integrity": "sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "arm64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -367,9 +367,9 @@
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@rollup/rollup-darwin-arm64": {
 | 
			
		||||
      "version": "4.13.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.0.tgz",
 | 
			
		||||
      "integrity": "sha512-Ovf2evVaP6sW5Ut0GHyUSOqA6tVKfrTHddtmxGQc1CTQa1Cw3/KMCDEEICZBbyppcwnhMwcDce9ZRxdWRpVd6g==",
 | 
			
		||||
      "version": "4.17.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz",
 | 
			
		||||
      "integrity": "sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "arm64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -379,9 +379,9 @@
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@rollup/rollup-darwin-x64": {
 | 
			
		||||
      "version": "4.13.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.0.tgz",
 | 
			
		||||
      "integrity": "sha512-U+Jcxm89UTK592vZ2J9st9ajRv/hrwHdnvyuJpa5A2ngGSVHypigidkQJP+YiGL6JODiUeMzkqQzbCG3At81Gg==",
 | 
			
		||||
      "version": "4.17.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz",
 | 
			
		||||
      "integrity": "sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "x64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -391,9 +391,21 @@
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
 | 
			
		||||
      "version": "4.13.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.0.tgz",
 | 
			
		||||
      "integrity": "sha512-8wZidaUJUTIR5T4vRS22VkSMOVooG0F4N+JSwQXWSRiC6yfEsFMLTYRFHvby5mFFuExHa/yAp9juSphQQJAijQ==",
 | 
			
		||||
      "version": "4.17.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz",
 | 
			
		||||
      "integrity": "sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==",
 | 
			
		||||
      "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": [
 | 
			
		||||
        "arm"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -403,9 +415,9 @@
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@rollup/rollup-linux-arm64-gnu": {
 | 
			
		||||
      "version": "4.13.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.0.tgz",
 | 
			
		||||
      "integrity": "sha512-Iu0Kno1vrD7zHQDxOmvweqLkAzjxEVqNhUIXBsZ8hu8Oak7/5VTPrxOEZXYC1nmrBVJp0ZcL2E7lSuuOVaE3+w==",
 | 
			
		||||
      "version": "4.17.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz",
 | 
			
		||||
      "integrity": "sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "arm64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -415,9 +427,9 @@
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@rollup/rollup-linux-arm64-musl": {
 | 
			
		||||
      "version": "4.13.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.0.tgz",
 | 
			
		||||
      "integrity": "sha512-C31QrW47llgVyrRjIwiOwsHFcaIwmkKi3PCroQY5aVq4H0A5v/vVVAtFsI1nfBngtoRpeREvZOkIhmRwUKkAdw==",
 | 
			
		||||
      "version": "4.17.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz",
 | 
			
		||||
      "integrity": "sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "arm64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -426,10 +438,22 @@
 | 
			
		||||
        "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": {
 | 
			
		||||
      "version": "4.13.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.0.tgz",
 | 
			
		||||
      "integrity": "sha512-Oq90dtMHvthFOPMl7pt7KmxzX7E71AfyIhh+cPhLY9oko97Zf2C9tt/XJD4RgxhaGeAraAXDtqxvKE1y/j35lA==",
 | 
			
		||||
      "version": "4.17.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz",
 | 
			
		||||
      "integrity": "sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "riscv64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -438,10 +462,22 @@
 | 
			
		||||
        "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": {
 | 
			
		||||
      "version": "4.13.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.0.tgz",
 | 
			
		||||
      "integrity": "sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA==",
 | 
			
		||||
      "version": "4.17.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz",
 | 
			
		||||
      "integrity": "sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "x64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -451,9 +487,9 @@
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@rollup/rollup-linux-x64-musl": {
 | 
			
		||||
      "version": "4.13.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.0.tgz",
 | 
			
		||||
      "integrity": "sha512-9RyNqoFNdF0vu/qqX63fKotBh43fJQeYC98hCaf89DYQpv+xu0D8QFSOS0biA7cGuqJFOc1bJ+m2rhhsKcw1hw==",
 | 
			
		||||
      "version": "4.17.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz",
 | 
			
		||||
      "integrity": "sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "x64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -463,9 +499,9 @@
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@rollup/rollup-win32-arm64-msvc": {
 | 
			
		||||
      "version": "4.13.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.0.tgz",
 | 
			
		||||
      "integrity": "sha512-46ue8ymtm/5PUU6pCvjlic0z82qWkxv54GTJZgHrQUuZnVH+tvvSP0LsozIDsCBFO4VjJ13N68wqrKSeScUKdA==",
 | 
			
		||||
      "version": "4.17.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz",
 | 
			
		||||
      "integrity": "sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "arm64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -475,9 +511,9 @@
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@rollup/rollup-win32-ia32-msvc": {
 | 
			
		||||
      "version": "4.13.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.0.tgz",
 | 
			
		||||
      "integrity": "sha512-P5/MqLdLSlqxbeuJ3YDeX37srC8mCflSyTrUsgbU1c/U9j6l2g2GiIdYaGD9QjdMQPMSgYm7hgg0551wHyIluw==",
 | 
			
		||||
      "version": "4.17.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz",
 | 
			
		||||
      "integrity": "sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "ia32"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -487,9 +523,9 @@
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/@rollup/rollup-win32-x64-msvc": {
 | 
			
		||||
      "version": "4.13.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.0.tgz",
 | 
			
		||||
      "integrity": "sha512-UKXUQNbO3DOhzLRwHSpa0HnhhCgNODvfoPWv2FCXme8N/ANFfhIPMGuOT+QuKd16+B5yxZ0HdpNlqPvTMS1qfw==",
 | 
			
		||||
      "version": "4.17.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz",
 | 
			
		||||
      "integrity": "sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==",
 | 
			
		||||
      "cpu": [
 | 
			
		||||
        "x64"
 | 
			
		||||
      ],
 | 
			
		||||
@@ -679,9 +715,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/rollup": {
 | 
			
		||||
      "version": "4.13.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.0.tgz",
 | 
			
		||||
      "integrity": "sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==",
 | 
			
		||||
      "version": "4.17.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.2.tgz",
 | 
			
		||||
      "integrity": "sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@types/estree": "1.0.5"
 | 
			
		||||
      },
 | 
			
		||||
@@ -693,19 +729,22 @@
 | 
			
		||||
        "npm": ">=8.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "optionalDependencies": {
 | 
			
		||||
        "@rollup/rollup-android-arm-eabi": "4.13.0",
 | 
			
		||||
        "@rollup/rollup-android-arm64": "4.13.0",
 | 
			
		||||
        "@rollup/rollup-darwin-arm64": "4.13.0",
 | 
			
		||||
        "@rollup/rollup-darwin-x64": "4.13.0",
 | 
			
		||||
        "@rollup/rollup-linux-arm-gnueabihf": "4.13.0",
 | 
			
		||||
        "@rollup/rollup-linux-arm64-gnu": "4.13.0",
 | 
			
		||||
        "@rollup/rollup-linux-arm64-musl": "4.13.0",
 | 
			
		||||
        "@rollup/rollup-linux-riscv64-gnu": "4.13.0",
 | 
			
		||||
        "@rollup/rollup-linux-x64-gnu": "4.13.0",
 | 
			
		||||
        "@rollup/rollup-linux-x64-musl": "4.13.0",
 | 
			
		||||
        "@rollup/rollup-win32-arm64-msvc": "4.13.0",
 | 
			
		||||
        "@rollup/rollup-win32-ia32-msvc": "4.13.0",
 | 
			
		||||
        "@rollup/rollup-win32-x64-msvc": "4.13.0",
 | 
			
		||||
        "@rollup/rollup-android-arm-eabi": "4.17.2",
 | 
			
		||||
        "@rollup/rollup-android-arm64": "4.17.2",
 | 
			
		||||
        "@rollup/rollup-darwin-arm64": "4.17.2",
 | 
			
		||||
        "@rollup/rollup-darwin-x64": "4.17.2",
 | 
			
		||||
        "@rollup/rollup-linux-arm-gnueabihf": "4.17.2",
 | 
			
		||||
        "@rollup/rollup-linux-arm-musleabihf": "4.17.2",
 | 
			
		||||
        "@rollup/rollup-linux-arm64-gnu": "4.17.2",
 | 
			
		||||
        "@rollup/rollup-linux-arm64-musl": "4.17.2",
 | 
			
		||||
        "@rollup/rollup-linux-powerpc64le-gnu": "4.17.2",
 | 
			
		||||
        "@rollup/rollup-linux-riscv64-gnu": "4.17.2",
 | 
			
		||||
        "@rollup/rollup-linux-s390x-gnu": "4.17.2",
 | 
			
		||||
        "@rollup/rollup-linux-x64-gnu": "4.17.2",
 | 
			
		||||
        "@rollup/rollup-linux-x64-musl": "4.17.2",
 | 
			
		||||
        "@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"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
@@ -739,9 +778,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/smob": {
 | 
			
		||||
      "version": "1.4.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/smob/-/smob-1.4.1.tgz",
 | 
			
		||||
      "integrity": "sha512-9LK+E7Hv5R9u4g4C3p+jjLstaLe11MDsL21UpYaCNmapvMkYhqCV4A/f/3gyH8QjMyh6l68q9xC85vihY9ahMQ==",
 | 
			
		||||
      "version": "1.5.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz",
 | 
			
		||||
      "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/source-map": {
 | 
			
		||||
@@ -780,9 +819,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/terser": {
 | 
			
		||||
      "version": "5.29.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.1.tgz",
 | 
			
		||||
      "integrity": "sha512-lZQ/fyaIGxsbGxApKmoPTODIzELy3++mXhS5hOqaAWZjQtpq/hFHAc+rm29NND1rYRxRWKcjuARNwULNXa5RtQ==",
 | 
			
		||||
      "version": "5.31.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz",
 | 
			
		||||
      "integrity": "sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@jridgewell/source-map": "^0.3.3",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								deps/crypt_blowfish
									
									
									
									
										vendored
									
									
										Submodule
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								deps/crypt_blowfish
									
									
									
									
										vendored
									
									
										Submodule
									
								
							 Submodule deps/crypt_blowfish added at 3354bb81ee
									
								
							
							
								
								
									
										29
									
								
								deps/crypt_blowfish/LINKS
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								deps/crypt_blowfish/LINKS
									
									
									
									
										vendored
									
									
								
							@@ -1,29 +0,0 @@
 | 
			
		||||
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
									
									
								
							
							
						
						
									
										77
									
								
								deps/crypt_blowfish/Makefile
									
									
									
									
										vendored
									
									
								
							@@ -1,77 +0,0 @@
 | 
			
		||||
#
 | 
			
		||||
# 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
									
									
								
							
							
						
						
									
										30
									
								
								deps/crypt_blowfish/PERFORMANCE
									
									
									
									
										vendored
									
									
								
							@@ -1,30 +0,0 @@
 | 
			
		||||
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
									
									
								
							
							
						
						
									
										68
									
								
								deps/crypt_blowfish/README
									
									
									
									
										vendored
									
									
								
							@@ -1,68 +0,0 @@
 | 
			
		||||
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
									
									
								
							
							
						
						
									
										575
									
								
								deps/crypt_blowfish/crypt.3
									
									
									
									
										vendored
									
									
								
							@@ -1,575 +0,0 @@
 | 
			
		||||
.\" 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
									
									
								
							
							
						
						
									
										24
									
								
								deps/crypt_blowfish/crypt.h
									
									
									
									
										vendored
									
									
								
							@@ -1,24 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
									
									
								
							
							
						
						
									
										907
									
								
								deps/crypt_blowfish/crypt_blowfish.c
									
									
									
									
										vendored
									
									
								
							@@ -1,907 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
									
									
								
							
							
						
						
									
										27
									
								
								deps/crypt_blowfish/crypt_blowfish.h
									
									
									
									
										vendored
									
									
								
							@@ -1,27 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
									
									
								
							
							
						
						
									
										124
									
								
								deps/crypt_blowfish/crypt_gensalt.c
									
									
									
									
										vendored
									
									
								
							@@ -1,124 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
									
									
								
							
							
						
						
									
										30
									
								
								deps/crypt_blowfish/crypt_gensalt.h
									
									
									
									
										vendored
									
									
								
							@@ -1,30 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
									
									
								
							
							
						
						
									
										53
									
								
								deps/crypt_blowfish/glibc-2.1.3-crypt.diff
									
									
									
									
										vendored
									
									
								
							@@ -1,53 +0,0 @@
 | 
			
		||||
--- 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
									
									
								
							
							
						
						
									
										55
									
								
								deps/crypt_blowfish/glibc-2.14-crypt.diff
									
									
									
									
										vendored
									
									
								
							@@ -1,55 +0,0 @@
 | 
			
		||||
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
									
									
								
							
							
						
						
									
										52
									
								
								deps/crypt_blowfish/glibc-2.3.6-crypt.diff
									
									
									
									
										vendored
									
									
								
							@@ -1,52 +0,0 @@
 | 
			
		||||
--- 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
									
									
								
							
							
						
						
									
										43
									
								
								deps/crypt_blowfish/ow-crypt.h
									
									
									
									
										vendored
									
									
								
							@@ -1,43 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
									
									
								
							
							
						
						
									
										551
									
								
								deps/crypt_blowfish/wrapper.c
									
									
									
									
										vendored
									
									
								
							@@ -1,551 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
									
									
								
							
							
						
						
									
										203
									
								
								deps/crypt_blowfish/x86.S
									
									
									
									
										vendored
									
									
								
							@@ -1,203 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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
									
									
										Submodule
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								deps/libbacktrace
									
									
									
									
										vendored
									
									
										Submodule
									
								
							 Submodule deps/libbacktrace added at 11427f31a6
									
								
							
							
								
								
									
										5
									
								
								deps/libbacktrace/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								deps/libbacktrace/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,5 +0,0 @@
 | 
			
		||||
*~
 | 
			
		||||
*.o
 | 
			
		||||
*.lo
 | 
			
		||||
*.a
 | 
			
		||||
*.la
 | 
			
		||||
							
								
								
									
										9286
									
								
								deps/libbacktrace/Isaac.Newton-Opticks.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9286
									
								
								deps/libbacktrace/Isaac.Newton-Opticks.txt
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										29
									
								
								deps/libbacktrace/LICENSE
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								deps/libbacktrace/LICENSE
									
									
									
									
										vendored
									
									
								
							@@ -1,29 +0,0 @@
 | 
			
		||||
# 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
									
									
								
							
							
						
						
									
										623
									
								
								deps/libbacktrace/Makefile.am
									
									
									
									
										vendored
									
									
								
							@@ -1,623 +0,0 @@
 | 
			
		||||
# 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
									
									
								
							
							
						
						
									
										2666
									
								
								deps/libbacktrace/Makefile.in
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										36
									
								
								deps/libbacktrace/README.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										36
									
								
								deps/libbacktrace/README.md
									
									
									
									
										vendored
									
									
								
							@@ -1,36 +0,0 @@
 | 
			
		||||
# 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
									
									
								
							
							
						
						
									
										864
									
								
								deps/libbacktrace/aclocal.m4
									
									
									
									
										vendored
									
									
								
							@@ -1,864 +0,0 @@
 | 
			
		||||
# 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
									
									
								
							
							
						
						
									
										167
									
								
								deps/libbacktrace/alloc.c
									
									
									
									
										vendored
									
									
								
							@@ -1,167 +0,0 @@
 | 
			
		||||
/* 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
									
									
								
							
							
						
						
									
										136
									
								
								deps/libbacktrace/allocfail.c
									
									
									
									
										vendored
									
									
								
							@@ -1,136 +0,0 @@
 | 
			
		||||
/* 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
									
									
								
							
							
						
						
									
										104
									
								
								deps/libbacktrace/allocfail.sh
									
									
									
									
										vendored
									
									
								
							@@ -1,104 +0,0 @@
 | 
			
		||||
#!/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
 | 
			
		||||
							
								
								
									
										113
									
								
								deps/libbacktrace/atomic.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										113
									
								
								deps/libbacktrace/atomic.c
									
									
									
									
										vendored
									
									
								
							@@ -1,113 +0,0 @@
 | 
			
		||||
/* atomic.c -- Support for atomic functions if not present.
 | 
			
		||||
   Copyright (C) 2013-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 <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include "backtrace.h"
 | 
			
		||||
#include "backtrace-supported.h"
 | 
			
		||||
#include "internal.h"
 | 
			
		||||
 | 
			
		||||
/* This file holds implementations of the atomic functions that are
 | 
			
		||||
   used if the host compiler has the sync functions but not the atomic
 | 
			
		||||
   functions, as is true of versions of GCC before 4.7.  */
 | 
			
		||||
 | 
			
		||||
#if !defined (HAVE_ATOMIC_FUNCTIONS) && defined (HAVE_SYNC_FUNCTIONS)
 | 
			
		||||
 | 
			
		||||
/* Do an atomic load of a pointer.  */
 | 
			
		||||
 | 
			
		||||
void *
 | 
			
		||||
backtrace_atomic_load_pointer (void *arg)
 | 
			
		||||
{
 | 
			
		||||
  void **pp;
 | 
			
		||||
  void *p;
 | 
			
		||||
 | 
			
		||||
  pp = (void **) arg;
 | 
			
		||||
  p = *pp;
 | 
			
		||||
  while (!__sync_bool_compare_and_swap (pp, p, p))
 | 
			
		||||
    p = *pp;
 | 
			
		||||
  return p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Do an atomic load of an int.  */
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
backtrace_atomic_load_int (int *p)
 | 
			
		||||
{
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  i = *p;
 | 
			
		||||
  while (!__sync_bool_compare_and_swap (p, i, i))
 | 
			
		||||
    i = *p;
 | 
			
		||||
  return i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Do an atomic store of a pointer.  */
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
backtrace_atomic_store_pointer (void *arg, void *p)
 | 
			
		||||
{
 | 
			
		||||
  void **pp;
 | 
			
		||||
  void *old;
 | 
			
		||||
 | 
			
		||||
  pp = (void **) arg;
 | 
			
		||||
  old = *pp;
 | 
			
		||||
  while (!__sync_bool_compare_and_swap (pp, old, p))
 | 
			
		||||
    old = *pp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Do an atomic store of a size_t value.  */
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
backtrace_atomic_store_size_t (size_t *p, size_t v)
 | 
			
		||||
{
 | 
			
		||||
  size_t old;
 | 
			
		||||
 | 
			
		||||
  old = *p;
 | 
			
		||||
  while (!__sync_bool_compare_and_swap (p, old, v))
 | 
			
		||||
    old = *p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Do an atomic store of a int value.  */
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
backtrace_atomic_store_int (int *p, int v)
 | 
			
		||||
{
 | 
			
		||||
  size_t old;
 | 
			
		||||
 | 
			
		||||
  old = *p;
 | 
			
		||||
  while (!__sync_bool_compare_and_swap (p, old, v))
 | 
			
		||||
    old = *p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										66
									
								
								deps/libbacktrace/backtrace-supported.h.in
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										66
									
								
								deps/libbacktrace/backtrace-supported.h.in
									
									
									
									
										vendored
									
									
								
							@@ -1,66 +0,0 @@
 | 
			
		||||
/* backtrace-supported.h.in -- Whether stack backtrace is supported.
 | 
			
		||||
   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.  */
 | 
			
		||||
 | 
			
		||||
/* The file backtrace-supported.h.in is used by configure to generate
 | 
			
		||||
   the file backtrace-supported.h.  The file backtrace-supported.h may
 | 
			
		||||
   be #include'd to see whether the backtrace library will be able to
 | 
			
		||||
   get a backtrace and produce symbolic information.  */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* BACKTRACE_SUPPORTED will be #define'd as 1 if the backtrace library
 | 
			
		||||
   should work, 0 if it will not.  Libraries may #include this to make
 | 
			
		||||
   other arrangements.  */
 | 
			
		||||
 | 
			
		||||
#define BACKTRACE_SUPPORTED @BACKTRACE_SUPPORTED@
 | 
			
		||||
 | 
			
		||||
/* BACKTRACE_USES_MALLOC will be #define'd as 1 if the backtrace
 | 
			
		||||
   library will call malloc as it works, 0 if it will call mmap
 | 
			
		||||
   instead.  This may be used to determine whether it is safe to call
 | 
			
		||||
   the backtrace functions from a signal handler.  In general this
 | 
			
		||||
   only applies to calls like backtrace and backtrace_pcinfo.  It does
 | 
			
		||||
   not apply to backtrace_simple, which never calls malloc.  It does
 | 
			
		||||
   not apply to backtrace_print, which always calls fprintf and
 | 
			
		||||
   therefore malloc.  */
 | 
			
		||||
 | 
			
		||||
#define BACKTRACE_USES_MALLOC @BACKTRACE_USES_MALLOC@
 | 
			
		||||
 | 
			
		||||
/* BACKTRACE_SUPPORTS_THREADS will be #define'd as 1 if the backtrace
 | 
			
		||||
   library is configured with threading support, 0 if not.  If this is
 | 
			
		||||
   0, the threaded parameter to backtrace_create_state must be passed
 | 
			
		||||
   as 0.  */
 | 
			
		||||
 | 
			
		||||
#define BACKTRACE_SUPPORTS_THREADS @BACKTRACE_SUPPORTS_THREADS@
 | 
			
		||||
 | 
			
		||||
/* BACKTRACE_SUPPORTS_DATA will be #defined'd as 1 if the backtrace_syminfo
 | 
			
		||||
   will work for variables.  It will always work for functions.  */
 | 
			
		||||
 | 
			
		||||
#define BACKTRACE_SUPPORTS_DATA @BACKTRACE_SUPPORTS_DATA@
 | 
			
		||||
							
								
								
									
										129
									
								
								deps/libbacktrace/backtrace.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										129
									
								
								deps/libbacktrace/backtrace.c
									
									
									
									
										vendored
									
									
								
							@@ -1,129 +0,0 @@
 | 
			
		||||
/* backtrace.c -- Entry point for stack backtrace library.
 | 
			
		||||
   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 <sys/types.h>
 | 
			
		||||
 | 
			
		||||
#include "unwind.h"
 | 
			
		||||
#include "backtrace.h"
 | 
			
		||||
#include "internal.h"
 | 
			
		||||
 | 
			
		||||
/* The main backtrace_full routine.  */
 | 
			
		||||
 | 
			
		||||
/* Data passed through _Unwind_Backtrace.  */
 | 
			
		||||
 | 
			
		||||
struct backtrace_data
 | 
			
		||||
{
 | 
			
		||||
  /* Number of frames to skip.  */
 | 
			
		||||
  int skip;
 | 
			
		||||
  /* Library state.  */
 | 
			
		||||
  struct backtrace_state *state;
 | 
			
		||||
  /* Callback routine.  */
 | 
			
		||||
  backtrace_full_callback callback;
 | 
			
		||||
  /* Error callback routine.  */
 | 
			
		||||
  backtrace_error_callback error_callback;
 | 
			
		||||
  /* Data to pass to callback routines.  */
 | 
			
		||||
  void *data;
 | 
			
		||||
  /* Value to return from backtrace_full.  */
 | 
			
		||||
  int ret;
 | 
			
		||||
  /* Whether there is any memory available.  */
 | 
			
		||||
  int can_alloc;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Unwind library callback routine.  This is passed to
 | 
			
		||||
   _Unwind_Backtrace.  */
 | 
			
		||||
 | 
			
		||||
static _Unwind_Reason_Code
 | 
			
		||||
unwind (struct _Unwind_Context *context, void *vdata)
 | 
			
		||||
{
 | 
			
		||||
  struct backtrace_data *bdata = (struct backtrace_data *) vdata;
 | 
			
		||||
  uintptr_t pc;
 | 
			
		||||
  int ip_before_insn = 0;
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_GETIPINFO
 | 
			
		||||
  pc = _Unwind_GetIPInfo (context, &ip_before_insn);
 | 
			
		||||
#else
 | 
			
		||||
  pc = _Unwind_GetIP (context);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (bdata->skip > 0)
 | 
			
		||||
    {
 | 
			
		||||
      --bdata->skip;
 | 
			
		||||
      return _URC_NO_REASON;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!ip_before_insn)
 | 
			
		||||
    --pc;
 | 
			
		||||
 | 
			
		||||
  if (!bdata->can_alloc)
 | 
			
		||||
    bdata->ret = bdata->callback (bdata->data, pc, NULL, 0, NULL);
 | 
			
		||||
  else
 | 
			
		||||
    bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback,
 | 
			
		||||
				   bdata->error_callback, bdata->data);
 | 
			
		||||
  if (bdata->ret != 0)
 | 
			
		||||
    return _URC_END_OF_STACK;
 | 
			
		||||
 | 
			
		||||
  return _URC_NO_REASON;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get a stack backtrace.  */
 | 
			
		||||
 | 
			
		||||
int __attribute__((noinline))
 | 
			
		||||
backtrace_full (struct backtrace_state *state, int skip,
 | 
			
		||||
		backtrace_full_callback callback,
 | 
			
		||||
		backtrace_error_callback error_callback, void *data)
 | 
			
		||||
{
 | 
			
		||||
  struct backtrace_data bdata;
 | 
			
		||||
  void *p;
 | 
			
		||||
 | 
			
		||||
  bdata.skip = skip + 1;
 | 
			
		||||
  bdata.state = state;
 | 
			
		||||
  bdata.callback = callback;
 | 
			
		||||
  bdata.error_callback = error_callback;
 | 
			
		||||
  bdata.data = data;
 | 
			
		||||
  bdata.ret = 0;
 | 
			
		||||
 | 
			
		||||
  /* If we can't allocate any memory at all, don't try to produce
 | 
			
		||||
     file/line information.  */
 | 
			
		||||
  p = backtrace_alloc (state, 4096, NULL, NULL);
 | 
			
		||||
  if (p == NULL)
 | 
			
		||||
    bdata.can_alloc = 0;
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      backtrace_free (state, p, 4096, NULL, NULL);
 | 
			
		||||
      bdata.can_alloc = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  _Unwind_Backtrace (unwind, &bdata);
 | 
			
		||||
  return bdata.ret;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										189
									
								
								deps/libbacktrace/backtrace.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										189
									
								
								deps/libbacktrace/backtrace.h
									
									
									
									
										vendored
									
									
								
							@@ -1,189 +0,0 @@
 | 
			
		||||
/* backtrace.h -- Public header file for stack backtrace library.
 | 
			
		||||
   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.  */
 | 
			
		||||
 | 
			
		||||
#ifndef BACKTRACE_H
 | 
			
		||||
#define BACKTRACE_H
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* The backtrace state.  This struct is intentionally not defined in
 | 
			
		||||
   the public interface.  */
 | 
			
		||||
 | 
			
		||||
struct backtrace_state;
 | 
			
		||||
 | 
			
		||||
/* The type of the error callback argument to backtrace functions.
 | 
			
		||||
   This function, if not NULL, will be called for certain error cases.
 | 
			
		||||
   The DATA argument is passed to the function that calls this one.
 | 
			
		||||
   The MSG argument is an error message.  The ERRNUM argument, if
 | 
			
		||||
   greater than 0, holds an errno value.  The MSG buffer may become
 | 
			
		||||
   invalid after this function returns.
 | 
			
		||||
 | 
			
		||||
   As a special case, the ERRNUM argument will be passed as -1 if no
 | 
			
		||||
   debug info can be found for the executable, or if the debug info
 | 
			
		||||
   exists but has an unsupported version, but the function requires
 | 
			
		||||
   debug info (e.g., backtrace_full, backtrace_pcinfo).  The MSG in
 | 
			
		||||
   this case will be something along the lines of "no debug info".
 | 
			
		||||
   Similarly, ERRNUM will be passed as -1 if there is no symbol table,
 | 
			
		||||
   but the function requires a symbol table (e.g., backtrace_syminfo).
 | 
			
		||||
   This may be used as a signal that some other approach should be
 | 
			
		||||
   tried.  */
 | 
			
		||||
 | 
			
		||||
typedef void (*backtrace_error_callback) (void *data, const char *msg,
 | 
			
		||||
					  int errnum);
 | 
			
		||||
 | 
			
		||||
/* Create state information for the backtrace routines.  This must be
 | 
			
		||||
   called before any of the other routines, and its return value must
 | 
			
		||||
   be passed to all of the other routines.  FILENAME is the path name
 | 
			
		||||
   of the executable file; if it is NULL the library will try
 | 
			
		||||
   system-specific path names.  If not NULL, FILENAME must point to a
 | 
			
		||||
   permanent buffer.  If THREADED is non-zero the state may be
 | 
			
		||||
   accessed by multiple threads simultaneously, and the library will
 | 
			
		||||
   use appropriate atomic operations.  If THREADED is zero the state
 | 
			
		||||
   may only be accessed by one thread at a time.  This returns a state
 | 
			
		||||
   pointer on success, NULL on error.  If an error occurs, this will
 | 
			
		||||
   call the ERROR_CALLBACK routine.
 | 
			
		||||
 | 
			
		||||
   Calling this function allocates resources that cannot be freed.
 | 
			
		||||
   There is no backtrace_free_state function.  The state is used to
 | 
			
		||||
   cache information that is expensive to recompute.  Programs are
 | 
			
		||||
   expected to call this function at most once and to save the return
 | 
			
		||||
   value for all later calls to backtrace functions.  */
 | 
			
		||||
 | 
			
		||||
extern struct backtrace_state *backtrace_create_state (
 | 
			
		||||
    const char *filename, int threaded,
 | 
			
		||||
    backtrace_error_callback error_callback, void *data);
 | 
			
		||||
 | 
			
		||||
/* The type of the callback argument to the backtrace_full function.
 | 
			
		||||
   DATA is the argument passed to backtrace_full.  PC is the program
 | 
			
		||||
   counter.  FILENAME is the name of the file containing PC, or NULL
 | 
			
		||||
   if not available.  LINENO is the line number in FILENAME containing
 | 
			
		||||
   PC, or 0 if not available.  FUNCTION is the name of the function
 | 
			
		||||
   containing PC, or NULL if not available.  This should return 0 to
 | 
			
		||||
   continuing tracing.  The FILENAME and FUNCTION buffers may become
 | 
			
		||||
   invalid after this function returns.  */
 | 
			
		||||
 | 
			
		||||
typedef int (*backtrace_full_callback) (void *data, uintptr_t pc,
 | 
			
		||||
					const char *filename, int lineno,
 | 
			
		||||
					const char *function);
 | 
			
		||||
 | 
			
		||||
/* Get a full stack backtrace.  SKIP is the number of frames to skip;
 | 
			
		||||
   passing 0 will start the trace with the function calling
 | 
			
		||||
   backtrace_full.  DATA is passed to the callback routine.  If any
 | 
			
		||||
   call to CALLBACK returns a non-zero value, the stack backtrace
 | 
			
		||||
   stops, and backtrace returns that value; this may be used to limit
 | 
			
		||||
   the number of stack frames desired.  If all calls to CALLBACK
 | 
			
		||||
   return 0, backtrace returns 0.  The backtrace_full function will
 | 
			
		||||
   make at least one call to either CALLBACK or ERROR_CALLBACK.  This
 | 
			
		||||
   function requires debug info for the executable.  */
 | 
			
		||||
 | 
			
		||||
extern int backtrace_full (struct backtrace_state *state, int skip,
 | 
			
		||||
			   backtrace_full_callback callback,
 | 
			
		||||
			   backtrace_error_callback error_callback,
 | 
			
		||||
			   void *data);
 | 
			
		||||
 | 
			
		||||
/* The type of the callback argument to the backtrace_simple function.
 | 
			
		||||
   DATA is the argument passed to simple_backtrace.  PC is the program
 | 
			
		||||
   counter.  This should return 0 to continue tracing.  */
 | 
			
		||||
 | 
			
		||||
typedef int (*backtrace_simple_callback) (void *data, uintptr_t pc);
 | 
			
		||||
 | 
			
		||||
/* Get a simple backtrace.  SKIP is the number of frames to skip, as
 | 
			
		||||
   in backtrace.  DATA is passed to the callback routine.  If any call
 | 
			
		||||
   to CALLBACK returns a non-zero value, the stack backtrace stops,
 | 
			
		||||
   and backtrace_simple returns that value.  Otherwise
 | 
			
		||||
   backtrace_simple returns 0.  The backtrace_simple function will
 | 
			
		||||
   make at least one call to either CALLBACK or ERROR_CALLBACK.  This
 | 
			
		||||
   function does not require any debug info for the executable.  */
 | 
			
		||||
 | 
			
		||||
extern int backtrace_simple (struct backtrace_state *state, int skip,
 | 
			
		||||
			     backtrace_simple_callback callback,
 | 
			
		||||
			     backtrace_error_callback error_callback,
 | 
			
		||||
			     void *data);
 | 
			
		||||
 | 
			
		||||
/* Print the current backtrace in a user readable format to a FILE.
 | 
			
		||||
   SKIP is the number of frames to skip, as in backtrace_full.  Any
 | 
			
		||||
   error messages are printed to stderr.  This function requires debug
 | 
			
		||||
   info for the executable.  */
 | 
			
		||||
 | 
			
		||||
extern void backtrace_print (struct backtrace_state *state, int skip, FILE *);
 | 
			
		||||
 | 
			
		||||
/* Given PC, a program counter in the current program, call the
 | 
			
		||||
   callback function with filename, line number, and function name
 | 
			
		||||
   information.  This will normally call the callback function exactly
 | 
			
		||||
   once.  However, if the PC happens to describe an inlined call, and
 | 
			
		||||
   the debugging information contains the necessary information, then
 | 
			
		||||
   this may call the callback function multiple times.  This will make
 | 
			
		||||
   at least one call to either CALLBACK or ERROR_CALLBACK.  This
 | 
			
		||||
   returns the first non-zero value returned by CALLBACK, or 0.  */
 | 
			
		||||
 | 
			
		||||
extern int backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc,
 | 
			
		||||
			     backtrace_full_callback callback,
 | 
			
		||||
			     backtrace_error_callback error_callback,
 | 
			
		||||
			     void *data);
 | 
			
		||||
 | 
			
		||||
/* The type of the callback argument to backtrace_syminfo.  DATA and
 | 
			
		||||
   PC are the arguments passed to backtrace_syminfo.  SYMNAME is the
 | 
			
		||||
   name of the symbol for the corresponding code.  SYMVAL is the
 | 
			
		||||
   value and SYMSIZE is the size of the symbol.  SYMNAME will be NULL
 | 
			
		||||
   if no error occurred but the symbol could not be found.  */
 | 
			
		||||
 | 
			
		||||
typedef void (*backtrace_syminfo_callback) (void *data, uintptr_t pc,
 | 
			
		||||
					    const char *symname,
 | 
			
		||||
					    uintptr_t symval,
 | 
			
		||||
					    uintptr_t symsize);
 | 
			
		||||
 | 
			
		||||
/* Given ADDR, an address or program counter in the current program,
 | 
			
		||||
   call the callback information with the symbol name and value
 | 
			
		||||
   describing the function or variable in which ADDR may be found.
 | 
			
		||||
   This will call either CALLBACK or ERROR_CALLBACK exactly once.
 | 
			
		||||
   This returns 1 on success, 0 on failure.  This function requires
 | 
			
		||||
   the symbol table but does not require the debug info.  Note that if
 | 
			
		||||
   the symbol table is present but ADDR could not be found in the
 | 
			
		||||
   table, CALLBACK will be called with a NULL SYMNAME argument.
 | 
			
		||||
   Returns 1 on success, 0 on error.  */
 | 
			
		||||
 | 
			
		||||
extern int backtrace_syminfo (struct backtrace_state *state, uintptr_t addr,
 | 
			
		||||
			      backtrace_syminfo_callback callback,
 | 
			
		||||
			      backtrace_error_callback error_callback,
 | 
			
		||||
			      void *data);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
} /* End extern "C".  */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										501
									
								
								deps/libbacktrace/btest.c
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										501
									
								
								deps/libbacktrace/btest.c
									
									
									
									
										vendored
									
									
								
							@@ -1,501 +0,0 @@
 | 
			
		||||
/* btest.c -- Test for libbacktrace library
 | 
			
		||||
   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.  */
 | 
			
		||||
 | 
			
		||||
/* This program tests the externally visible interfaces of the
 | 
			
		||||
   libbacktrace library.  */
 | 
			
		||||
 | 
			
		||||
#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"
 | 
			
		||||
 | 
			
		||||
/* Test the backtrace function with non-inlined functions.  */
 | 
			
		||||
 | 
			
		||||
static int test1 (void) __attribute__ ((noinline, noclone, unused));
 | 
			
		||||
static int f2 (int) __attribute__ ((noinline, noclone));
 | 
			
		||||
static int f3 (int, int) __attribute__ ((noinline, noclone));
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
test1 (void)
 | 
			
		||||
{
 | 
			
		||||
  /* Returning a value here and elsewhere avoids a tailcall which
 | 
			
		||||
     would mess up the backtrace.  */
 | 
			
		||||
  return f2 (__LINE__) + 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
f2 (int f1line)
 | 
			
		||||
{
 | 
			
		||||
  return f3 (f1line, __LINE__) + 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
f3 (int f1line, int f2line)
 | 
			
		||||
{
 | 
			
		||||
  struct info all[20];
 | 
			
		||||
  struct bdata data;
 | 
			
		||||
  int f3line;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  data.all = &all[0];
 | 
			
		||||
  data.index = 0;
 | 
			
		||||
  data.max = 20;
 | 
			
		||||
  data.failed = 0;
 | 
			
		||||
 | 
			
		||||
  f3line = __LINE__ + 1;
 | 
			
		||||
  i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
 | 
			
		||||
 | 
			
		||||
  if (i != 0)
 | 
			
		||||
    {
 | 
			
		||||
      fprintf (stderr, "test1: unexpected return value %d\n", i);
 | 
			
		||||
      data.failed = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (data.index < 3)
 | 
			
		||||
    {
 | 
			
		||||
      fprintf (stderr,
 | 
			
		||||
	       "test1: not enough frames; got %zu, expected at least 3\n",
 | 
			
		||||
	       data.index);
 | 
			
		||||
      data.failed = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  check ("test1", 0, all, f3line, "f3", "btest.c", &data.failed);
 | 
			
		||||
  check ("test1", 1, all, f2line, "f2", "btest.c", &data.failed);
 | 
			
		||||
  check ("test1", 2, all, f1line, "test1", "btest.c", &data.failed);
 | 
			
		||||
 | 
			
		||||
  printf ("%s: backtrace_full noinline\n", data.failed ? "FAIL" : "PASS");
 | 
			
		||||
 | 
			
		||||
  if (data.failed)
 | 
			
		||||
    ++failures;
 | 
			
		||||
 | 
			
		||||
  return failures;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Test the backtrace function with inlined functions.  */
 | 
			
		||||
 | 
			
		||||
static inline int test2 (void) __attribute__ ((always_inline, unused));
 | 
			
		||||
static inline int f12 (int) __attribute__ ((always_inline));
 | 
			
		||||
static inline int f13 (int, int) __attribute__ ((always_inline));
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
test2 (void)
 | 
			
		||||
{
 | 
			
		||||
  return f12 (__LINE__) + 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
f12 (int f1line)
 | 
			
		||||
{
 | 
			
		||||
  return f13 (f1line, __LINE__) + 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
f13 (int f1line, int f2line)
 | 
			
		||||
{
 | 
			
		||||
  struct info all[20];
 | 
			
		||||
  struct bdata data;
 | 
			
		||||
  int f3line;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  data.all = &all[0];
 | 
			
		||||
  data.index = 0;
 | 
			
		||||
  data.max = 20;
 | 
			
		||||
  data.failed = 0;
 | 
			
		||||
 | 
			
		||||
  f3line = __LINE__ + 1;
 | 
			
		||||
  i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
 | 
			
		||||
 | 
			
		||||
  if (i != 0)
 | 
			
		||||
    {
 | 
			
		||||
      fprintf (stderr, "test2: unexpected return value %d\n", i);
 | 
			
		||||
      data.failed = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  check ("test2", 0, all, f3line, "f13", "btest.c", &data.failed);
 | 
			
		||||
  check ("test2", 1, all, f2line, "f12", "btest.c", &data.failed);
 | 
			
		||||
  check ("test2", 2, all, f1line, "test2", "btest.c", &data.failed);
 | 
			
		||||
 | 
			
		||||
  printf ("%s: backtrace_full inline\n", data.failed ? "FAIL" : "PASS");
 | 
			
		||||
 | 
			
		||||
  if (data.failed)
 | 
			
		||||
    ++failures;
 | 
			
		||||
 | 
			
		||||
  return failures;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Test the backtrace_simple function with non-inlined functions.  */
 | 
			
		||||
 | 
			
		||||
static int test3 (void) __attribute__ ((noinline, noclone, unused));
 | 
			
		||||
static int f22 (int) __attribute__ ((noinline, noclone));
 | 
			
		||||
static int f23 (int, int) __attribute__ ((noinline, noclone));
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
test3 (void)
 | 
			
		||||
{
 | 
			
		||||
  return f22 (__LINE__) + 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
f22 (int f1line)
 | 
			
		||||
{
 | 
			
		||||
  return f23 (f1line, __LINE__) + 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
f23 (int f1line, int f2line)
 | 
			
		||||
{
 | 
			
		||||
  uintptr_t addrs[20];
 | 
			
		||||
  struct sdata data;
 | 
			
		||||
  int f3line;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  data.addrs = &addrs[0];
 | 
			
		||||
  data.index = 0;
 | 
			
		||||
  data.max = 20;
 | 
			
		||||
  data.failed = 0;
 | 
			
		||||
 | 
			
		||||
  f3line = __LINE__ + 1;
 | 
			
		||||
  i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
 | 
			
		||||
 | 
			
		||||
  if (i != 0)
 | 
			
		||||
    {
 | 
			
		||||
      fprintf (stderr, "test3: unexpected return value %d\n", i);
 | 
			
		||||
      data.failed = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!data.failed)
 | 
			
		||||
    {
 | 
			
		||||
      struct info all[20];
 | 
			
		||||
      struct bdata bdata;
 | 
			
		||||
      int j;
 | 
			
		||||
 | 
			
		||||
      bdata.all = &all[0];
 | 
			
		||||
      bdata.index = 0;
 | 
			
		||||
      bdata.max = 20;
 | 
			
		||||
      bdata.failed = 0;
 | 
			
		||||
 | 
			
		||||
      for (j = 0; j < 3; ++j)
 | 
			
		||||
	{
 | 
			
		||||
	  i = backtrace_pcinfo (state, addrs[j], callback_one,
 | 
			
		||||
				error_callback_one, &bdata);
 | 
			
		||||
	  if (i != 0)
 | 
			
		||||
	    {
 | 
			
		||||
	      fprintf (stderr,
 | 
			
		||||
		       ("test3: unexpected return value "
 | 
			
		||||
			"from backtrace_pcinfo %d\n"),
 | 
			
		||||
		       i);
 | 
			
		||||
	      bdata.failed = 1;
 | 
			
		||||
	    }
 | 
			
		||||
	  if (!bdata.failed && bdata.index != (size_t) (j + 1))
 | 
			
		||||
	    {
 | 
			
		||||
	      fprintf (stderr,
 | 
			
		||||
		       ("wrong number of calls from backtrace_pcinfo "
 | 
			
		||||
			"got %u expected %d\n"),
 | 
			
		||||
		       (unsigned int) bdata.index, j + 1);
 | 
			
		||||
	      bdata.failed = 1;
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      check ("test3", 0, all, f3line, "f23", "btest.c", &bdata.failed);
 | 
			
		||||
      check ("test3", 1, all, f2line, "f22", "btest.c", &bdata.failed);
 | 
			
		||||
      check ("test3", 2, all, f1line, "test3", "btest.c", &bdata.failed);
 | 
			
		||||
 | 
			
		||||
      if (bdata.failed)
 | 
			
		||||
	data.failed = 1;
 | 
			
		||||
 | 
			
		||||
      for (j = 0; j < 3; ++j)
 | 
			
		||||
	{
 | 
			
		||||
	  struct symdata symdata;
 | 
			
		||||
 | 
			
		||||
	  symdata.name = NULL;
 | 
			
		||||
	  symdata.val = 0;
 | 
			
		||||
	  symdata.size = 0;
 | 
			
		||||
	  symdata.failed = 0;
 | 
			
		||||
 | 
			
		||||
	  i = backtrace_syminfo (state, addrs[j], callback_three,
 | 
			
		||||
				 error_callback_three, &symdata);
 | 
			
		||||
	  if (i == 0)
 | 
			
		||||
	    {
 | 
			
		||||
	      fprintf (stderr,
 | 
			
		||||
		       ("test3: [%d]: unexpected return value "
 | 
			
		||||
			"from backtrace_syminfo %d\n"),
 | 
			
		||||
		       j, i);
 | 
			
		||||
	      symdata.failed = 1;
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	  if (!symdata.failed)
 | 
			
		||||
	    {
 | 
			
		||||
	      const char *expected;
 | 
			
		||||
 | 
			
		||||
	      switch (j)
 | 
			
		||||
		{
 | 
			
		||||
		case 0:
 | 
			
		||||
		  expected = "f23";
 | 
			
		||||
		  break;
 | 
			
		||||
		case 1:
 | 
			
		||||
		  expected = "f22";
 | 
			
		||||
		  break;
 | 
			
		||||
		case 2:
 | 
			
		||||
		  expected = "test3";
 | 
			
		||||
		  break;
 | 
			
		||||
		default:
 | 
			
		||||
		  assert (0);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	      if (symdata.name == NULL)
 | 
			
		||||
		{
 | 
			
		||||
		  fprintf (stderr, "test3: [%d]: NULL syminfo name\n", j);
 | 
			
		||||
		  symdata.failed = 1;
 | 
			
		||||
		}
 | 
			
		||||
	      /* Use strncmp, not strcmp, because GCC might create a
 | 
			
		||||
		 clone.  */
 | 
			
		||||
	      else if (strncmp (symdata.name, expected, strlen (expected))
 | 
			
		||||
		       != 0)
 | 
			
		||||
		{
 | 
			
		||||
		  fprintf (stderr,
 | 
			
		||||
			   ("test3: [%d]: unexpected syminfo name "
 | 
			
		||||
			    "got %s expected %s\n"),
 | 
			
		||||
			   j, symdata.name, expected);
 | 
			
		||||
		  symdata.failed = 1;
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
 | 
			
		||||
	  if (symdata.failed)
 | 
			
		||||
	    data.failed = 1;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  printf ("%s: backtrace_simple noinline\n", data.failed ? "FAIL" : "PASS");
 | 
			
		||||
 | 
			
		||||
  if (data.failed)
 | 
			
		||||
    ++failures;
 | 
			
		||||
 | 
			
		||||
  return failures;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Test the backtrace_simple function with inlined functions.  */
 | 
			
		||||
 | 
			
		||||
static inline int test4 (void) __attribute__ ((always_inline, unused));
 | 
			
		||||
static inline int f32 (int) __attribute__ ((always_inline));
 | 
			
		||||
static inline int f33 (int, int) __attribute__ ((always_inline));
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
test4 (void)
 | 
			
		||||
{
 | 
			
		||||
  return f32 (__LINE__) + 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
f32 (int f1line)
 | 
			
		||||
{
 | 
			
		||||
  return f33 (f1line, __LINE__) + 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
f33 (int f1line, int f2line)
 | 
			
		||||
{
 | 
			
		||||
  uintptr_t addrs[20];
 | 
			
		||||
  struct sdata data;
 | 
			
		||||
  int f3line;
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  data.addrs = &addrs[0];
 | 
			
		||||
  data.index = 0;
 | 
			
		||||
  data.max = 20;
 | 
			
		||||
  data.failed = 0;
 | 
			
		||||
 | 
			
		||||
  f3line = __LINE__ + 1;
 | 
			
		||||
  i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
 | 
			
		||||
 | 
			
		||||
  if (i != 0)
 | 
			
		||||
    {
 | 
			
		||||
      fprintf (stderr, "test3: unexpected return value %d\n", i);
 | 
			
		||||
      data.failed = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!data.failed)
 | 
			
		||||
    {
 | 
			
		||||
      struct info all[20];
 | 
			
		||||
      struct bdata bdata;
 | 
			
		||||
 | 
			
		||||
      bdata.all = &all[0];
 | 
			
		||||
      bdata.index = 0;
 | 
			
		||||
      bdata.max = 20;
 | 
			
		||||
      bdata.failed = 0;
 | 
			
		||||
 | 
			
		||||
      i = backtrace_pcinfo (state, addrs[0], callback_one, error_callback_one,
 | 
			
		||||
			    &bdata);
 | 
			
		||||
      if (i != 0)
 | 
			
		||||
	{
 | 
			
		||||
	  fprintf (stderr,
 | 
			
		||||
		   ("test4: unexpected return value "
 | 
			
		||||
		    "from backtrace_pcinfo %d\n"),
 | 
			
		||||
		   i);
 | 
			
		||||
	  bdata.failed = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
      check ("test4", 0, all, f3line, "f33", "btest.c", &bdata.failed);
 | 
			
		||||
      check ("test4", 1, all, f2line, "f32", "btest.c", &bdata.failed);
 | 
			
		||||
      check ("test4", 2, all, f1line, "test4", "btest.c", &bdata.failed);
 | 
			
		||||
 | 
			
		||||
      if (bdata.failed)
 | 
			
		||||
	data.failed = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  printf ("%s: backtrace_simple inline\n", data.failed ? "FAIL" : "PASS");
 | 
			
		||||
 | 
			
		||||
  if (data.failed)
 | 
			
		||||
    ++failures;
 | 
			
		||||
 | 
			
		||||
  return failures;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int test5 (void) __attribute__ ((unused));
 | 
			
		||||
 | 
			
		||||
int global = 1;
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
test5 (void)
 | 
			
		||||
{
 | 
			
		||||
  struct symdata symdata;
 | 
			
		||||
  int i;
 | 
			
		||||
  uintptr_t addr = (uintptr_t) &global;
 | 
			
		||||
 | 
			
		||||
  if (sizeof (global) > 1)
 | 
			
		||||
    addr += 1;
 | 
			
		||||
 | 
			
		||||
  symdata.name = NULL;
 | 
			
		||||
  symdata.val = 0;
 | 
			
		||||
  symdata.size = 0;
 | 
			
		||||
  symdata.failed = 0;
 | 
			
		||||
 | 
			
		||||
  i = backtrace_syminfo (state, addr, callback_three,
 | 
			
		||||
			 error_callback_three, &symdata);
 | 
			
		||||
  if (i == 0)
 | 
			
		||||
    {
 | 
			
		||||
      fprintf (stderr,
 | 
			
		||||
	       "test5: unexpected return value from backtrace_syminfo %d\n",
 | 
			
		||||
	       i);
 | 
			
		||||
      symdata.failed = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (!symdata.failed)
 | 
			
		||||
    {
 | 
			
		||||
      if (symdata.name == NULL)
 | 
			
		||||
	{
 | 
			
		||||
	  fprintf (stderr, "test5: NULL syminfo name\n");
 | 
			
		||||
	  symdata.failed = 1;
 | 
			
		||||
	}
 | 
			
		||||
      else if (!(strncmp (symdata.name, "global", 6) == 0
 | 
			
		||||
		 && (symdata.name[6] == '\0'|| symdata.name[6] == '.')))
 | 
			
		||||
	{
 | 
			
		||||
	  fprintf (stderr,
 | 
			
		||||
		   "test5: unexpected syminfo name got %s expected %s\n",
 | 
			
		||||
		   symdata.name, "global");
 | 
			
		||||
	  symdata.failed = 1;
 | 
			
		||||
	}
 | 
			
		||||
      else if (symdata.val != (uintptr_t) &global)
 | 
			
		||||
	{
 | 
			
		||||
	  fprintf (stderr,
 | 
			
		||||
		   "test5: unexpected syminfo value got %lx expected %lx\n",
 | 
			
		||||
		   (unsigned long) symdata.val,
 | 
			
		||||
		   (unsigned long) (uintptr_t) &global);
 | 
			
		||||
	  symdata.failed = 1;
 | 
			
		||||
	}
 | 
			
		||||
      else if (symdata.size != sizeof (global))
 | 
			
		||||
	{
 | 
			
		||||
	  fprintf (stderr,
 | 
			
		||||
		   "test5: unexpected syminfo size got %lx expected %lx\n",
 | 
			
		||||
		   (unsigned long) symdata.size,
 | 
			
		||||
		   (unsigned long) sizeof (global));
 | 
			
		||||
	  symdata.failed = 1;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  printf ("%s: backtrace_syminfo variable\n",
 | 
			
		||||
	  symdata.failed ? "FAIL" : "PASS");
 | 
			
		||||
 | 
			
		||||
  if (symdata.failed)
 | 
			
		||||
    ++failures;
 | 
			
		||||
 | 
			
		||||
  return failures;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Check that are no files left open.  */
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
check_open_files (void)
 | 
			
		||||
{
 | 
			
		||||
  int i;
 | 
			
		||||
 | 
			
		||||
  for (i = 3; i < 10; i++)
 | 
			
		||||
    {
 | 
			
		||||
      if (close (i) == 0)
 | 
			
		||||
	{
 | 
			
		||||
	  fprintf (stderr,
 | 
			
		||||
		   "ERROR: descriptor %d still open after tests complete\n",
 | 
			
		||||
		   i);
 | 
			
		||||
	  ++failures;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Run all the tests.  */
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main (int argc ATTRIBUTE_UNUSED, char **argv)
 | 
			
		||||
{
 | 
			
		||||
  state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
 | 
			
		||||
				  error_callback_create, NULL);
 | 
			
		||||
 | 
			
		||||
#if BACKTRACE_SUPPORTED
 | 
			
		||||
  test1 ();
 | 
			
		||||
  test2 ();
 | 
			
		||||
  test3 ();
 | 
			
		||||
  test4 ();
 | 
			
		||||
#if BACKTRACE_SUPPORTS_DATA
 | 
			
		||||
  test5 ();
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  check_open_files ();
 | 
			
		||||
 | 
			
		||||
  exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
 | 
			
		||||
}
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user