Compare commits

...

117 Commits

Author SHA1 Message Date
e00f73e1d5 Merge branch 'submodules' of https://dev.tildefriends.net/tasiaiso/tildefriends into submodules 2024-03-22 20:25:42 +01:00
4c11667ebd android sdk, makefile changes 2024-03-22 20:25:32 +01:00
658e7089be Merge branch 'nix_package' into submodules 2024-03-22 12:29:09 +01:00
0965e90d7b build(nix): test nix package 2024-03-22 10:12:21 +01:00
d1f87a8fb4 remove lit 2024-03-22 10:07:13 +01:00
2b4265f9ee Merge branch 'main' into submodules 2024-03-22 09:02:12 +00:00
3bd827a9f7 remove some of the preinstalled dependencies (code_mirror, prettier) 2024-03-22 01:57:17 +01:00
474e39c9c3 add picohttpparser as a submodule 2024-03-22 01:37:45 +01:00
0272382e0e remove picohttpparser 2024-03-22 01:35:48 +01:00
b1c8b51377 add libuv as a submodule 2024-03-22 01:24:30 +01:00
1a5acca5cf remove libuv 2024-03-22 01:22:14 +01:00
2d5417f7dc add libbacktrace as a submodule 2024-03-22 01:14:27 +01:00
2a10d26215 remove libbacktrace 2024-03-22 01:08:23 +01:00
b8e5caba0d add crypt_blowfish as a submodule 2024-03-22 01:06:13 +01:00
a4b324127a remove crypt_blowfish 2024-03-22 01:05:29 +01:00
acae3e9562 add quickjs as a submodule 2024-03-22 00:55:37 +01:00
4aa7424977 remove quickjs 2024-03-22 00:51:31 +01:00
758f177617 add libsodium as a submodule 2024-03-22 00:45:21 +01:00
9291de41d8 remove libsodium 2024-03-22 00:43:03 +01:00
3603ce5ba6 add zlib as a submodule 2024-03-22 00:32:52 +01:00
bff231751e remove zlib 2024-03-22 00:32:01 +01:00
fdda628be8 Fix paths in the source tarball. 2024-03-20 20:43:41 -04:00
2b45d8aa05 Doh. Never mean to add that. 2024-03-20 20:37:52 -04:00
0e2fc65301 Document run -k flag. 2024-03-20 20:33:23 -04:00
e8ef7e74de Fixed a leak in JS blob store. 2024-03-18 12:46:12 -04:00
c32e1b9583 http request cleanup crash fix. 2024-03-18 16:34:07 +00:00
9d0f6ec155 Fix the sneaker app RE: JSONB. 2024-03-18 12:32:40 -04:00
855d603795 docs + prettier 2024-03-17 13:21:33 -04:00
af25782185 More http/request shutdown issues. 2024-03-17 12:38:37 -04:00
e5ba51b80a Chasing a leak that looks like an EBT clock. Deleted some unneeded code and adding a missing JS free. 2024-03-17 13:44:05 +00:00
5e240de677 Fix requesting blobs from blob_wants. ids were trucated. Yikes. 2024-03-17 09:16:06 -04:00
418cfac0e3 Add a stock app with local room connection info. #15 2024-03-14 00:43:11 +00:00
9d09607013 Update CodeMirror. 2024-03-13 20:23:48 -04:00
eddf25b622 Give libuv the same download treatment as sqlite. 2024-03-13 19:53:57 -04:00
537a8654fa Rename sequence_before_author => flags. #29 2024-03-13 19:40:09 -04:00
9de33d06d2 Specifying -fsanitize=... early seems good. 2024-03-13 18:26:24 -04:00
0e5f320664 sqlite 3.45.2. 2024-03-13 12:30:14 -04:00
88d8e60511 Some minor paranoia to appease valgrind. 2024-03-12 21:44:20 -04:00
439f07162e Disable Haiku automation tests until I find a way to automate a browser on Haiku. 2024-03-09 08:44:06 -05:00
efe2b6cbd9 A make target to run prettier. 2024-03-08 21:43:08 -05:00
0aa1ed9464 Fix a failure requesting more blobs. 2024-03-08 21:38:31 -05:00
cb94ed6a2a Some plumbing to expose the actual bound SHS port so that I can make a dynamic room app. 2024-03-07 21:03:14 -05:00
cf187ee46b Reorder things so that we only zipalign -z during a dist build. To slow for make all. 2024-03-07 20:42:08 -05:00
3e71fc20fd Prettier. 2024-03-06 21:14:09 -05:00
f3601321f7 That's all the doxygen warnings. #27 2024-03-06 21:13:16 -05:00
540059368c 11 make docs warnings left, but I'm out of time for tonight. 2024-03-06 20:57:38 -05:00
7ce89123f7 85 make docs warnings remain. 2024-03-06 12:46:27 -05:00
e3c7c86212 All but the two biggest .h files have docs. 2024-03-06 12:31:17 -05:00
794804e27f A few more .h file docs. 2024-03-05 21:17:20 -05:00
6d89c1da6e Format. 2024-03-05 20:49:30 -05:00
d059554464 Some workarounds for Haiku. uv_fs_scandir can't tell if a dirent is a file. setrlimit doesn't do anything productive for us. 2024-03-05 20:49:16 -05:00
3a392d4a9f More .h docs. 2024-03-05 12:47:58 -05:00
e3071b372a Poking at TCP binds from Haiku. 2024-03-04 21:51:27 -05:00
18bd279b0c Some progress on .h docs, and add a preliminary CONTRIBUTING.md. 2024-03-04 12:23:00 -05:00
5b93db7463 A buncha muncha cruncha .h docs. Also add vim temporary files to .gitignore. 2024-03-03 18:12:44 -05:00
5b7e5eb91b Give fts a better chance of working with jsonb messages.content. 2024-03-03 18:55:58 +00:00
78ca383e3c http.h docs. 2024-03-03 12:35:10 -05:00
c1eed9ada3 Fixed a leak in ssb.getServerIdentity(). 2024-03-03 12:20:03 -05:00
8d6feb5394 Set the root of private messages correct so that other clients show them. 2024-03-03 12:09:03 -05:00
42994f8977 Make the SSB network key configurable by command-line argument. 2024-03-02 15:01:09 -05:00
f0a871e1f8 More docs. 2024-03-01 21:18:12 -05:00
a710c30572 Fix apps for jsonb. 2024-02-29 19:26:56 -05:00
c991763b00 tests.h and tlscontext.js.h docs. 2024-02-28 21:18:59 -05:00
72dae14f87 Android NDK update. 2024-02-28 21:04:22 -05:00
5800340762 Fix up some more jsonb references. 2024-02-28 20:41:27 -05:00
c5f5adcac6 Missed some more jsonb messages.content use issues. 2024-02-28 20:31:25 -05:00
591642efb3 Convert messages.content to JSONB. This is a very disruptive change. 2024-02-28 20:01:52 -05:00
6182ffa1d4 Docs for tls.h and trace.h. 2024-02-28 19:12:41 -05:00
402a898d96 Let's start working on 0.0.17. 2024-02-28 18:47:21 -05:00
13d43d8319 Let's release 0.0.16. 2024-02-28 18:24:12 -05:00
7bcdbd3813 Revert "Update commonmark.js to 0.31.0."
This reverts commit 165f25db69.
2024-02-26 12:34:50 -05:00
60ada22674 Add a button to toggle visible whitespace for now. Not yet persisted. 2024-02-25 22:31:31 -05:00
637119d46d ideviceinstaller makes this unnecessary. 2024-02-25 21:41:32 -05:00
40f3da6a65 Fix a leak in returning HTTP responses. 2024-02-25 19:38:00 -05:00
f4697fe7f7 Update CodeMirror. 2024-02-25 18:54:35 -05:00
3bc18b9021 Docs for util.js.h. 2024-02-25 18:52:34 -05:00
c21581aefa Use zipalign w/zopfli for APKs to save a little on size. 2024-02-25 18:29:10 -05:00
165f25db69 Update commonmark.js to 0.31.0. 2024-02-25 16:25:23 -05:00
9aa0617aa1 Fix android argv. 2024-02-25 16:02:56 -05:00
ddce88dce6 Merge branch 'tasiaiso-wiki-improvements' 2024-02-25 15:37:56 -05:00
6aa2bce2be Merge branch 'wiki-improvements' of https://dev.tildefriends.net/tasiaiso/tildefriends into tasiaiso-wiki-improvements 2024-02-25 15:37:13 -05:00
a43c1d3d1e Format. 2024-02-25 15:03:43 -05:00
1ed0e817e8 BSD compile fix. 2024-02-25 14:57:14 -05:00
709ca55e65 Fix overbuild on macos. 2024-02-25 14:52:35 -05:00
8c13f5dbba xopt => getopt_long. I give up on xopt. It didn't help me as much as I had hoped, and I had problems building for mingw with only some versions of GCC. Not worth any further time. 2024-02-25 14:45:31 -05:00
4cb82d81b7 apps/gg doesn't belong here and isn't ready for prime time.. 2024-02-24 11:19:36 -05:00
0c42921387 Appease prettier in index.html. 2024-02-24 11:16:07 -05:00
70a3e7fc7d Make app export append a trailing newline to the app.json files so that we match prettier. 2024-02-24 11:12:35 -05:00
d5267be38c Run prettier. 2024-02-24 11:09:34 -05:00
8e7e0ed490 Merge branch 'tasiaiso-prettier' 2024-02-24 11:03:36 -05:00
8cf2837725 Export app json files indented with tabs. 2024-02-24 10:58:53 -05:00
63ae186c76 Export app json files indented with tabs. 2024-02-24 10:55:09 -05:00
dbf5c7b832 Merge branch 'main' into prettier 2024-02-23 09:50:49 +00:00
bfbfc01e99 keep the new config files 2024-02-23 10:42:26 +01:00
8fa9d0e843 Revert "build: Add prettier to the project"
This reverts commit 41024ddb79.
2024-02-23 10:35:39 +01:00
2d3e108fd9 Reapply "build: Add prettier to the project"
This reverts commit 7822b30dcb.
2024-02-23 10:29:46 +01:00
7822b30dcb Revert "build: Add prettier to the project"
This reverts commit 41024ddb79.
2024-02-23 10:25:51 +01:00
2701b7d04e Address some gcc-13 analyzer warnings. #33 2024-02-22 20:13:51 -05:00
e361c3f975 chore(wiki): the button class is now optional for input elements 2024-02-22 22:34:11 +01:00
260706c172 chore: copy .prettierrc.yaml over to client.js 2024-02-22 21:31:15 +01:00
390668ec34 Merge branch 'master' into prettier 2024-02-22 21:23:39 +01:00
1d5cdf9607 feat(wiki): improvements to the wiki's UI 2024-02-22 18:39:53 +01:00
a4bf3542e0 Merge branch 'main' into wiki-improvements 2024-02-22 15:14:49 +00:00
df82cfe66b chore rename core.css to tildefriends.css, remove license from tildefriends.css 2024-02-22 16:11:49 +01:00
53f9547cc5 style(wiki): use core.js 2024-02-22 13:03:21 +01:00
4bfd9de100 Give iOS the same openssl build treatment as android and mingw. #11 2024-02-21 20:23:35 -05:00
c01e00d77d Get geckodriver.log from 'tildefriends test -t auto' out of the root. 2024-02-21 20:06:25 -05:00
825191c08f Fix 'make dist'. 2024-02-21 19:59:26 -05:00
9dc6670795 Fetch and build OpenSSL as part of the code build. 2024-02-21 19:46:28 -05:00
1db8eee9f7 Merge pull request 'Documentation, build improvements' (#1) from tasiaiso/tildefriends:dev_tasia into main
Reviewed-on: cory/tildefriends#1
2024-02-21 23:51:01 +00:00
1bc50cb62c Remove prebuilt OpenSSL from source control. #11 2024-02-21 12:31:05 -05:00
450b07fd08 Add a Doxyfile and preliminary module-level docs. 2024-02-20 21:41:37 -05:00
12c7515ee8 chore: revert changes to codemirror's config 2024-02-20 18:45:46 +01:00
ed65da4340 doc: typos 2024-02-19 19:26:15 +01:00
d9d2917cf5 chore: add folders to .gitignore 2024-02-19 19:16:05 +01:00
ce5ca1875b doc: add JSDoc annotations in the core folder
start documenting a bit, mostly inconsequential changes
2024-02-19 19:12:42 +01:00
4f869252a2 codemirror: add build script, edit build settings
Disabled `highlightWhitespace()` and `highlightTrailingWhitespace()`, could be reverted if necessary
2024-02-19 15:15:41 +01:00
4092 changed files with 9673 additions and 1106108 deletions

12
.gitignore vendored
View File

@ -1,2 +1,14 @@
db.*
deps/ios_toolchain/
deps/openssl/
dist/
.keys
**/node_modules
out
*.swo
*.swp
.zsign_cache/
deps/codemirror/cm6.js
deps/prettier/standalone.mjs
deps/lit

22
.gitmodules vendored Normal file
View File

@ -0,0 +1,22 @@
[submodule "deps/zlib"]
path = deps/zlib
url = https://github.com/madler/zlib.git
branch = master
[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

View File

@ -3,8 +3,3 @@ useTabs: true
semi: true
singleQuote: true
bracketSpacing: false
# overrides:
# - files: '**/*.json'
# options:
# useTabs: false
# tabWidth: 2

37
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,37 @@
# Contributing to Tilde Friends
Thank you for your interest in Tilde Friends.
Above all, Tilde Friends aims to be a fun, safe place to play. When that is at
odds with the course of development, we will work through it with respectful
communication.
## How can I contribute?
The nature of Tilde Friends makes for a wide range of ways to contribute
- Just use it. Really, just kicking the tires will probably shake out issues
in useful ways at this point.
- Report and comment on bugs: https://dev.tildefriends.net/issues.
- Make apps. You don't need my permission to make and share apps with Tilde
Friends. I hope that an ecosystem of good apps grows outside of this
repository. If you want to recreate better versions of the stock apps, just
do it. If you make a better ssb app or whatever and drop me a line however
is most convenient for you, I will probably take a look and consider
replacing the stock one with it.
- Write about it. Docs in the git repository, blog posts, private messages to
me with ideas...really there is no wrong answer. Just make some noise, and
I'll do my best to incorporate or otherwise link your feedback and make the
most of it.
- Write C code in the git repository. I'm really striving for it to be the
case that other people don't really need to meddle in there, but if you can
help out, I will gladly review your pull requests via
https://dev.tildefriends.net/pulls.
## Best practices
- The C code is formatted with clang-format. Run `make format`.
- The rest is formatted with prettier. Run `npm run prettier`.
- We strive to have code compile on all platforms with no warnings and run with
no sanitizer issues.
- There are tests. Run `out/debug/tildefriends test`.

2614
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@ -3,16 +3,31 @@
MAKEFLAGS += --warn-undefined-variables
MAKEFLAGS += --no-builtin-rules
VERSION_CODE := 16
VERSION_NUMBER := 0.0.16-wip
VERSION_NAME := Medium English breakfast tea.
VERSION_CODE := 17
VERSION_NUMBER := 0.0.17-wip
VERSION_NAME := Please enjoy responsibly.
SQLITE_URL := https://www.sqlite.org/2024/sqlite-amalgamation-3450200.zip
PROJECT = tildefriends
BUILD_DIR ?= out
UNAME_S := $(shell uname -s)
UNAME_M := $(shell uname -m)
ANDROID_SDK ?= ~/Android/Sdk
#ANDROID_SDK ?= ~/Android/Sdk
ANDROID_SDK ?= /nix/store/54n9xsbb8gxa719g0bs7ghp336pax6mq-androidsdk/libexec/android-sdk
ifeq ($(UNAME_M),x86_64)
ifneq ($(UNAME_S),Haiku)
debug: CFLAGS += -fsanitize=address -fsanitize=undefined -fno-common
debug: LDFLAGS += -fsanitize=address -fsanitize=undefined
endif
endif
ifeq ($(UNAME_M),aarch64)
debug: CFLAGS += -fsanitize=address -fsanitize=undefined -fno-common
debug: LDFLAGS += -fsanitize=address -fsanitize=undefined
endif
ifeq ($(UNAME_S),Darwin)
BUILD_TYPES := macosdebug macosrelease iosdebug iosrelease iossimdebug iossimrelease
@ -55,7 +70,7 @@ CFLAGS += \
ANDROID_BUILD_TOOLS := $(ANDROID_SDK)/build-tools/34.0.0
ANDROID_PLATFORM := $(ANDROID_SDK)/platforms/android-34
ANDROID_NDK ?= $(ANDROID_SDK)/ndk/26.1.10909125
ANDROID_NDK ?= $(ANDROID_SDK)/ndk/26.2.11394342
ANDROID_MIN_SDK_VERSION := 24
ANDROID_TARGET_SDK_VERSION := 34
@ -207,18 +222,6 @@ $(IOS_TARGETS): LDFLAGS += -Ldeps/openssl/ios/ios64-xcrun/usr/local/lib
$(IOSSIM_TARGETS): CFLAGS += -Ideps/openssl/ios/iossimulator-xcrun/usr/local/include
$(IOSSIM_TARGETS): LDFLAGS += -Ldeps/openssl/ios/iossimulator-xcrun/usr/local/lib
ifeq ($(UNAME_M),x86_64)
ifneq ($(UNAME_S),Haiku)
debug: CFLAGS += -fsanitize=address -fsanitize=undefined -fno-common
debug: LDFLAGS += -fsanitize=address -fsanitize=undefined
endif
endif
ifeq ($(UNAME_M),aarch64)
debug: CFLAGS += -fsanitize=address -fsanitize=undefined -fno-common
debug: LDFLAGS += -fsanitize=address -fsanitize=undefined
endif
get_objs = \
$(foreach build_type,$(BUILD_TYPES),$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)))))) \
$(foreach build_type,debug release,$(addprefix $(BUILD_DIR)/$(build_type)/,$(addsuffix .o,$(basename $(value $(1)_unix))))) \
@ -245,7 +248,6 @@ $(APP_OBJS): CFLAGS += \
-Ideps/quickjs \
-Ideps/sqlite \
-Ideps/valgrind \
-Ideps/xopt \
-Wdouble-promotion \
-Werror
ifeq ($(UNAME_M),x86_64)
@ -497,18 +499,6 @@ $(SQLITE_OBJS): CFLAGS += \
-Wno-unused-function \
-Wno-unused-variable
XOPT_SOURCES := deps/xopt/xopt.c
XOPT_OBJS := $(call get_objs,XOPT_SOURCES)
$(filter $(BUILD_DIR)/win%,$(XOPT_OBJS)): CFLAGS += \
-DHAVE_SNPRINTF \
-DHAVE_VSNPRINTF \
-DHAVE_VASNPRINTF \
-DHAVE_VASPRINTF \
-Dvsnprintf=rpl_vsnprintf
$(XOPT_OBJS): CFLAGS += \
-Wno-implicit-const-int-float-conversion \
-Wno-pointer-to-int-cast
QUICKJS_SOURCES := \
deps/quickjs/cutils.c \
deps/quickjs/libbf.c \
@ -637,8 +627,7 @@ ALL_APP_OBJS := \
$(QUICKJS_OBJS) \
$(SODIUM_OBJS) \
$(SQLITE_OBJS) \
$(UV_OBJS) \
$(XOPT_OBJS)
$(UV_OBJS)
DEPS = $(ALL_APP_OBJS:.o=.d)
-include $(DEPS)
@ -696,6 +685,7 @@ out/res/drawable_icon.xml.flat: src/android/res/drawable/icon.xml
out/apk/res.apk out/gen/com/unprompted/tildefriends/R.java: out/res/layout_activity_main.xml.flat out/res/drawable_icon.xml.flat src/android/AndroidManifest.xml
@mkdir -p $(dir $@)
mkdir -p out/apk
@$(ANDROID_BUILD_TOOLS)/aapt2 link -I $(ANDROID_PLATFORM)/android.jar out/res/layout_activity_main.xml.flat out/res/drawable_icon.xml.flat --manifest src/android/AndroidManifest.xml -o out/apk/res.apk --java out/gen/
JAVA_FILES := out/gen/com/unprompted/tildefriends/R.java $(wildcard src/android/com/unprompted/tildefriends/*.java)
@ -717,7 +707,7 @@ PACKAGE_DIRS := \
deps/prettier/ \
deps/lit/
RAW_FILES := $(filter-out apps/blog% apps/gg% apps/issues% apps/welcome% apps/journal% %.map, $(shell find $(PACKAGE_DIRS) -type f))
RAW_FILES := $(filter-out apps/blog% apps/issues% apps/welcome% apps/journal% %.map, $(shell find $(PACKAGE_DIRS) -type f))
out/apk/TildeFriends-arm-debug.unsigned.apk: BUILD_TYPE := debug
out/apk/TildeFriends-arm-release.unsigned.apk: BUILD_TYPE := release
@ -736,10 +726,11 @@ out/apk/TildeFriends-arm-%.unsigned.apk:
@cp out/android$(BUILD_TYPE)-armv7a/tildefriends out/apk-arm-$(BUILD_TYPE)/lib/armeabi-v7a/tildefriends.so
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-arm-$(BUILD_TYPE)/lib/arm64-v8a/tildefriends.so
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-arm-$(BUILD_TYPE)/lib/armeabi-v7a/tildefriends.so
@cp out/apk/res.apk $@
@cp out/apk/res.apk $@.zip
@cp out/apk/classes.dex out/apk-arm-$(BUILD_TYPE)/
@cd out/apk-arm-$(BUILD_TYPE) && zip -u ../../$@ -q -9 -r . && cd ../../
@zip -u $@ -q -9 $(RAW_FILES)
@cd out/apk-arm-$(BUILD_TYPE) && zip -u ../../$@.zip -q -9 -r . && cd ../../
@zip -u $@.zip -q $(RAW_FILES)
@$(ANDROID_BUILD_TOOLS)/zipalign -f 4 $@.zip $@
out/apk/TildeFriends-x86-%.unsigned.apk:
@mkdir -p $(dir $@) out/apk-x86-$(BUILD_TYPE)/lib/x86_64/ out/apk-x86-$(BUILD_TYPE)/lib/x86/
@ -748,16 +739,22 @@ out/apk/TildeFriends-x86-%.unsigned.apk:
@cp out/android$(BUILD_TYPE)-x86/tildefriends out/apk-x86-$(BUILD_TYPE)/lib/x86/tildefriends.so
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-x86-$(BUILD_TYPE)/lib/x86_64/tildefriends.so
@$(ANDROID_NDK)/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip out/apk-x86-$(BUILD_TYPE)/lib/x86/tildefriends.so
@cp out/apk/res.apk $@
@cp out/apk/res.apk $@.zip
@cp out/apk/classes.dex out/apk-x86-$(BUILD_TYPE)/
@cd out/apk-x86-$(BUILD_TYPE) && zip -u ../../$@ -q -9 -r . && cd ../../
@zip -u $@ -q -9 $(RAW_FILES)
@cd out/apk-x86-$(BUILD_TYPE) && zip -u ../../$@.zip -q -9 -r . && cd ../../
@zip -u $@.zip -q $(RAW_FILES)
@$(ANDROID_BUILD_TOOLS)/zipalign -f 4 $@.zip $@
out/%.apk: out/apk/%.unsigned.apk
@echo "[apksigner] $(notdir $@)"
@$(ANDROID_BUILD_TOOLS)/apksigner sign --ks .keys/android.jks --ks-key-alias androidKey --ks-pass pass:android --key-pass pass:android --out $@ $<
@$(ANDROID_BUILD_TOOLS)/apksigner sign --ks .keys/android.jks --ks-key-alias androidKey --ks-pass pass:android --key-pass pass:android --min-sdk-version $(ANDROID_MIN_SDK_VERSION) --out $@ $<
release-apk: out/TildeFriends-arm-release.apk out/TildeFriends-x86-release.apk
out/%.zopfli.apk: out/%.apk
@echo "[zopfli] $(notdir $@)"
$(ANDROID_BUILD_TOOLS)/zipalign -f -z 4 $< $@.zopfli
@$(ANDROID_BUILD_TOOLS)/apksigner sign --ks .keys/android.jks --ks-key-alias androidKey --ks-pass pass:android --key-pass pass:android --min-sdk-version $(ANDROID_MIN_SDK_VERSION) --out $@ $@.zopfli
release-apk: out/TildeFriends-arm-release.zopfli.apk out/TildeFriends-x86-release.zopfli.apk
.PHONY: release-apk
releaseapkgo: out/TildeFriends-arm-release.apk
@ -813,31 +810,46 @@ apklog:
.PHONY: apklog
fetchdeps:
@echo "[fetch] libuv"
@test -f out/deps/libuv.tar.gz || (mkdir -p out/deps/ && curl -q https://dist.libuv.org/dist/v1.48.0/libuv-v1.48.0.tar.gz -o out/deps/libuv.tar.gz)
@test -d deps/libuv/ || (mkdir -p deps/libuv/ && tar -C deps/libuv/ -m --strip=1 -xf out/deps/libuv.tar.gz)
@echo "[fetch] sqlite"
@test -f out/deps/sqlite.zip || (mkdir -p out/deps/ && curl -q https://www.sqlite.org/2024/sqlite-amalgamation-3450100.zip -o out/deps/sqlite.zip)
@test -d deps/sqlite/ || (mkdir -p deps/sqlite/ && unzip -qDj -d deps/sqlite/ out/deps/sqlite.zip)
@test -f out/deps/sqlite.zip && test "$$(cat out/deps/sqlite.txt 2>/dev/null)" = $(SQLITE_URL) || (mkdir -p out/deps/ && curl -q $(SQLITE_URL) -o out/deps/sqlite.zip)
@test -d deps/sqlite/ && test "$$(cat out/deps/sqlite.txt 2>/dev/null)" = $(SQLITE_URL) || (mkdir -p deps/sqlite/ && unzip -qDjo -d deps/sqlite/ out/deps/sqlite.zip)
@echo -n $(SQLITE_URL) > out/deps/sqlite.txt
@echo "[fetch] prettier"
@test -f deps/prettier/standalone.mjs || curl -q --create-dirs -O --output-dir deps/prettier/ https://cdn.jsdelivr.net/npm/prettier@3.2.5/standalone.mjs
@test -f deps/prettier/html.mjs || curl -q --create-dirs -O --output-dir deps/prettier/ https://cdn.jsdelivr.net/npm/prettier@3.2.5/plugins/html.mjs
@test -f deps/prettier/babel.mjs || curl -q --create-dirs -O --output-dir deps/prettier/ https://cdn.jsdelivr.net/npm/prettier@3.2.5/plugins/babel.mjs
@test -f deps/prettier/estree.mjs || curl -q --create-dirs -O --output-dir deps/prettier/ https://cdn.jsdelivr.net/npm/prettier@3.2.5/plugins/estree.mjs
.PHONE: fetchdeps
.PHONY: fetchdeps
ANDROID_DEPS := deps/openssl/android/arm64-v8a/usr/local/lib/libssl.a
$(ANDROID_DEPS):
+@tools/ssl-android
$(filter $(BUILD_DIR)/android%,$(APP_OBJS)): | $(ANDROID_DEPS)
ifeq ($(HAVE_WIN),1)
WINDOWS_DEPS := deps/openssl/mingw64/usr/local/lib/libssl.a
$(WINDOWS_DEPS):
+@tools/ssl-mingw64
$(filter $(BUILD_DIR)/win%,$(APP_OBJS)): | $(WINDOWS_DEPS)
endif
ifeq ($(UNAME_S),Darwin)
IOS_DEPS := deps/openssl/ios/ios64-xcrun/usr/local/lib/libssl.a
$(IOS_DEPS):
+@tools/ssl-ios
$(filter $(BUILD_DIR)/ios%,$(APP_OBJS)): | $(IOS_DEPS)
endif
clean:
rm -rf $(BUILD_DIR)
.PHONY: clean
dist: release-apk iosrelease-ipa
@echo "[export] $$(svn info --show-item url)"
@rm -rf tildefriends-$(VERSION_NUMBER)
@svn export -q . tildefriends-$(VERSION_NUMBER)
@echo "tildefriends-$(VERSION_NUMBER): $(VERSION_NAME)" > tildefriends-$(VERSION_NUMBER)/VERSION
@echo "[tar] tildefriends-$(VERSION_NUMBER).tar.xz"
@echo [archive] dist/tildefriends-$(VERSION_NUMBER).tar.xz
@rm -rf out/tildefriends-$(VERSION_NUMBER)
@mkdir -p dist/ out/tildefriends-$(VERSION_NUMBER)
@git archive main | tar -x -C out/tildefriends-$(VERSION_NUMBER)
@tar \
--exclude=apps/gg* \
--exclude=apps/welcome* \
--exclude=deps/libbacktrace/Isaac.Newton-Opticks.txt \
--exclude=deps/libsodium/builds/msvc/vs* \
@ -852,14 +864,15 @@ dist: release-apk iosrelease-ipa
--exclude=deps/sqlite/shell.c \
--exclude=deps/zlib/contrib/vstudio \
--exclude=deps/zlib/doc \
-caf tildefriends-$(VERSION_NUMBER).tar.xz tildefriends-$(VERSION_NUMBER)
@rm -rf tildefriends-$(VERSION_NUMBER)
-caf dist/tildefriends-$(VERSION_NUMBER).tar.xz \
-C out/ \
tildefriends-$(VERSION_NUMBER)
@echo "[cp] TildeFriends-x86-$(VERSION_NUMBER).apk"
@cp out/TildeFriends-x86-release.apk TildeFriends-x86-$(VERSION_NUMBER).apk
@cp out/TildeFriends-x86-release.zopfli.apk dist/TildeFriends-x86-$(VERSION_NUMBER).apk
@echo "[cp] TildeFriends-arm-$(VERSION_NUMBER).apk"
@cp out/TildeFriends-arm-release.apk TildeFriends-arm-$(VERSION_NUMBER).apk
@cp out/TildeFriends-arm-release.zopfli.apk dist/TildeFriends-arm-$(VERSION_NUMBER).apk
@echo "[cp] TildeFriends-$(VERSION_NUMBER).ipa"
@cp out/tildefriends-release.ipa TildeFriends-$(VERSION_NUMBER).ipa
@cp out/tildefriends-release.ipa dist/TildeFriends-$(VERSION_NUMBER).ipa
.PHONY: dist
dist-test: dist
@ -872,3 +885,11 @@ dist-test: dist
format:
@clang-format -i $(wildcard src/*.c src/*.h src/*.m)
.PHONY: format
prettier:
@npm run prettier
.PHONY: prettier
docs:
@doxygen
.PHONY: docs

View File

@ -4,34 +4,46 @@ 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.
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.
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`.
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.
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/>.
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/>.
## 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:
<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 unless otherwise noted in is provided under the
[MIT](https://opensource.org/licenses/MIT) license.

27
android-sdk.nix Normal file
View File

@ -0,0 +1,27 @@
with import <nixpkgs> {};
let
androidComposition = androidenv.composeAndroidPackages {
cmdLineToolsVersion = "9.0";
toolsVersion = "26.1.1";
platformToolsVersion = "34.0.5";
buildToolsVersions = [ "34.0.0" ];
includeEmulator = false;
#emulatorVersion = "30.3.4";
platformVersions = [ "34" ];
includeSources = false;
includeSystemImages = false;
#systemImageTypes = [ "google_apis_playstore" ];
#abiVersions = [ "armeabi-v7a" "arm64-v8a" ];
#cmakeVersions = [ "3.10.2" ];
includeNDK = true;
ndkVersions = ["26.0.10792818"];
useGoogleAPIs = false;
useGoogleTVAddOns = false;
#includeExtras = [
# "extras;google;gcm"
#];
};
in
androidComposition.androidsdk
# $ NIXPKGS_ACCEPT_ANDROID_SDK_LICENSE=1 NIXPKGS_ALLOW_UNFREE=1 nix-build android-sdk.nix --impure

View File

@ -87,6 +87,6 @@ window.addEventListener('load', function () {
.map((x) => html`${input_template(x, data.settings[x])}`)}
</div>
${users_template(data.users)}
</div>`;
</div> `;
render(page_template(g_data), document.body);
});

View File

@ -1,5 +1,5 @@
{
"type": "tildefriends-app",
"emoji": "💻",
"previous": "&RdVEsVscZm3aWzcMrEZS8mskO5tUmvaEUihex2MMfZQ=.sha256"
"previous": "&icsPplXHgmpkbNWyo/WTvRdT/A8BXxW4lJixOtP4ueQ=.sha256"
}

View File

@ -28,10 +28,10 @@ async function fetch_shared_apps() {
await ssb.sqlAsync(
`
SELECT messages.*
SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
FROM messages_fts('"application/tildefriends"')
JOIN messages ON messages.rowid = messages_fts.rowid
ORDER BY timestamp
ORDER BY messages.timestamp
`,
[],
function (row) {

View File

@ -1,4 +1,4 @@
{
"type": "tildefriends-app",
"emoji": "💽"
}
"type": "tildefriends-app",
"emoji": "💽"
}

View File

@ -1,5 +0,0 @@
{
"type": "tildefriends-app",
"emoji": "🗺",
"previous": "&0XSp+xdQwVtQ88bXzvWdH15Ex63hv5zUKTa4zx7HBGM=.sha256"
}

View File

@ -1,85 +0,0 @@
import * as tfrpc from '/tfrpc.js';
import * as strava from './strava.js';
let g_database;
let g_shared_database;
tfrpc.register(async function createIdentity() {
return ssb.createIdentity();
});
tfrpc.register(async function appendMessage(id, message) {
print('APPEND', JSON.stringify(message));
return ssb.appendMessageWithIdentity(id, message);
});
tfrpc.register(function url() {
return core.url;
});
tfrpc.register(async function getUser() {
return core.user;
});
tfrpc.register(function getIdentities() {
return ssb.getIdentities();
});
tfrpc.register(async function databaseGet(key) {
return g_database ? g_database.get(key) : undefined;
});
tfrpc.register(async function databaseSet(key, value) {
return g_database ? g_database.set(key, value) : undefined;
});
tfrpc.register(async function databaseRemove(key, value) {
return g_database ? g_database.remove(key, value) : undefined;
});
tfrpc.register(async function sharedDatabaseGet(key) {
return g_shared_database ? g_shared_database.get(key) : undefined;
});
tfrpc.register(async function sharedDatabaseSet(key, value) {
return g_shared_database ? g_shared_database.set(key, value) : undefined;
});
tfrpc.register(async function sharedDatabaseRemove(key, value) {
return g_shared_database ? g_shared_database.remove(key, value) : undefined;
});
tfrpc.register(async function query(sql, args) {
let result = [];
await ssb.sqlAsync(sql, args, function callback(row) {
result.push(row);
});
return result;
});
tfrpc.register(async function store_blob(blob) {
if (typeof blob == 'string') {
blob = utf8Encode(blob);
}
if (Array.isArray(blob)) {
blob = Uint8Array.from(blob);
}
return await ssb.blobStore(blob);
});
tfrpc.register(async function get_blob(id) {
return utf8Decode(await ssb.blobGet(id));
});
tfrpc.register(strava.refresh_token);
async function main() {
g_shared_database = await shared_database('state');
if (core.user.credentials?.session?.name) {
g_database = await database('state');
}
let attempt;
if (core.user.credentials?.session?.name) {
let shared_db = await shared_database('state');
attempt = await shared_db.get(core.user.credentials.session.name);
}
app.setDocument(
utf8Decode(getFile('index.html')).replace(
'${data}',
JSON.stringify({
attempt: attempt,
state: core.user?.credentials?.session?.name,
})
)
);
}
main();

File diff suppressed because one or more lines are too long

View File

@ -1,84 +0,0 @@
function xml_parse(xml) {
let result;
let path = [];
let tag_begin;
let text_begin;
for (let i = 0; i < xml.length; i++) {
let c = xml.charAt(i);
if (!tag_begin && c == '<') {
if (i > text_begin && path.length) {
let value = xml.substring(text_begin, i);
if (!/^\s*$/.test(value)) {
path[path.length - 1].value = value;
}
}
tag_begin = i + 1;
} else if (tag_begin && c == '>') {
let tag = xml.substring(tag_begin, i).trim();
if (tag.startsWith('?') && tag.endsWith('?')) {
/* Ignore directives. */
} else if (tag.startsWith('/')) {
path.pop();
} else {
let parts = tag.split(' ');
let attributes = {};
for (let j = 1; j < parts.length; j++) {
let eq = parts[j].indexOf('=');
let value = parts[j].substring(eq + 1);
if (value.startsWith('"') && value.endsWith('"')) {
value = value.substring(1, value.length - 1);
}
attributes[parts[j].substring(0, eq)] = value;
}
let next = {name: parts[0], children: [], attributes: attributes};
if (path.length) {
path[path.length - 1].children.push(next);
} else {
result = next;
}
if (!tag.endsWith('/')) {
path.push(next);
}
}
tag_begin = undefined;
text_begin = i + 1;
}
}
return result;
}
function* xml_each(node, name) {
for (let child of node.children) {
if (child.name == name) {
yield child;
}
}
}
export function gpx_parse(xml) {
let result = {segments: []};
let tree = xml_parse(xml);
if (tree?.name == 'gpx') {
for (let trk of xml_each(tree, 'trk')) {
for (let trkseg of xml_each(trk, 'trkseg')) {
let segment = [];
for (let trkpt of xml_each(trkseg, 'trkpt')) {
segment.push({
lat: parseFloat(trkpt.attributes.lat),
lon: parseFloat(trkpt.attributes.lon),
});
}
result.segments.push(segment);
}
}
}
for (let metadata of xml_each(tree, 'metadata')) {
for (let link of xml_each(metadata, 'link')) {
result.link = link.attributes.href;
}
for (let time of xml_each(metadata, 'time')) {
result.time = time.value;
}
}
return result;
}

View File

@ -1,21 +0,0 @@
import * as strava from './strava.js';
async function main() {
print('handler running');
let r = await strava.authorization_code(request.query.code);
print('state =', request.query.state);
print('body = ', r.body);
if (request.query.state && r.body) {
let shared_db = await shared_database('state');
await shared_db.set(request.query.state, utf8Decode(r.body));
}
await respond({
data: r.body,
content_type: 'text/plain',
headers: {
Location: 'https://tildefriends.net/~cory/gg/',
},
status_code: 307,
});
}
main();

View File

@ -1,26 +0,0 @@
<!doctype html>
<html style="width: 100%; height: 100%; margin: 0; padding: 0">
<head>
<script>
window.litDisableBundleWarning = true;
</script>
<script>
let g_data = ${data};
</script>
<script src="script.js" type="module"></script>
<script src="leaflet.js"></script>
</head>
<body
style="
color: #fff;
display: flex;
flex-flow: column;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
"
>
<gg-app style="width: 100%; height: 100%" id="ggapp"></gg-app>
</body>
</html>

View File

@ -1,661 +0,0 @@
/* required styles */
.leaflet-pane,
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-tile-container,
.leaflet-pane > svg,
.leaflet-pane > canvas,
.leaflet-zoom-box,
.leaflet-image-layer,
.leaflet-layer {
position: absolute;
left: 0;
top: 0;
}
.leaflet-container {
overflow: hidden;
}
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
-webkit-user-drag: none;
}
/* Prevents IE11 from highlighting tiles in blue */
.leaflet-tile::selection {
background: transparent;
}
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
.leaflet-safari .leaflet-tile {
image-rendering: -webkit-optimize-contrast;
}
/* hack that prevents hw layers "stretching" when loading new tiles */
.leaflet-safari .leaflet-tile-container {
width: 1600px;
height: 1600px;
-webkit-transform-origin: 0 0;
}
.leaflet-marker-icon,
.leaflet-marker-shadow {
display: block;
}
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
.leaflet-container .leaflet-overlay-pane svg {
max-width: none !important;
max-height: none !important;
}
.leaflet-container .leaflet-marker-pane img,
.leaflet-container .leaflet-shadow-pane img,
.leaflet-container .leaflet-tile-pane img,
.leaflet-container img.leaflet-image-layer,
.leaflet-container .leaflet-tile {
max-width: none !important;
max-height: none !important;
width: auto;
padding: 0;
}
.leaflet-container img.leaflet-tile {
/* See: https://bugs.chromium.org/p/chromium/issues/detail?id=600120 */
mix-blend-mode: plus-lighter;
}
.leaflet-container.leaflet-touch-zoom {
-ms-touch-action: pan-x pan-y;
touch-action: pan-x pan-y;
}
.leaflet-container.leaflet-touch-drag {
-ms-touch-action: pinch-zoom;
/* Fallback for FF which doesn't support pinch-zoom */
touch-action: none;
touch-action: pinch-zoom;
}
.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
-ms-touch-action: none;
touch-action: none;
}
.leaflet-container {
-webkit-tap-highlight-color: transparent;
}
.leaflet-container a {
-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
}
.leaflet-tile {
filter: inherit;
visibility: hidden;
}
.leaflet-tile-loaded {
visibility: inherit;
}
.leaflet-zoom-box {
width: 0;
height: 0;
-moz-box-sizing: border-box;
box-sizing: border-box;
z-index: 800;
}
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
.leaflet-overlay-pane svg {
-moz-user-select: none;
}
.leaflet-pane { z-index: 400; }
.leaflet-tile-pane { z-index: 200; }
.leaflet-overlay-pane { z-index: 400; }
.leaflet-shadow-pane { z-index: 500; }
.leaflet-marker-pane { z-index: 600; }
.leaflet-tooltip-pane { z-index: 650; }
.leaflet-popup-pane { z-index: 700; }
.leaflet-map-pane canvas { z-index: 100; }
.leaflet-map-pane svg { z-index: 200; }
.leaflet-vml-shape {
width: 1px;
height: 1px;
}
.lvml {
behavior: url(#default#VML);
display: inline-block;
position: absolute;
}
/* control positioning */
.leaflet-control {
position: relative;
z-index: 800;
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
.leaflet-top,
.leaflet-bottom {
position: absolute;
z-index: 1000;
pointer-events: none;
}
.leaflet-top {
top: 0;
}
.leaflet-right {
right: 0;
}
.leaflet-bottom {
bottom: 0;
}
.leaflet-left {
left: 0;
}
.leaflet-control {
float: left;
clear: both;
}
.leaflet-right .leaflet-control {
float: right;
}
.leaflet-top .leaflet-control {
margin-top: 10px;
}
.leaflet-bottom .leaflet-control {
margin-bottom: 10px;
}
.leaflet-left .leaflet-control {
margin-left: 10px;
}
.leaflet-right .leaflet-control {
margin-right: 10px;
}
/* zoom and fade animations */
.leaflet-fade-anim .leaflet-popup {
opacity: 0;
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
opacity: 1;
}
.leaflet-zoom-animated {
-webkit-transform-origin: 0 0;
-ms-transform-origin: 0 0;
transform-origin: 0 0;
}
svg.leaflet-zoom-animated {
will-change: transform;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
}
.leaflet-zoom-anim .leaflet-tile,
.leaflet-pan-anim .leaflet-tile {
-webkit-transition: none;
-moz-transition: none;
transition: none;
}
.leaflet-zoom-anim .leaflet-zoom-hide {
visibility: hidden;
}
/* cursors */
.leaflet-interactive {
cursor: pointer;
}
.leaflet-grab {
cursor: -webkit-grab;
cursor: -moz-grab;
cursor: grab;
}
.leaflet-crosshair,
.leaflet-crosshair .leaflet-interactive {
cursor: crosshair;
}
.leaflet-popup-pane,
.leaflet-control {
cursor: auto;
}
.leaflet-dragging .leaflet-grab,
.leaflet-dragging .leaflet-grab .leaflet-interactive,
.leaflet-dragging .leaflet-marker-draggable {
cursor: move;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
cursor: grabbing;
}
/* marker & overlays interactivity */
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-image-layer,
.leaflet-pane > svg path,
.leaflet-tile-container {
pointer-events: none;
}
.leaflet-marker-icon.leaflet-interactive,
.leaflet-image-layer.leaflet-interactive,
.leaflet-pane > svg path.leaflet-interactive,
svg.leaflet-image-layer.leaflet-interactive path {
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
/* visual tweaks */
.leaflet-container {
background: #ddd;
outline-offset: 1px;
}
.leaflet-container a {
color: #0078A8;
}
.leaflet-zoom-box {
border: 2px dotted #38f;
background: rgba(255,255,255,0.5);
}
/* general typography */
.leaflet-container {
font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
font-size: 12px;
font-size: 0.75rem;
line-height: 1.5;
}
/* general toolbar styles */
.leaflet-bar {
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
border-radius: 4px;
}
.leaflet-bar a {
background-color: #fff;
border-bottom: 1px solid #ccc;
width: 26px;
height: 26px;
line-height: 26px;
display: block;
text-align: center;
text-decoration: none;
color: black;
}
.leaflet-bar a,
.leaflet-control-layers-toggle {
background-position: 50% 50%;
background-repeat: no-repeat;
display: block;
}
.leaflet-bar a:hover,
.leaflet-bar a:focus {
background-color: #f4f4f4;
}
.leaflet-bar a:first-child {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.leaflet-bar a:last-child {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom: none;
}
.leaflet-bar a.leaflet-disabled {
cursor: default;
background-color: #f4f4f4;
color: #bbb;
}
.leaflet-touch .leaflet-bar a {
width: 30px;
height: 30px;
line-height: 30px;
}
.leaflet-touch .leaflet-bar a:first-child {
border-top-left-radius: 2px;
border-top-right-radius: 2px;
}
.leaflet-touch .leaflet-bar a:last-child {
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
}
/* zoom control */
.leaflet-control-zoom-in,
.leaflet-control-zoom-out {
font: bold 18px 'Lucida Console', Monaco, monospace;
text-indent: 1px;
}
.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {
font-size: 22px;
}
/* layers control */
.leaflet-control-layers {
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
background: #fff;
border-radius: 5px;
}
.leaflet-control-layers-toggle {
background-image: url(images/layers.png);
width: 36px;
height: 36px;
}
.leaflet-retina .leaflet-control-layers-toggle {
background-image: url(images/layers-2x.png);
background-size: 26px 26px;
}
.leaflet-touch .leaflet-control-layers-toggle {
width: 44px;
height: 44px;
}
.leaflet-control-layers .leaflet-control-layers-list,
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
display: none;
}
.leaflet-control-layers-expanded .leaflet-control-layers-list {
display: block;
position: relative;
}
.leaflet-control-layers-expanded {
padding: 6px 10px 6px 6px;
color: #333;
background: #fff;
}
.leaflet-control-layers-scrollbar {
overflow-y: scroll;
overflow-x: hidden;
padding-right: 5px;
}
.leaflet-control-layers-selector {
margin-top: 2px;
position: relative;
top: 1px;
}
.leaflet-control-layers label {
display: block;
font-size: 13px;
font-size: 1.08333em;
}
.leaflet-control-layers-separator {
height: 0;
border-top: 1px solid #ddd;
margin: 5px -10px 5px -6px;
}
/* Default icon URLs */
.leaflet-default-icon-path { /* used only in path-guessing heuristic, see L.Icon.Default */
background-image: url(images/marker-icon.png);
}
/* attribution and scale controls */
.leaflet-container .leaflet-control-attribution {
background: #fff;
background: rgba(255, 255, 255, 0.8);
margin: 0;
}
.leaflet-control-attribution,
.leaflet-control-scale-line {
padding: 0 5px;
color: #333;
line-height: 1.4;
}
.leaflet-control-attribution a {
text-decoration: none;
}
.leaflet-control-attribution a:hover,
.leaflet-control-attribution a:focus {
text-decoration: underline;
}
.leaflet-attribution-flag {
display: inline !important;
vertical-align: baseline !important;
width: 1em;
height: 0.6669em;
}
.leaflet-left .leaflet-control-scale {
margin-left: 5px;
}
.leaflet-bottom .leaflet-control-scale {
margin-bottom: 5px;
}
.leaflet-control-scale-line {
border: 2px solid #777;
border-top: none;
line-height: 1.1;
padding: 2px 5px 1px;
white-space: nowrap;
-moz-box-sizing: border-box;
box-sizing: border-box;
background: rgba(255, 255, 255, 0.8);
text-shadow: 1px 1px #fff;
}
.leaflet-control-scale-line:not(:first-child) {
border-top: 2px solid #777;
border-bottom: none;
margin-top: -2px;
}
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
border-bottom: 2px solid #777;
}
.leaflet-touch .leaflet-control-attribution,
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
box-shadow: none;
}
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
border: 2px solid rgba(0,0,0,0.2);
background-clip: padding-box;
}
/* popup */
.leaflet-popup {
position: absolute;
text-align: center;
margin-bottom: 20px;
}
.leaflet-popup-content-wrapper {
padding: 1px;
text-align: left;
border-radius: 12px;
}
.leaflet-popup-content {
margin: 13px 24px 13px 20px;
line-height: 1.3;
font-size: 13px;
font-size: 1.08333em;
min-height: 1px;
}
.leaflet-popup-content p {
margin: 17px 0;
margin: 1.3em 0;
}
.leaflet-popup-tip-container {
width: 40px;
height: 20px;
position: absolute;
left: 50%;
margin-top: -1px;
margin-left: -20px;
overflow: hidden;
pointer-events: none;
}
.leaflet-popup-tip {
width: 17px;
height: 17px;
padding: 1px;
margin: -10px auto 0;
pointer-events: auto;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
background: white;
color: #333;
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
}
.leaflet-container a.leaflet-popup-close-button {
position: absolute;
top: 0;
right: 0;
border: none;
text-align: center;
width: 24px;
height: 24px;
font: 16px/24px Tahoma, Verdana, sans-serif;
color: #757575;
text-decoration: none;
background: transparent;
}
.leaflet-container a.leaflet-popup-close-button:hover,
.leaflet-container a.leaflet-popup-close-button:focus {
color: #585858;
}
.leaflet-popup-scrolled {
overflow: auto;
}
.leaflet-oldie .leaflet-popup-content-wrapper {
-ms-zoom: 1;
}
.leaflet-oldie .leaflet-popup-tip {
width: 24px;
margin: 0 auto;
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
}
.leaflet-oldie .leaflet-control-zoom,
.leaflet-oldie .leaflet-control-layers,
.leaflet-oldie .leaflet-popup-content-wrapper,
.leaflet-oldie .leaflet-popup-tip {
border: 1px solid #999;
}
/* div icon */
.leaflet-div-icon {
background: #fff;
border: 1px solid #666;
}
/* Tooltip */
/* Base styles for the element that has a tooltip */
.leaflet-tooltip {
position: absolute;
padding: 6px;
background-color: #fff;
border: 1px solid #fff;
border-radius: 3px;
color: #222;
white-space: nowrap;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
pointer-events: none;
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
}
.leaflet-tooltip.leaflet-interactive {
cursor: pointer;
pointer-events: auto;
}
.leaflet-tooltip-top:before,
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
position: absolute;
pointer-events: none;
border: 6px solid transparent;
background: transparent;
content: "";
}
/* Directions */
.leaflet-tooltip-bottom {
margin-top: 6px;
}
.leaflet-tooltip-top {
margin-top: -6px;
}
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-top:before {
left: 50%;
margin-left: -6px;
}
.leaflet-tooltip-top:before {
bottom: 0;
margin-bottom: -12px;
border-top-color: #fff;
}
.leaflet-tooltip-bottom:before {
top: 0;
margin-top: -12px;
margin-left: -6px;
border-bottom-color: #fff;
}
.leaflet-tooltip-left {
margin-left: -6px;
}
.leaflet-tooltip-right {
margin-left: 6px;
}
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
top: 50%;
margin-top: -6px;
}
.leaflet-tooltip-left:before {
right: 0;
margin-right: -12px;
border-left-color: #fff;
}
.leaflet-tooltip-right:before {
left: 0;
margin-left: -12px;
border-right-color: #fff;
}
/* Printing */
@media print {
/* Prevent printers from removing background-images of controls. */
.leaflet-control {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

120
apps/gg/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

View File

@ -1,162 +0,0 @@
/**
* Based off of [the offical Google document](https://developers.google.com/maps/documentation/utilities/polylinealgorithm)
*
* Some parts from [this implementation](http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/PolylineEncoder.js)
* by [Mark McClure](http://facstaff.unca.edu/mcmcclur/)
*
* @module polyline
*/
var polyline = {};
function py2_round(value) {
// Google's polyline algorithm uses the same rounding strategy as Python 2, which is different from JS for negative values
return Math.floor(Math.abs(value) + 0.5) * (value >= 0 ? 1 : -1);
}
function encode(current, previous, factor) {
current = py2_round(current * factor);
previous = py2_round(previous * factor);
var coordinate = (current - previous) * 2;
if (coordinate < 0) {
coordinate = -coordinate - 1;
}
var output = '';
while (coordinate >= 0x20) {
output += String.fromCharCode((0x20 | (coordinate & 0x1f)) + 63);
coordinate /= 32;
}
output += String.fromCharCode((coordinate | 0) + 63);
return output;
}
/**
* Decodes to a [latitude, longitude] coordinates array.
*
* This is adapted from the implementation in Project-OSRM.
*
* @param {String} str
* @param {Number} precision
* @returns {Array}
*
* @see https://github.com/Project-OSRM/osrm-frontend/blob/master/WebContent/routing/OSRM.RoutingGeometry.js
*/
polyline.decode = function (str, precision) {
var index = 0,
lat = 0,
lng = 0,
coordinates = [],
shift = 0,
result = 0,
byte = null,
latitude_change,
longitude_change,
factor = Math.pow(10, Number.isInteger(precision) ? precision : 5);
// Coordinates have variable length when encoded, so just keep
// track of whether we've hit the end of the string. In each
// loop iteration, a single coordinate is decoded.
while (index < str.length) {
// Reset shift, result, and byte
byte = null;
shift = 1;
result = 0;
do {
byte = str.charCodeAt(index++) - 63;
result += (byte & 0x1f) * shift;
shift *= 32;
} while (byte >= 0x20);
latitude_change = result & 1 ? (-result - 1) / 2 : result / 2;
shift = 1;
result = 0;
do {
byte = str.charCodeAt(index++) - 63;
result += (byte & 0x1f) * shift;
shift *= 32;
} while (byte >= 0x20);
longitude_change = result & 1 ? (-result - 1) / 2 : result / 2;
lat += latitude_change;
lng += longitude_change;
coordinates.push([lat / factor, lng / factor]);
}
return coordinates;
};
/**
* Encodes the given [latitude, longitude] coordinates array.
*
* @param {Array.<Array.<Number>>} coordinates
* @param {Number} precision
* @returns {String}
*/
polyline.encode = function (coordinates, precision) {
if (!coordinates.length) {
return '';
}
var factor = Math.pow(10, Number.isInteger(precision) ? precision : 5),
output =
encode(coordinates[0][0], 0, factor) +
encode(coordinates[0][1], 0, factor);
for (var i = 1; i < coordinates.length; i++) {
var a = coordinates[i],
b = coordinates[i - 1];
output += encode(a[0], b[0], factor);
output += encode(a[1], b[1], factor);
}
return output;
};
function flipped(coords) {
var flipped = [];
for (var i = 0; i < coords.length; i++) {
var coord = coords[i].slice();
flipped.push([coord[1], coord[0]]);
}
return flipped;
}
/**
* Encodes a GeoJSON LineString feature/geometry.
*
* @param {Object} geojson
* @param {Number} precision
* @returns {String}
*/
polyline.fromGeoJSON = function (geojson, precision) {
if (geojson && geojson.type === 'Feature') {
geojson = geojson.geometry;
}
if (!geojson || geojson.type !== 'LineString') {
throw new Error('Input must be a GeoJSON LineString');
}
return polyline.encode(flipped(geojson.coordinates), precision);
};
/**
* Decodes to a GeoJSON LineString geometry.
*
* @param {String} str
* @param {Number} precision
* @returns {Object}
*/
polyline.toGeoJSON = function (str, precision) {
var coords = polyline.decode(str, precision);
return {
type: 'LineString',
coordinates: flipped(coords),
};
};
let polyline_decode = polyline.decode;
export {polyline_decode as decode};

View File

@ -1,909 +0,0 @@
import {
LitElement,
html,
unsafeHTML,
css,
guard,
until,
} from './lit-all.min.js';
import * as tfrpc from '/static/tfrpc.js';
import * as polyline from './polyline.js';
import {gpx_parse} from './gpx.js';
const k_client_id = '28276';
const k_redirect_url = 'https://tildefriends.net/~cory/gg/login';
const k_color_snow = [128, 128, 255, 255];
const k_color_ice = [160, 160, 255, 255];
const k_color_water = [0, 0, 255, 255];
const k_color_dirt = [128, 129, 130, 255];
const k_color_pavement = [32, 32, 32, 255];
const k_color_grass = [0, 255, 0, 255];
const k_color_default = [128, 128, 128, 255];
const k_store = {
'🦞': 15,
'🛶': 10,
'🏠': 10,
'⛰': 10,
'🐠': 10,
};
const k_marker_snap = {x: 5, y: 4};
class GgAppElement extends LitElement {
static get properties() {
return {
user: {type: Object},
strava: {type: Object},
activities: {type: Array},
activity: {type: Object},
world: {type: Object},
whoami: {type: String},
status: {type: Object},
tab: {type: String},
url: {type: String},
currency: {type: Number},
to_build: {type: String},
emoji_of_the_day: {type: String},
};
}
constructor() {
super();
this.activities = [];
this.activity = {};
this.loaded_activities = [];
this.placed_emojis = [];
this.strava = {};
this.min_lat = Number.MAX_VALUE;
this.min_lon = Number.MAX_VALUE;
this.max_lat = -Number.MAX_VALUE;
this.max_lon = -Number.MAX_VALUE;
this.focus = undefined;
this.status = undefined;
this.tab = 'map';
this.load().catch(function (e) {
console.log('load error', e);
});
this.to_build = '🏠';
}
async load() {
console.log('load');
let emojis = await (await fetch('emojis.json')).json();
emojis = Object.values(emojis)
.map((x) => Object.values(x))
.flat();
let today = new Date();
let date_index =
today.getYear() * 356 + today.getMonth() * 31 + today.getDate();
this.emoji_of_the_day = emojis[(date_index * 123457) % emojis.length];
this.user = await tfrpc.rpc.getUser();
this.url = (await tfrpc.rpc.url()).split('?')[0];
try {
await this.update_credentials();
} catch (e) {
console.log('update_credentials failed', e);
}
try {
await this.update_activities();
} catch (e) {
console.log('update_activities failed', e);
}
await this.acquire_ssb_identity();
if (this.whoami && this.activities?.length) {
await this.sync_activities();
}
await this.get_activities_from_ssb();
}
/* https://gist.github.com/jcouyang/632709f30e12a7879a73e9e132c0d56b?permalink_comment_id=3591045#gistcomment-3591045 */
async promise_all(promises, max_concurrent) {
let index = 0;
let results = [];
async function exec_thread() {
while (index < promises.length) {
const current = index++;
results[current] = await promises[current];
}
}
const threads = [];
for (let thread = 0; thread < max_concurrent; thread++) {
threads.push(exec_thread());
}
await Promise.all(threads);
return results;
}
async get_activities_from_ssb() {
this.status = {text: 'loading activities'};
this.loaded_activities = [];
let rows = await tfrpc.rpc.query(
`
SELECT messages.author, json_extract(mention.value, '$.link') AS blob_id
FROM messages_fts('"gg-activity"')
JOIN messages ON messages.rowid = messages_fts.rowid,
json_each(messages.content, '$.mentions') as mention
WHERE json_extract(messages.content, '$.type') = 'gg-activity' AND
json_extract(mention.value, '$.name') = 'activity_data'
ORDER BY messages.timestamp DESC
`,
[]
);
this.status = {text: 'loading activity data'};
let authors = rows.map((x) => x.author);
let blobs = await this.promise_all(
rows.map((x) => tfrpc.rpc.get_blob(x.blob_id)),
8
);
this.status = {text: 'processing activity data'};
for (let [index, blob] of blobs.entries()) {
let activity;
try {
activity = JSON.parse(blob);
} catch {
activity = gpx_parse(blob);
}
if (activity) {
activity.author = authors[index];
this.loaded_activities.push(activity);
}
}
this.status = {text: 'calculating balance'};
rows = await tfrpc.rpc.query(
`
SELECT count(*) AS currency FROM messages WHERE author = ? AND json_extract(content, '$.type') = 'gg-activity'
`,
[this.whoami]
);
let currency = rows[0].currency;
rows = await tfrpc.rpc.query(
`
SELECT SUM(json_extract(content, '$.cost')) AS cost FROM messages WHERE author = ? AND json_extract(content, '$.type') = 'gg-place'
`,
[this.whoami]
);
let spent = rows[0].cost;
this.currency = currency - spent;
this.status = {text: 'getting placed emojis'};
rows = await tfrpc.rpc.query(`
SELECT messages.content
FROM messages_fts('"gg-place"')
JOIN messages ON messages.rowid = messages_fts.rowid
WHERE json_extract(messages.content, '$.type') = 'gg-place'
ORDER BY messages.timestamp
`);
for (let row of rows) {
console.log(row.content);
let content = JSON.parse(row.content);
this.placed_emojis.push({
position: content.position,
emoji: content.emoji,
});
}
console.log(this.placed_emojis);
this.status = undefined;
this.update_map();
}
async sync_activities() {
let ids = this.activities.map(
(x) => `https://www.strava.com/activities/${x.id}`
);
let missing = await tfrpc.rpc.query(
`
WITH my_activities AS (
SELECT json_extract(mention.value, '$.link') AS url
FROM messages, json_each(messages.content, '$.mentions') AS mention
WHERE
author = ? AND
json_extract(messages.content, '$.type') = 'gg-activity' AND
json_extract(mention.value, '$.name') = 'activity_url')
SELECT from_strava.value FROM json_each(?) AS from_strava
LEFT OUTER JOIN my_activities ON from_strava.value = my_activities.url
WHERE my_activities.url IS NULL
`,
[this.whoami, JSON.stringify(ids)]
);
console.log('missing = ', missing);
for (let [index, row] of missing.entries()) {
this.status = {
text: 'syncing from strava',
value: index,
max: missing.length,
};
let url = row.value;
let id = url.match(/.*\/(\d+)/)[1];
let response = await fetch(
`https://www.strava.com/api/v3/activities/${id}`,
{
headers: {
Authorization: `Bearer ${this.strava.access_token}`,
},
}
);
let activity = await response.json();
let blob_id = await tfrpc.rpc.store_blob(JSON.stringify(activity));
let message = {
type: 'gg-activity',
mentions: [
{
link: url,
name: 'activity_url',
},
{
link: blob_id,
name: 'activity_data',
},
],
};
await tfrpc.rpc.appendMessage(this.whoami, message);
}
this.status = undefined;
}
async acquire_ssb_identity() {
let user = await tfrpc.rpc.getUser();
if (!user?.credentials?.session?.name) {
return;
}
let ids = await tfrpc.rpc.getIdentities();
let players = ids.length
? (
await tfrpc.rpc.query(
`
SELECT author FROM messages JOIN json_each(?) ON messages.author = json_each.value
WHERE
json_extract(messages.content, '$.type') = 'gg-player' AND
json_extract(messages.content, '$.active')
ORDER BY timestamp DESC limit 1
`,
[JSON.stringify(ids)]
)
).map((row) => row.author)
: [];
if (!players.length) {
this.whoami = await tfrpc.rpc.createIdentity();
if (this.whoami) {
await tfrpc.rpc.appendMessage(this.whoami, {
type: 'gg-player',
active: true,
});
}
} else {
players.sort();
this.whoami = players[0];
}
}
async update_credentials() {
let name = this.user?.credentials?.session?.name;
if (!name) {
return;
}
let shared = await tfrpc.rpc.sharedDatabaseGet(name);
if (shared) {
await tfrpc.rpc.databaseSet('strava', shared);
await tfrpc.rpc.sharedDatabaseRemove(name);
}
this.strava = JSON.parse((await tfrpc.rpc.databaseGet('strava')) || '{}');
if (new Date().valueOf() / 1000 > this.strava.expires_at) {
console.log(
'this looks expired',
new Date().valueOf() / 1000,
'>',
this.strava.expires_at
);
let x = await tfrpc.rpc.refresh_token(this.strava);
if (x) {
this.strava = x;
await tfrpc.rpc.databaseSet('strava', JSON.stringify(x));
} else {
this.strava = null;
}
}
}
async update_activities() {
if (this?.strava?.access_token) {
let response = await fetch(
'https://www.strava.com/api/v3/athlete/activities',
{
headers: {
Authorization: `Bearer ${this.strava.access_token}`,
},
}
);
this.activities = await response.json();
this.activities.sort((a, b) => a.id - b.id);
}
}
color_to_emoji(color) {
const k_map = [
[k_color_snow, '⬜'],
[k_color_ice, '🟦'],
[k_color_water, '🟦'],
[k_color_dirt, '🟫'],
[k_color_pavement, '⬛'],
[k_color_grass, '🟩'],
[k_color_default, '🟧'],
];
for (let m of k_map) {
if (
m[0][0] == color[0] &&
m[0][1] == color[1] &&
m[0][2] == color[2] &&
m[0][3] == color[3]
) {
return m[1];
}
}
}
activity_bounds(activity) {
let min_lat = Number.MAX_VALUE;
let min_lon = Number.MAX_VALUE;
let max_lat = -Number.MAX_VALUE;
let max_lon = -Number.MAX_VALUE;
if (activity?.map?.polyline) {
for (let pt of polyline.decode(activity.map.polyline)) {
min_lat = Math.min(min_lat, pt[0]);
min_lon = Math.min(min_lon, pt[1]);
max_lat = Math.max(max_lat, pt[0]);
max_lon = Math.max(max_lon, pt[1]);
}
}
if (activity?.segments) {
for (let segment of activity.segments) {
for (let pt of segment) {
min_lat = Math.min(min_lat, pt.lat);
min_lon = Math.min(min_lon, pt.lon);
max_lat = Math.max(max_lat, pt.lat);
max_lon = Math.max(max_lon, pt.lon);
}
}
}
return {
min: {
lat: min_lat,
lng: min_lon,
},
max: {
lat: max_lat,
lng: max_lon,
},
};
}
on_click(event) {
let popup = L.popup()
.setLatLng(event.latlng)
.setContent(
`
<div><a target="_top" href="https://www.google.com/maps/search/?api=1&query=${event.latlng.lat},${event.latlng.lng}">${event.latlng.lat}, ${event.latlng.lng}</a></div>
`
)
.openOn(this.leaflet);
}
async build() {
if (this.popup) {
this.popup.remove();
}
if (!this.marker) {
return;
}
let latlng = this.marker.getLatLng();
let cost = k_store[this.to_build];
if (cost > this.currency) {
alert('Insufficient funds.');
return;
}
let message = {
type: 'gg-place',
position: {lat: latlng.lat, lng: latlng.lng},
emoji: this.to_build,
cost: cost,
};
let id = await tfrpc.rpc.appendMessage(this.whoami, message);
this.marker.remove();
this.placed_emojis.push({
position: {lat: latlng.lat, lng: latlng.lng},
emoji: this.to_build,
});
this.currency -= cost;
return this.update_map();
}
on_marker_click(event) {
this.popup = L.popup()
.setLatLng(event.latlng)
.setContent(
`
${this.to_build} (-${k_store[this.to_build]}) <input type="button" value="Build" onclick="document.getElementById('ggapp').build()"></input>
`
)
.openOn(this.leaflet);
}
snap_to_grid(latlng, fudge, zoom) {
let position = this.leaflet.options.crs.latLngToPoint(
latlng,
zoom ?? this.leaflet.getZoom()
);
position.x = Math.round(position.x / 16) * 16 + (fudge?.x ?? 0);
position.y = Math.round(position.y / 16) * 16 + (fudge?.y ?? 0);
position = this.leaflet.options.crs.pointToLatLng(
position,
zoom ?? this.leaflet.getZoom()
);
return position;
}
on_marker_move(event) {
if (!this.no_snap && this.marker) {
this.no_snap = true;
this.marker.setLatLng(
this.snap_to_grid(this.marker.getLatLng(), k_marker_snap)
);
this.no_snap = false;
}
}
on_zoom(event) {
if (this.marker) {
this.marker.setLatLng(
this.snap_to_grid(this.marker.getLatLng(), k_marker_snap)
);
}
}
on_mouse_down(event) {
if (this.marker) {
this.marker.remove();
this.marker = undefined;
}
if (this.to_build) {
this.marker = L.marker(this.snap_to_grid(event.latlng, k_marker_snap), {
icon: L.divIcon({className: 'build-icon'}),
draggable: true,
}).addTo(this.leaflet);
this.marker.on({click: this.on_marker_click.bind(this)});
this.marker.on({drag: this.on_marker_move.bind(this)});
}
}
async update_map() {
let map = this.shadowRoot.getElementById('map');
if (!map || !this.loaded_activities.length) {
this.leaflet = undefined;
this.grid_layer = undefined;
return;
}
if (!this.leaflet) {
this.leaflet = L.map(map, {
attributionControl: false,
maxZoom: 16,
bounceAtZoomLimits: false,
});
this.leaflet.on({contextmenu: this.on_click.bind(this)});
this.leaflet.on({click: this.on_mouse_down.bind(this)});
this.leaflet.on({zoom: this.on_zoom.bind(this)});
}
let self = this;
let grid_layer = L.GridLayer.extend({
createTile: function (coords) {
var tile = L.DomUtil.create('canvas', 'leaflet-tile');
var size = this.getTileSize();
tile.width = size.x;
tile.height = size.y;
var context = tile.getContext('2d');
context.font = '10pt sans';
let bounds = this._tileCoordsToBounds(coords);
let degrees = 360.0 / 2 ** coords.z;
let ul = bounds.getNorthWest();
let lr = bounds.getSouthEast();
let mini = document.createElement('canvas');
mini.width = Math.floor(size.x / 16.0);
mini.height = Math.floor(size.y / 16.0);
let mini_context = mini.getContext('2d');
let image_data = context.getImageData(0, 0, mini.width, mini.height);
for (let activity of self.loaded_activities) {
self.draw_activity_to_tile(
image_data,
mini.width,
mini.height,
ul,
lr,
activity
);
}
context.textAlign = 'left';
context.textBaseline = 'bottom';
for (let x = 0; x < mini.width; x++) {
for (let y = 0; y < mini.height; y++) {
let start = (y * mini.width + x) * 4;
let pixel = self.color_to_emoji(
image_data.data.slice(start, start + 4)
);
if (pixel) {
//context.fillRect(x * size.x / mini.width, y * size.y / mini.height, size.x / mini.width, size.y / mini.height);
context.fillText(
pixel,
(x * size.x) / mini.width,
(y * size.y) / mini.height + mini.height
);
}
}
}
for (let placed of self.placed_emojis) {
let position = self.leaflet.options.crs.latLngToPoint(
self.snap_to_grid(placed.position, undefined, coords.z),
coords.z
);
let tile_x = Math.floor(position.x / size.x);
let tile_y = Math.floor(position.y / size.y);
position.x = position.x - tile_x * size.x;
position.y = position.y - tile_y * size.y;
if (tile_x == coords.x && tile_y == coords.y) {
//context.fillRect(position.x, position.y, size.x / mini.width, size.y / mini.height);
context.fillText(
placed.emoji,
position.x,
position.y + mini.height
);
}
}
return tile;
},
});
if (this.grid_layer) {
this.grid_layer.redraw();
} else {
this.grid_layer = new grid_layer();
this.grid_layer.addTo(this.leaflet);
}
for (let activity of this.loaded_activities) {
let bounds = this.activity_bounds(activity);
this.min_lat = Math.min(this.min_lat, bounds.min.lat);
this.min_lon = Math.min(this.min_lon, bounds.min.lng);
this.max_lat = Math.max(this.max_lat, bounds.max.lat);
this.max_lon = Math.max(this.max_lon, bounds.max.lng);
}
if (this.focus) {
this.leaflet.fitBounds([this.focus.min, this.focus.max]);
this.focus = undefined;
} else {
this.leaflet.fitBounds([
[this.min_lat, this.min_lon],
[this.max_lat, this.max_lon],
]);
}
}
activity_to_color(activity) {
let color = [0, 0, 0, 255];
switch (activity.sport_type) {
/* Implies snow. */
case 'AlpineSki':
case 'BackcountrySki':
case 'NordicSki':
case 'Snowshoe':
case 'Snowboard':
color = k_color_snow;
break;
/* Implies ice. */
case 'IceSkate':
case 'InlineSkate':
color = k_color_ice;
break;
/* Implies water. */
case 'Canoeing':
case 'Kayaking':
case 'Kitesurf':
case 'Rowing':
case 'Sail':
case 'StandUpPaddling':
case 'Surfing':
case 'Swim':
case 'Windsurf':
color = k_color_water;
break;
/* Implies dirt. */
case 'EMountainBikeRide':
case 'Hike':
case 'MountainBikeRide':
case 'RockClimbing':
case 'TrailRun':
color = k_color_dirt;
break;
/* Implies pavement. */
case 'EBikeRide':
case 'GravelRide':
case 'Handcycle':
case 'Ride':
case 'RollerSki':
case 'Run':
case 'Skateboard':
case 'Badminton':
case 'Tennis':
case 'Velomobile':
case 'Walk':
case 'Wheelchair':
color = k_color_pavement;
break;
/* Grass, maybe? */
case 'Golf':
case 'Soccer':
case 'Squash':
color = k_color_grass;
break;
// Crossfit,
// Elliptical
// HighIntensityIntervalTraining
// Pickleball
// Pilates
// Racquetball
// StairStepper
// TableTennis,
// VirtualRide
// VirtualRow
// VirtualRun
// WeightTraining
// Workout
// Yoga
default:
color = k_color_default;
}
return color;
}
line(image_data, x0, y0, x1, y1, value) {
/* <3 https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm */
let dx = Math.abs(x1 - x0);
let sx = x0 < x1 ? 1 : -1;
let dy = -Math.abs(y1 - y0);
let sy = y0 < y1 ? 1 : -1;
let error = dx + dy;
while (true) {
if (
x0 >= 0 &&
y0 >= 0 &&
x0 < image_data.width &&
y0 < image_data.height
) {
let base = (y0 * image_data.width + x0) * 4;
image_data.data[base + 0] = value[0];
image_data.data[base + 1] = value[1];
image_data.data[base + 2] = value[2];
image_data.data[base + 3] = value[3];
}
if (x0 == x1 && y0 == y1) {
break;
}
let e2 = 2 * error;
if (e2 >= dy) {
if (x0 == x1) {
break;
}
error += dy;
x0 = Math.round(x0 + sx);
}
if (e2 <= dx) {
if (y0 == y1) {
break;
}
error += dx;
y0 = Math.round(y0 + sy);
}
}
}
draw_activity_to_tile(image_data, width, height, ul, lr, activity) {
let color = this.activity_to_color(activity);
if (activity?.map?.polyline) {
let last;
for (let pt of polyline.decode(activity.map.polyline)) {
let px = [
Math.floor((width * (pt[1] - ul.lng)) / (lr.lng - ul.lng)),
Math.floor((height * (pt[0] - ul.lat)) / (lr.lat - ul.lat)),
];
if (last) {
this.line(image_data, last[0], last[1], px[0], px[1], color);
}
last = px;
}
}
if (activity?.segments) {
for (let segment of activity.segments) {
let last;
for (let pt of segment) {
let px = [
Math.floor((width * (pt.lon - ul.lng)) / (lr.lng - ul.lng)),
Math.floor((height * (pt.lat - ul.lat)) / (lr.lat - ul.lat)),
];
if (last) {
this.line(image_data, last[0], last[1], px[0], px[1], color);
}
last = px;
}
}
}
}
async on_upload(event) {
try {
let file = event.srcElement.files[0];
let xml = await file.text();
let gpx = gpx_parse(xml);
let blob_id = await tfrpc.rpc.store_blob(xml);
console.log('blob_id = ', blob_id);
console.log(gpx);
let message = {
type: 'gg-activity',
mentions: [
{
link: `https://${gpx.link}/activity/${gpx.time}`,
name: 'activity_url',
},
{
link: blob_id,
name: 'activity_data',
},
],
};
console.log('id =', this.whoami, 'message = ', message);
let id = await tfrpc.rpc.appendMessage(this.whoami, message);
console.log('appended message', id);
alert('Activity uploaded.');
await this.get_activities_from_ssb();
} catch (e) {
alert(`Error: ${JSON.stringify(e, null, 2)}`);
}
}
upload() {
let input = document.createElement('input');
input.type = 'file';
input.onchange = (event) => this.on_upload(event);
input.click();
}
updated() {
this.update_map();
}
focus_map(activity) {
let bounds = this.activity_bounds(activity);
if (bounds.min.lat < bounds.max.lat && bounds.min.lng < bounds.max.lng) {
this.tab = 'map';
this.focus = bounds;
}
}
render_news() {
return html`
<ul>
${this.loaded_activities.map(
(x) => html`
<li style="cursor: pointer" @click=${() => this.focus_map(x)}>
${x.author} ${x.name ?? x.time}
</li>
`
)}
</ul>
`;
}
render_store_item(item) {
let [emoji, cost] = item;
return html`
<div>
<input type="button" value="${emoji}" @click=${() => (this.to_build = emoji)}></input> ${cost} ${emoji == this.to_build ? '<-- Will be built next' : undefined}
</div>
`;
}
render_store() {
let store = Object.assign({}, k_store);
store[this.emoji_of_the_day] = 5;
return html`
<h2>Store</h2>
<div><b>Your balance:</b> ${this.currency}</div>
${Object.entries(store).map(this.render_store_item.bind(this))}
`;
}
render() {
let header;
if (!this.user?.credentials?.session?.name) {
header = html`<div style="flex: 1 0">
Please <a target="_top" href="/login?return=${this.url}">login</a> to
Tilde Friends, first.
</div>`;
} else if (!this.strava?.access_token) {
let strava_url = `https://www.strava.com/oauth/authorize?client_id=${k_client_id}&redirect_uri=${k_redirect_url}&response_type=code&approval_prompt=auto&scope=activity%3Aread&state=${g_data.state}`;
header = html`
<div style="flex: 1 0; display: flex; flex-direction: row; align-items: center; gap: 1em; width: 100%">
<div style="flex: 1 1">Please <a target="_top" href=${strava_url}>login</a> to Strava.</div>
<span style="font-size: xx-small; flex: 1 1; word-break: break-all">${this.whoami}</span>
<input type="button" value="📁" @click=${this.upload}></input>
</div>
`;
} else {
header = html`
<div>
<div style="flex: 1 0; display: flex; flex-direction: row; align-items: center; gap: 1em; width: 100%">
<h1>Welcome, ${this.user.credentials.session.name}</h1>
<span style="font-size: xx-small; flex: 1 1; word-break: break-all">${this.whoami}</span>
<input type="button" value="📁" @click=${this.upload}></input>
</div>
<h3 ?hidden=${!this.status?.text}>${this.status?.text} <progress ?hidden=${!this.status?.max} value=${this.status?.value} max=${this.status?.max}>${this.status?.value}</progress></h3>
</div>
`;
}
let navigation = html`
<style>
#navigation input[type="button"] {
min-width: 3em;
min-height: 3em;
flex: 1 0;
font-size: large;
}
</style>
<div id="navigation" style="display: flex; flex-direction: row">
<input type="button" id="button_map" @click=${() => (this.tab = 'map')} value="🗺Map"></input>
<input type="button" id="button_news" @click=${() => (this.tab = 'news')} value="🏃News"></input>
<input type="button" id="button_friends" @click=${() => (this.tab = 'friends')} value="👫Friends"></input>
<input type="button" id="button_store" @click=${() => (this.tab = 'store')} value="🏗Store"></input>
</div>
`;
let content;
switch (this.tab) {
case 'map':
content = html`<div id="map" style="width: 100%; height: 100%"></div>`;
break;
case 'news':
content = this.render_news();
break;
case 'friends':
content = html`<div>Friends</div>`;
break;
case 'store':
content = this.render_store();
break;
}
return html`
<style>
.build-icon::before {
content: '📍';
border: 2px solid red;
}
</style>
<link rel="stylesheet" href="leaflet.css" />
<div
style="width: 100%; height: 100%; display: flex; flex-direction: column"
>
${header}
<div style="flex: 1 0; overflow: scroll">${content}</div>
${navigation}
</div>
`;
}
}
customElements.define('gg-app', GgAppElement);

View File

@ -1,20 +0,0 @@
const k_client_id = '28276';
const k_client_secret = '3123f1f5afe132d9731111066d1d17bdb22ef27e';
const k_access_token = 'f753e77764c26252bd2d80e7c5cc17ace51a8864';
const k_refresh_token = 'f58d8e1b5a3ec3bf96e681589d5014f9a294f5a4';
const k_redirect_url = 'https://tildefriends.net/~cory/gg/login';
export async function refresh_token(token) {
let r = await fetch('https://www.strava.com/api/v3/oauth/token', {
method: 'POST',
body: `client_id=${k_client_id}&client_secret=${k_client_secret}&refresh_token=${token.refresh_token}&grant_type=refresh_token`,
});
return r?.body ? JSON.parse(utf8Decode(r.body)) : undefined;
}
export async function authorization_code(code) {
return await fetch('https://www.strava.com/api/v3/oauth/token', {
method: 'POST',
body: `client_id=${k_client_id}&client_secret=${k_client_secret}&code=${code}&grant_type=authorization_code`,
});
}

View File

@ -1,5 +1,5 @@
{
"type": "tildefriends-app",
"emoji": "📝",
"previous": "&2hdIDbBrAg63T2X1MzdGSF7yiqHvlnfF0PnInQLp0DA=.sha256"
"previous": "&b//KqE4Vx6kOSBRODK1p/8wjOLKZJ+CBB5IkaBt5YsM=.sha256"
}

5
apps/room.json Normal file
View File

@ -0,0 +1,5 @@
{
"type": "tildefriends-app",
"emoji": "📦",
"previous": "&IU+TwyM7TznD8NBfnw7tgW2zxVlMqTVxSqWFjuosLwo=.sha256"
}

13
apps/room/app.js Normal file
View File

@ -0,0 +1,13 @@
async function main() {
let host = core.url.match(/.*\/\/(.*?)\//)[1];
let id = (await ssb.getServerIdentity()).substring(1);
let room = `net:${host}:${ssb.port}~shs:${id}:SSB+Room+SK3TLYC2T86EHQCUHBUHASCASE18JBV24=`;
await app.setDocument(`
<body style="color: #fff">
<h1>Server</h1>
<div>The local server address is:</div>
<div><input type="text" readonly value="${room}" style="width: 100%"></input></div>
</body>
`);
}
main();

View File

@ -1,4 +1,5 @@
{
"type": "tildefriends-app",
"emoji": "👟"
"emoji": "👟",
"previous": "&lYZRnT2UGQxXxYISbuaZewik9AuxBpcJumakwrePw5c=.sha256"
}

View File

@ -38,10 +38,11 @@ class TfSneakerAppElement extends LitElement {
}
format_message(message) {
const k_flag_sequence_before_author = 1;
let out = {
previous: message.previous ?? null,
};
if (message.sequence_before_author) {
if (message.flags & k_flag_sequence_before_author) {
out.sequence = message.sequence;
out.author = message.author;
} else {
@ -72,25 +73,104 @@ class TfSneakerAppElement extends LitElement {
return true;
}
// prettier-ignore
if (startsWith(data, [0xff, 0xd8, 0xff, 0xdb]) ||
startsWith(data, [0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01]) ||
if (
startsWith(data, [0xff, 0xd8, 0xff, 0xdb]) ||
startsWith(
data,
[0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01]
) ||
startsWith(data, [0xff, 0xd8, 0xff, 0xee]) ||
startsWith(data, [0xff, 0xd8, 0xff, 0xe1, null, null, 0x45, 0x78, 0x69, 0x66, 0x00, 0x00])) {
startsWith(data, [
0xff,
0xd8,
0xff,
0xe1,
null,
null,
0x45,
0x78,
0x69,
0x66,
0x00,
0x00,
])
) {
return '.jpg';
} else if (startsWith(data, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])) {
} else if (
startsWith(data, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])
) {
return '.png';
} else if (startsWith(data, [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]) ||
startsWith(data, [0x47, 0x49, 0x46, 0x38, 0x39, 0x61])) {
} else if (
startsWith(data, [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]) ||
startsWith(data, [0x47, 0x49, 0x46, 0x38, 0x39, 0x61])
) {
return '.gif';
} else if (startsWith(data, [0x52, 0x49, 0x46, 0x46, null, null, null, null, 0x57, 0x45, 0x42, 0x50])) {
} else if (
startsWith(data, [
0x52,
0x49,
0x46,
0x46,
null,
null,
null,
null,
0x57,
0x45,
0x42,
0x50,
])
) {
return '.webp';
} else if (startsWith(data, [0x3c, 0x73, 0x76, 0x67])) {
return '.svg';
} else if (startsWith(data, [null, null, null, null, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32])) {
} else if (
startsWith(data, [
null,
null,
null,
null,
0x66,
0x74,
0x79,
0x70,
0x6d,
0x70,
0x34,
0x32,
])
) {
return '.mp3';
} else if (startsWith(data, [null, null, null, null, 0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6f, 0x6d]) ||
startsWith(data, [null, null, null, null, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32])) {
} else if (
startsWith(data, [
null,
null,
null,
null,
0x66,
0x74,
0x79,
0x70,
0x69,
0x73,
0x6f,
0x6d,
]) ||
startsWith(data, [
null,
null,
null,
null,
0x66,
0x74,
0x79,
0x70,
0x6d,
0x70,
0x34,
0x32,
])
) {
return '.mp4';
} else {
return '.bin';
@ -109,7 +189,12 @@ class TfSneakerAppElement extends LitElement {
)[0].total;
while (true) {
let messages = await tfrpc.rpc.query(
'SELECT * FROM messages WHERE author = ? AND SEQUENCE > ? ORDER BY sequence LIMIT 100',
`
SELECT author, id, sequence, timestamp, hash, json(content) AS content, signature, flags
FROM messages
WHERE author = ? AND SEQUENCE > ?
ORDER BY sequence LIMIT 100
`,
[id, sequence]
);
if (messages?.length) {

View File

@ -1,5 +1,5 @@
{
"type": "tildefriends-app",
"emoji": "🐌",
"previous": "&DUxMMCJcuhm6S9jg/eKgEyWodkITu6Tg9g5I5wgLWFU=.sha256"
"previous": "&Xs1X5TzLCk6KVr+5IDc80JAHYxJyoD10cXKBUYpFqWQ=.sha256"
}

View File

@ -107,7 +107,7 @@ class TfElement extends LitElement {
let abouts = await tfrpc.rpc.query(
`
SELECT
messages.*
messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
FROM
messages,
json_each(?1) AS following
@ -118,7 +118,7 @@ class TfElement extends LitElement {
json_extract(messages.content, '$.type') = 'about'
UNION
SELECT
messages.*
messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
FROM
messages,
json_each(?2) AS following
@ -158,7 +158,7 @@ class TfElement extends LitElement {
async fetch_new_message(id) {
let messages = await tfrpc.rpc.query(
`
SELECT messages.*
SELECT messages.id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
FROM messages
JOIN json_each(?) AS following ON messages.author = following.value
WHERE messages.id = ?
@ -221,7 +221,7 @@ class TfElement extends LitElement {
this.tags = await tfrpc.rpc.query(
`
WITH
recent AS (SELECT id, content FROM messages
recent AS (SELECT id, json(content) AS content FROM messages
WHERE messages.timestamp > ? AND json_extract(content, '$.type') = 'post'
ORDER BY timestamp DESC LIMIT 1024),
recent_channels AS (SELECT recent.id, '#' || json_extract(content, '$.channel') AS tag

View File

@ -262,7 +262,7 @@ class TfComposeElement extends LitElement {
try {
let rows = await tfrpc.rpc.query(
`
SELECT messages.content FROM messages_fts(?)
SELECT json(messages.content) FROM messages_fts(?)
JOIN messages ON messages.rowid = messages_fts.rowid
WHERE messages.content LIKE ?
ORDER BY timestamp DESC LIMIT 10

View File

@ -3,7 +3,7 @@ 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.
** Provide a list of IDs, and this lets the user pick one.
*/
class TfIdentityPickerElement extends LitElement {
static get properties() {

View File

@ -265,10 +265,7 @@ ${JSON.stringify(mention, null, 2)}</pre
new CustomEvent('tf-expand', {
bubbles: true,
composed: true,
detail: {
id: (this.message.id || '') + (tag || ''),
expanded: expanded,
},
detail: {id: (this.message.id || '') + (tag || ''), expanded: expanded},
})
);
}
@ -497,7 +494,7 @@ ${JSON.stringify(mention, null, 2)}</pre
<tf-compose
whoami=${this.whoami}
.users=${this.users}
root=${this.message.content.root || this.message.id}
root=${content.root || this.message.id}
branch=${this.message.id}
.drafts=${this.drafts}
@tf-discard=${this.discard_reply}
@ -684,7 +681,7 @@ ${JSON.stringify(content, null, 2)}</pre
<tf-compose
whoami=${this.whoami}
.users=${this.users}
root=${this.message.content.root || this.message.id}
root=${content.root || this.message.id}
branch=${this.message.id}
.drafts=${this.drafts}
@tf-discard=${this.discard_reply}

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,7 @@ class TfTabMentionsElement extends LitElement {
console.log('Loading...', this.whoami);
let results = await tfrpc.rpc.query(
`
SELECT messages.*
SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
FROM messages_fts(?)
JOIN messages ON messages.rowid = messages_fts.rowid
JOIN json_each(?) AS following ON messages.author = following.value

View File

@ -33,12 +33,12 @@ class TfTabNewsFeedElement extends LitElement {
if (this.hash.startsWith('#@')) {
let r = await tfrpc.rpc.query(
`
WITH mine AS (SELECT messages.*
WITH mine AS (SELECT id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
FROM messages
WHERE messages.author = ?
ORDER BY sequence DESC
LIMIT 20)
SELECT messages.*
SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
FROM mine
JOIN messages_refs ON mine.id = messages_refs.ref
JOIN messages ON messages_refs.message = messages.id
@ -51,11 +51,11 @@ class TfTabNewsFeedElement extends LitElement {
} else if (this.hash.startsWith('#%')) {
return await tfrpc.rpc.query(
`
SELECT messages.*
SELECT id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
FROM messages
WHERE id = ?1
UNION
SELECT messages.*
SELECT id, previous, author, sequence, timestamp, hash, json(content) AS content, signature
FROM messages JOIN messages_refs
ON messages.id = messages_refs.message
WHERE messages_refs.ref = ?1
@ -69,17 +69,17 @@ class TfTabNewsFeedElement extends LitElement {
promises.push(
tfrpc.rpc.query(
`
WITH news AS (SELECT messages.*
WITH news AS (SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
FROM messages
JOIN json_each(?) AS following ON messages.author = following.value
WHERE messages.timestamp > ? AND messages.timestamp < ?
ORDER BY messages.timestamp DESC)
SELECT messages.*
SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
FROM news
JOIN messages_refs ON news.id = messages_refs.ref
JOIN messages ON messages_refs.message = messages.id
UNION
SELECT messages.*
SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
FROM news
JOIN messages_refs ON news.id = messages_refs.message
JOIN messages ON messages_refs.ref = messages.id
@ -107,18 +107,18 @@ class TfTabNewsFeedElement extends LitElement {
this.start_time = last_start_time - 24 * 60 * 60 * 1000;
let more = await tfrpc.rpc.query(
`
WITH news AS (SELECT messages.*
WITH news AS (SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
FROM messages
JOIN json_each(?) AS following ON messages.author = following.value
WHERE messages.timestamp > ?
AND messages.timestamp <= ?
ORDER BY messages.timestamp DESC)
SELECT messages.*
SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
FROM news
JOIN messages_refs ON news.id = messages_refs.ref
JOIN messages ON messages_refs.message = messages.id
UNION
SELECT messages.*
SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
FROM news
JOIN messages_refs ON news.id = messages_refs.message
JOIN messages ON messages_refs.ref = messages.id

View File

@ -35,7 +35,7 @@ class TfTabSearchElement extends LitElement {
await tfrpc.rpc.setHash('#q=' + encodeURIComponent(query));
let results = await tfrpc.rpc.query(
`
SELECT messages.*
SELECT messages.id, messages.previous, messages.author, messages.sequence, messages.timestamp, messages.hash, json(messages.content) AS content, messages.signature
FROM messages_fts(?)
JOIN messages ON messages.rowid = messages_fts.rowid
JOIN json_each(?) AS following ON messages.author = following.value

View File

@ -1,5 +1,5 @@
{
"type": "tildefriends-app",
"emoji": "📝",
"previous": "&/wl8HE2jZShRXTYEVYRrK3pjHwi41Wbxl9HoSJaQP6Y=.sha256"
"previous": "&DnfuAUGzzalSh9NgZXnzDc9Ru5aM0omfRJ4h27jYw4k=.sha256"
}

View File

@ -2,8 +2,9 @@
<html>
<head>
<base target="_top" />
<link rel="stylesheet" href="tildefriends.css" />
</head>
<body style="color: #fff">
<body>
<tf-collections-app></tf-collections-app>
<script>
window.litDisableBundleWarning = true;

View File

@ -5,6 +5,7 @@ class TfCollectionElement extends LitElement {
static get properties() {
return {
whoami: {type: String},
category: {type: String},
collection: {type: Object},
selected_id: {type: String},
is_creating: {type: Boolean},
@ -75,9 +76,10 @@ class TfCollectionElement extends LitElement {
render() {
let self = this;
return html`
<span style="display: inline-flex; flex-direction: row">
<link rel="stylesheet" href="tildefriends.css"/>
<span class="inline-flex-row">
<select @change=${this.on_selected} id="select" value=${this.selected_id}>
<option value="" ?selected=${this.selected_id === ''} disabled hidden>(select)</option>
<option value="" ?selected=${this.selected_id === ''} disabled hidden>(select ${this.category})</option>
${Object.values(this.collection ?? {})
.sort((x, y) => x.name.localeCompare(y.name))
.map(
@ -91,22 +93,22 @@ class TfCollectionElement extends LitElement {
)}
</select>
<span ?hidden=${!this.is_renaming || !this.whoami}>
<span style="display: inline-flex; flex-direction: row; margin-left: 8px; margin-right: 8px">
<span class="inline-flex-row" style="margin-left: 8px; margin-right: 8px">
<label for="rename_name">🏷Rename to:</label>
<input type="text" id="rename_name"></input>
<button @click=${this.on_rename}>Rename ${this.type}</button>
<button @click=${() => (self.is_renaming = false)}>x</button>
</span>
</span>
<button @click=${() => (self.is_renaming = true)} ?disabled=${this.is_renaming || !this.selected_id} ?hidden=${!this.whoami}>🏷</button>
<button @click=${self.on_tombstone} ?disabled=${!this.selected_id} ?hidden=${!this.whoami}>🪦</button>
<button class="yellow" @click=${() => (self.is_renaming = true)} ?disabled=${this.is_renaming || !this.selected_id} ?hidden=${!this.whoami}>🏷</button>
<button class="red" @click=${self.on_tombstone} ?disabled=${!this.selected_id} ?hidden=${!this.whoami}>🪦</button>
<span ?hidden=${!this.is_creating || !this.whoami}>
<label for="create_name">New ${this.type} name:</label>
<input type="text" id="create_name"></input>
<button @click=${this.on_create}>Create ${this.type}</button>
<button @click=${() => (self.is_creating = false)}>x</button>
</span>
<button @click=${() => (self.is_creating = true)} ?hidden=${this.is_creating || !this.whoami}>+</button>
<button class="green" @click=${() => (self.is_creating = true)} ?hidden=${this.is_creating || !this.whoami}>+</button>
</span>
`;
}

View File

@ -28,6 +28,7 @@ class TfIdentityPickerElement extends LitElement {
render() {
return html`
<link rel="stylesheet" href="tildefriends.css" />
<select @change=${this.changed} style="max-width: 100%">
${(this.ids ?? []).map(
(id) =>

View File

@ -255,12 +255,22 @@ class TfCollectionsAppElement extends LitElement {
render() {
let self = this;
return html`
<link rel="stylesheet" href="tildefriends.css"/>
<style>
.toc:hover {
.toc-item {
white-space: nowrap;
cursor: pointer;
}
.toc-item:hover {
background-color: #0cc;
}
.toc.selected {
.toc-item.selected {
background-color: #088;
font-weight: bold;
}
.table-of-contents {
flex: 0 0;
margin-right: 16px;
}
</style>
<div>
@ -272,6 +282,7 @@ class TfCollectionsAppElement extends LitElement {
html`<tf-collection
.collection=${this.wikis}
whoami=${this.whoami}
category="wiki"
selected_id=${this.wiki?.id}
@create=${this.on_wiki_create}
@rename=${this.on_wiki_rename}
@ -284,6 +295,7 @@ class TfCollectionsAppElement extends LitElement {
html`<tf-collection
.collection=${this.wiki_docs}
whoami=${this.whoami}
category="document"
selected_id=${this.wiki_doc &&
this.wiki_doc?.parent == this.wiki?.id
? this.wiki_doc?.id
@ -298,9 +310,9 @@ class TfCollectionsAppElement extends LitElement {
<div ?hidden=${!this.wiki?.editors || !this.expand_editors}>
<div>
<ul>
${this.wiki?.editors.map((id) => html`<li><button ?hidden=${id == this.whoami} @click=${() => self.on_remove_editor(id)}>x</button> ${id}</li>`)}
${this.wiki?.editors.map((id) => html`<li><button class="red" ?hidden=${id == this.whoami} @click=${() => self.on_remove_editor(id)}>x</button> ${id}</li>`)}
<li>
<button @click=${() => (self.adding_editor = true)} ?hidden=${this.wiki?.editors?.indexOf(this.whoami) == -1 || this.adding_editor}>+</button>
<button class="green" @click=${() => (self.adding_editor = true)} ?hidden=${this.wiki?.editors?.indexOf(this.whoami) == -1 || this.adding_editor}>+</button>
<div ?hidden=${!this.adding_editor}>
<label for="add_editor">Add Editor:</label>
<input type="text" id="add_editor"></input>
@ -312,18 +324,19 @@ class TfCollectionsAppElement extends LitElement {
</div>
</div>
</div>
<div style="display: flex; flex-direction: row">
<div style="flex: 0 0">
<div class="flex-row">
<div class="box table-of-contents">
${Object.values(this.wikis || {})
.sort((x, y) => x.name.localeCompare(y.name))
.map(
(wiki) => html`
<div
class="toc ${self.wiki?.id === wiki.id ? 'selected' : ''}"
style="white-space: nowrap; cursor: pointer"
class="toc-item ${self.wiki?.id === wiki.id
? 'selected'
: ''}"
@click=${() => self.on_wiki_changed({detail: {value: wiki}})}
>
${wiki.name}
${self.wiki?.id === wiki.id ? '' : '>'} ${wiki.name}
</div>
<ul>
${Object.values(self.wiki_docs || {})
@ -332,14 +345,12 @@ class TfCollectionsAppElement extends LitElement {
.map(
(doc) => html`
<li
class="toc ${self.wiki_doc?.id === doc.id
class="toc-item ${self.wiki_doc?.id === doc.id
? 'selected'
: ''}"
style="white-space: nowrap; cursor: pointer; list-style: none; text-indent: -1rem"
style="list-style: none; text-indent: -1rem"
@click=${() =>
self.on_wiki_doc_changed({
detail: {value: doc},
})}
self.on_wiki_doc_changed({detail: {value: doc}})}
>
${doc?.private ? '🔒' : '📄'} ${doc.name}
</li>

View File

@ -84,7 +84,11 @@ class TfWikiDocElement extends LitElement {
async load_blob() {
let blob = await tfrpc.rpc.get_blob(this.value?.blob);
if (blob.endsWith('.box')) {
if (!blob) {
console.warn(
"no blob found, we're going to assume the document is empty (load_blob())"
);
} else if (blob.endsWith('.box')) {
let d = await tfrpc.rpc.try_decrypt(this.whoami, blob);
if (d) {
blob = d;
@ -253,85 +257,43 @@ class TfWikiDocElement extends LitElement {
let self = this;
let thumbnail_ref = this.thumbnail(this.blob);
return html`
<link rel="stylesheet" href="tildefriends.css"/>
<style>
a:link {
color: #268bd2;
}
a:visited {
color: #6c71c4;
}
a:hover {
color: #859900;
}
a:active {
color: #2aa198;
}
a:link { color: #268bd2 }
a:visited { color: #6c71c4 }
a:hover { color: #859900 }
a:active { color: #2aa198 }
#editor-text-area {
background-color: #00000040;
color: white;
style="flex: 1 1;
min-height: 10em;
font-size: larger;
${this.value?.private ? 'border: 4px solid #800' : ''}
</style>
<div style="display: inline-flex; flex-direction: row">
<button
?disabled=${!this.whoami || this.is_editing}
@click=${() => (self.is_editing = true)}
>
Edit
</button>
<button
?disabled=${this.blob == this.blob_original}
@click=${this.on_save_draft}
>
Save Draft
</button>
<button
?disabled=${this.blob == this.blob_original && !this.value?.draft}
@click=${this.on_publish}
>
Publish
</button>
<button ?disabled=${!this.is_editing} @click=${this.on_discard}>
Discard
</button>
<button
?disabled=${!this.is_editing}
@click=${() =>
(self.value = Object.assign({}, self.value, {
private: !self.value.private,
}))}
>
${this.value?.private ? 'Make Public' : 'Make Private'}
</button>
<button ?disabled=${!this.is_editing} @click=${this.on_blog_publish}>
Publish Blog
</button>
<div class="inline-flex-row">
<button ?disabled=${!this.whoami || this.is_editing} @click=${() => (self.is_editing = true)}>Edit</button>
<button ?disabled=${this.blob == this.blob_original} @click=${this.on_save_draft}>Save Draft</button>
<button ?disabled=${this.blob == this.blob_original && !this.value?.draft} @click=${this.on_publish}>Publish</button>
<button ?disabled=${!this.is_editing} @click=${this.on_discard}>Discard</button>
<button ?disabled=${!this.is_editing} @click=${() => (self.value = Object.assign({}, self.value, {private: !self.value.private}))}>${this.value?.private ? 'Make Public' : 'Make Private'}</button>
<button ?disabled=${!this.is_editing} @click=${this.on_blog_publish}>Publish Blog</button>
</div>
<div ?hidden=${!this.value?.private} style="color: #800">
🔒 document is private
</div>
<div
style="display: flex; flex-direction: row; ${this.value?.private
? 'border-top: 4px solid #800'
: ''}"
>
<div ?hidden=${!this.value?.private} style="color: #800">🔒 document is private</div>
<div class="flex-column" ${this.value?.private ? 'border-top: 4px solid #800' : ''}">
<textarea
rows="25"
?hidden=${!this.is_editing}
style="flex: 1 1; min-height: 10em; ${this.value?.private
? 'border: 4px solid #800'
: ''}"
id="editor-text-area"
@input=${this.on_edit}
@paste=${this.paste}
.value=${this.blob ?? ''}
></textarea>
<div style="flex: 1 1">
<div
?hidden=${!this.is_editing}
style="border: 1px solid #fff; border-radius: 1em; padding: 0.5em"
>
<img
?hidden=${!thumbnail_ref}
style="max-width: 128px; max-height: 128px; float: right"
src="/${thumbnail_ref}/view"
/>
<h1 ?hidden=${!this.title(this.blob)}>
${unsafeHTML(this.markdown(this.title(this.blob)))}
</h1>
.value=${this.blob ?? ''}></textarea>
<div style="flex: 1 1; margin-top: 16px">
<div ?hidden=${!this.is_editing} class="box">
Summary
<img ?hidden=${!thumbnail_ref} style="max-width: 128px; max-height: 128px; float: right" src="/${thumbnail_ref}/view">
<h1 ?hidden=${!this.title(this.blob)}>${unsafeHTML(this.markdown(this.title(this.blob)))}</h1>
${unsafeHTML(this.markdown(this.summary(this.blob)))}
</div>
${unsafeHTML(this.markdown(this.blob))}

115
apps/wiki/tildefriends.css Normal file
View File

@ -0,0 +1,115 @@
/*
* Tilde Friends core stylesheet
* This is a prototype; things may change based on feedback.
*
* This Software is an external library that is part of
* Tilde Friends and is shared under the MIT license.
*
* Inject this file in your app at tildefriends.css
* and use this tag to import it:
* <link rel="stylesheet" href="tildefriends.css"/>
*
* Revision 0 / 2024 M02 19
*/
body {
color: white;
font-family: sans-serif;
}
button,
.button,
input[type='button'],
input[type='submit'],
select {
border: none;
border-radius: 8px;
padding: 8px 12px;
text-align: center;
text-decoration: none;
display: inline-block;
margin: 4px;
&.red {
background-color: #bd1e24;
color: white;
}
&.green {
background-color: #18922d;
color: white;
}
&.blue {
background-color: #0067a7;
color: white;
}
&.yellow {
background-color: #ee9600;
color: black;
}
&:hover {
filter: brightness(0.75);
}
}
a:link {
color: #268bd2;
}
a:visited {
color: #6c71c4;
}
a:hover {
color: #859900;
}
a:active {
color: #2aa198;
}
table {
border-collapse: collapse;
width: 100%;
}
td,
th {
border: 1px solid #ffffff40;
text-align: left;
padding: 8px;
}
tr:nth-child(even) {
background-color: #ffffff20;
}
.flex {
display: flex;
}
.flex-column {
display: flex;
flex-direction: column;
}
.flex-row {
display: flex;
flex-direction: row;
}
.inline-flex-row {
display: inline-flex;
flex-direction: row;
}
.box {
background-color: #00000020;
border: 1px solid grey;
border-radius: 8px;
padding: 16px;
margin: 4px;
}

BIN
bleh.tar.xz Normal file

Binary file not shown.

View File

@ -6,20 +6,37 @@ let g_calls = {};
let gSessionIndex = 0;
/**
* TODOC
* @returns
*/
function makeSessionId() {
return (gSessionIndex++).toString();
}
/**
* TODOC
* @returns
*/
function App() {
this._on_output = null;
this._send_queue = [];
return this;
}
/**
* TODOC
* @param {*} callback
*/
App.prototype.readOutput = function (callback) {
this._on_output = callback;
};
/**
* TODOC
* @param {*} api
* @returns
*/
App.prototype.makeFunction = function (api) {
let self = this;
let result = function () {
@ -43,6 +60,10 @@ App.prototype.makeFunction = function (api) {
return result;
};
/**
* TODOC
* @param {*} message
*/
App.prototype.send = function (message) {
if (this._send_queue) {
if (this._on_output) {
@ -57,11 +78,17 @@ App.prototype.send = function (message) {
}
};
/**
* TODOC
* @param {*} request
* @param {*} response
* @param {*} client
*/
function socket(request, response, client) {
let process;
let options = {};
let credentials = auth.query(request.headers);
let refresh = auth.make_refresh(credentials);
let refresh = auth.makeRefresh(credentials);
response.onClose = async function () {
if (process && process.task) {

View File

@ -5,9 +5,15 @@ 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 {
@ -15,9 +21,15 @@ function b64url(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) {
@ -27,16 +39,22 @@ function unb64url(value) {
}
}
/**
* Creates a JSON Web Token
* @param {object} payload Object: {"name": "username"}
* @returns the JWT
*/
function makeJwt(payload) {
let ids = ssb.getIdentities(':auth');
const ids = ssb.getIdentities(':auth');
let id;
if (ids?.length) {
id = ids[0];
} else {
id = ssb.createIdentity(':auth');
}
let final_payload = b64url(
const final_payload = b64url(
base64Encode(
JSON.stringify(
Object.assign({}, payload, {
@ -45,7 +63,7 @@ function makeJwt(payload) {
)
)
);
let jwt = [
const jwt = [
b64url(base64Encode(JSON.stringify({alg: 'HS256', typ: 'JWT'}))),
final_payload,
b64url(ssb.hmacsha256sign(final_payload, ':auth', id)),
@ -53,17 +71,26 @@ function makeJwt(payload) {
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)) {
let result = JSON.parse(utf8Decode(base64Decode(unb64url(payload))));
let now = new Date().valueOf();
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;
@ -79,15 +106,30 @@ function readSession(session) {
}
}
/**
* 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;
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 ||
@ -100,6 +142,10 @@ function noAdministrator() {
);
}
/**
* Makes a user an administrator
* @param {string} name the user's name
*/
function makeAdministrator(name) {
if (!core.globalSettings.permissions) {
core.globalSettings.permissions = {};
@ -110,9 +156,15 @@ function makeAdministrator(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 = {};
@ -129,7 +181,13 @@ function getCookies(headers) {
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')) &&
@ -144,7 +202,14 @@ function isNameValid(name) {
);
}
/**
* 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);
@ -285,6 +350,11 @@ function handler(request, response) {
}
}
/**
* Gets a user's permissions based on it's session ?
* @param {*} session TODOC
* @returns
*/
function getPermissions(session) {
let permissions;
let entry = readSession(session);
@ -295,6 +365,11 @@ function getPermissions(session) {
return permissions || {};
}
/**
* Get a user's permissions ?
* @param {string} userName TODOC
* @returns
*/
function getPermissionsForUser(userName) {
let permissions = {};
if (
@ -309,6 +384,11 @@ function getPermissionsForUser(userName) {
return permissions;
}
/**
* TODOC
* @param {*} headers
* @returns
*/
function query(headers) {
let session = getCookies(headers).session;
let entry;
@ -323,7 +403,12 @@ function query(headers) {
}
}
function make_refresh(credentials) {
/**
* Refreshes a JWT ?
* @param {*} credentials TODOC
* @returns
*/
function makeRefresh(credentials) {
if (credentials?.session?.name) {
return {
token: makeJwt({name: credentials.session.name}),
@ -332,4 +417,4 @@ function make_refresh(credentials) {
}
}
export {handler, query, make_refresh};
export {handler, query, makeRefresh};

View File

@ -12,7 +12,7 @@ let gOriginalInput;
let kErrorColor = '#dc322f';
let kStatusColor = '#fff';
/* Functions that server-side app code can call through the app object. */
// Functions that server-side app code can call through the app object.
const k_api = {
setDocument: {args: ['content'], func: api_setDocument},
postMessage: {args: ['message'], func: api_postMessage},
@ -24,6 +24,7 @@ const k_api = {
setHash: {args: ['hash'], func: api_setHash},
};
// TODO(tasiaiso): this is only used once, move it down ?
const k_global_style = css`
a:link {
color: #268bd2;
@ -42,6 +43,9 @@ const k_global_style = css`
}
`;
/**
* Class that represents the top bar
*/
class TfNavigationElement extends LitElement {
static get properties() {
return {
@ -63,6 +67,10 @@ class TfNavigationElement extends LitElement {
this.spark_lines = {};
}
/**
* TODOC
* @param {*} event
*/
toggle_edit(event) {
event.preventDefault();
if (editing()) {
@ -72,10 +80,20 @@ class TfNavigationElement extends LitElement {
}
}
/**
* TODOC
* @param {*} key
*/
reset_permission(key) {
send({action: 'resetPermission', permission: key});
}
/**
* TODOC
* @param {*} key
* @param {*} options
* @returns
*/
get_spark_line(key, options) {
if (!this.spark_lines[key]) {
let spark_line = document.createElement('tf-sparkline');
@ -94,6 +112,10 @@ class TfNavigationElement extends LitElement {
return this.spark_lines[key];
}
/**
* TODOC
* @returns
*/
render_login() {
if (this?.credentials?.session?.name) {
return html`<a id="login" href="/login/logout?return=${url() + hash()}"
@ -106,6 +128,10 @@ class TfNavigationElement extends LitElement {
}
}
/**
* TODOC
* @returns
*/
render_permissions() {
if (this.show_permissions) {
return html`
@ -137,13 +163,15 @@ class TfNavigationElement extends LitElement {
}
}
/**
* TODOC
* @returns
*/
render() {
let self = this;
return html`
<style>
/* prettier-ignore */
${k_global_style}
.tooltip {
${k_global_style} .tooltip {
position: absolute;
z-index: 1;
display: none;
@ -230,8 +258,12 @@ class TfNavigationElement extends LitElement {
`;
}
}
customElements.define('tf-navigation', TfNavigationElement);
/**
* TODOC
*/
class TfFilesElement extends LitElement {
static get properties() {
return {
@ -247,6 +279,10 @@ class TfFilesElement extends LitElement {
this.dropping = 0;
}
/**
* TODOC
* @param {*} file
*/
file_click(file) {
this.dispatchEvent(
new CustomEvent('file_click', {
@ -259,6 +295,11 @@ class TfFilesElement extends LitElement {
);
}
/**
* TODOC
* @param {*} file
* @returns
*/
render_file(file) {
let classes = ['file'];
if (file == this.current) {
@ -275,6 +316,10 @@ class TfFilesElement extends LitElement {
</div>`;
}
/**
* TODOC
* @param {*} event
*/
async drop(event) {
event.preventDefault();
event.stopPropagation();
@ -296,15 +341,27 @@ class TfFilesElement extends LitElement {
updateFiles();
}
/**
* TODOC
* @param {*} event
*/
drag_enter(event) {
this.dropping++;
event.preventDefault();
}
/**
* TODOC
* @param {*} event
*/
drag_leave(event) {
this.dropping--;
}
/**
* TODOC
* @returns
*/
render() {
let self = this;
return html`
@ -350,8 +407,12 @@ class TfFilesElement extends LitElement {
`;
}
}
customElements.define('tf-files', TfFilesElement);
/**
* TODOC
*/
class TfFilesPaneElement extends LitElement {
static get properties() {
return {
@ -367,11 +428,19 @@ class TfFilesPaneElement extends LitElement {
this.files = {};
}
/**
* TODOC
* @param {*} expanded
*/
set_expanded(expanded) {
this.expanded = expanded;
window.localStorage.setItem('files', expanded ? '1' : '0');
}
/**
* TODOC
* @returns
*/
render() {
let self = this;
let expander = this.expanded
@ -425,8 +494,12 @@ class TfFilesPaneElement extends LitElement {
`;
}
}
customElements.define('tf-files-pane', TfFilesPaneElement);
/**
* TODOC
*/
class TfSparkLineElement extends LitElement {
static get properties() {
return {
@ -444,6 +517,11 @@ class TfSparkLineElement extends LitElement {
this.k_values_max = 100;
}
/**
* TODOC
* @param {*} key
* @param {*} value
*/
append(key, value) {
let line = null;
for (let it of this.lines) {
@ -468,6 +546,11 @@ class TfSparkLineElement extends LitElement {
this.requestUpdate();
}
/**
* TODOC
* @param {*} line
* @returns
*/
render_line(line) {
if (line?.values?.length >= 2) {
let max = Math.max(this.max, ...line.values);
@ -481,6 +564,10 @@ class TfSparkLineElement extends LitElement {
}
}
/**
* TODOC
* @returns
*/
render() {
let max =
Math.round(
@ -503,8 +590,10 @@ class TfSparkLineElement extends LitElement {
`;
}
}
customElements.define('tf-sparkline', TfSparkLineElement);
// TODOC
window.addEventListener('keydown', function (event) {
if (event.keyCode == 83 && (event.altKey || event.ctrlKey)) {
if (editing()) {
@ -519,6 +608,12 @@ window.addEventListener('keydown', function (event) {
}
});
/**
* TODOC
* @param {*} nodes
* @param {*} callback
* @returns
*/
function ensureLoaded(nodes, callback) {
if (!nodes.length) {
callback();
@ -559,14 +654,26 @@ function ensureLoaded(nodes, callback) {
}
}
/**
* TODOC
* @returns
*/
function editing() {
return document.getElementById('editPane').style.display != 'none';
}
/**
* TODOC
* @returns
*/
function is_edit_only() {
return window.location.search == '?editonly=1' || window.innerWidth < 1024;
}
/**
* TODOC
* @returns
*/
async function edit() {
if (editing()) {
return;
@ -591,10 +698,18 @@ async function edit() {
}
}
/**
* TODOC
*/
function trace() {
window.open(`/speedscope/#profileURL=${encodeURIComponent('/trace')}`);
}
/**
* TODOC
* @param {*} name
* @returns
*/
function guessMode(name) {
return name.endsWith('.js')
? 'javascript'
@ -603,6 +718,12 @@ function guessMode(name) {
: null;
}
/**
* TODOC
* @param {*} name
* @param {*} id
* @returns
*/
function loadFile(name, id) {
return fetch('/' + id + '/view')
.then(function (response) {
@ -626,6 +747,11 @@ function loadFile(name, id) {
});
}
/**
* TODOC
* @param {*} path
* @returns
*/
async function load(path) {
let response = await fetch((path || url()) + 'view');
let json;
@ -663,16 +789,28 @@ async function load(path) {
return Promise.all(promises);
}
/**
* TODOC
*/
function closeEditor() {
window.localStorage.setItem('editing', '0');
document.getElementById('editPane').style.display = 'none';
document.getElementById('viewPane').style.display = 'flex';
}
/**
* TODOC
* @returns
*/
function explodePath() {
return /^\/~([^\/]+)\/([^\/]+)(.*)/.exec(window.location.pathname);
}
/**
* TODOC
* @param {*} save_to
* @returns
*/
function save(save_to) {
document.getElementById('save').disabled = true;
if (gCurrentFile) {
@ -778,6 +916,9 @@ function save(save_to) {
});
}
/**
* TODOC
*/
function changeIcon() {
let value = prompt('Enter a new app icon emoji:');
if (value !== undefined) {
@ -786,6 +927,9 @@ function changeIcon() {
}
}
/**
* TODOC
*/
function deleteApp() {
let name = document.getElementById('name');
let path = name && name.value ? name.value : url();
@ -804,6 +948,10 @@ function deleteApp() {
}
}
/**
* TODOC
* @returns
*/
function url() {
let hash = window.location.href.indexOf('#');
let question = window.location.href.indexOf('?');
@ -819,20 +967,36 @@ function url() {
: window.location.href;
}
/**
* TODOC
* @returns
*/
function hash() {
return window.location.hash != '#' ? window.location.hash : '';
}
/**
* TODOC
* @param {*} content
*/
function api_setDocument(content) {
let iframe = document.getElementById('document');
iframe.srcdoc = content;
}
/**
* TODOC
* @param {*} message
*/
function api_postMessage(message) {
let iframe = document.getElementById('document');
iframe.contentWindow.postMessage(message, '*');
}
/**
* TODOC
* @param {*} error
*/
function api_error(error) {
if (error) {
if (typeof error == 'string') {
@ -844,14 +1008,30 @@ function api_error(error) {
console.log('error', error);
}
/**
* TODOC
* @param {*} key
* @param {*} value
*/
function api_localStorageSet(key, value) {
window.localStorage.setItem('app:' + key, value);
}
/**
* TODOC
* @param {*} key
* @returns
*/
function api_localStorageGet(key) {
return window.localStorage.getItem('app:' + key);
}
/**
* TODOC
* @param {*} permission
* @param {*} id
* @returns
*/
function api_requestPermission(permission, id) {
let outer = document.createElement('div');
outer.classList.add('permissions');
@ -917,14 +1097,25 @@ function api_requestPermission(permission, id) {
});
}
/**
* TODOC
*/
function api_print() {
console.log('app>', ...arguments);
}
/**
* TODOC
* @param {*} hash
*/
function api_setHash(hash) {
window.location.hash = hash;
}
/**
* TODOC
* @param {*} message
*/
function _receive_websocket_message(message) {
if (message && message.action == 'session') {
setStatusMessage('🟢 Executing...', kStatusColor);
@ -1011,6 +1202,11 @@ function _receive_websocket_message(message) {
}
}
/**
* TODOC
* @param {*} message
* @param {*} color
*/
function setStatusMessage(message, color) {
document.getElementsByTagName('tf-navigation')[0].status = {
message: message,
@ -1018,6 +1214,10 @@ function setStatusMessage(message, color) {
};
}
/**
* TODOC
* @param {*} value
*/
function send(value) {
try {
if (gSocket && gSocket.readyState == gSocket.OPEN) {
@ -1028,6 +1228,13 @@ function send(value) {
}
}
/**
* TODOC
* @param {*} sourceData
* @param {*} maxWidth
* @param {*} maxHeight
* @param {*} callback
*/
function fixImage(sourceData, maxWidth, maxHeight, callback) {
let result = sourceData;
let image = new Image();
@ -1054,16 +1261,26 @@ function fixImage(sourceData, maxWidth, maxHeight, callback) {
image.src = sourceData;
}
/**
* TODOC
* @param {*} image
*/
function sendImage(image) {
fixImage(image, 320, 240, function (result) {
send({image: result});
});
}
/**
* TODOC
*/
function hashChange() {
send({event: 'hashChange', hash: window.location.hash});
}
/**
* TODOC
*/
function focus() {
if (gSocket && gSocket.readyState == gSocket.CLOSED) {
connectSocket();
@ -1072,12 +1289,19 @@ function focus() {
}
}
/**
* TODOC
*/
function blur() {
if (gSocket && gSocket.readyState == gSocket.OPEN) {
send({event: 'blur'});
}
}
/**
* TODOC
* @param {*} event
*/
function message(event) {
if (
event.data &&
@ -1123,6 +1347,10 @@ function message(event) {
}
}
/**
* TODOC
* @param {*} path
*/
function reconnect(path) {
let oldSocket = gSocket;
gSocket = null;
@ -1135,6 +1363,10 @@ function reconnect(path) {
connectSocket(path);
}
/**
* TODOC
* @param {*} path
*/
function connectSocket(path) {
if (!gSocket || gSocket.readyState != gSocket.OPEN) {
if (gSocket) {
@ -1194,6 +1426,10 @@ function connectSocket(path) {
}
}
/**
* TODOC
* @param {*} name
*/
function openFile(name) {
let newDoc =
name && gFiles[name]
@ -1216,6 +1452,9 @@ function openFile(name) {
gEditor.focus();
}
/**
* TODOC
*/
function updateFiles() {
let files = document.getElementsByTagName('tf-files-pane')[0];
if (files) {
@ -1235,6 +1474,10 @@ function updateFiles() {
gEditor.focus();
}
/**
* TODOC
* @param {*} name
*/
function makeNewFile(name) {
gFiles[name] = {
doc: cm6.EditorState.create({extensions: cm6.extensions}),
@ -1242,6 +1485,9 @@ function makeNewFile(name) {
openFile(name);
}
/**
* TODOC
*/
function newFile() {
let name = prompt('Name of new file:', 'file.js');
if (name && !gFiles[name]) {
@ -1249,6 +1495,9 @@ function newFile() {
}
}
/**
* TODOC
*/
function removeFile() {
if (confirm('Remove ' + gCurrentFile + '?')) {
delete gFiles[gCurrentFile];
@ -1256,6 +1505,9 @@ function removeFile() {
}
}
/**
* TODOC
*/
async function appExport() {
let JsZip = (await import('/static/jszip.min.js')).default;
let owner = window.location.pathname.split('/')[1].replace('~', '');
@ -1284,6 +1536,12 @@ async function appExport() {
a.click();
}
/**
* TODOC
* @param {*} name
* @param {*} file
* @returns
*/
async function save_file_to_blob_id(name, file) {
console.log(`Saving ${name}.`);
let response = await fetch('/save', {
@ -1305,6 +1563,9 @@ async function save_file_to_blob_id(name, file) {
return blob_id;
}
/**
* TODOC
*/
async function appImport() {
let JsZip = (await import('/static/jszip.min.js')).default;
let input = document.createElement('input');
@ -1373,6 +1634,9 @@ async function appImport() {
};
}
/**
*
*/
async function sourcePretty() {
let prettier = (await import('/prettier/standalone.mjs')).default;
let babel = (await import('/prettier/babel.mjs')).default;
@ -1381,7 +1645,11 @@ async function sourcePretty() {
let formatted = await prettier.format(source, {
parser: 'babel',
plugins: [babel, estree],
trailingComma: 'es5',
useTabs: true,
semi: true,
singleQuote: true,
bracketSpacing: false,
});
if (source !== formatted) {
gEditor.dispatch({
@ -1394,6 +1662,32 @@ async function sourcePretty() {
}
}
function toggleVisibleWhitespace() {
let editor_style = document.getElementById('editor_style');
/*
* There is likely a better way to do this, but stomping on the CSS was
* the easiest to wrangle at the time.
*/
if (editor_style.innerHTML.length) {
editor_style.innerHTML = '';
window.localStorage.setItem('visible_whitespace', '0');
} else {
editor_style.innerHTML = css`
.cm-trailingSpace {
background-color: unset !important;
}
.cm-highlightTab {
background-image: unset !important;
}
.cm-highlightSpace:before {
content: unset !important;
}
`;
window.localStorage.setItem('visible_whitespace', '1');
}
}
// TODOC
window.addEventListener('load', function () {
window.addEventListener('hashchange', hashChange);
window.addEventListener('focus', focus);
@ -1418,6 +1712,9 @@ window.addEventListener('load', function () {
document
.getElementById('pretty')
.addEventListener('click', () => sourcePretty());
document
.getElementById('whitespace')
.addEventListener('click', () => toggleVisibleWhitespace());
document
.getElementById('trace_button')
.addEventListener('click', function (event) {
@ -1431,4 +1728,7 @@ window.addEventListener('load', function () {
} else {
closeEditor();
}
if (window.localStorage.getItem('visible_whitespace') == '1') {
toggleVisibleWhitespace();
}
});

View File

@ -18,20 +18,104 @@ const k_mime_types = {
svg: 'image/svg+xml',
};
// prettier-ignore
const k_magic_bytes = [
{bytes: [0xff, 0xd8, 0xff, 0xdb], type: 'image/jpeg'},
{bytes: [0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01], type: 'image/jpeg'},
{
bytes: [
0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
],
type: 'image/jpeg',
},
{bytes: [0xff, 0xd8, 0xff, 0xee], type: 'image/jpeg'},
{bytes: [0xff, 0xd8, 0xff, 0xe1, null, null, 0x45, 0x78, 0x69, 0x66, 0x00, 0x00], type: 'image/jpeg'},
{
bytes: [
0xff,
0xd8,
0xff,
0xe1,
null,
null,
0x45,
0x78,
0x69,
0x66,
0x00,
0x00,
],
type: 'image/jpeg',
},
{bytes: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], type: 'image/png'},
{bytes: [0x47, 0x49, 0x46, 0x38, 0x37, 0x61], type: 'image/gif'},
{bytes: [0x47, 0x49, 0x46, 0x38, 0x39, 0x61], type: 'image/gif'},
{bytes: [0x52, 0x49, 0x46, 0x46, null, null, null, null, 0x57, 0x45, 0x42, 0x50], type: 'image/webp'},
{
bytes: [
0x52,
0x49,
0x46,
0x46,
null,
null,
null,
null,
0x57,
0x45,
0x42,
0x50,
],
type: 'image/webp',
},
{bytes: [0x3c, 0x73, 0x76, 0x67], type: 'image/svg+xml'},
{bytes: [null, null, null, null, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32], type: 'audio/mpeg'},
{bytes: [null, null, null, null, 0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6f, 0x6d], type: 'video/mp4'},
{bytes: [null, null, null, null, 0x66, 0x74, 0x79, 0x70, 0x6d, 0x70, 0x34, 0x32], type: 'video/mp4'},
{
bytes: [
null,
null,
null,
null,
0x66,
0x74,
0x79,
0x70,
0x6d,
0x70,
0x34,
0x32,
],
type: 'audio/mpeg',
},
{
bytes: [
null,
null,
null,
null,
0x66,
0x74,
0x79,
0x70,
0x69,
0x73,
0x6f,
0x6d,
],
type: 'video/mp4',
},
{
bytes: [
null,
null,
null,
null,
0x66,
0x74,
0x79,
0x70,
0x6d,
0x70,
0x34,
0x32,
],
type: 'video/mp4',
},
{bytes: [0x4d, 0x54, 0x68, 0x64], type: 'audio/midi'},
];
@ -103,6 +187,11 @@ let gGlobalSettings = {
let kPingInterval = 60 * 1000;
/**
* TODOC
* @param {*} out
* @param {*} error
*/
function printError(out, error) {
if (error.stackTrace) {
out.print(error.fileName + ':' + error.lineNumber + ': ' + error.message);
@ -115,6 +204,12 @@ function printError(out, error) {
}
}
/**
* TODOC
* @param {*} handlers
* @param {*} argv
* @returns
*/
function invoke(handlers, argv) {
let promises = [];
if (handlers) {
@ -135,6 +230,12 @@ function invoke(handlers, argv) {
return Promise.all(promises);
}
/**
* TODOC
* @param {*} eventName
* @param {*} argv
* @returns
*/
function broadcastEvent(eventName, argv) {
let promises = [];
for (let process of Object.values(gProcesses)) {
@ -144,7 +245,11 @@ function broadcastEvent(eventName, argv) {
}
return Promise.all(promises);
}
/**
* TODOC
* @param {*} message
* @returns
*/
function broadcast(message) {
let sender = this;
let promises = [];
@ -161,6 +266,12 @@ function broadcast(message) {
return Promise.all(promises);
}
/**
* TODOC
* @param {*} caller
* @param {*} process
* @returns
*/
function getUser(caller, process) {
return {
key: process.key,
@ -171,6 +282,12 @@ function getUser(caller, process) {
};
}
/**
* TODOC
* @param {*} user
* @param {*} process
* @returns
*/
function getApps(user, process) {
if (
process.credentials &&
@ -195,12 +312,26 @@ function getApps(user, process) {
return {};
}
/**
* TODOC
* @param {*} from
* @param {*} to
* @param {*} message
* @returns
*/
function postMessageInternal(from, to, message) {
if (to.eventHandlers['message']) {
return invoke(to.eventHandlers['message'], [getUser(from, from), message]);
}
}
/**
* TODOC
* @param {*} blobId
* @param {*} session
* @param {*} options
* @returns
*/
async function getSessionProcessBlob(blobId, session, options) {
let actualOptions = {timeout: kPingInterval};
if (options) {
@ -211,7 +342,15 @@ async function getSessionProcessBlob(blobId, session, options) {
return getProcessBlob(blobId, 'session_' + session, actualOptions);
}
/**
* TODOC
* @param {*} blobId
* @param {*} key
* @param {*} options
* @returns
*/
async function getProcessBlob(blobId, key, options) {
// TODO(tasiaiso): break this down ?
let process = gProcesses[key];
if (!process && !(options && 'create' in options && !options.create)) {
let resolveReady;
@ -439,6 +578,7 @@ async function getProcessBlob(blobId, key, options) {
imports.ssb = Object.fromEntries(
Object.keys(ssb).map((key) => [key, ssb[key].bind(ssb)])
);
imports.ssb.port = tildefriends.ssb_port;
imports.ssb.createIdentity = function () {
if (
process.credentials &&
@ -678,6 +818,11 @@ async function getProcessBlob(blobId, key, options) {
return process;
}
/**
* TODOC
* @param {*} settings
* @returns
*/
function setGlobalSettings(settings) {
gGlobalSettings = settings;
try {
@ -687,6 +832,12 @@ function setGlobalSettings(settings) {
}
}
/**
* TODOC
* @param {*} data
* @param {*} bytes
* @returns
*/
function startsWithBytes(data, bytes) {
if (data.byteLength >= bytes.length) {
let dataBytes = new Uint8Array(data.slice(0, bytes.length));
@ -699,11 +850,21 @@ function startsWithBytes(data, bytes) {
}
}
/**
* TODOC
* @param {*} path
* @returns
*/
function guessTypeFromName(path) {
let extension = path.split('.').pop();
return k_mime_types[extension];
}
/**
* TODOC
* @param {*} data
* @returns
*/
function guessTypeFromMagicBytes(data) {
for (let magic of k_magic_bytes) {
if (startsWithBytes(data, magic.bytes)) {
@ -712,6 +873,14 @@ function guessTypeFromMagicBytes(data) {
}
}
/**
* TODOC
* @param {*} response
* @param {*} data
* @param {*} type
* @param {*} headers
* @param {*} status_code
*/
function sendData(response, data, type, headers, status_code) {
if (data) {
response.writeHead(
@ -741,6 +910,11 @@ function sendData(response, data, type, headers, status_code) {
}
}
/**
* TODOC
* @param {*} id
* @returns
*/
async function getBlobOrContent(id) {
if (!id) {
return;
@ -752,6 +926,18 @@ async function getBlobOrContent(id) {
}
let g_handler_index = 0;
/**
* TODOC
* @param {*} response
* @param {*} handler_blob_id
* @param {*} path
* @param {*} query
* @param {*} headers
* @param {*} packageOwner
* @param {*} packageName
* @returns
*/
async function useAppHandler(
response,
handler_blob_id,
@ -797,7 +983,16 @@ async function useAppHandler(
return result;
}
/**
* TODOC
* @param {*} request
* @param {*} response
* @param {*} blobId
* @param {*} uri
* @returns
*/
async function blobHandler(request, response, blobId, uri) {
// TODO(tasiaiso): break this down ?
for (let i in k_static_files) {
if (uri === k_static_files[i].uri && k_static_files[i].path) {
let stat = await File.stat('core/' + k_static_files[i].path);
@ -1079,6 +1274,9 @@ ssb.addEventListener('connections', function () {
broadcastEvent('onConnectionsChanged', []);
});
/**
* TODOC
*/
async function loadSettings() {
let data = {};
try {
@ -1097,6 +1295,9 @@ async function loadSettings() {
gGlobalSettings = data;
}
/**
* TODOC
*/
function sendStats() {
let apps = Object.values(gProcesses)
.filter((process) => process.app && process.stats)
@ -1112,6 +1313,11 @@ function sendStats() {
}
}
/**
* TODOC
* @param {*} process
* @param {*} enabled
*/
function enableStats(process, enabled) {
process.stats = enabled;
if (!gStatsTimer) {
@ -1120,6 +1326,9 @@ function enableStats(process, enabled) {
}
}
/**
* TODOC
*/
loadSettings()
.then(function () {
if (tildefriends.https_port && gGlobalSettings.http_redirect) {
@ -1213,6 +1422,14 @@ loadSettings()
exit(1);
});
/**
* TODOC
* @param {*} user
* @param {*} packageOwner
* @param {*} packageName
* @param {*} permission
* @param {*} allow
*/
function storePermission(user, packageOwner, packageName, permission, allow) {
if (!gGlobalSettings.userPermissions) {
gGlobalSettings.userPermissions = {};

View File

@ -1,3 +1,8 @@
/**
* TODOC
* @param {*} encoded
* @returns
*/
function decode(encoded) {
let result = '';
for (let i = 0; i < encoded.length; i++) {
@ -14,6 +19,12 @@ function decode(encoded) {
return result;
}
/**
* TODOC
* @param {*} encoded
* @param {*} initial
* @returns
*/
function decodeForm(encoded, initial) {
let result = initial || {};
if (encoded) {

View File

@ -1,3 +1,9 @@
/**
* TODOC
* TODO: document so we can improve this
* @param {*} url
* @returns
*/
function parseUrl(url) {
// XXX: Hack.
let match = url.match(new RegExp('(\\w+)://([^/:]+)(?::(\\d+))?(.*)'));
@ -9,6 +15,11 @@ function parseUrl(url) {
};
}
/**
* TODOC
* @param {*} data
* @returns
*/
function parseResponse(data) {
let firstLine;
let headers = {};
@ -28,6 +39,13 @@ function parseResponse(data) {
return {body: data};
}
/**
* TODOC
* @param {*} url
* @param {*} options
* @param {*} allowed_hosts
* @returns
*/
export function fetch(url, options, allowed_hosts) {
let parsed = parseUrl(url);
return new Promise(function (resolve, reject) {

View File

@ -57,7 +57,7 @@
class="w3-bar-item w3-button w3-blue"
id="icon"
name="icon"
accesskey="i"
accesskey="j"
onmouseover="set_access_key_title(event)"
data-tip="Set an icon/emoji for the app"
>
@ -93,6 +93,16 @@
>
🧼
</button>
<button
class="w3-bar-item w3-button w3-blue"
id="whitespace"
name="whitespace"
accesskey="w"
onmouseover="set_access_key_title(event)"
data-tip="Toggle visible whitespace"
>
</button>
<input
class="w3-bar-item w3-input w3-border w3-blue"
type="text"
@ -125,6 +135,7 @@
<tf-files-pane style="overflow: auto"></tf-files-pane>
</div>
<div style="flex: 1 1; overflow: auto">
<style id="editor_style"></style>
<div id="editor" style="width: 100%; height: 100%"></div>
</div>
</div>

View File

@ -3,6 +3,10 @@ let g_api = {};
let g_next_id = 1;
let g_calls = {};
/**
* TODOC
* @returns
*/
function get_is_browser() {
try {
return window !== undefined && console !== undefined;
@ -15,6 +19,13 @@ if (k_is_browser) {
print = console.log;
}
/**
* TODOC
* @param {*} target
* @param {*} prop
* @param {*} receiver
* @returns
*/
function make_rpc(target, prop, receiver) {
return function () {
let id = g_next_id++;
@ -43,6 +54,10 @@ function make_rpc(target, prop, receiver) {
};
}
/**
* TODOC
* @param {*} response
*/
function send(response) {
if (k_is_browser) {
window.parent.postMessage(response, '*');
@ -51,6 +66,10 @@ function send(response) {
}
}
/**
* TODOC
* @param {*} message
*/
function call_rpc(message) {
if (message && message.message === 'tfrpc') {
let id = message.id;
@ -105,6 +124,10 @@ if (k_is_browser) {
export let rpc = new Proxy({}, {get: make_rpc});
/**
* TODOC
* @param {*} method
*/
export function register(method) {
g_api[method.name] = method;
}

36
default.nix Normal file
View File

@ -0,0 +1,36 @@
with import <nixpkgs> {};
stdenv.mkDerivation rec {
pname = "tildefriends";
version = "0.0.16";
src = fetchurl {
url = "https://dev.tildefriends.net/cory/${pname}/archive/v${version}.tar.gz";
sha256 = "19iay794xxs3j3mhnpl4vwx65sflw5vvjaahp0jk85wlwlrc7ddw";
};
nativeBuildInputs = [
gnumake
openssl
];
# buildInputs = [ ]
#doCheck = true;
strictDeps = true;
outputs = [ "out" ];
meta = with lib; {
#description = "A program that produces a familiar, friendly greeting";
#longDescription = ''
# GNU Hello is a program that prints "Hello, world!" when you run it.
# It is fully customizable.
#'';
#homepage = "https://www.gnu.org/software/hello/manual/";
#changelog = "https://git.savannah.gnu.org/cgit/hello.git/plain/NEWS?h=v${version}";
license = licenses.gpl3Plus;
maintainers = [ maintainers.tasiaiso ];
platforms = platforms.all;
};
}

File diff suppressed because one or more lines are too long

806
deps/codemirror_src/package-lock.json generated vendored Normal file
View File

@ -0,0 +1,806 @@
{
"name": "codemirror_src",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"@codemirror/lang-css": "6.2.1",
"@codemirror/lang-html": "6.4.8",
"@codemirror/lang-javascript": "6.2.2",
"@codemirror/lang-json": "6.0.1",
"@codemirror/theme-one-dark": "6.1.2",
"@rollup/plugin-node-resolve": "15.2.3",
"codemirror": "6.0.1",
"rollup": "4.13.0"
},
"devDependencies": {
"@rollup/plugin-terser": "0.4.4"
}
},
"node_modules/@codemirror/autocomplete": {
"version": "6.15.0",
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.15.0.tgz",
"integrity": "sha512-G2Zm0mXznxz97JhaaOdoEG2cVupn4JjPaS4AcNvZzhOsnnG9YVN68VzfoUw6dYTsIxT6a/cmoFEN47KAWhXaOg==",
"dependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.17.0",
"@lezer/common": "^1.0.0"
},
"peerDependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/common": "^1.0.0"
}
},
"node_modules/@codemirror/commands": {
"version": "6.3.3",
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.3.3.tgz",
"integrity": "sha512-dO4hcF0fGT9tu1Pj1D2PvGvxjeGkbC6RGcZw6Qs74TH+Ed1gw98jmUgd2axWvIZEqTeTuFrg1lEB1KV6cK9h1A==",
"dependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.4.0",
"@codemirror/view": "^6.0.0",
"@lezer/common": "^1.1.0"
}
},
"node_modules/@codemirror/lang-css": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.2.1.tgz",
"integrity": "sha512-/UNWDNV5Viwi/1lpr/dIXJNWiwDxpw13I4pTUAsNxZdg6E0mI2kTQb0P2iHczg1Tu+H4EBgJR+hYhKiHKko7qg==",
"dependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@lezer/common": "^1.0.2",
"@lezer/css": "^1.0.0"
}
},
"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==",
"dependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/lang-css": "^6.0.0",
"@codemirror/lang-javascript": "^6.0.0",
"@codemirror/language": "^6.4.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.17.0",
"@lezer/common": "^1.0.0",
"@lezer/css": "^1.1.0",
"@lezer/html": "^1.3.0"
}
},
"node_modules/@codemirror/lang-javascript": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.2.tgz",
"integrity": "sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==",
"dependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/language": "^6.6.0",
"@codemirror/lint": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.17.0",
"@lezer/common": "^1.0.0",
"@lezer/javascript": "^1.0.0"
}
},
"node_modules/@codemirror/lang-json": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.1.tgz",
"integrity": "sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==",
"dependencies": {
"@codemirror/language": "^6.0.0",
"@lezer/json": "^1.0.0"
}
},
"node_modules/@codemirror/language": {
"version": "6.10.1",
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.1.tgz",
"integrity": "sha512-5GrXzrhq6k+gL5fjkAwt90nYDmjlzTIJV8THnxNFtNKWotMIlzzN+CpqxqwXOECnUdOndmSeWntVrVcv5axWRQ==",
"dependencies": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.23.0",
"@lezer/common": "^1.1.0",
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0",
"style-mod": "^4.0.0"
}
},
"node_modules/@codemirror/lint": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.5.0.tgz",
"integrity": "sha512-+5YyicIaaAZKU8K43IQi8TBy6mF6giGeWAH7N96Z5LC30Wm5JMjqxOYIE9mxwMG1NbhT2mA3l9hA4uuKUM3E5g==",
"dependencies": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"crelt": "^1.0.5"
}
},
"node_modules/@codemirror/search": {
"version": "6.5.6",
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz",
"integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==",
"dependencies": {
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"crelt": "^1.0.5"
}
},
"node_modules/@codemirror/state": {
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz",
"integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A=="
},
"node_modules/@codemirror/theme-one-dark": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.2.tgz",
"integrity": "sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==",
"dependencies": {
"@codemirror/language": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0",
"@lezer/highlight": "^1.0.0"
}
},
"node_modules/@codemirror/view": {
"version": "6.25.1",
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.25.1.tgz",
"integrity": "sha512-2LXLxsQnHDdfGzDvjzAwZh2ZviNJm7im6tGpa0IONIDnFd8RZ80D2SNi8PDi6YjKcMoMRK20v6OmKIdsrwsyoQ==",
"dependencies": {
"@codemirror/state": "^6.4.0",
"style-mod": "^4.1.0",
"w3c-keyname": "^2.2.4"
}
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
"dev": true,
"dependencies": {
"@jridgewell/set-array": "^1.2.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
"@jridgewell/trace-mapping": "^0.3.24"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/set-array": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/source-map": {
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
"dev": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.15",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
"dev": true
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.25",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@lezer/common": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz",
"integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ=="
},
"node_modules/@lezer/css": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.8.tgz",
"integrity": "sha512-7JhxupKuMBaWQKjQoLtzhGj83DdnZY9MckEOG5+/iLKNK2ZJqKc6hf6uc0HjwCX7Qlok44jBNqZhHKDhEhZYLA==",
"dependencies": {
"@lezer/common": "^1.2.0",
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0"
}
},
"node_modules/@lezer/highlight": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz",
"integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==",
"dependencies": {
"@lezer/common": "^1.0.0"
}
},
"node_modules/@lezer/html": {
"version": "1.3.9",
"resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.9.tgz",
"integrity": "sha512-MXxeCMPyrcemSLGaTQEZx0dBUH0i+RPl8RN5GwMAzo53nTsd/Unc/t5ZxACeQoyPUM5/GkPLRUs2WliOImzkRA==",
"dependencies": {
"@lezer/common": "^1.2.0",
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0"
}
},
"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==",
"dependencies": {
"@lezer/common": "^1.2.0",
"@lezer/highlight": "^1.1.3",
"@lezer/lr": "^1.3.0"
}
},
"node_modules/@lezer/json": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.2.tgz",
"integrity": "sha512-xHT2P4S5eeCYECyKNPhr4cbEL9tc8w83SPwRC373o9uEdrvGKTZoJVAGxpOsZckMlEh9W23Pc72ew918RWQOBQ==",
"dependencies": {
"@lezer/common": "^1.2.0",
"@lezer/highlight": "^1.0.0",
"@lezer/lr": "^1.0.0"
}
},
"node_modules/@lezer/lr": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.0.tgz",
"integrity": "sha512-Wst46p51km8gH0ZUmeNrtpRYmdlRHUpN1DQd3GFAyKANi8WVz8c2jHYTf1CVScFaCjQw1iO3ZZdqGDxQPRErTg==",
"dependencies": {
"@lezer/common": "^1.0.0"
}
},
"node_modules/@rollup/plugin-node-resolve": {
"version": "15.2.3",
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz",
"integrity": "sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==",
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
"@types/resolve": "1.20.2",
"deepmerge": "^4.2.2",
"is-builtin-module": "^3.2.1",
"is-module": "^1.0.0",
"resolve": "^1.22.1"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^2.78.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/plugin-terser": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz",
"integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==",
"dev": true,
"dependencies": {
"serialize-javascript": "^6.0.1",
"smob": "^1.0.0",
"terser": "^5.17.4"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/pluginutils": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz",
"integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==",
"dependencies": {
"@types/estree": "^1.0.0",
"estree-walker": "^2.0.2",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"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==",
"cpu": [
"arm"
],
"optional": true,
"os": [
"android"
]
},
"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==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"android"
]
},
"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==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"darwin"
]
},
"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==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"darwin"
]
},
"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==",
"cpu": [
"arm"
],
"optional": true,
"os": [
"linux"
]
},
"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==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
]
},
"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==",
"cpu": [
"arm64"
],
"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==",
"cpu": [
"riscv64"
],
"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==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"linux"
]
},
"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==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"linux"
]
},
"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==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"win32"
]
},
"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==",
"cpu": [
"ia32"
],
"optional": true,
"os": [
"win32"
]
},
"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==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"win32"
]
},
"node_modules/@types/estree": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
},
"node_modules/@types/resolve": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="
},
"node_modules/acorn": {
"version": "8.11.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
"integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true
},
"node_modules/builtin-modules": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
"integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/codemirror": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz",
"integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==",
"dependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/commands": "^6.0.0",
"@codemirror/language": "^6.0.0",
"@codemirror/lint": "^6.0.0",
"@codemirror/search": "^6.0.0",
"@codemirror/state": "^6.0.0",
"@codemirror/view": "^6.0.0"
}
},
"node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
"node_modules/crelt": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="
},
"node_modules/deepmerge": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/is-builtin-module": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz",
"integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==",
"dependencies": {
"builtin-modules": "^3.3.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-core-module": {
"version": "2.13.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
"integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
"dependencies": {
"hasown": "^2.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-module": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g=="
},
"node_modules/path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dev": true,
"dependencies": {
"safe-buffer": "^5.1.0"
}
},
"node_modules/resolve": {
"version": "1.22.8",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
"dependencies": {
"is-core-module": "^2.13.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
"bin": {
"resolve": "bin/resolve"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/rollup": {
"version": "4.13.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.0.tgz",
"integrity": "sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==",
"dependencies": {
"@types/estree": "1.0.5"
},
"bin": {
"rollup": "dist/bin/rollup"
},
"engines": {
"node": ">=18.0.0",
"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",
"fsevents": "~2.3.2"
}
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/serialize-javascript": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"dev": true,
"dependencies": {
"randombytes": "^2.1.0"
}
},
"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==",
"dev": true
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-support": {
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
"dev": true,
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"node_modules/style-mod": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz",
"integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw=="
},
"node_modules/supports-preserve-symlinks-flag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"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==",
"dev": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
"acorn": "^8.8.2",
"commander": "^2.20.0",
"source-map-support": "~0.5.20"
},
"bin": {
"terser": "bin/terser"
},
"engines": {
"node": ">=10"
}
},
"node_modules/w3c-keyname": {
"version": "2.2.8",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="
}
}
}

View File

@ -1,15 +1,18 @@
{
"scripts": {
"build": "rollup --config rollup.config.mjs --input editor.mjs"
},
"dependencies": {
"@codemirror/lang-css": "^6.2.1",
"@codemirror/lang-html": "^6.4.8",
"@codemirror/lang-javascript": "^6.2.1",
"@codemirror/lang-json": "^6.0.1",
"@codemirror/theme-one-dark": "^6.1.2",
"@rollup/plugin-node-resolve": "^15.2.3",
"codemirror": "^6.0.1",
"rollup": "^4.9.6"
"@codemirror/lang-css": "6.2.1",
"@codemirror/lang-html": "6.4.8",
"@codemirror/lang-javascript": "6.2.2",
"@codemirror/lang-json": "6.0.1",
"@codemirror/theme-one-dark": "6.1.2",
"@rollup/plugin-node-resolve": "15.2.3",
"codemirror": "6.0.1",
"rollup": "4.13.0"
},
"devDependencies": {
"@rollup/plugin-terser": "^0.4.4"
"@rollup/plugin-terser": "0.4.4"
}
}

1
deps/crypt_blowfish vendored Submodule

Submodule deps/crypt_blowfish added at 3354bb81ee

View File

@ -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 $

View File

@ -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

View File

@ -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 $

View File

@ -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 $

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

Submodule deps/libbacktrace added at 9ae4f4ae44

View File

@ -1,5 +0,0 @@
*~
*.o
*.lo
*.a
*.la

File diff suppressed because it is too large Load Diff

View File

@ -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.

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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.

View File

@ -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])

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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@

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -1,348 +0,0 @@
#! /bin/sh
# Wrapper for compilers which do not understand '-c -o'.
scriptversion=2016-01-11.22; # UTC
# Copyright (C) 1999-2017 Free Software Foundation, Inc.
# Written by Tom Tromey <tromey@cygnus.com>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# This file is maintained in Automake, please report
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
nl='
'
# We need space, tab and new line, in precisely that order. Quoting is
# there to prevent tools from complaining about whitespace usage.
IFS=" "" $nl"
file_conv=
# func_file_conv build_file lazy
# Convert a $build file to $host form and store it in $file
# Currently only supports Windows hosts. If the determined conversion
# type is listed in (the comma separated) LAZY, no conversion will
# take place.
func_file_conv ()
{
file=$1
case $file in
/ | /[!/]*) # absolute file, and not a UNC file
if test -z "$file_conv"; then
# lazily determine how to convert abs files
case `uname -s` in
MINGW*)
file_conv=mingw
;;
CYGWIN*)
file_conv=cygwin
;;
*)
file_conv=wine
;;
esac
fi
case $file_conv/,$2, in
*,$file_conv,*)
;;
mingw/*)
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
;;
cygwin/*)
file=`cygpath -m "$file" || echo "$file"`
;;
wine/*)
file=`winepath -w "$file" || echo "$file"`
;;
esac
;;
esac
}
# func_cl_dashL linkdir
# Make cl look for libraries in LINKDIR
func_cl_dashL ()
{
func_file_conv "$1"
if test -z "$lib_path"; then
lib_path=$file
else
lib_path="$lib_path;$file"
fi
linker_opts="$linker_opts -LIBPATH:$file"
}
# func_cl_dashl library
# Do a library search-path lookup for cl
func_cl_dashl ()
{
lib=$1
found=no
save_IFS=$IFS
IFS=';'
for dir in $lib_path $LIB
do
IFS=$save_IFS
if $shared && test -f "$dir/$lib.dll.lib"; then
found=yes
lib=$dir/$lib.dll.lib
break
fi
if test -f "$dir/$lib.lib"; then
found=yes
lib=$dir/$lib.lib
break
fi
if test -f "$dir/lib$lib.a"; then
found=yes
lib=$dir/lib$lib.a
break
fi
done
IFS=$save_IFS
if test "$found" != yes; then
lib=$lib.lib
fi
}
# func_cl_wrapper cl arg...
# Adjust compile command to suit cl
func_cl_wrapper ()
{
# Assume a capable shell
lib_path=
shared=:
linker_opts=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
eat=1
case $2 in
*.o | *.[oO][bB][jJ])
func_file_conv "$2"
set x "$@" -Fo"$file"
shift
;;
*)
func_file_conv "$2"
set x "$@" -Fe"$file"
shift
;;
esac
;;
-I)
eat=1
func_file_conv "$2" mingw
set x "$@" -I"$file"
shift
;;
-I*)
func_file_conv "${1#-I}" mingw
set x "$@" -I"$file"
shift
;;
-l)
eat=1
func_cl_dashl "$2"
set x "$@" "$lib"
shift
;;
-l*)
func_cl_dashl "${1#-l}"
set x "$@" "$lib"
shift
;;
-L)
eat=1
func_cl_dashL "$2"
;;
-L*)
func_cl_dashL "${1#-L}"
;;
-static)
shared=false
;;
-Wl,*)
arg=${1#-Wl,}
save_ifs="$IFS"; IFS=','
for flag in $arg; do
IFS="$save_ifs"
linker_opts="$linker_opts $flag"
done
IFS="$save_ifs"
;;
-Xlinker)
eat=1
linker_opts="$linker_opts $2"
;;
-*)
set x "$@" "$1"
shift
;;
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
func_file_conv "$1"
set x "$@" -Tp"$file"
shift
;;
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
func_file_conv "$1" mingw
set x "$@" "$file"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -n "$linker_opts"; then
linker_opts="-link$linker_opts"
fi
exec "$@" $linker_opts
exit 1
}
eat=
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: compile [--help] [--version] PROGRAM [ARGS]
Wrapper for compilers which do not understand '-c -o'.
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
arguments, and rename the output as expected.
If you are trying to build a whole package this is not the
right script to run: please start by reading the file 'INSTALL'.
Report bugs to <bug-automake@gnu.org>.
EOF
exit $?
;;
-v | --v*)
echo "compile $scriptversion"
exit $?
;;
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
func_cl_wrapper "$@" # Doesn't return...
;;
esac
ofile=
cfile=
for arg
do
if test -n "$eat"; then
eat=
else
case $1 in
-o)
# configure might choose to run compile as 'compile cc -o foo foo.c'.
# So we strip '-o arg' only if arg is an object.
eat=1
case $2 in
*.o | *.obj)
ofile=$2
;;
*)
set x "$@" -o "$2"
shift
;;
esac
;;
*.c)
cfile=$1
set x "$@" "$1"
shift
;;
*)
set x "$@" "$1"
shift
;;
esac
fi
shift
done
if test -z "$ofile" || test -z "$cfile"; then
# If no '-o' option was seen then we might have been invoked from a
# pattern rule where we don't need one. That is ok -- this is a
# normal compilation that the losing compiler can handle. If no
# '.c' file was seen then we are probably linking. That is also
# ok.
exec "$@"
fi
# Name of file we expect compiler to create.
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
# Create the lock directory.
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
# that we are using for the .o file. Also, base the name on the expected
# object file name, since that is what matters with a parallel build.
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
while true; do
if mkdir "$lockdir" >/dev/null 2>&1; then
break
fi
sleep 1
done
# FIXME: race condition here if user kills between mkdir and trap.
trap "rmdir '$lockdir'; exit 1" 1 2 15
# Run the compile.
"$@"
ret=$?
if test -f "$cofile"; then
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
elif test -f "${cofile}bj"; then
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
fi
rmdir "$lockdir"
exit $ret
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

File diff suppressed because it is too large Load Diff

View File

@ -1,179 +0,0 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* ELF size: 32 or 64 */
#undef BACKTRACE_ELF_SIZE
/* XCOFF size: 32 or 64 */
#undef BACKTRACE_XCOFF_SIZE
/* Define to 1 if you have the __atomic functions */
#undef HAVE_ATOMIC_FUNCTIONS
/* Define to 1 if you have the `clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME
/* Define to 1 if you have the declaration of `getpagesize', and to 0 if you
don't. */
#undef HAVE_DECL_GETPAGESIZE
/* Define to 1 if you have the declaration of `strnlen', and to 0 if you
don't. */
#undef HAVE_DECL_STRNLEN
/* Define to 1 if you have the declaration of `_pgmptr', and to 0 if you
don't. */
#undef HAVE_DECL__PGMPTR
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define if dl_iterate_phdr is available. */
#undef HAVE_DL_ITERATE_PHDR
/* Define to 1 if you have the fcntl function */
#undef HAVE_FCNTL
/* Define if getexecname is available. */
#undef HAVE_GETEXECNAME
/* Define if _Unwind_GetIPInfo is available. */
#undef HAVE_GETIPINFO
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have KERN_PROC and KERN_PROC_PATHNAME in <sys/sysctl.h>.
*/
#undef HAVE_KERN_PROC
/* Define to 1 if you have KERN_PROCARGS and KERN_PROC_PATHNAME in
<sys/sysctl.h>. */
#undef HAVE_KERN_PROC_ARGS
/* Define if -llzma is available. */
#undef HAVE_LIBLZMA
/* Define to 1 if you have the <link.h> header file. */
#undef HAVE_LINK_H
/* Define if AIX loadquery is available. */
#undef HAVE_LOADQUERY
/* Define to 1 if you have the `lstat' function. */
#undef HAVE_LSTAT
/* Define to 1 if you have the <mach-o/dyld.h> header file. */
#undef HAVE_MACH_O_DYLD_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the `readlink' function. */
#undef HAVE_READLINK
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the __sync functions */
#undef HAVE_SYNC_FUNCTIONS
/* Define to 1 if you have the <sys/ldr.h> header file. */
#undef HAVE_SYS_LDR_H
/* Define to 1 if you have the <sys/link.h> header file. */
#undef HAVE_SYS_LINK_H
/* Define to 1 if you have the <sys/mman.h> header file. */
#undef HAVE_SYS_MMAN_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define if -lz is available. */
#undef HAVE_ZLIB
/* Define if -lzstd is available. */
#undef HAVE_ZSTD
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
#endif
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
/* Define for large files, on AIX-style hosts. */
#undef _LARGE_FILES
/* Define to 1 if on MINIX. */
#undef _MINIX
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
#undef _POSIX_1_SOURCE
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE

File diff suppressed because it is too large Load Diff

View File

@ -1,38 +0,0 @@
dnl ----------------------------------------------------------------------
dnl This whole bit snagged from libstdc++-v3.
dnl
dnl GCC_ENABLE
dnl (FEATURE, DEFAULT, HELP-ARG, HELP-STRING)
dnl (FEATURE, DEFAULT, HELP-ARG, HELP-STRING, permit a|b|c)
dnl (FEATURE, DEFAULT, HELP-ARG, HELP-STRING, SHELL-CODE-HANDLER)
dnl
dnl See docs/html/17_intro/configury.html#enable for documentation.
dnl
AC_DEFUN([GCC_ENABLE],[dnl
m4_define([_g_switch],[--enable-$1])dnl
m4_define([_g_help],[AC_HELP_STRING(_g_switch$3,[$4 @<:@default=$2@:>@])])dnl
AC_ARG_ENABLE($1,_g_help,
m4_bmatch([$5],
[^permit ],
[[
case "$enableval" in
m4_bpatsubst([$5],[permit ])) ;;
*) AC_MSG_ERROR(Unknown argument to enable/disable $1) ;;
dnl Idea for future: generate a URL pointing to
dnl "onlinedocs/configopts.html#whatever"
esac
]],
[^$],
[[
case "$enableval" in
yes|no) ;;
*) AC_MSG_ERROR(Argument to enable/disable $1 must be yes or no) ;;
esac
]],
[[$5]]),
[enable_]m4_bpatsubst([$1],-,_)[=][$2])
m4_undefine([_g_switch])dnl
m4_undefine([_g_help])dnl
])

View File

@ -1,31 +0,0 @@
# -*- Autoconf -*-
# Copyright (C) 2003, 2009 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
# serial 1
# Check whether the underlying file-system supports filenames
# with a leading dot. For instance MS-DOS doesn't.
AC_DEFUN([AM_SET_LEADING_DOT],
[rm -rf .tst 2>/dev/null
mkdir .tst 2>/dev/null
if test -d .tst; then
am__leading_dot=.
else
am__leading_dot=_
fi
rmdir .tst 2>/dev/null
AC_SUBST([am__leading_dot])])

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More