Merge branches/quickjs to trunk. This is the way.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3621 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
COPYINGMakefileREADME.mdSConstruct
apps/cory
core
app.jsauth.htmlauth.jsbCrypt.jsclient.jscore.jshttpd.jsindex.htmlisaac.jsnetwork.jsstyle.cssterminal.js
deps
base64c
crypt_blowfish
LINKSMakefilePERFORMANCEREADMEcrypt.3crypt.hcrypt_blowfish.ccrypt_blowfish.hcrypt_gensalt.ccrypt_gensalt.hglibc-2.1.3-crypt.diffglibc-2.14-crypt.diffglibc-2.3.6-crypt.diffow-crypt.hwrapper.cx86.S
libuv
.gitattributes
.github
.gitignore.mailmapAUTHORSCMakeLists.txtCONTRIBUTING.mdChangeLogLICENSELICENSE-docsMAINTAINERS.mdMakefile.amREADME.mdSUPPORTED_PLATFORMS.mdautogen.shconfigure.acdocs
Makefilemake.bat
code
cgi
detach
dns
helloworld
idle-basic
idle-compute
interfaces
locks
multi-echo-server
onchange
pipe-echo-server
plugin
proc-streams
progress
queue-cancel
queue-work
ref-timer
signal
spawn
tcp-echo-server
thread-create
tty-gravity
tty
udp-dhcp
uvcat
uvstop
uvtee
uvwget
src
api.rstasync.rstcheck.rstconf.pydesign.rstdll.rstdns.rsterrors.rstfs.rstfs_event.rstfs_poll.rstguide.rst
guide
about.rstbasics.rsteventloops.rstfilesystem.rstintroduction.rstnetworking.rstprocesses.rstthreads.rstutilities.rst
handle.rstidle.rstindex.rstloop.rstmetrics.rstmigration_010_100.rstmisc.rstpipe.rstpoll.rstprepare.rstprocess.rstrequest.rstsignal.rstsphinx-plugins
static
architecture.png
stream.rsttcp.rstthreading.rstthreadpool.rsttimer.rsttty.rstudp.rstupgrading.rstversion.rstdiagrams.key
favicon.icologo.pngloop_iteration.pngimg
include
uv.h
libuv-static.pc.inlibuv.pc.inuv
m4
src
fs-poll.cheap-inl.hidna.cidna.hinet.cqueue.hrandom.cstrscpy.cstrscpy.hthreadpool.ctimer.c
unix
aix-common.caix.candroid-ifaddrs.casync.catomic-ops.hbsd-ifaddrs.cbsd-proctitle.ccore.ccygwin.cdarwin-proctitle.cdarwin-stub.hdarwin.cdl.cfreebsd.cfs.cfsevents.cgetaddrinfo.cgetnameinfo.chaiku.cibmi.cinternal.hkqueue.clinux-core.clinux-inotify.clinux-syscalls.clinux-syscalls.hloop-watcher.cloop.cnetbsd.cno-fsevents.cno-proctitle.copenbsd.cos390-syscalls.cos390-syscalls.hos390.cpipe.cpoll.cposix-hrtime.cposix-poll.cprocess.cprocfs-exepath.cproctitle.cpthread-fixes.cqnx.crandom-devurandom.crandom-getentropy.crandom-getrandom.crandom-sysctl-linux.csignal.cspinlock.hstream.csunos.csysinfo-loadavg.csysinfo-memory.ctcp.cthread.ctty.cudp.c
uv-common.cuv-common.huv-data-getter-setters.cversion.cwin
async.catomicops-inl.hcore.cdetect-wakeup.cdl.cerror.cfs-event.cfs-fd-hash-inl.hfs.cgetaddrinfo.cgetnameinfo.chandle-inl.hhandle.cinternal.hloop-watcher.cpipe.cpoll.cprocess-stdio.cprocess.creq-inl.hsignal.csnprintf.cstream-inl.hstream.ctcp.cthread.ctty.cudp.cutil.cwinapi.cwinapi.hwinsock.cwinsock.h
test
benchmark-async-pummel.cbenchmark-async.cbenchmark-fs-stat.cbenchmark-getaddrinfo.cbenchmark-list.hbenchmark-loop-count.cbenchmark-million-async.cbenchmark-million-timers.cbenchmark-multi-accept.cbenchmark-ping-pongs.cbenchmark-ping-udp.cbenchmark-pound.cbenchmark-pump.cbenchmark-sizes.cbenchmark-spawn.cbenchmark-tcp-write-batch.cbenchmark-thread.cbenchmark-udp-pummel.cblackhole-server.cdns-server.cecho-server.c
fixtures
run-benchmarks.crun-tests.crunner-unix.crunner-unix.hrunner-win.crunner-win.hrunner.crunner.htask.htest-active.ctest-async-null-cb.ctest-async.ctest-barrier.ctest-callback-order.ctest-callback-stack.ctest-close-fd.ctest-close-order.ctest-condvar.ctest-connect-unspecified.ctest-connection-fail.ctest-cwd-and-chdir.ctest-default-loop-close.ctest-delayed-accept.ctest-dlerror.ctest-eintr-handling.ctest-embed.ctest-emfile.ctest-env-vars.ctest-error.ctest-fail-always.ctest-fork.ctest-fs-copyfile.ctest-fs-event.ctest-fs-fd-hash.ctest-fs-open-flags.ctest-fs-poll.ctest-fs-readdir.ctest-fs.ctest-get-currentexe.ctest-get-loadavg.ctest-get-memory.ctest-get-passwd.ctest-getaddrinfo.ctest-gethostname.ctest-getnameinfo.ctest-getsockname.ctest-getters-setters.ctest-gettimeofday.ctest-handle-fileno.ctest-homedir.ctest-hrtime.ctest-idle.ctest-idna.ctest-ip4-addr.ctest-ip6-addr.ctest-ipc-heavy-traffic-deadlock-bug.ctest-ipc-send-recv.ctest-ipc.ctest-list.htest-loop-alive.ctest-loop-close.ctest-loop-configure.ctest-loop-handles.ctest-loop-stop.ctest-loop-time.ctest-metrics.ctest-multiple-listen.ctest-mutexes.ctest-osx-select.ctest-pass-always.ctest-ping-pong.ctest-pipe-bind-error.ctest-pipe-close-stdout-read-stdin.ctest-pipe-connect-error.ctest-pipe-connect-multiple.ctest-pipe-connect-prepare.ctest-pipe-getsockname.ctest-pipe-pending-instances.ctest-pipe-sendmsg.ctest-pipe-server-close.ctest-pipe-set-fchmod.ctest-pipe-set-non-blocking.ctest-platform-output.ctest-poll-close-doesnt-corrupt-stack.ctest-poll-close.ctest-poll-closesocket.ctest-poll-oob.ctest-poll.ctest-process-priority.ctest-process-title-threadsafe.ctest-process-title.ctest-queue-foreach-delete.ctest-random.ctest-ref.ctest-run-nowait.ctest-run-once.ctest-semaphore.ctest-shutdown-close.ctest-shutdown-eof.ctest-shutdown-twice.ctest-signal-multiple-loops.ctest-signal-pending-on-close.ctest-signal.ctest-socket-buffer-size.ctest-spawn.ctest-stdio-over-pipes.ctest-strscpy.ctest-tcp-alloc-cb-fail.ctest-tcp-bind-error.ctest-tcp-bind6-error.ctest-tcp-close-accept.ctest-tcp-close-reset.ctest-tcp-close-while-connecting.ctest-tcp-close.ctest-tcp-connect-error-after-write.ctest-tcp-connect-error.ctest-tcp-connect-timeout.ctest-tcp-connect6-error.ctest-tcp-create-socket-early.ctest-tcp-flags.ctest-tcp-oob.ctest-tcp-open.ctest-tcp-read-stop-start.ctest-tcp-read-stop.ctest-tcp-shutdown-after-write.ctest-tcp-try-write-error.ctest-tcp-try-write.ctest-tcp-unexpected-read.ctest-tcp-write-after-connect.ctest-tcp-write-fail.ctest-tcp-write-queue-order.ctest-tcp-write-to-half-open-connection.ctest-tcp-writealot.ctest-test-macros.ctest-thread-equal.ctest-thread.ctest-threadpool-cancel.ctest-threadpool.ctest-timer-again.ctest-timer-from-check.ctest-timer.ctest-tmpdir.ctest-tty-duplicate-key.ctest-tty-escape-sequence-processing.ctest-tty.ctest-udp-alloc-cb-fail.ctest-udp-bind.ctest-udp-connect.ctest-udp-create-socket-early.ctest-udp-dgram-too-big.ctest-udp-ipv6.ctest-udp-mmsg.ctest-udp-multicast-interface.ctest-udp-multicast-interface6.ctest-udp-multicast-join.ctest-udp-multicast-join6.ctest-udp-multicast-ttl.ctest-udp-open.ctest-udp-options.ctest-udp-send-and-recv.ctest-udp-send-hang-loop.ctest-udp-send-immediate.ctest-udp-send-unreachable.ctest-udp-sendmmsg-error.ctest-udp-try-send.ctest-uname.ctest-walk-handles.ctest-watcher-cross-stop.ctools
uv_win_longpath.manifestquickjs
ChangelogMakefileTODOVERSIONcutils.ccutils.h
doc
examples
jscompress.clibbf.clibbf.hlibregexp.clibregexp.hlibunicode-table.hlibunicode.cqjs.cqjsc.cqjscalc.jsquickjs-atom.hquickjs-libc.cquickjs-libc.hquickjs-opcode.hquickjs.cquickjs.hrelease.shrepl.jsrun-test262.ctest262.conftest262_errors.txttest262bn.conftest262bn_errors.txttests
bjson.cmicrobench.jstest262.patchtest_bignum.jstest_bjson.jstest_builtin.jstest_language.jstest_op_overloading.jstest_qjscalc.jstest_std.jstest_worker.jstest_worker_module.js
unicode_download.shunicode_gen.cunicode_gen_def.hsqlite
xopt
.circleci
.dockerignore.editorconfig.gitignoreCMakeLists.txtREADME.mdsnprintf.ctest
.gitignoreautohelp-1.outautohelp.cmacro-1.outmacro.cnocondense-1.outnocondense-sloppy-1.outnocondense-sloppy-2.outnocondense-sloppy-3.outnocondense-sloppy.cnocondense.coptional-longarg-1.outoptional-longarg.crequired-1.outrequired.csimple-1.outsimple.csloppyshorts-1.outsloppyshorts.ctest-case.sh
xopt.cxopt.hpackages/cory
about
administration
await
bbs
blink
blog
chat
chattest
contest
db
documentation
emojipush
geolocation
guess
hello
images
index
invite
invite2
ldjam34
libchat
libdocument
libencoding
libhttp
libiframe
libirc
liblist
libunfurl
libxml
libxmpp
meetup
messages
mmoturtle
monitor
news
reminder
sharedwiki
smtp
splits
tanks
test
tmirce
todo
turtle
ui
whatnext
wiki
xmas2016
youtube
src
Database.cppDatabase.hFile.cppFile.hMutex.cppMutex.hPacketStream.cppPacketStream.hSerialize.cppSerialize.hSocket.cppSocket.hTask.cppTask.hTaskStub.cppTaskStub.hTaskTryCatch.cppTaskTryCatch.hTls.hTlsContextWrapper.cppTlsContextWrapper.hbcrypt.cbcrypt.hdatabase.cdatabase.hfile.cfile.hmain.cmain.cpppacketstream.cpacketstream.hquickjstest.cserialize.cserialize.hsocket.csocket.hssb.cssb.connections.cssb.connections.hssb.hssb.qjs.cssb.qjs.hssb.rpc.cssb.rpc.hssb.tests.ctask.ctask.htaskstub.ctaskstub.htls.ctls.htlscontextwrapper.ctlscontextwrapper.htrace.ctrace.h
tests
tools
17
COPYING
17
COPYING
@ -16,13 +16,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Additional permission under GNU GPL version 3 section 7
|
||||
|
||||
If you modify this Program, or any covered work, by linking or combining it
|
||||
with V8 (or a modified version of that library), containing parts covered by
|
||||
the terms of the New BSD License, the licensors of this Program grant you
|
||||
additional permission to convey the resulting work. {Corresponding Source for
|
||||
a non-source form of such a combination shall include the source code for the
|
||||
parts of V8 used as well as that of the covered work.}
|
||||
|
||||
If you modify this Program, or any covered work, by linking or combining it
|
||||
with libuv (or a modified version of that library), containing parts covered by
|
||||
the terms of the MIT License, the licensors of this Program grant you
|
||||
@ -31,11 +24,11 @@ a non-source form of such a combination shall include the source code for the
|
||||
parts of libuv used as well as that of the covered work.}
|
||||
|
||||
If you modify this Program, or any covered work, by linking or combining it
|
||||
with liblmdb (or a modified version of that library), containing parts covered
|
||||
by the terms of the OpenLDAP Public License, the licensors of this Program
|
||||
grant you additional permission to convey the resulting work. {Corresponding
|
||||
Source for a non-source form of such a combination shall include the source
|
||||
code for the parts of liblmdb used as well as that of the covered work.}
|
||||
with QuickJS (or a modified version of that library), containing parts covered
|
||||
by the terms of the MIT License, the licensors of this Program grant you
|
||||
additional permission to convey the resulting work. {Corresponding Source for
|
||||
a non-source form of such a combination shall include the source code for the
|
||||
parts of QuickJS used as well as that of the covered work.}
|
||||
|
||||
If you modify this Program, or any covered work, by linking or combining it
|
||||
with javascript-bcrypt (or a modified version of that library), containing
|
||||
|
169
Makefile
Normal file
169
Makefile
Normal file
@ -0,0 +1,169 @@
|
||||
PROJECT = tildefriends
|
||||
BUILD_DIR ?= out
|
||||
|
||||
COMMON_CFLAGS = \
|
||||
-Wall \
|
||||
-Werror \
|
||||
-Wextra \
|
||||
-Wno-unused-parameter \
|
||||
-Wno-cast-function-type \
|
||||
-MMD \
|
||||
-ffunction-sections \
|
||||
-fdata-sections
|
||||
COMMON_LDFLAGS += -Wl,-gc-sections
|
||||
|
||||
ifneq ($(UNUSED),)
|
||||
COMMON_LDFLAGS += -Wl,-print-gc-sections
|
||||
endif
|
||||
|
||||
ifneq ($(DEBUG),)
|
||||
COMMON_CFLAGS += -g -fsanitize=address -fsanitize=undefined
|
||||
COMMON_LDFLAGS += -fsanitize=address -fsanitize=undefined
|
||||
BUILD_DIR := $(BUILD_DIR)/debug
|
||||
else
|
||||
COMMON_CFLAGS += -DNDEBUG -O3
|
||||
BUILD_DIR := $(BUILD_DIR)/release
|
||||
endif
|
||||
|
||||
APP_BIN = $(BUILD_DIR)/$(PROJECT)
|
||||
APP_SOURCES = $(wildcard src/*.c)
|
||||
APP_OBJS = $(patsubst %.c,$(BUILD_DIR)/%.o,$(APP_SOURCES))
|
||||
$(APP_OBJS): CFLAGS += \
|
||||
-Ideps/base64c/include \
|
||||
-Ideps/crypt_blowfish \
|
||||
-Ideps/quickjs \
|
||||
-Ideps/sqlite \
|
||||
-Ideps/libuv/include \
|
||||
-Ideps/xopt
|
||||
|
||||
BASE64C_SOURCES = deps/base64c/src/base64c.c
|
||||
BASE64C_OBJS = $(patsubst %.c,$(BUILD_DIR)/%.o,$(BASE64C_SOURCES))
|
||||
$(BASE64C_OBJS): CFLAGS += \
|
||||
-Wno-sign-compare
|
||||
|
||||
BLOWFISH_SOURCES = \
|
||||
deps/crypt_blowfish/crypt_blowfish.c \
|
||||
deps/crypt_blowfish/crypt_gensalt.c \
|
||||
deps/crypt_blowfish/wrapper.c
|
||||
BLOWFISH_OBJS = $(patsubst %.c,$(BUILD_DIR)/%.o,$(BLOWFISH_SOURCES))
|
||||
|
||||
UV_SOURCES = \
|
||||
deps/libuv/src/fs-poll.c \
|
||||
deps/libuv/src/idna.c \
|
||||
deps/libuv/src/inet.c \
|
||||
deps/libuv/src/random.c \
|
||||
deps/libuv/src/strscpy.c \
|
||||
deps/libuv/src/threadpool.c \
|
||||
deps/libuv/src/timer.c \
|
||||
deps/libuv/src/unix/async.c \
|
||||
deps/libuv/src/unix/core.c \
|
||||
deps/libuv/src/unix/dl.c \
|
||||
deps/libuv/src/unix/fs.c \
|
||||
deps/libuv/src/unix/getaddrinfo.c \
|
||||
deps/libuv/src/unix/getnameinfo.c \
|
||||
deps/libuv/src/unix/linux-core.c \
|
||||
deps/libuv/src/unix/linux-inotify.c \
|
||||
deps/libuv/src/unix/linux-syscalls.c \
|
||||
deps/libuv/src/unix/loop-watcher.c \
|
||||
deps/libuv/src/unix/loop.c \
|
||||
deps/libuv/src/unix/pipe.c \
|
||||
deps/libuv/src/unix/poll.c \
|
||||
deps/libuv/src/unix/process.c \
|
||||
deps/libuv/src/unix/procfs-exepath.c \
|
||||
deps/libuv/src/unix/proctitle.c \
|
||||
deps/libuv/src/unix/random-devurandom.c \
|
||||
deps/libuv/src/unix/random-getrandom.c \
|
||||
deps/libuv/src/unix/random-sysctl-linux.c \
|
||||
deps/libuv/src/unix/signal.c \
|
||||
deps/libuv/src/unix/stream.c \
|
||||
deps/libuv/src/unix/tcp.c \
|
||||
deps/libuv/src/unix/thread.c \
|
||||
deps/libuv/src/unix/tty.c \
|
||||
deps/libuv/src/unix/udp.c \
|
||||
deps/libuv/src/uv-common.c \
|
||||
deps/libuv/src/uv-data-getter-setters.c \
|
||||
deps/libuv/src/version.c
|
||||
UV_OBJS = $(patsubst %.c,$(BUILD_DIR)/%.o,$(UV_SOURCES))
|
||||
$(UV_OBJS): CFLAGS += \
|
||||
-Ideps/libuv/include \
|
||||
-Ideps/libuv/src \
|
||||
-Wno-unused-but-set-variable \
|
||||
-Wno-incompatible-pointer-types \
|
||||
-Wno-sign-compare \
|
||||
-D_GNU_SOURCE \
|
||||
|
||||
SQLITE_SOURCES = deps/sqlite/sqlite3.c
|
||||
SQLITE_OBJS = $(patsubst %.c,$(BUILD_DIR)/%.o,$(SQLITE_SOURCES))
|
||||
$(SQLITE_OBJS): CFLAGS += \
|
||||
-DSQLITE_DBCONFIG_DEFAULT_DEFENSIVE \
|
||||
-DSQLITE_ENABLE_JSON1 \
|
||||
-DSQLITE_MAX_LENGTH=5242880 \
|
||||
-DSQLITE_MAX_SQL_LENGTH=100000 \
|
||||
-DSQLITE_MAX_COLUMN=100 \
|
||||
-DSQLITE_MAX_EXPR_DEPTH=20 \
|
||||
-DSQLITE_MAX_COMPOUND_SELECT=3 \
|
||||
-DSQLITE_MAX_VDBE_OP=25000 \
|
||||
-DSQLITE_MAX_FUNCTION_ARG=8 \
|
||||
-DSQLITE_MAX_ATTACHED=0 \
|
||||
-DSQLITE_MAX_LIKE_PATTERN_LENGTH=50 \
|
||||
-DSQLITE_MAX_VARIABLE_NUMBER=100 \
|
||||
-DSQLITE_MAX_TRIGGER_DEPTH=10 \
|
||||
-Wno-implicit-fallthrough
|
||||
|
||||
XOPT_SOURCES = deps/xopt/xopt.c
|
||||
XOPT_OBJS = $(patsubst %.c,$(BUILD_DIR)/%.o,$(XOPT_SOURCES))
|
||||
|
||||
QUICKJS_SOURCES = \
|
||||
deps/quickjs/cutils.c \
|
||||
deps/quickjs/libbf.c \
|
||||
deps/quickjs/libregexp.c \
|
||||
deps/quickjs/libunicode.c \
|
||||
deps/quickjs/quickjs-libc.c \
|
||||
deps/quickjs/quickjs.c
|
||||
QUICKJS_OBJS = $(patsubst %.c,$(BUILD_DIR)/%.o,$(QUICKJS_SOURCES))
|
||||
$(QUICKJS_OBJS): CFLAGS += \
|
||||
-DCONFIG_VERSION=\"$(shell cat deps/quickjs/VERSION)\" \
|
||||
-DDUMP_LEAKS \
|
||||
-D_GNU_SOURCE \
|
||||
-Wno-sign-compare \
|
||||
-Wno-implicit-fallthrough \
|
||||
-Wno-unused-variable \
|
||||
-Wno-unused-but-set-variable
|
||||
|
||||
APP_LDFLAGS = \
|
||||
$(COMMON_LDFLAGS) \
|
||||
$(LDFLAGS) \
|
||||
-pthread \
|
||||
-ldl \
|
||||
-lm \
|
||||
-lssl \
|
||||
-lcrypto \
|
||||
-lsodium
|
||||
|
||||
DEFAULT_TARGET = $(APP_BIN)
|
||||
all: $(DEFAULT_TARGET)
|
||||
.PHONY: all
|
||||
|
||||
ALL_APP_OBJS = \
|
||||
$(APP_OBJS) \
|
||||
$(BASE64C_OBJS) \
|
||||
$(BLOWFISH_OBJS) \
|
||||
$(UV_OBJS) \
|
||||
$(SQLITE_OBJS) \
|
||||
$(QUICKJS_OBJS) \
|
||||
$(XOPT_OBJS)
|
||||
|
||||
DEPS = $(ALL_APP_OBJS:.o=.d)
|
||||
-include $(DEPS)
|
||||
|
||||
$(APP_BIN): $(ALL_APP_OBJS)
|
||||
$(CC) -o $@ $^ $(APP_LDFLAGS)
|
||||
|
||||
$(BUILD_DIR)/%.o: %.c
|
||||
@mkdir -p $(dir $@)
|
||||
@echo [c] $@
|
||||
@$(CC) $(COMMON_CFLAGS) $(CFLAGS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR)
|
||||
.PHONY: clean
|
34
README.md
34
README.md
@ -1,33 +1,41 @@
|
||||
# Tilde Friends
|
||||
Tilde Friends is a program that aims to securely host pure JavaScript web applications.
|
||||
Tilde Friends is a program that aims to securely host and share pure JavaScript
|
||||
web applications.
|
||||
|
||||
## Goals
|
||||
1. Make it easy to run all sorts of servers and web applications.
|
||||
1. Make it easy and fun to run all sorts of web applications.
|
||||
2. Provide a security model that is easy to understand and protects your data.
|
||||
3. Make creating and sharing web applications accessible to anyone from a web interface.
|
||||
|
||||
## Building
|
||||
Tilde Friends is [routinely](https://www.unprompted.com/projects/build/tildefriends) built on Linux, Windows, and OS X.
|
||||
|
||||
1. Get and build [Google V8](https://github.com/v8/v8/wiki/Building%20from%20Source) (latest 5.5).
|
||||
2. Get and build [libuv](https://github.com/libuv/libuv) (latest 1.10.1).
|
||||
3. Run:
|
||||
1. Requires libsodium and openssl. Other dependencies are kept up to date in the tree.
|
||||
2. To build, run:
|
||||
```
|
||||
scons uv=path/to/libuv v8=path/to/v8
|
||||
make
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
make DEBUG=1
|
||||
```
|
||||
|
||||
Note for Raspberry Pi: http://www.mccarroll.net/blog/v8_pi2/index.html
|
||||
|
||||
## Running
|
||||
Running the built tildefriends executable will start a web server. This is a good starting point: <http://localhost:12345/>.
|
||||
Running the built tildefriends executable will start a web server. This is a
|
||||
good starting point: <http://localhost:12345/>.
|
||||
|
||||
The first use to create an account and log in will be granted administrative privileges. Everything can be managed entirely from the web interface.
|
||||
The first user to create an account and log in will be granted administrative
|
||||
privileges. Everything can be managed entirely from the web interface.
|
||||
|
||||
This is all a work in progress.
|
||||
|
||||
## Documentation
|
||||
|
||||
See the [users guide](docs/guide.md) for documentation.
|
||||
|
||||
## License
|
||||
All code unless otherwise noted in [COPYING](https://www.unprompted.com/projects/browser/projects/tildefriends/trunk/COPYING) is provided under the [Affero GPL 3.0](https://www.unprompted.com/projects/browser/projects/tildefriends/trunk/LICENSE) license.
|
||||
All code unless otherwise noted in
|
||||
[COPYING](https://www.unprompted.com/projects/browser/projects/tildefriends/trunk/COPYING)
|
||||
is provided under the [Affero GPL
|
||||
3.0](https://www.unprompted.com/projects/browser/projects/tildefriends/trunk/LICENSE)
|
||||
license.
|
||||
|
163
SConstruct
163
SConstruct
@ -1,163 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import os
|
||||
import platform
|
||||
import sys
|
||||
|
||||
options = Variables('options.cache', ARGUMENTS)
|
||||
options.AddVariables(PathVariable('uv', 'Location of libuv', 'deps/%s/uv' % sys.platform))
|
||||
options.AddVariables(PathVariable('v8', 'Location of v8', 'deps/%s/v8' % sys.platform))
|
||||
options.AddVariables(PathVariable('lmdb', 'Location of liblmdb', 'deps/%s/lmdb' % sys.platform))
|
||||
options.AddVariables(BoolVariable('package', 'Build a package', False))
|
||||
|
||||
VariantDir('build/src', 'src', duplicate=0)
|
||||
VariantDir('build/deps', 'deps', duplicate=0)
|
||||
kwargs = {}
|
||||
if sys.platform == 'darwin':
|
||||
kwargs['CXX'] = 'clang++'
|
||||
|
||||
env = Environment(options=options, tools=['default', 'packaging'], **kwargs)
|
||||
options.Save('options.cache', env)
|
||||
Help(options.GenerateHelpText(env))
|
||||
|
||||
v8 = env['v8']
|
||||
uv = env['uv']
|
||||
liblmdb = env['lmdb']
|
||||
env.Append(CPPPATH=[
|
||||
os.path.join(v8, 'include'),
|
||||
v8,
|
||||
os.path.join(uv, 'include'),
|
||||
os.path.join(liblmdb, 'libraries', 'liblmdb'),
|
||||
])
|
||||
|
||||
objectSuffix = '.obj' if sys.platform == 'win32' else '.o'
|
||||
raspi = platform.machine() == 'armv7l'
|
||||
if raspi:
|
||||
env.Append(LIBS = [
|
||||
os.path.join(v8, 'out', 'arm.release', 'obj.target', 'src', 'libv8_libplatform.a'),
|
||||
os.path.join(v8, 'out', 'arm.release', 'obj.target', 'src', 'libv8_base.a'),
|
||||
os.path.join(v8, 'out', 'arm.release', 'obj.target', 'src', 'libv8_libbase.a'),
|
||||
os.path.join(v8, 'out', 'arm.release', 'obj.target', 'src', 'libv8_libsampler.a'),
|
||||
os.path.join(v8, 'out', 'arm.release', 'obj.target', 'src', 'libv8_nosnapshot.a'),
|
||||
os.path.join(v8, 'out', 'arm.release', 'obj.target', 'third_party', 'icu', 'libicui18n.a'),
|
||||
os.path.join(v8, 'out', 'arm.release', 'obj.target', 'third_party', 'icu', 'libicuuc.a'),
|
||||
])
|
||||
else:
|
||||
env.Append(LIBPATH = [
|
||||
os.path.join(v8, 'out', 'obj'),
|
||||
os.path.join(v8, 'out', 'obj', 'third_party', 'icu'),
|
||||
])
|
||||
if sys.platform == 'win32':
|
||||
env.Append(LIBS = [
|
||||
'v8_base_0',
|
||||
'v8_base_1',
|
||||
])
|
||||
else:
|
||||
env.Append(LIBS = [
|
||||
'v8_base',
|
||||
])
|
||||
env.Append(LIBS = [
|
||||
'v8_libplatform',
|
||||
'v8_libbase',
|
||||
'v8_libsampler',
|
||||
'v8_snapshot',
|
||||
'icui18n',
|
||||
'icuuc',
|
||||
])
|
||||
|
||||
if sys.platform == 'win32':
|
||||
env.Append(LIBS=['libuv', 'advapi32', 'winmm', 'wsock32', 'ws2_32', 'psapi', 'iphlpapi', 'userenv', 'user32', 'dbghelp', 'shlwapi'])
|
||||
env.Append(CXXFLAGS=['/EHsc', '/MTd', '/Zi', '/Gy'])
|
||||
env.Append(CFLAGS=['/EHsc', '/MTd', '/Zi', '/Gy'])
|
||||
env.Append(LIBPATH=[
|
||||
os.path.join(uv, 'Release/lib'),
|
||||
])
|
||||
env.Append(LINKFLAGS=['/RELEASE', '/OPT:REF', '/OPT:ICF', '/NODEFAULTLIB:libcmt', '/LTCG'])
|
||||
elif sys.platform == 'darwin':
|
||||
env.Append(LIBS=['pthread', 'uv'])
|
||||
env.Append(CXXFLAGS=['--std=c++11', '-g', '-Wall', '-stdlib=libc++'])
|
||||
env.Append(CFLAGS=['-g', '-Wall'])
|
||||
env.Append(LINKFLAGS=['-g', '-stdlib=libc++'])
|
||||
env.Append(LIBPATH=[
|
||||
os.path.join(uv, 'build/Release'),
|
||||
])
|
||||
else:
|
||||
env.Append(LIBS=['uv', 'rt', 'dl', 'pthread'])
|
||||
env.Append(CXXFLAGS=['--std=c++11', '-g', '-Wall'])
|
||||
env.Append(CFLAGS=['-g', '-Wall'])
|
||||
env.Append(LINKFLAGS=['-g'])
|
||||
env.Append(LIBPATH=[
|
||||
os.path.join(uv, 'out/Debug/obj.target'),
|
||||
])
|
||||
|
||||
env.Command('icudtl.dat', os.path.join(v8, 'out/arm.release/icudtl.dat' if raspi else 'out/icudtl.dat'), Copy("$TARGET", "$SOURCE"))
|
||||
|
||||
ldapEnv = env.Clone()
|
||||
if sys.platform == 'win32':
|
||||
ldapEnv.Append(CPPPATH=['deps/win32'])
|
||||
lmdb = ldapEnv.Library('build/lmdb', [
|
||||
os.path.join(liblmdb, 'libraries', 'liblmdb', 'mdb.c'),
|
||||
os.path.join(liblmdb, 'libraries', 'liblmdb', 'midl.c'),
|
||||
])
|
||||
env.Append(LIBS=[lmdb])
|
||||
|
||||
if sys.platform == 'linux2':
|
||||
env.Append(LIBS=['crypto', 'ssl'])
|
||||
env.Append(LINKFLAGS=['-std=c++0x'])
|
||||
|
||||
quickjsEnv = env.Clone()
|
||||
quickjsEnv.Append(CPPDEFINES=[
|
||||
'CONFIG_VERSION=\\"' + open('deps/quickjs/VERSION').read().strip() + '\\"',
|
||||
'_GNU_SOURCE',
|
||||
])
|
||||
quickjs = quickjsEnv.Library('build/quickjs', [
|
||||
'build/deps/quickjs/bjson.c',
|
||||
'build/deps/quickjs/cutils.c',
|
||||
'build/deps/quickjs/jscompress.c',
|
||||
'build/deps/quickjs/libbf.c',
|
||||
'build/deps/quickjs/libregexp.c',
|
||||
'build/deps/quickjs/libunicode.c',
|
||||
'build/deps/quickjs/quickjs-libc.c',
|
||||
'build/deps/quickjs/quickjs.c',
|
||||
'build/deps/quickjs/unicode_gen.c',
|
||||
])
|
||||
env.Append(LIBS=[quickjs])
|
||||
env.Append(CPPPATH=['deps/quickjs'])
|
||||
|
||||
env.Program('qjst', ['build/src/quickjstest.c'], LIBS=['m', 'dl', quickjs])
|
||||
|
||||
source = [s for s in Glob('build/src/*.cpp') if not os.path.basename(str(s)).startswith("SecureSocket_")]
|
||||
|
||||
if sys.platform == 'darwin':
|
||||
env.Append(FRAMEWORKS=['CoreFoundation', 'Security'])
|
||||
elif sys.platform == 'win32':
|
||||
env.Append(LIBS=['Crypt32'])
|
||||
env.Program('tildefriends', source)
|
||||
|
||||
def listAllFiles(root):
|
||||
for root, dirs, files in os.walk(root):
|
||||
for f in files:
|
||||
if not f.startswith('.'):
|
||||
yield os.path.join(root, f)
|
||||
hidden = [d for d in dirs if d.startswith('.')]
|
||||
for d in hidden:
|
||||
dirs.remove(d)
|
||||
|
||||
if env['package'] and sys.platform == 'win32':
|
||||
files = [
|
||||
'COPYING',
|
||||
'LICENSE',
|
||||
'SConstruct',
|
||||
'tildefriends.exe',
|
||||
'icudtl.dat',
|
||||
]
|
||||
files += listAllFiles('src')
|
||||
files += listAllFiles('packages')
|
||||
files += listAllFiles('core')
|
||||
env.Package(
|
||||
NAME='TildeFriends',
|
||||
target='dist/TildeFriends-win32.zip',
|
||||
PACKAGETYPE='zip',
|
||||
PACKAGEROOT='TildeFriends-win32',
|
||||
source=files
|
||||
)
|
1
apps/cory/docs.json
Normal file
1
apps/cory/docs.json
Normal file
@ -0,0 +1 @@
|
||||
{"type":"tildefriends-app","files":{"app.js":"&WCq6ssQedT5denXPXlz2BswPD6hmt++EmWIMIDUMurA=.sha256","index.md":"&Lr7IXs8osbmWz6SDsGTQCiybbxkbWSK2MrUcXMzgqTs=.sha256","todo.md":"&/vzp5PrF93TPAuS/97fbj6+mzyNOxYFjBGQJmZYe4As=.sha256","structure.md":"&xRhQ4Mpom1Idskum07osbBQYcYWroH0sELQBkQHrOMg=.sha256","purpose.md":"&c0/YqFhXC0X3DqiEo55NqzI5wq0VTw6cVZTf/gAWS3w=.sha256","guide.md":"&SgnGL0+rjetY2o9A2+lVRbNvHIkqKwMnZr9gXWneIlc=.sha256"}}
|
28
apps/cory/docs/app.js
Normal file
28
apps/cory/docs/app.js
Normal file
File diff suppressed because one or more lines are too long
16
apps/cory/docs/guide.md
Normal file
16
apps/cory/docs/guide.md
Normal file
@ -0,0 +1,16 @@
|
||||
# Tilde Friends Developer's Guide
|
||||
[Back to index](#index)
|
||||
|
||||
A Tilde Friends application runs on the server. To make an interesting
|
||||
application that interacts with the client, it's necessary to understand
|
||||
how the parts work together.
|
||||
|
||||
## Hello, world!
|
||||
|
||||
A simple starting point. Presents `Hello, world!` in the browser when
|
||||
visited.
|
||||
|
||||
**app.js**:
|
||||
```
|
||||
app.setDocument('<h1>Hello, world!</h1>');
|
||||
```
|
11
apps/cory/docs/index.md
Normal file
11
apps/cory/docs/index.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Tilde Friends Documentation
|
||||
|
||||
Tilde Friends is a participating member of a greater social
|
||||
network, [Secure Scuttlebutt](https://scuttlebutt.nz/),
|
||||
augmenting it with a way to safely and securely write, share,
|
||||
and run code.
|
||||
|
||||
- [Purpose](#purpose)
|
||||
- [Structure](#structure)
|
||||
- [Guide](#guide)
|
||||
- [TODO](#todo)
|
4
apps/cory/docs/markdeep.min.js
vendored
Normal file
4
apps/cory/docs/markdeep.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
24
apps/cory/docs/purpose.md
Normal file
24
apps/cory/docs/purpose.md
Normal file
@ -0,0 +1,24 @@
|
||||
# Tilde Friends Purpose
|
||||
[Back to index](#index)
|
||||
|
||||
## Beliefs
|
||||
1. The web is the universal virtual machine.
|
||||
- It is here, ready to be used from your desktop, laptop, smart phone,
|
||||
tablet, game console, and smart TV.
|
||||
- It is not ideal, but it is the best we have right now,
|
||||
and all signs point to it continuing to improve, at least
|
||||
in terms of features, security, and device support.
|
||||
2. Distributed is superior to centralized.
|
||||
- Distributed services don't need ads.
|
||||
- Distributed services can't be acquired by evil corporations.
|
||||
- Distributed services respect the user's privacy.
|
||||
- Distributed services respect the user.
|
||||
3. Offline-first is superior to online-only.
|
||||
- The internet goes down sometimes. Applications should continue
|
||||
to work.
|
||||
3. Making and sharing code should be easy.
|
||||
- Cloning your repository, installing dev tools, running a
|
||||
docker image, or fighting with dependencies is *not* easy.
|
||||
- If you see a thing in a web browser, you should be able to click
|
||||
`edit`, make a change, save, and see the result.
|
||||
[Wikipedia](https://www.wikipedia.org/) is easy.
|
67
apps/cory/docs/structure.md
Normal file
67
apps/cory/docs/structure.md
Normal file
@ -0,0 +1,67 @@
|
||||
# Tilde Friends Structure
|
||||
[Back to index](#index)
|
||||
|
||||
Tilde Friends is a mostly-self-contained executable written in C.
|
||||
|
||||
In combines the following key components:
|
||||
- A Secure Scuttlebutt (SSB) client/server. This talks with other SSB
|
||||
instances, storing messages and blobs for anyone visible to local
|
||||
users as they are encountered and sharing anything published locally
|
||||
as appropriate.
|
||||
- An sqlite database. This is where the SSB instance stores its data.
|
||||
The general schema involves a `messages` table, storing mostly JSON,
|
||||
a `blobs` table storing arbitrary blob data, and a `properties` table,
|
||||
storing arbitrary state gleaned from `messages` and `blobs`, generally
|
||||
updated on demand and incrementally.
|
||||
- A QuickJS runtime. The core process runs stock scripts and has access
|
||||
and permission to use all resources. All other processes, which
|
||||
includes everything which runs untrusted code created by Tilde Friends
|
||||
users, are strictly sandboxed in ways similar to how web browsers run
|
||||
untrusted code. All attempts to access potentially sensitive resources
|
||||
are mediated through the core process.
|
||||
|
||||
When run with no arguments, it starts a web server on
|
||||
[http://localhost:12345/](http://localhost:12345/) and an SSB server.
|
||||
|
||||
## Web Interface
|
||||
The Tilde Friends web server provides access to Tilde Friends applications,
|
||||
which are arbitrary user-defined web applications.
|
||||
|
||||
At the top left, in addition to some basic navigation links, is an `edit`
|
||||
link. Anyone can view, modify, and run in-place the code to any Tilde
|
||||
Friends application by using the in-browser editor.
|
||||
|
||||
At the top right, one can `login` (to save work in their own space)
|
||||
or `logout` (proceeding as a guest).
|
||||
|
||||
The rest of the page is an iframe belonging to the application.
|
||||
|
||||
## Special Paths
|
||||
|
||||
- `/~user/app/` - Tilde Friends application paths take the form `/~user/app/`, where `user`
|
||||
is a username of a Tilde Friends account, and `app` is an arbitrary name
|
||||
of an application saved by the given user.
|
||||
- `/~user/app/file` - A raw file in an app.
|
||||
- `/&blobid.ed25519` - A raw blob. Content-Type is inferred for at least
|
||||
a few common image types.
|
||||
|
||||
## Communication Channels
|
||||
Web Browser <-> Core <-> Sandbox
|
||||
|
||||
Visiting an application path delivers stock HTML and JavaScript which
|
||||
establishes a WebSocket connection back to the server.
|
||||
|
||||
At this point, a new sandbox process is started in Tilde Friends, much
|
||||
as a new sandboxed process might be started for a new tab in a web
|
||||
browser. This process has a custom RPC connection to the core process
|
||||
which holds the WebSocket connection to the browser.
|
||||
|
||||
The custom RPC communication between the sandbox process and the core
|
||||
process facilitates calling functions asynchronously. Calling a remote
|
||||
function (ie. a function in another process) returns a `Promise`. In
|
||||
addition, any functions passed in either direction are serialized in
|
||||
such a way that they can be called remotely.
|
||||
|
||||
An application will typically call `app.setDocument()` at startup to
|
||||
populate the app's iframe in the web browser with its own client web
|
||||
application resources.
|
44
apps/cory/docs/todo.md
Normal file
44
apps/cory/docs/todo.md
Normal file
@ -0,0 +1,44 @@
|
||||
# Tilde Friends TODO
|
||||
[Back to index](#index)
|
||||
|
||||
## MVP
|
||||
- release
|
||||
- blog
|
||||
- update COPYING
|
||||
- update README
|
||||
- auto-populate data on initial launch
|
||||
- audit + document API exposed to apps
|
||||
- ssb core
|
||||
- good refresh
|
||||
- live updates
|
||||
- apps
|
||||
- app messages
|
||||
- installable apps
|
||||
- web interface
|
||||
- live updates
|
||||
- strip out unnecessary things?
|
||||
- more raw views until it's more functional?
|
||||
|
||||
## Done
|
||||
- likely classes of script errors
|
||||
- tf core
|
||||
- good error feedback
|
||||
- markdeep demo
|
||||
- send blobs
|
||||
|
||||
## Later
|
||||
- DB migration
|
||||
- stop using CDNs
|
||||
- collect loads of stats
|
||||
- faster save - parallel / don't save unmodified
|
||||
- test likely denials of service
|
||||
- package standalone executable
|
||||
- ideas
|
||||
- visualizations / analysis of gps data
|
||||
- good web interface for managing connections
|
||||
- identity
|
||||
- multiple identities
|
||||
- tie identities to TF login accounts
|
||||
- tf account timeout why
|
||||
- make some demo apps
|
||||
- rock paper scissors, somehow
|
1
apps/cory/index.json
Normal file
1
apps/cory/index.json
Normal file
@ -0,0 +1 @@
|
||||
{"type":"tildefriends-app","files":{"app.js":"&GOWmWDTHuNMz2XpxNxspAqsITn/RwvlB4Um6euxHFbU=.sha256","index.html":"&/noD6q/rH4VgszVb6W0D3mnK9t0GbDYYZtBGM/xs2kY=.sha256","vue-material.js":"&K5cdLqXYCENPak/TCINHQhyJhpS4G9DlZHGwoh/LF2g=.sha256"}}
|
378
apps/cory/index/app.js
Normal file
378
apps/cory/index/app.js
Normal file
@ -0,0 +1,378 @@
|
||||
"use strict";
|
||||
|
||||
const k_posts_max = 20;
|
||||
const k_votes_max = 100;
|
||||
|
||||
async function following(db, id) {
|
||||
var o = await db.get(id + ":following");
|
||||
const k_version = 4;
|
||||
var f = o ? JSON.parse(o) : o;
|
||||
if (!f || f.version != k_version) {
|
||||
f = {users: [], sequence: 0, version: k_version};
|
||||
}
|
||||
f.users = new Set(f.users);
|
||||
await ssb.sqlStream(
|
||||
"SELECT "+
|
||||
" sequence, "+
|
||||
" json_extract(content, '$.contact') AS contact, "+
|
||||
" json_extract(content, '$.following') AS following "+
|
||||
"FROM messages "+
|
||||
"WHERE "+
|
||||
" author = ?1 AND "+
|
||||
" sequence > ?2 AND "+
|
||||
" json_extract(content, '$.type') = 'contact' "+
|
||||
"UNION SELECT MAX(sequence) AS sequence, NULL, NULL FROM messages WHERE author = ?1 "+
|
||||
"ORDER BY sequence",
|
||||
[id, f.sequence],
|
||||
async function(row) {
|
||||
if (row.following) {
|
||||
f.users.add(row.contact);
|
||||
} else {
|
||||
f.users.delete(row.contact);
|
||||
}
|
||||
f.sequence = row.sequence;
|
||||
});
|
||||
f.users = Array.from(f.users);
|
||||
var j = JSON.stringify(f);
|
||||
if (o != j) {
|
||||
await db.set(id + ":following", j);
|
||||
}
|
||||
return f.users;
|
||||
}
|
||||
|
||||
async function followingDeep(db, seed_ids, depth) {
|
||||
if (depth <= 0) {
|
||||
return seed_ids;
|
||||
}
|
||||
var f = await Promise.all(seed_ids.map(x => following(db, x)));
|
||||
var ids = [].concat(...f);
|
||||
var x = await followingDeep(db, [...new Set(ids)].sort(), depth - 1);
|
||||
x = [].concat(...x, ...seed_ids);
|
||||
return x;
|
||||
}
|
||||
|
||||
async function followers(db, id) {
|
||||
var o = await db.get(id + ":followers");
|
||||
const k_version = 2;
|
||||
var f = o ? JSON.parse(o) : o;
|
||||
if (!f || f.version != k_version) {
|
||||
f = {users: [], rowid: 0, version: k_version};
|
||||
}
|
||||
f.users = new Set(f.users);
|
||||
await ssb.sqlStream(
|
||||
"SELECT "+
|
||||
" rowid, "+
|
||||
" author AS contact, "+
|
||||
" json_extract(content, '$.following') AS following "+
|
||||
"FROM messages "+
|
||||
"WHERE "+
|
||||
" rowid > $1 AND "+
|
||||
" json_extract(content, '$.type') = 'contact' AND "+
|
||||
" json_extract(content, '$.contact') = $2 "+
|
||||
"UNION SELECT MAX(rowid) as rowid, NULL, NULL FROM messages "+
|
||||
"ORDER BY rowid",
|
||||
[f.rowid, id],
|
||||
async function(row) {
|
||||
if (row.following) {
|
||||
f.users.add(row.contact);
|
||||
} else {
|
||||
f.users.delete(row.contact);
|
||||
}
|
||||
f.rowid = row.rowid;
|
||||
});
|
||||
f.users = Array.from(f.users);
|
||||
var j = JSON.stringify(f);
|
||||
if (o != j) {
|
||||
await db.set(id + ":followers", j);
|
||||
}
|
||||
return f.users;
|
||||
}
|
||||
|
||||
async function sendUser(db, id) {
|
||||
return Promise.all([
|
||||
following(db, id).then(async function(following) {
|
||||
return app.postMessage({following: {id: id, users: following}});
|
||||
}),
|
||||
followers(db, id).then(async function(followers) {
|
||||
return app.postMessage({followers: {id: id, users: followers}});
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
async function pubsByUser(db, id) {
|
||||
var o = await db.get(id + ":pubs");
|
||||
const k_version = 2;
|
||||
var f = o ? JSON.parse(o) : o;
|
||||
if (!f || f.version != k_version) {
|
||||
f = {pubs: [], sequence: 0, version: k_version};
|
||||
}
|
||||
f.pubs = Object.fromEntries(f.pubs.map(x => [JSON.stringify(x), x]));
|
||||
await ssb.sqlStream(
|
||||
"SELECT "+
|
||||
" sequence, "+
|
||||
" json_extract(content, '$.address.host') AS host, "+
|
||||
" json_extract(content, '$.address.port') AS port, "+
|
||||
" json_extract(content, '$.address.key') AS key "+
|
||||
"FROM messages "+
|
||||
"WHERE "+
|
||||
" sequence > ?1 AND "+
|
||||
" author = ?2 AND "+
|
||||
" json_extract(content, '$.type') = 'pub' "+
|
||||
"UNION SELECT MAX(sequence) as sequence, NULL, NULL, NULL FROM messages WHERE author = ?2 "+
|
||||
"ORDER BY sequence",
|
||||
[f.sequence, id],
|
||||
async function(row) {
|
||||
f.sequence = row.sequence;
|
||||
if (row.host) {
|
||||
row = {host: row.host, port: row.port, key: row.key};
|
||||
f.pubs[JSON.stringify(row)] = row;
|
||||
}
|
||||
});
|
||||
f.pubs = Object.values(f.pubs);
|
||||
var j = JSON.stringify(f);
|
||||
if (o != j) {
|
||||
await db.set(id + ":pubs", j);
|
||||
}
|
||||
return f.pubs;
|
||||
}
|
||||
|
||||
async function visiblePubs(db, id) {
|
||||
var ids = [id].concat(await following(db, id));
|
||||
var pubs = {};
|
||||
for (var follow of ids) {
|
||||
var followPubs = await pubsByUser(db, follow);
|
||||
for (var pub of followPubs) {
|
||||
pubs[JSON.stringify(pub)] = pub;
|
||||
}
|
||||
}
|
||||
return Object.values(pubs);
|
||||
}
|
||||
|
||||
async function getAbout(db, id) {
|
||||
var o = await db.get(id + ":about");
|
||||
const k_version = 3;
|
||||
var f = o ? JSON.parse(o) : o;
|
||||
if (!f || f.version != k_version) {
|
||||
f = {about: {}, sequence: 0, version: k_version};
|
||||
}
|
||||
await ssb.sqlStream(
|
||||
"SELECT "+
|
||||
" sequence, "+
|
||||
" content "+
|
||||
"FROM messages "+
|
||||
"WHERE "+
|
||||
" sequence > ?1 AND "+
|
||||
" author = ?2 AND "+
|
||||
" json_extract(content, '$.type') = 'about' AND "+
|
||||
" json_extract(content, '$.about') = author "+
|
||||
"UNION SELECT MAX(sequence) as sequence, NULL FROM messages WHERE author = ?2 "+
|
||||
"ORDER BY sequence",
|
||||
[f.sequence, id],
|
||||
async function(row) {
|
||||
f.sequence = row.sequence;
|
||||
if (row.content) {
|
||||
var about = {};
|
||||
try {
|
||||
about = JSON.parse(row.content);
|
||||
} catch {
|
||||
}
|
||||
delete about.about;
|
||||
delete about.type;
|
||||
f.about = Object.assign(f.about, about);
|
||||
}
|
||||
});
|
||||
var j = JSON.stringify(f);
|
||||
if (o != j) {
|
||||
await db.set(id + ":about", j);
|
||||
}
|
||||
return f.about;
|
||||
}
|
||||
|
||||
function fnv32a(value)
|
||||
{
|
||||
var result = 0x811c9dc5;
|
||||
for (var i = 0; i < value.length; i++) {
|
||||
result ^= value.charCodeAt(i);
|
||||
result += (result << 1) + (result << 4) + (result << 7) + (result << 8) + (result << 24);
|
||||
}
|
||||
return result >>> 0;
|
||||
}
|
||||
|
||||
async function getRecentPostIds(db, id, ids, limit) {
|
||||
const k_version = 6;
|
||||
var o = await db.get(id + ':recent_posts');
|
||||
var recent = [];
|
||||
var f = o ? JSON.parse(o) : o;
|
||||
var ids_hash = fnv32a(JSON.stringify(ids));
|
||||
if (!f || f.version != k_version || f.ids_hash != ids_hash) {
|
||||
f = {recent: [], rowid: 0, version: k_version, ids_hash: ids_hash};
|
||||
}
|
||||
await ssb.sqlStream(
|
||||
"SELECT "+
|
||||
" rowid, "+
|
||||
" id "+
|
||||
"FROM messages "+
|
||||
"WHERE "+
|
||||
" rowid > ? AND "+
|
||||
" author IN (" + ids.map(x => '?').join(", ") + ") AND "+
|
||||
" json_extract(content, '$.type') = 'post' "+
|
||||
"UNION SELECT MAX(rowid) as rowid, NULL FROM messages "+
|
||||
"ORDER BY rowid DESC LIMIT ?",
|
||||
[].concat([f.rowid], ids, [limit + 1]),
|
||||
function(row) {
|
||||
if (row.id) {
|
||||
recent.push(row.id);
|
||||
}
|
||||
if (row.rowid) {
|
||||
f.rowid = row.rowid;
|
||||
}
|
||||
});
|
||||
f.recent = [].concat(recent, f.recent).slice(0, limit);
|
||||
var j = JSON.stringify(f);
|
||||
if (o != j) {
|
||||
await db.set(id + ":recent_posts", j);
|
||||
}
|
||||
return f.recent;
|
||||
}
|
||||
|
||||
async function getVotes(db, id) {
|
||||
var o = await db.get(id + ":votes");
|
||||
const k_version = 2;
|
||||
var votes = [];
|
||||
var f = o ? JSON.parse(o) : o;
|
||||
if (!f || f.version != k_version) {
|
||||
f = {votes: [], rowid: 0, version: k_version};
|
||||
}
|
||||
await ssb.sqlStream(
|
||||
"SELECT "+
|
||||
" rowid, "+
|
||||
" author, "+
|
||||
" id, "+
|
||||
" sequence, "+
|
||||
" timestamp, "+
|
||||
" content "+
|
||||
"FROM messages "+
|
||||
"WHERE "+
|
||||
" rowid > ? AND "+
|
||||
" author = ? AND "+
|
||||
" json_extract(content, '$.type') = 'vote' "+
|
||||
"UNION SELECT MAX(rowid) as rowid, NULL, NULL AS id, NULL, NULL, NULL FROM messages "+
|
||||
"ORDER BY rowid DESC LIMIT ?",
|
||||
[f.rowid, id, k_votes_max],
|
||||
async function(row) {
|
||||
if (row.id) {
|
||||
votes.push(row);
|
||||
} else {
|
||||
f.rowid = row.rowid;
|
||||
}
|
||||
});
|
||||
f.votes = [].concat(votes.reverse(), f.votes).slice(0, k_votes_max);
|
||||
var j = JSON.stringify(f);
|
||||
if (o != j) {
|
||||
await db.set(id + ":votes", j);
|
||||
}
|
||||
return f.votes;
|
||||
}
|
||||
|
||||
async function getPosts(db, ids) {
|
||||
var posts = [];
|
||||
if (ids.length) {
|
||||
await ssb.sqlStream(
|
||||
"SELECT * FROM messages WHERE id IN (" + ids.map(x => "?").join(", ") + ")",
|
||||
ids,
|
||||
async function(row) {
|
||||
try {
|
||||
posts.push(row);
|
||||
} catch {
|
||||
}
|
||||
});
|
||||
}
|
||||
return posts;
|
||||
}
|
||||
|
||||
async function ready() {
|
||||
var whoami = await ssb.whoami();
|
||||
var db = await database("ssb");
|
||||
await Promise.all([
|
||||
app.postMessage({whoami: whoami}),
|
||||
app.postMessage({pubs: await visiblePubs(db, whoami)}),
|
||||
app.postMessage({broadcasts: await ssb.getBroadcasts()}),
|
||||
app.postMessage({connections: await ssb.connections()}),
|
||||
followingDeep(db, [whoami], 2).then(function(f) {
|
||||
getRecentPostIds(db, whoami, [].concat([whoami], f), k_posts_max).then(async function(ids) {
|
||||
return getPosts(db, ids);
|
||||
}).then(async function(posts) {
|
||||
var roots = posts.map(function(x) {
|
||||
try {
|
||||
return JSON.parse(x.content).root;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
roots = roots.filter(function(root) {
|
||||
return root && posts.every(post => post.id != root);
|
||||
});
|
||||
return [].concat(posts, await getPosts(db, roots));
|
||||
}).then(async function(posts) {
|
||||
posts.forEach(async function(post) {
|
||||
await app.postMessage({message: post});
|
||||
});
|
||||
});
|
||||
f.forEach(async function(id) {
|
||||
await Promise.all([
|
||||
getVotes(db, id).then(async function(votes) {
|
||||
return Promise.all(votes.map(vote => app.postMessage({vote: vote})));
|
||||
}),
|
||||
getAbout(db, id).then(async function(user) {
|
||||
return app.postMessage({user: {user: id, about: user}});
|
||||
}),
|
||||
]);
|
||||
});
|
||||
}),
|
||||
sendUser(db, whoami),
|
||||
]);
|
||||
}
|
||||
|
||||
core.register('onBroadcastsChanged', async function() {
|
||||
await app.postMessage({broadcasts: await ssb.getBroadcasts()});
|
||||
});
|
||||
|
||||
core.register('onConnectionsChanged', async function() {
|
||||
var connections = await ssb.connections();
|
||||
await app.postMessage({connections: connections});
|
||||
});
|
||||
|
||||
async function refresh() {
|
||||
var db = await database("ssb");
|
||||
var whoami = await ssb.whoami();
|
||||
var ids = await followingDeep(db, [whoami], 2);
|
||||
for (var id of ids) {
|
||||
await ssb.createHistoryStream(id);
|
||||
}
|
||||
}
|
||||
|
||||
core.register('message', async function(m) {
|
||||
if (m.message == 'ready') {
|
||||
await ready();
|
||||
} else if (m.message) {
|
||||
if (m.message.connect) {
|
||||
await ssb.connect(m.message.connect);
|
||||
} else if (m.message.post) {
|
||||
await ssb.post(m.message.post);
|
||||
} else if (m.message.appendMessage) {
|
||||
await ssb.appendMessage(m.message.appendMessage);
|
||||
} else if (m.message.user) {
|
||||
await sendUser(await database("ssb"), m.message.user);
|
||||
} else if (m.message.refresh) {
|
||||
await refresh();
|
||||
}
|
||||
} else {
|
||||
print(JSON.stringify(m));
|
||||
}
|
||||
});
|
||||
|
||||
async function main() {
|
||||
await app.setDocument(utf8Decode(await getFile("index.html")));
|
||||
}
|
||||
|
||||
main();
|
278
apps/cory/index/index.html
Normal file
278
apps/cory/index/index.html
Normal file
@ -0,0 +1,278 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta content="width=device-width,initial-scale=1,minimal-ui" name="viewport">
|
||||
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:400,500,700,400italic|Material+Icons">
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://unpkg.com/vue-material/dist/vue-material.min.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/vue-material/dist/theme/default-dark.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
|
||||
<script src="vue-material.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/commonmark/0.29.1/commonmark.min.js"></script>
|
||||
<script>
|
||||
var g_data = {
|
||||
whoami: null,
|
||||
connections: [],
|
||||
messages: [],
|
||||
users: {},
|
||||
broadcasts: [],
|
||||
showUsers: false,
|
||||
show_connect_dialog: false,
|
||||
show_user_dialog: null,
|
||||
connect: null,
|
||||
pubs: [],
|
||||
votes: [],
|
||||
};
|
||||
window.addEventListener('message', function(event) {
|
||||
var key = Object.keys(event.data)[0];
|
||||
if (key + 's' in g_data && Array.isArray(g_data[key + 's'])) {
|
||||
g_data[key + 's'].push(event.data[key]);
|
||||
} else if (key == 'user') {
|
||||
Vue.set(g_data.users, event.data.user.user, Object.assign({}, g_data.users[event.data.user.user] || {}, event.data.user.about));
|
||||
} else if (key == 'followers') {
|
||||
if (!g_data.users[event.data.followers.id]) {
|
||||
Vue.set(g_data.users, event.data.followers.id, {});
|
||||
}
|
||||
Vue.set(g_data.users[event.data.followers.id], 'followers', event.data.followers.users);
|
||||
} else if (key == 'following') {
|
||||
if (!g_data.users[event.data.following.id]) {
|
||||
Vue.set(g_data.users, event.data.following.id, {});
|
||||
}
|
||||
Vue.set(g_data.users[event.data.following.id], 'following', event.data.following.users);
|
||||
} else if (key == 'broadcasts') {
|
||||
g_data.broadcasts = event.data.broadcasts;
|
||||
} else if (key == 'pubs') {
|
||||
g_data.pubs = event.data.pubs;
|
||||
} else {
|
||||
g_data[key] = event.data[key];
|
||||
}
|
||||
});
|
||||
window.addEventListener('load', function() {
|
||||
Vue.use(VueMaterial.default);
|
||||
Vue.component('tf-user', {
|
||||
data: function() { return {users: g_data.users, show_user_dialog: false, show_follow_dialog: false} },
|
||||
props: ['id'],
|
||||
mounted: function() {
|
||||
window.parent.postMessage({user: this.id}, '*');
|
||||
},
|
||||
computed: {
|
||||
following: {
|
||||
get: function() {
|
||||
return g_data.users[g_data.whoami] &&
|
||||
g_data.users[g_data.whoami].following &&
|
||||
g_data.users[g_data.whoami].following.indexOf(this.id) != -1;
|
||||
},
|
||||
set: function(newValue) {
|
||||
if (g_data.users[g_data.whoami] &&
|
||||
g_data.users[g_data.whoami].following) {
|
||||
if (newValue && g_data.users[g_data.whoami].following.indexOf(this.id) == -1) {
|
||||
window.parent.postMessage({appendMessage: {type: "contact", following: true, contact: this.id}}, '*');
|
||||
} else if (!newValue) {
|
||||
window.parent.postMessage({appendMessage: {type: "contact", following: false, contact: this.id}}, '*');
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
template: `<span @click="show_user_dialog = true">
|
||||
{{users[id] && users[id].name ? users[id].name : id}}
|
||||
<md-tooltip v-if="users[id] && users[id].name">{{id}}</md-tooltip>
|
||||
<md-dialog :md-active.sync="show_user_dialog">
|
||||
<md-dialog-title>{{users[id] && users[id].name ? users[id].name : id}}</md-dialog-title>
|
||||
<md-dialog-content v-if="users[id]">
|
||||
<div v-if="users[id].image"><img :src="'/' + users[id].image + '/view'"></div>
|
||||
<div v-if="users[id].name">{{id}}</div>
|
||||
<div>{{users[id].description}}</div>
|
||||
<div><md-switch v-model="following">Following</md-switch></div>
|
||||
<md-list>
|
||||
<md-subheader>Followers</md-subheader>
|
||||
<md-list-item v-for="follower in (users[id] || []).followers" v-bind:key="'follower-' + follower">
|
||||
<tf-user :id="follower"></tf-user>
|
||||
</md-list-item>
|
||||
<md-subheader>Following</md-subheader>
|
||||
<md-list-item v-for="user in (users[id] || []).following" v-bind:key="'following-' + user">
|
||||
<tf-user :id="user"></tf-user>
|
||||
</md-list-item>
|
||||
</md-list>
|
||||
</md-dialog-content>
|
||||
<md-dialog-actions>
|
||||
<md-button @click="show_user_dialog = false">Close</md-button>
|
||||
</md-dialog-actions>
|
||||
</md-dialog>
|
||||
</span>`,
|
||||
});
|
||||
Vue.component('tf-message', {
|
||||
props: ['message', 'messages'],
|
||||
data: function() { return { showRaw: false } },
|
||||
computed: {
|
||||
content_json: function() {
|
||||
try {
|
||||
return JSON.parse(this.message.content);
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
sub_messages: function() {
|
||||
var id = this.message.id;
|
||||
return this.messages.filter(function (x) {
|
||||
try {
|
||||
return JSON.parse(x.content).root == id;
|
||||
} catch {}
|
||||
});
|
||||
},
|
||||
votes: function() {
|
||||
return [];
|
||||
var id = this.message.id;
|
||||
return this.votes.filter(function (x) {
|
||||
try {
|
||||
var j = JSON.parse(x.content);
|
||||
return j.type == 'vote' && j.vote.link == id;
|
||||
} catch {}
|
||||
}).reduce(function (accum, value) {
|
||||
var expression = JSON.parse(value.content).vote.expression;
|
||||
if (!accum[expression]) {
|
||||
accum[expression] = [];
|
||||
}
|
||||
accum[expression].push(value);
|
||||
return accum;
|
||||
}, {});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
markdown: function(md) {
|
||||
var reader = new commonmark.Parser({safe: true});
|
||||
var writer = new commonmark.HtmlRenderer();
|
||||
return writer.render(reader.parse(md));
|
||||
},
|
||||
json: function(message) {
|
||||
try {
|
||||
return JSON.parse(message.content);
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
},
|
||||
template: `<md-app class="md-elevation-8" style="margin: 1em" v-if="!content_json || ['pub', 'vote'].indexOf(content_json.type) == -1">
|
||||
<md-app-toolbar>
|
||||
<h3>
|
||||
<tf-user :id="message.author"></tf-user>
|
||||
</h3>
|
||||
<div style="font-size: x-small">
|
||||
{{new Date(message.timestamp)}}
|
||||
</div>
|
||||
<div class="md-toolbar-section-end">
|
||||
<md-menu>
|
||||
<md-button md-menu-trigger class="md-icon-button"><md-icon>more_vert</md-icon></md-button>
|
||||
<md-menu-content>
|
||||
<md-menu-item v-if="!showRaw" v-on:click="showRaw = true">View Raw</md-menu-item>
|
||||
<md-menu-item v-else v-on:click="showRaw = false">View Message</md-menu-item>
|
||||
</md-menu-content>
|
||||
</md-menu>
|
||||
</div>
|
||||
</md-app-toolbar>
|
||||
<md-app-content>
|
||||
<div v-if="showRaw">{{message.content}}</div>
|
||||
<div v-else>
|
||||
<div v-if="content_json && content_json.type == 'post'">
|
||||
<div v-html="this.markdown(content_json.text)"></div>
|
||||
<img v-for="mention in content_json.mentions" v-if="mention.link && typeof(mention.link) == 'string' && mention.link.startsWith('&')" :src="'/' + mention.link + '/view'"></img>
|
||||
</div>
|
||||
<div v-else-if="content_json && content_json.type == 'contact'"><tf-user :id="message.author"></tf-user> {{content_json.following ? '==>' : '=/=>'}} <tf-user :id="content_json.contact"></tf-user></div>
|
||||
<div v-else>{{message.content}}</div>
|
||||
</div>
|
||||
<tf-message v-for="sub_message in sub_messages" v-bind:message="sub_message" v-bind:messages="messages" v-bind:key="sub_message.id"></tf-message>
|
||||
<md-chip v-for="vote in Object.keys(votes)" v-bind:key="vote">
|
||||
{{vote + (votes[vote].length > 1 ? ' (' + votes[vote].length + ')' : '')}}
|
||||
</md-chip>
|
||||
</md-app-content>
|
||||
</md-app>`,
|
||||
});
|
||||
function markdown(d) { return d; }
|
||||
Vue.config.performance = true;
|
||||
var vue = new Vue({
|
||||
el: '#app',
|
||||
data: g_data,
|
||||
methods: {
|
||||
post_message: function() {
|
||||
window.parent.postMessage({post: document.getElementById('post_text').value}, '*');
|
||||
},
|
||||
ssb_connect: function(connection) {
|
||||
window.parent.postMessage({connect: connection}, '*');
|
||||
},
|
||||
content_json: function(message) {
|
||||
try {
|
||||
return JSON.parse(message.content);
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
refresh: function() {
|
||||
window.parent.postMessage({refresh: true}, '*');
|
||||
},
|
||||
}
|
||||
});
|
||||
});
|
||||
window.parent.postMessage('ready', '*');
|
||||
</script>
|
||||
</head>
|
||||
<body style="color: #fff">
|
||||
<div id="app">
|
||||
<md-dialog :md-active.sync="show_connect_dialog">
|
||||
<md-dialog-title>Connect</md-dialog-title>
|
||||
<md-dialog-content>
|
||||
<md-field>
|
||||
<label>net:127.0.0.1:8008~shs:id</label>
|
||||
<md-input v-model="connect"></md-input>
|
||||
</md-field>
|
||||
</md-dialog-content>
|
||||
<md-dialog-actions>
|
||||
<md-button class="md-primary" @click="ssb_connect(connect); connect = null; show_connect_dialog = false">Connect</md-button>
|
||||
<md-button @click="connect = null; show_connect_dialog = false">Cancel</md-button>
|
||||
</md-dialog-actions>
|
||||
</md-dialog>
|
||||
<md-app style="position: absolute; height: 100%; width: 100%">
|
||||
<md-app-toolbar class="md-primary">
|
||||
<md-button class="md-icon-button" @click="showUsers = !showUsers">
|
||||
<md-icon>menu</md-icon>
|
||||
</md-button>
|
||||
<span class="md-title">Tilde Friends Secure Scuttlebutt Test</span>
|
||||
</md-app-toolbar>
|
||||
<md-app-drawer :md-active.sync="showUsers" md-persistent="full">
|
||||
<md-list>
|
||||
<md-subheader>Followers</md-subheader>
|
||||
<md-list-item v-for="follower in (users[whoami] || []).followers" v-bind:key="'follower-' + follower"><tf-user :id="follower"></tf-user></md-list-item>
|
||||
<md-subheader>Following</md-subheader>
|
||||
<md-list-item v-for="user in (users[whoami] || []).following" v-bind:key="'following-' + user"><tf-user :id="user"></tf-user></md-list-item>
|
||||
<md-subheader>Network</md-subheader>
|
||||
<md-list-item v-for="broadcast in broadcasts" v-bind:key="JSON.stringify(broadcast)" @click="ssb_connect(broadcast)">{{broadcast.address}}:{{broadcast.port}} <tf-user :id="broadcast.pubkey"></tf-user></md-list-item>
|
||||
<md-subheader>Pubs</md-subheader>
|
||||
<md-list-item v-for="pub in pubs" v-bind:key="JSON.stringify(pub)" @click="ssb_connect({address: pub.host, port: pub.port, pubkey: pub.key})">{{pub.host}}:{{pub.port}} <tf-user :id="pub.key"></tf-user></md-list-item>
|
||||
<md-subheader>Connections</md-subheader>
|
||||
<md-list-item v-for="connection in connections" v-bind:key="'connection-' + JSON.stringify(connection)"><tf-user :id="connection"></tf-user></md-list-item>
|
||||
<md-list-item @click="show_connect_dialog = true">Connect</md-list-item>
|
||||
</md-list>
|
||||
</md-app-drawer>
|
||||
<md-app-content>
|
||||
<md-button @click="refresh()" class="md-icon-button md-dense md-raised md-primary">
|
||||
<md-icon>cached</md-icon>
|
||||
</md-button>
|
||||
Welcome, <tf-user :id="whoami"></tf-user>.
|
||||
<md-card class="md-elevation-8">
|
||||
<md-card-header>
|
||||
<div class="md-title">What's up?</div>
|
||||
</md-card-header>
|
||||
<md-card-content>
|
||||
<md-field>
|
||||
<label>Post a message</label>
|
||||
<md-textarea id="post_text"></md-textarea>
|
||||
</md-field>
|
||||
</md-card-content>
|
||||
<md-card-actions>
|
||||
<md-button class="md-raised md-primary" v-on:click="post_message()">Submit Post</md-button>
|
||||
</md-card-actions>
|
||||
</md-card>
|
||||
<tf-message v-for="message in messages" v-if="!content_json(message).root" v-bind:message="message" v-bind:messages="messages" v-bind:key="message.id"></tf-message>
|
||||
</md-app-content>
|
||||
</md-app>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
6
apps/cory/index/vue-material.js
Normal file
6
apps/cory/index/vue-material.js
Normal file
File diff suppressed because one or more lines are too long
127
core/app.js
Normal file
127
core/app.js
Normal file
@ -0,0 +1,127 @@
|
||||
"use strict";
|
||||
|
||||
function App() {
|
||||
this._on_output = null;
|
||||
this._send_queue = [];
|
||||
return this;
|
||||
}
|
||||
|
||||
App.prototype.readOutput = function(callback) {
|
||||
this._on_output = callback;
|
||||
}
|
||||
|
||||
App.prototype.makeFunction = function(api) {
|
||||
let self = this;
|
||||
let result = function() {
|
||||
let message = {action: api[0]};
|
||||
for (let i = 1; i < api.length; i++) {
|
||||
message[api[i]] = arguments[i - 1];
|
||||
}
|
||||
self.send(message);
|
||||
};
|
||||
Object.defineProperty(result, 'name', {value: api[0], writable: false});
|
||||
return result;
|
||||
}
|
||||
|
||||
App.prototype.send = function(message) {
|
||||
if (message) {
|
||||
this._send_queue.push(message);
|
||||
}
|
||||
if (this._on_output) {
|
||||
this._send_queue.forEach(message => this._on_output(message));
|
||||
this._send_queue = [];
|
||||
}
|
||||
}
|
||||
|
||||
function socket(request, response, client) {
|
||||
var process;
|
||||
var options = {};
|
||||
var credentials = auth.query(request.headers);
|
||||
|
||||
response.onMessage = async function(event) {
|
||||
if (event.opCode == 0x1 || event.opCode == 0x2) {
|
||||
var message;
|
||||
try {
|
||||
message = JSON.parse(event.data);
|
||||
} catch (error) {
|
||||
print("ERROR", error, event.data, event.data.length, event.opCode);
|
||||
return;
|
||||
}
|
||||
if (message.action == "hello") {
|
||||
var packageOwner;
|
||||
var packageName;
|
||||
var blobId;
|
||||
var match;
|
||||
if (match = /^\/(&[^\.]*\.\w+)(\/?.*)/.exec(message.path)) {
|
||||
blobId = match[1];
|
||||
} else if (match = /^\/\~([^\/]+)\/([^\/]+)\/$/.exec(message.path)) {
|
||||
var user = match[1];
|
||||
var path = match[2];
|
||||
blobId = await new Database(user).get('path:' + path);
|
||||
if (!blobId) {
|
||||
response.send(JSON.stringify({action: "error", error: message.path + ' not found'}), 0x1);
|
||||
request.close();
|
||||
}
|
||||
}
|
||||
response.send(JSON.stringify({action: "session", credentials: credentials}), 0x1);
|
||||
|
||||
options.api = message.api || [];
|
||||
options.credentials = credentials;
|
||||
var sessionId = makeSessionId();
|
||||
if (blobId) {
|
||||
process = await getSessionProcessBlob(blobId, sessionId, options);
|
||||
}
|
||||
if (process) {
|
||||
process.app.readOutput(function(message) {
|
||||
response.send(JSON.stringify(message), 0x1);
|
||||
});
|
||||
process.app.send();
|
||||
}
|
||||
|
||||
var ping = function() {
|
||||
var now = Date.now();
|
||||
var again = true;
|
||||
if (now - process.lastActive < process.timeout) {
|
||||
// Active.
|
||||
} else if (process.lastPing > process.lastActive) {
|
||||
// We lost them.
|
||||
if (process.task) {
|
||||
process.task.kill();
|
||||
}
|
||||
again = false;
|
||||
} else {
|
||||
// Idle. Ping them.
|
||||
response.send("", 0x9);
|
||||
process.lastPing = now;
|
||||
}
|
||||
|
||||
if (again) {
|
||||
setTimeout(ping, process.timeout);
|
||||
}
|
||||
}
|
||||
|
||||
if (process && process.timeout > 0) {
|
||||
setTimeout(ping, process.timeout);
|
||||
}
|
||||
} else {
|
||||
if (process && process.eventHandlers['message']) {
|
||||
await invoke(process.eventHandlers['message'], [message]);
|
||||
}
|
||||
}
|
||||
} else if (event.opCode == 0x8) {
|
||||
// Close.
|
||||
if (process) {
|
||||
process.task.kill();
|
||||
}
|
||||
response.send(event.data, 0x8);
|
||||
} else if (event.opCode == 0xa) {
|
||||
// PONG
|
||||
}
|
||||
|
||||
if (process) {
|
||||
process.lastActive = Date.now();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.socket = socket;
|
@ -7,8 +7,8 @@
|
||||
document.getElementById("confirmPassword").style.display = document.getElementById("register").checked ? "block" : "none";
|
||||
}
|
||||
</script>
|
||||
<link type="text/css" rel="stylesheet" href="/terminal/style.css">
|
||||
<link type="image/png" rel="shortcut icon" href="/terminal/favicon.png">
|
||||
<link type="text/css" rel="stylesheet" href="/static/style.css">
|
||||
<link type="image/png" rel="shortcut icon" href="/static/favicon.png">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!--HEAD-->
|
||||
</head>
|
||||
|
112
core/auth.js
112
core/auth.js
@ -1,27 +1,14 @@
|
||||
"use strict";
|
||||
var kAccountsFile = "data/auth/accounts.json";
|
||||
|
||||
var gAccounts = {};
|
||||
var gTokens = {};
|
||||
|
||||
var bCryptLib = require('bCrypt');
|
||||
bCrypt = new bCryptLib.bCrypt();
|
||||
|
||||
var form = require('form');
|
||||
var http = require('http');
|
||||
|
||||
File.makeDirectory("data");
|
||||
File.makeDirectory("data/auth");
|
||||
File.makeDirectory("data/auth/db");
|
||||
var gDatabase = new Database("data/auth/db");
|
||||
|
||||
try {
|
||||
gAccounts = JSON.parse(new TextDecoder("UTF-8").decode(File.readFile(kAccountsFile)));
|
||||
} catch (error) {
|
||||
}
|
||||
var gDatabase = new Database("auth");
|
||||
|
||||
function readSession(session) {
|
||||
var result = session ? gDatabase.get("session_" + session) : null;
|
||||
var result = session ? gDatabase.get("session:" + session) : null;
|
||||
|
||||
if (result) {
|
||||
result = JSON.parse(result);
|
||||
@ -38,11 +25,11 @@ function readSession(session) {
|
||||
}
|
||||
|
||||
function writeSession(session, value) {
|
||||
gDatabase.set("session_" + session, JSON.stringify(value));
|
||||
gDatabase.set("session:" + session, JSON.stringify(value));
|
||||
}
|
||||
|
||||
function removeSession(session, value) {
|
||||
gDatabase.remove("session_" + session);
|
||||
gDatabase.remove("session:" + session);
|
||||
}
|
||||
|
||||
function newSession() {
|
||||
@ -95,12 +82,14 @@ function authHandler(request, response) {
|
||||
sessionIsNew = true;
|
||||
formData = form.decodeForm(request.body, formData);
|
||||
if (formData.submit == "Login") {
|
||||
var account = gDatabase.get("user:" + formData.name);
|
||||
account = account ? JSON.parse(account) : account;
|
||||
if (formData.register == "1") {
|
||||
if (!gAccounts[formData.name] &&
|
||||
if (!account &&
|
||||
formData.password == formData.confirm) {
|
||||
gAccounts[formData.name] = {password: hashPassword(formData.password)};
|
||||
writeSession(session, {name: formData.name});
|
||||
File.writeFile(kAccountsFile, JSON.stringify(gAccounts));
|
||||
account = {password: hashPassword(formData.password)};
|
||||
gDatabase.set("user:" + formData.name, JSON.stringify(account));
|
||||
if (noAdministrator()) {
|
||||
makeAdministrator(formData.name);
|
||||
}
|
||||
@ -108,9 +97,9 @@ function authHandler(request, response) {
|
||||
loginError = "Error registering account.";
|
||||
}
|
||||
} else {
|
||||
if (gAccounts[formData.name] &&
|
||||
gAccounts[formData.name].password &&
|
||||
verifyPassword(formData.password, gAccounts[formData.name].password)) {
|
||||
if (account &&
|
||||
account.password &&
|
||||
verifyPassword(formData.password, account.password)) {
|
||||
writeSession(session, {name: formData.name});
|
||||
if (noAdministrator()) {
|
||||
makeAdministrator(formData.name);
|
||||
@ -142,44 +131,6 @@ function authHandler(request, response) {
|
||||
}
|
||||
contents += '<div><a href="/login/logout">Logout</a></div>\n';
|
||||
} else {
|
||||
if (gGlobalSettings && gGlobalSettings['google-signin-client_id']) {
|
||||
html = html.replace("<!--HEAD-->", `
|
||||
<script src="https://apis.google.com/js/platform.js" async defer></script>
|
||||
<meta name="google-signin-client_id" content="${gGlobalSettings['google-signin-client_id']}">
|
||||
<script>
|
||||
function onGoogleSignIn(user) {
|
||||
var token = user.getAuthResponse().id_token;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "/login/google");
|
||||
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||
xhr.onload = function() {
|
||||
if (xhr.status == 200) {
|
||||
var redirected = false;
|
||||
if (window.location.search.length) {
|
||||
var query = window.location.search.substring(1);
|
||||
var parts = query.split("&");
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var part = decodeURIComponent(parts[i]);
|
||||
var key = part.substring(0, part.indexOf('='));
|
||||
var value = part.substring(part.indexOf('=') + 1);
|
||||
if (key == "return") {
|
||||
redirected = true;
|
||||
window.location.href = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!redirected) {
|
||||
window.location.path = "/";
|
||||
}
|
||||
} else {
|
||||
alert(xhr.response);
|
||||
}
|
||||
};
|
||||
xhr.send('token=' + token);
|
||||
}
|
||||
</script>
|
||||
`);
|
||||
}
|
||||
contents += '<form method="POST">\n';
|
||||
if (loginError) {
|
||||
contents += "<p>" + loginError + "</p>\n";
|
||||
@ -197,10 +148,6 @@ function authHandler(request, response) {
|
||||
contents += '<div><input id="loginButton" type="submit" name="submit" value="Login"></div>\n';
|
||||
contents += '</div>';
|
||||
contents += '<div class="auth_or"> - or - </div>';
|
||||
if (gGlobalSettings && gGlobalSettings['google-signin-client_id']) {
|
||||
contents += '<div class="g-signin2" data-onsuccess="onGoogleSignIn" data-scope="profile"></div>';
|
||||
contents += '<div class="auth_or"> - or - </div>';
|
||||
}
|
||||
contents += '<div id="auth_guest">\n';
|
||||
contents += '<input id="guestButton" type="submit" name="submit" value="Proceeed as Guest">\n';
|
||||
contents += '</div>\n';
|
||||
@ -215,47 +162,12 @@ function authHandler(request, response) {
|
||||
removeSession(session);
|
||||
response.writeHead(303, {"Set-Cookie": "session=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT", "Location": "/login" + (request.query ? "?" + request.query : "")});
|
||||
response.end();
|
||||
} else if (request.uri == "/login/google") {
|
||||
var formData = form.decodeForm(request.query, form.decodeForm(request.body));
|
||||
return verifyGoogleToken(formData.token).then(function(user) {
|
||||
if (user && user.aud == gGlobalSettings['google-signin-client_id']) {
|
||||
session = newSession();
|
||||
var userId = user.name;
|
||||
if (gAccounts[userId] && !gAccounts[userId].google) {
|
||||
response.writeHead(500, {"Content-Type": "text/plain; charset=utf-8", "Connection": "close"});
|
||||
response.end("Account already exists and is not a Google account.");
|
||||
} else {
|
||||
if (!gAccounts[userId]) {
|
||||
gAccounts[userId] = {google: true};
|
||||
File.writeFile(kAccountsFile, JSON.stringify(gAccounts));
|
||||
if (noAdministrator()) {
|
||||
makeAdministrator(userId);
|
||||
}
|
||||
}
|
||||
|
||||
writeSession(session, {name: userId, google: true});
|
||||
|
||||
var cookie = "session=" + session + "; path=/; Max-Age=604800";
|
||||
response.writeHead(200, {"Content-Type": "text/json; charset=utf-8", "Connection": "close", "Set-Cookie": cookie});
|
||||
response.end(JSON.stringify(user));
|
||||
}
|
||||
} else {
|
||||
response.writeHead(500, {"Content-Type": "text/plain; charset=utf-8", "Connection": "close"});
|
||||
response.end();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
response.writeHead(200, {"Content-Type": "text/plain; charset=utf-8", "Connection": "close"});
|
||||
response.end("Hello, " + request.client.peerName + ".");
|
||||
}
|
||||
}
|
||||
|
||||
function verifyGoogleToken(token) {
|
||||
return http.get("https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=" + token).then(function(response) {
|
||||
return JSON.parse(response.body);
|
||||
});
|
||||
}
|
||||
|
||||
function getPermissions(session) {
|
||||
var permissions;
|
||||
var entry = readSession(session);
|
||||
|
533
core/bCrypt.js
533
core/bCrypt.js
@ -1,533 +0,0 @@
|
||||
var isaac = require('isaac');
|
||||
|
||||
function bCrypt() {
|
||||
this.GENSALT_DEFAULT_LOG2_ROUNDS = 10;
|
||||
this.BCRYPT_SALT_LEN = 16;
|
||||
this.BLOWFISH_NUM_ROUNDS = 16;
|
||||
this.MAX_EXECUTION_TIME = 100;
|
||||
this.P_orig = [0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822,
|
||||
0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377,
|
||||
0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5,
|
||||
0xb5470917, 0x9216d5d9, 0x8979fb1b];
|
||||
this.S_orig = [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];
|
||||
this.bf_crypt_ciphertext = [0x4f727068, 0x65616e42, 0x65686f6c, 0x64657253,
|
||||
0x63727944, 0x6f756274];
|
||||
this.base64_code = ['.', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
|
||||
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
|
||||
'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
|
||||
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8',
|
||||
'9'];
|
||||
this.index_64 = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1,
|
||||
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, -1, -1, -1, -1, -1, -1, -1,
|
||||
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, -1, -1, -1, -1, -1, -1, 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, -1, -1, -1, -1, -1];
|
||||
this.P;
|
||||
this.S;
|
||||
this.lr;
|
||||
this.offp;
|
||||
};
|
||||
bCrypt.prototype.getByte = function(c) {
|
||||
var ret = 0;
|
||||
try {
|
||||
var b = c.charCodeAt(0);
|
||||
} catch (err) {
|
||||
b = c;
|
||||
}
|
||||
if (b > 127) {
|
||||
return -128 + (b % 128);
|
||||
} else {
|
||||
return b;
|
||||
}
|
||||
};
|
||||
bCrypt.prototype.encode_base64 = function(d, len) {
|
||||
var off = 0;
|
||||
var rs = [];
|
||||
var c1;
|
||||
var c2;
|
||||
if (len <= 0 || len > d.length)
|
||||
throw "Invalid len";
|
||||
while (off < len) {
|
||||
c1 = d[off++] & 0xff;
|
||||
rs.push(this.base64_code[(c1 >> 2) & 0x3f]);
|
||||
c1 = (c1 & 0x03) << 4;
|
||||
if (off >= len) {
|
||||
rs.push(this.base64_code[c1 & 0x3f]);
|
||||
break;
|
||||
}
|
||||
c2 = d[off++] & 0xff;
|
||||
c1 |= (c2 >> 4) & 0x0f;
|
||||
rs.push(this.base64_code[c1 & 0x3f]);
|
||||
c1 = (c2 & 0x0f) << 2;
|
||||
if (off >= len) {
|
||||
rs.push(this.base64_code[c1 & 0x3f]);
|
||||
break;
|
||||
}
|
||||
c2 = d[off++] & 0xff;
|
||||
c1 |= (c2 >> 6) & 0x03;
|
||||
rs.push(this.base64_code[c1 & 0x3f]);
|
||||
rs.push(this.base64_code[c2 & 0x3f]);
|
||||
}
|
||||
return rs.join('');
|
||||
};
|
||||
bCrypt.prototype.char64 = function(x) {
|
||||
var code = x.charCodeAt(0);
|
||||
if (code < 0 || code > this.index_64.length) {
|
||||
return -1;
|
||||
}
|
||||
return this.index_64[code];
|
||||
};
|
||||
bCrypt.prototype.decode_base64 = function(s, maxolen) {
|
||||
var off = 0;
|
||||
var slen = s.length;
|
||||
var olen = 0;
|
||||
var rs = [];
|
||||
var c1, c2, c3, c4, o;
|
||||
if (maxolen <= 0)
|
||||
throw "Invalid maxolen";
|
||||
while (off < slen - 1 && olen < maxolen) {
|
||||
c1 = this.char64(s.charAt(off++));
|
||||
c2 = this.char64(s.charAt(off++));
|
||||
if (c1 == -1 || c2 == -1) {
|
||||
break;
|
||||
}
|
||||
o = this.getByte(c1 << 2);
|
||||
o |= (c2 & 0x30) >> 4;
|
||||
rs.push(String.fromCharCode(o));
|
||||
if (++olen >= maxolen || off >= slen) {
|
||||
break;
|
||||
}
|
||||
c3 = this.char64(s.charAt(off++));
|
||||
if (c3 == -1) {
|
||||
break;
|
||||
}
|
||||
o = this.getByte((c2 & 0x0f) << 4);
|
||||
o |= (c3 & 0x3c) >> 2;
|
||||
rs.push(String.fromCharCode(o));
|
||||
if (++olen >= maxolen || off >= slen) {
|
||||
break;
|
||||
}
|
||||
c4 = this.char64(s.charAt(off++));
|
||||
o = this.getByte((c3 & 0x03) << 6);
|
||||
o |= c4;
|
||||
rs.push(String.fromCharCode(o));
|
||||
++olen;
|
||||
}
|
||||
var ret = [];
|
||||
for (off = 0; off < olen; off++) {
|
||||
ret.push(this.getByte(rs[off]));
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
bCrypt.prototype.encipher = function(lr, off) {
|
||||
var i;
|
||||
var n;
|
||||
var l = lr[off];
|
||||
var r = lr[off + 1];
|
||||
|
||||
l ^= this.P[0];
|
||||
for (i = 0; i <= this.BLOWFISH_NUM_ROUNDS - 2;) {
|
||||
// Feistel substitution on left word
|
||||
n = this.S[(l >> 24) & 0xff];
|
||||
n += this.S[0x100 | ((l >> 16) & 0xff)];
|
||||
n ^= this.S[0x200 | ((l >> 8) & 0xff)];
|
||||
n += this.S[0x300 | (l & 0xff)];
|
||||
r ^= n ^ this.P[++i];
|
||||
|
||||
// Feistel substitution on right word
|
||||
n = this.S[(r >> 24) & 0xff];
|
||||
n += this.S[0x100 | ((r >> 16) & 0xff)];
|
||||
n ^= this.S[0x200 | ((r >> 8) & 0xff)];
|
||||
n += this.S[0x300 | (r & 0xff)];
|
||||
l ^= n ^ this.P[++i];
|
||||
}
|
||||
lr[off] = r ^ this.P[this.BLOWFISH_NUM_ROUNDS + 1];
|
||||
lr[off + 1] = l;
|
||||
};
|
||||
bCrypt.prototype.streamtoword = function(data, offp) {
|
||||
var i;
|
||||
var word = 0;
|
||||
var off = offp;
|
||||
for (i = 0; i < 4; i++) {
|
||||
word = (word << 8) | (data[off] & 0xff);
|
||||
off = (off + 1) % data.length;
|
||||
}
|
||||
this.offp = off;
|
||||
return word;
|
||||
};
|
||||
bCrypt.prototype.init_key = function() {
|
||||
this.P = this.P_orig.slice();
|
||||
this.S = this.S_orig.slice();
|
||||
};
|
||||
bCrypt.prototype.key = function(key) {
|
||||
var i;
|
||||
this.offp = 0;
|
||||
var lr = new Array(0x00000000, 0x00000000);
|
||||
var plen = this.P.length;
|
||||
var slen = this.S.length;
|
||||
|
||||
for (i = 0; i < plen; i++) {
|
||||
this.P[i] = this.P[i] ^ this.streamtoword(key, this.offp);
|
||||
}
|
||||
for (i = 0; i < plen; i += 2) {
|
||||
this.encipher(lr, 0);
|
||||
this.P[i] = lr[0];
|
||||
this.P[i + 1] = lr[1];
|
||||
}
|
||||
|
||||
for (i = 0; i < slen; i += 2) {
|
||||
this.encipher(lr, 0);
|
||||
this.S[i] = lr[0];
|
||||
this.S[i + 1] = lr[1];
|
||||
}
|
||||
};
|
||||
bCrypt.prototype.ekskey = function(data, key) {
|
||||
var i;
|
||||
this.offp = 0;
|
||||
var lr = new Array(0x00000000, 0x00000000);
|
||||
var plen = this.P.length;
|
||||
var slen = this.S.length;
|
||||
|
||||
for (i = 0; i < plen; i++)
|
||||
this.P[i] = this.P[i] ^ this.streamtoword(key, this.offp);
|
||||
this.offp = 0;
|
||||
for (i = 0; i < plen; i += 2) {
|
||||
lr[0] ^= this.streamtoword(data, this.offp);
|
||||
lr[1] ^= this.streamtoword(data, this.offp);
|
||||
this.encipher(lr, 0);
|
||||
this.P[i] = lr[0];
|
||||
this.P[i + 1] = lr[1];
|
||||
}
|
||||
for (i = 0; i < slen; i += 2) {
|
||||
lr[0] ^= this.streamtoword(data, this.offp);
|
||||
lr[1] ^= this.streamtoword(data, this.offp);
|
||||
this.encipher(lr, 0);
|
||||
this.S[i] = lr[0];
|
||||
this.S[i + 1] = lr[1];
|
||||
}
|
||||
};
|
||||
|
||||
bCrypt.prototype.crypt_raw = function(password, salt, log_rounds) {
|
||||
var rounds;
|
||||
var j;
|
||||
var cdata = this.bf_crypt_ciphertext.slice();
|
||||
var clen = cdata.length;
|
||||
var one_percent;
|
||||
|
||||
if (log_rounds < 4 || log_rounds > 31)
|
||||
throw "Bad number of rounds";
|
||||
if (salt.length != this.BCRYPT_SALT_LEN)
|
||||
throw "Bad salt length";
|
||||
|
||||
rounds = 1 << log_rounds;
|
||||
one_percent = Math.floor(rounds / 100) + 1;
|
||||
this.init_key();
|
||||
this.ekskey(salt, password);
|
||||
|
||||
var obj = this;
|
||||
var i = 0;
|
||||
for (; i < rounds;) {
|
||||
i = i + 1;
|
||||
obj.key(password);
|
||||
obj.key(salt);
|
||||
}
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
for (j = 0; j < (clen >> 1); j++) {
|
||||
obj.encipher(cdata, j << 1);
|
||||
}
|
||||
}
|
||||
var ret = [];
|
||||
for (i = 0; i < clen; i++) {
|
||||
ret.push(obj.getByte((cdata[i] >> 24) & 0xff));
|
||||
ret.push(obj.getByte((cdata[i] >> 16) & 0xff));
|
||||
ret.push(obj.getByte((cdata[i] >> 8) & 0xff));
|
||||
ret.push(obj.getByte(cdata[i] & 0xff));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bCrypt.prototype.hashpw = function(password, salt) {
|
||||
var real_salt;
|
||||
var passwordb = [];
|
||||
var saltb = [];
|
||||
var hashed = [];
|
||||
var minor = String.fromCharCode(0);
|
||||
var rounds = 0;
|
||||
var off = 0;
|
||||
|
||||
if (!progress){
|
||||
var progress = function() {};
|
||||
}
|
||||
|
||||
if (salt.charAt(0) != '$' || salt.charAt(1) != '2')
|
||||
throw "Invalid salt version";
|
||||
if (salt.charAt(2) == '$')
|
||||
off = 3;
|
||||
else {
|
||||
minor = salt.charAt(2);
|
||||
if (minor != 'a' || salt.charAt(3) != '$')
|
||||
throw "Invalid salt revision";
|
||||
off = 4;
|
||||
}
|
||||
|
||||
// Extract number of rounds
|
||||
if (salt.charAt(off + 2) > '$')
|
||||
throw "Missing salt rounds";
|
||||
var r1 = parseInt(salt.substring(off, off + 1)) * 10;
|
||||
var r2 = parseInt(salt.substring(off + 1, off + 2));
|
||||
rounds = r1 + r2;
|
||||
real_salt = salt.substring(off + 3, off + 25);
|
||||
password = password + (minor >= 'a' ? "\000" : "");
|
||||
for (var r = 0; r < password.length; r++) {
|
||||
passwordb.push(this.getByte(password.charAt(r)));
|
||||
}
|
||||
saltb = this.decode_base64(real_salt, this.BCRYPT_SALT_LEN);
|
||||
var obj = this;
|
||||
var hashed = this.crypt_raw(passwordb, saltb, rounds);
|
||||
var rs = [];
|
||||
rs.push("$2");
|
||||
if (minor >= 'a')
|
||||
rs.push(minor);
|
||||
rs.push("$");
|
||||
if (rounds < 10)
|
||||
rs.push("0");
|
||||
rs.push(rounds.toString());
|
||||
rs.push("$");
|
||||
rs.push(obj.encode_base64(saltb, saltb.length));
|
||||
rs.push(obj.encode_base64(hashed, obj.bf_crypt_ciphertext.length * 4 - 1));
|
||||
return rs.join('');
|
||||
};
|
||||
|
||||
bCrypt.prototype.gensalt = function(rounds) {
|
||||
var iteration_count = rounds;
|
||||
if (iteration_count < 4 || iteration_count > 31) {
|
||||
iteration_count = this.GENSALT_DEFAULT_LOG2_ROUNDS;
|
||||
}
|
||||
var output = [];
|
||||
output.push("$2a$");
|
||||
if (iteration_count < 10)
|
||||
output.push("0");
|
||||
output.push(iteration_count.toString());
|
||||
output.push('$');
|
||||
var s1 = [];
|
||||
for (var r = 0; r < this.BCRYPT_SALT_LEN; r++){
|
||||
s1.push(Math.abs(isaac.rand()));
|
||||
}
|
||||
output.push(this.encode_base64(s1,this.BCRYPT_SALT_LEN))
|
||||
return output.join('');
|
||||
};
|
||||
|
||||
bCrypt.prototype.ready = function(){
|
||||
return true;
|
||||
};
|
||||
|
||||
exports.bCrypt = bCrypt;
|
781
core/client.js
781
core/client.js
@ -2,16 +2,10 @@
|
||||
|
||||
var gSocket;
|
||||
var gCredentials;
|
||||
var gErrorCount = 0;
|
||||
var gCommandHistory = [];
|
||||
var gSendKeyEvents = false;
|
||||
var gSendDeviceOrientationEvents = false;
|
||||
var gGeolocatorWatch;
|
||||
|
||||
var gCurrentFile;
|
||||
var gFiles = {};
|
||||
var gEditor;
|
||||
var gBackup;
|
||||
|
||||
var kMaxCommandHistory = 16;
|
||||
|
||||
var kErrorColor = "#dc322f";
|
||||
var kStatusColor = "#fff";
|
||||
@ -35,31 +29,6 @@ window.addEventListener("keydown", function(event) {
|
||||
}
|
||||
});
|
||||
|
||||
function keydown(event) {
|
||||
if (event.keyCode == 13) {
|
||||
gCommandHistory.push(document.getElementById("input").value);
|
||||
if (gCommandHistory.length > kMaxCommandHistory) {
|
||||
gCommandHistory.shift();
|
||||
}
|
||||
send();
|
||||
event.preventDefault();
|
||||
} else if (event.keyCode == 38 && !event.altKey) {
|
||||
if (gCommandHistory.length) {
|
||||
var input = document.getElementById("input");
|
||||
gCommandHistory.unshift(input.value);
|
||||
input.value = gCommandHistory.pop();
|
||||
event.preventDefault();
|
||||
}
|
||||
} else if (event.keyCode == 40 && !event.altKey) {
|
||||
if (gCommandHistory.length) {
|
||||
var input = document.getElementById("input");
|
||||
gCommandHistory.push(input.value);
|
||||
input.value = gCommandHistory.shift();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ensureLoaded(nodes, callback) {
|
||||
if (!nodes.length) {
|
||||
callback();
|
||||
@ -107,49 +76,42 @@ function edit() {
|
||||
}
|
||||
|
||||
ensureLoaded([
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/codemirror.min.js"}},
|
||||
{tagName: "link", attributes: {rel: "stylesheet", href: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/theme/base16-dark.min.css"}},
|
||||
{tagName: "link", attributes: {rel: "stylesheet", href: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/addon/search/matchesonscrollbar.min.css"}},
|
||||
{tagName: "link", attributes: {rel: "stylesheet", href: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/addon/dialog/dialog.min.css"}},
|
||||
{tagName: "link", attributes: {rel: "stylesheet", href: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/codemirror.min.css"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/addon/edit/trailingspace.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/addon/dialog/dialog.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/addon/search/search.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/addon/search/searchcursor.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/addon/search/jump-to-line.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/addon/search/matchesonscrollbar.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/addon/scroll/annotatescrollbar.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.23.0/mode/javascript/javascript.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.57.0/codemirror.min.js"}},
|
||||
{tagName: "link", attributes: {rel: "stylesheet", href: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.57.0/theme/base16-dark.min.css"}},
|
||||
{tagName: "link", attributes: {rel: "stylesheet", href: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.57.0/addon/search/matchesonscrollbar.min.css"}},
|
||||
{tagName: "link", attributes: {rel: "stylesheet", href: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.57.0/addon/dialog/dialog.min.css"}},
|
||||
{tagName: "link", attributes: {rel: "stylesheet", href: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.57.0/codemirror.min.css"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.57.0/addon/edit/trailingspace.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.57.0/addon/dialog/dialog.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.57.0/addon/search/search.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.57.0/addon/search/searchcursor.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.57.0/addon/search/jump-to-line.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.57.0/addon/search/matchesonscrollbar.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.57.0/addon/scroll/annotatescrollbar.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.57.0/mode/javascript/javascript.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.57.0/mode/css/css.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.57.0/mode/xml/xml.min.js"}},
|
||||
{tagName: "script", attributes: {src: "https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.57.0/mode/htmlmixed/htmlmixed.min.js"}},
|
||||
], function() {
|
||||
load();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function load() {
|
||||
function guessMode(name) {
|
||||
return name.endsWith(".js") ? "javascript" :
|
||||
name.endsWith(".html") ? "htmlmixed" :
|
||||
null;
|
||||
}
|
||||
|
||||
function loadFile(name, id) {
|
||||
var request = new XMLHttpRequest();
|
||||
request.addEventListener("loadend", function() {
|
||||
if (request.status == 200 || request.status == 404) {
|
||||
document.getElementById("editPane").style.display = 'flex';
|
||||
if (!gEditor) {
|
||||
gEditor = CodeMirror.fromTextArea(document.getElementById("editor"), {
|
||||
'theme': 'base16-dark',
|
||||
'lineNumbers': true,
|
||||
'tabSize': 4,
|
||||
'indentUnit': 4,
|
||||
'indentWithTabs': true,
|
||||
'showTrailingSpace': true,
|
||||
});
|
||||
if (request.status == 200) {
|
||||
gFiles[name].doc = new CodeMirror.Doc(request.responseText, guessMode(name));
|
||||
if (!Object.values(gFiles).some(x => !x.doc)) {
|
||||
document.getElementById("editPane").style.display = 'flex';
|
||||
openFile(Object.keys(gFiles).sort()[0]);
|
||||
}
|
||||
var text;
|
||||
if (request.status == 200) {
|
||||
text = request.responseText;
|
||||
} else {
|
||||
text = '// New script\nterminal.print("Hello, world!");\n';
|
||||
}
|
||||
gEditor.setValue(text);
|
||||
gEditor.focus();
|
||||
gBackup = text;
|
||||
}
|
||||
});
|
||||
request.addEventListener("error", function() {
|
||||
@ -164,7 +126,67 @@ function load() {
|
||||
alert("Loading source aborted.");
|
||||
closeEditor();
|
||||
});
|
||||
request.open("GET", url() + "/view");
|
||||
request.open("GET", "/" + id + "/view");
|
||||
request.send();
|
||||
}
|
||||
|
||||
function load() {
|
||||
var request = new XMLHttpRequest();
|
||||
request.addEventListener("loadend", function() {
|
||||
if (request.status == 200 || request.status == 404) {
|
||||
if (!gEditor) {
|
||||
gEditor = CodeMirror.fromTextArea(document.getElementById("editor"), {
|
||||
'theme': 'base16-dark',
|
||||
'lineNumbers': true,
|
||||
'tabSize': 4,
|
||||
'indentUnit': 4,
|
||||
'indentWithTabs': true,
|
||||
'showTrailingSpace': true,
|
||||
});
|
||||
}
|
||||
gFiles = {};
|
||||
var text;
|
||||
var isApp = false;
|
||||
if (request.status == 200) {
|
||||
text = request.responseText;
|
||||
try {
|
||||
var json = JSON.parse(text);
|
||||
if (json && json['type'] == 'tildefriends-app') {
|
||||
isApp = true;
|
||||
Object.keys(json['files']).forEach(function(name) {
|
||||
gFiles[name] = {};
|
||||
loadFile(name, json['files'][name]);
|
||||
});
|
||||
}
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
if (!isApp) {
|
||||
document.getElementById("editPane").style.display = 'flex';
|
||||
if (!text) {
|
||||
text = '// New script.\n';
|
||||
}
|
||||
gCurrentFile = 'app.js';
|
||||
gFiles[gCurrentFile] = {
|
||||
doc: new CodeMirror.Doc(text, guessMode(gCurrentFile)),
|
||||
};
|
||||
openFile(gCurrentFile);
|
||||
}
|
||||
}
|
||||
});
|
||||
request.addEventListener("error", function() {
|
||||
alert("Error loading source.");
|
||||
closeEditor();
|
||||
});
|
||||
request.addEventListener("timeout", function() {
|
||||
alert("Timed out loading source.");
|
||||
closeEditor();
|
||||
});
|
||||
request.addEventListener("abort", function() {
|
||||
alert("Loading source aborted.");
|
||||
closeEditor();
|
||||
});
|
||||
request.open("GET", url() + "view");
|
||||
request.send();
|
||||
}
|
||||
|
||||
@ -172,73 +194,114 @@ function closeEditor() {
|
||||
document.getElementById("editPane").style.display = 'none';
|
||||
}
|
||||
|
||||
function revert() {
|
||||
gEditor.setValue(gBackup);
|
||||
}
|
||||
|
||||
function explodePath() {
|
||||
return /^\/~([^\/]+)\/([^\/]+)(.*)/.exec(window.location.pathname);
|
||||
}
|
||||
|
||||
function packageOwner() {
|
||||
return explodePath()[1];
|
||||
}
|
||||
|
||||
function packageName() {
|
||||
return explodePath()[2];
|
||||
}
|
||||
|
||||
function save(newName) {
|
||||
function save() {
|
||||
document.getElementById("save").disabled = true;
|
||||
document.getElementById("saveAs").disabled = true;
|
||||
if (gCurrentFile) {
|
||||
gFiles[gCurrentFile].doc = gEditor.getDoc();
|
||||
}
|
||||
|
||||
var contents = gEditor.getValue();
|
||||
var run = document.getElementById("run").checked;
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
var appFinished = function(success) {
|
||||
document.getElementById("save").disabled = false;
|
||||
}
|
||||
|
||||
var always = function() {
|
||||
document.getElementById("save").disabled = false;
|
||||
document.getElementById("saveAs").disabled = false;
|
||||
var anyUnfinished = Object.values(gFiles).some(x => x.request);
|
||||
var anyUnsaved = Object.values(gFiles).some(x => !x.id);
|
||||
if (!anyUnfinished && !anyUnsaved) {
|
||||
var app = {
|
||||
type: "tildefriends-app",
|
||||
files: Object.fromEntries(Object.keys(gFiles).map(x => [x, gFiles[x].id])),
|
||||
};
|
||||
Object.values(gFiles).forEach(function(file) { delete file.id; });
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
request.addEventListener("error", function() {
|
||||
alert("Error saving: " + request.responseText);
|
||||
appFinished(false);
|
||||
});
|
||||
request.addEventListener("loadend", function() {
|
||||
if (request.status == 200) {
|
||||
var latest = document.getElementById('latest');
|
||||
latest.href = request.responseText;
|
||||
latest.style.visibility = request.responseText != window.location.path ? 'visible' : 'hidden';
|
||||
if (run) {
|
||||
if (request.responseText) {
|
||||
reconnect(request.responseText);
|
||||
} else {
|
||||
reconnect(window.location.path);
|
||||
}
|
||||
}
|
||||
appFinished(true);
|
||||
} else {
|
||||
alert("Unable to save: " + request.responseText);
|
||||
appFinished(false);
|
||||
}
|
||||
});
|
||||
request.addEventListener("timeout", function() {
|
||||
alert("Timed out saving: " + request.responseText);
|
||||
appFinished(false);
|
||||
});
|
||||
request.addEventListener("abort", function() {
|
||||
alert("Save aborted: " + request.responseText);
|
||||
appFinished(false);
|
||||
});
|
||||
|
||||
var saveTo = null;
|
||||
var name = document.getElementById("name");
|
||||
if (name && name.value) {
|
||||
saveTo = name.value + "save";
|
||||
} else {
|
||||
saveTo = url() + "save";
|
||||
}
|
||||
request.open("POST", saveTo, true);
|
||||
request.setRequestHeader("Content-Type", "text/json");
|
||||
request.send(JSON.stringify(app));
|
||||
} else if (!anyUnfinished) {
|
||||
appFinished(false);
|
||||
}
|
||||
};
|
||||
|
||||
request.addEventListener("error", function() {
|
||||
alert("Error saving: " + request.responseText);
|
||||
always();
|
||||
});
|
||||
request.addEventListener("loadend", function() {
|
||||
if (request.status == 200) {
|
||||
gBackup = contents;
|
||||
if (run) {
|
||||
if (newName) {
|
||||
window.location.href = "/~" + packageOwner() + "/" + newName + hash();
|
||||
} else {
|
||||
reconnect();
|
||||
Object.values(gFiles).forEach(function(file) {
|
||||
delete file.id;
|
||||
file.request = new XMLHttpRequest();
|
||||
file.request.addEventListener("error", function() {
|
||||
alert("Error saving: " + file.request.responseText);
|
||||
file.request = null;
|
||||
always();
|
||||
});
|
||||
file.request.addEventListener("loadend", function() {
|
||||
if (file.request.status == 200) {
|
||||
file.id = file.request.responseText;
|
||||
if (file.id.charAt(0) == '/') {
|
||||
file.id = file.id.substr(1);
|
||||
}
|
||||
} else {
|
||||
alert("Unable to save: " + file.request.responseText);
|
||||
}
|
||||
} else {
|
||||
alert("Unable to save: " + request.responseText);
|
||||
}
|
||||
always();
|
||||
});
|
||||
request.addEventListener("timeout", function() {
|
||||
alert("Timed out saving: " + request.responseText);
|
||||
always();
|
||||
});
|
||||
request.addEventListener("abort", function() {
|
||||
alert("Save aborted: " + request.responseText);
|
||||
always();
|
||||
});
|
||||
request.open("POST", newName ? newName + "/save" : packageName() + "/save", true);
|
||||
request.setRequestHeader("Content-Type", "text/plain");
|
||||
request.send(contents);
|
||||
}
|
||||
file.request = null;
|
||||
always();
|
||||
});
|
||||
file.request.addEventListener("timeout", function() {
|
||||
alert("Timed out saving: " + file.request.responseText);
|
||||
file.request = null;
|
||||
always();
|
||||
});
|
||||
file.request.addEventListener("abort", function() {
|
||||
alert("Save aborted: " + file.request.responseText);
|
||||
file.request = null;
|
||||
always();
|
||||
});
|
||||
|
||||
function saveAs() {
|
||||
var newName = prompt("Save as:", packageName());
|
||||
if (newName) {
|
||||
save(newName);
|
||||
}
|
||||
file.request.open("POST", "/save", true);
|
||||
file.request.setRequestHeader("Content-Type", "text/plain");
|
||||
file.request.send(file.doc.getValue());
|
||||
});
|
||||
}
|
||||
|
||||
function url() {
|
||||
@ -260,191 +323,30 @@ function hash() {
|
||||
return window.location.hash != "#" ? window.location.hash : "";
|
||||
}
|
||||
|
||||
function split(container, children) {
|
||||
if (container) {
|
||||
while (container.firstChild) {
|
||||
container.removeChild(container.firstChild);
|
||||
}
|
||||
}
|
||||
if (children) {
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
if (children[i].name) {
|
||||
var node = document.createElement("div");
|
||||
node.setAttribute("id", "terminal_" + children[i].name);
|
||||
var grow = children[i].grow || "1";
|
||||
var shrink = children[i].shrink || "1";
|
||||
var basis = children[i].basis || "auto";
|
||||
var style = children[i].style || "";
|
||||
node.setAttribute("style", style + "; flex: " + grow + " " + shrink + " " + basis);
|
||||
|
||||
var classes = ["terminal"];
|
||||
if (children[i].type == "vertical") {
|
||||
classes.push("vbox");
|
||||
} else if (children[i].type == "horizontal") {
|
||||
classes.push("hbox");
|
||||
}
|
||||
node.setAttribute("class", classes.join(" "));
|
||||
container.appendChild(node);
|
||||
} else if (children[i].type) {
|
||||
node = document.createElement("div");
|
||||
if (children[i].type == "horizontal") {
|
||||
node.setAttribute("class", "hbox");
|
||||
} else if (children[i].type == "vertical") {
|
||||
node.setAttribute("class", "vbox");
|
||||
}
|
||||
container.appendChild(node);
|
||||
split(node, children[i].children);
|
||||
}
|
||||
function receive(message) {
|
||||
if (message && message.action == "session") {
|
||||
setStatusMessage("...Executing...", kStatusColor, true);
|
||||
gCredentials = message.credentials;
|
||||
updateLogin();
|
||||
} else if (message && message.action == "ready") {
|
||||
setStatusMessage(null);
|
||||
if (window.location.hash) {
|
||||
send({event: "hashChange", hash: window.location.hash});
|
||||
}
|
||||
} else if (message && message.action == "setDocument") {
|
||||
var iframe = document.getElementById("document");
|
||||
iframe.srcdoc = message.content;
|
||||
} else if (message && message.action == "postMessage") {
|
||||
var iframe = document.getElementById("document");
|
||||
iframe.contentWindow.postMessage(message.message, "*");
|
||||
} else if (message && message.action == "ping") {
|
||||
gSocket.send(JSON.stringify({action: "pong"}));
|
||||
} else if (message && message.action == "error") {
|
||||
setStatusMessage(message.error.message + '\n' + message.error.stack, '#f00', false);
|
||||
console.log(message.error);
|
||||
}
|
||||
}
|
||||
|
||||
var gCorkCount = 0;
|
||||
var gCorkLines = [];
|
||||
|
||||
function receive(data) {
|
||||
for (var i in data.lines) {
|
||||
var line = data.lines[i];
|
||||
|
||||
if (line && line[0] && line[0].action == "cork"
|
||||
|| line && line.value && line.value[0].action == "cork") {
|
||||
++gCorkCount;
|
||||
continue;
|
||||
} else if (line && line[0] && line[0].action == "uncork"
|
||||
|| line && line.value && line.value[0].action == "uncork") {
|
||||
if (--gCorkCount <= 0) {
|
||||
receive({lines: gCorkLines});
|
||||
gCorkLines.length = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (gCorkCount > 0) {
|
||||
gCorkLines.push(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
var target = document.getElementsByClassName("terminal")[0].id;
|
||||
if (line && line.terminal) {
|
||||
if (document.getElementById("terminal_" + line.terminal)) {
|
||||
target = "terminal_" + line.terminal;
|
||||
}
|
||||
line = line.value;
|
||||
}
|
||||
|
||||
if (line && line.action == "ping") {
|
||||
gSocket.send(JSON.stringify({action: "pong"}));
|
||||
} else if (line && line.action == "session") {
|
||||
setStatusMessage("...Executing...", kStatusColor, true);
|
||||
gCredentials = line.credentials;
|
||||
updateLogin();
|
||||
} else if (line && line[0] && line[0].action == "ready") {
|
||||
setStatusMessage(null);
|
||||
if (window.location.hash) {
|
||||
send({event: "hashChange", hash: window.location.hash});
|
||||
}
|
||||
} else if (line && line[0] && line[0].action == "notify") {
|
||||
if (window.Notification) {
|
||||
new Notification(line[0].title, line[0].options);
|
||||
}
|
||||
} else if (line && line[0] && line[0].action == "setTitle") {
|
||||
window.document.title = line[0].value;
|
||||
} else if (line && line[0] && line[0].action == "setPrompt") {
|
||||
var prompt = document.getElementById("prompt");
|
||||
while (prompt.firstChild) {
|
||||
prompt.removeChild(prompt.firstChild);
|
||||
}
|
||||
prompt.appendChild(document.createTextNode(line[0].value));
|
||||
} else if (line && line[0] && line[0].action == "setPassword") {
|
||||
var prompt = document.getElementById("input");
|
||||
prompt.setAttribute("type", line[0].value ? "password" : "text");
|
||||
} else if (line && line[0] && line[0].action == "setHash") {
|
||||
window.location.hash = line[0].value;
|
||||
} else if (line && line[0] && line[0].action == "update") {
|
||||
document.getElementById("update").setAttribute("Style", "display: inline");
|
||||
} else if (line && line[0] && line[0].action == "split") {
|
||||
split(document.getElementById("terminals"), line[0].options);
|
||||
} else if (line && line[0] && line[0].action == "postMessageToIframe") {
|
||||
var iframe = document.getElementById("iframe_" + line[0].name);
|
||||
if (iframe) {
|
||||
iframe.contentWindow.postMessage(line[0].message, "*");
|
||||
}
|
||||
} else if (line && line[0] && line[0].action == "setSendKeyEvents") {
|
||||
var value = line[0].value;
|
||||
if (value && !gSendKeyEvents) {
|
||||
window.addEventListener("keydown", keyEvent);
|
||||
window.addEventListener("keypress", keyEvent);
|
||||
window.addEventListener("keyup", keyEvent);
|
||||
} else if (!value && gSendKeyEvents) {
|
||||
window.removeEventListener("keydown", keyEvent);
|
||||
window.removeEventListener("keypress", keyEvent);
|
||||
window.removeEventListener("keyup", keyEvent);
|
||||
}
|
||||
gSendKeyEvents = value;
|
||||
} else if (line && line[0] && line[0].action == "getCurrentPosition") {
|
||||
navigator.geolocation.getCurrentPosition(geolocationPosition, geolocationError, line[0].options);
|
||||
} else if (line && line[0] && line[0].action == "watchPosition") {
|
||||
if (navigator && navigator.geolocation && gGeolocatorWatch === undefined) {
|
||||
gGeolocatorWatch = navigator.geolocation.watchPosition(geolocationPosition, geolocationError, line[0].options);
|
||||
}
|
||||
} else if (line && line[0] && line[0].action == "clearWatch") {
|
||||
if (navigator && navigator.geolocation && gGeolocatorWatch !== undefined) {
|
||||
navigator.geolocation.clearWatch(gGeolocatorWatch);
|
||||
}
|
||||
} else if (line && line[0] && line[0].action == "setSendDeviceOrientationEvents") {
|
||||
let value = line[0].value;
|
||||
if (value && !gSendDeviceOrientationEvents) {
|
||||
window.addEventListener("deviceorientation", deviceOrientation);
|
||||
} else if (!value && gSendDeviceOrientationEvents) {
|
||||
window.removeEventListener("deviceorientation", deviceOrientation);
|
||||
}
|
||||
gSendDeviceOrientationEvents = value;
|
||||
} else {
|
||||
print(document.getElementById(target), line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function geolocationPosition(position) {
|
||||
send({
|
||||
event: 'geolocation',
|
||||
position: {
|
||||
timestamp: position.timestamp,
|
||||
coords: {
|
||||
latitude: position.coords.latitude,
|
||||
longitude: position.coords.longitude,
|
||||
altitude: position.coords.altitude,
|
||||
accuracy: position.coords.accuracy,
|
||||
altitudeAccuracy: position.coords.altitudeAccuracy,
|
||||
heading: position.coords.heading,
|
||||
speed: position.coords.speed,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function geolocationError(error) {
|
||||
send({
|
||||
event: 'geolocation',
|
||||
error: {
|
||||
code: error.code,
|
||||
message: error.message,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function deviceOrientation(event) {
|
||||
send({
|
||||
event: 'deviceorientation',
|
||||
orientation: {
|
||||
alpha: event.alpha,
|
||||
beta: event.beta,
|
||||
gamma: event.gamma,
|
||||
absolute: event.absolute,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
function keyEvent(event) {
|
||||
send({
|
||||
event: "key",
|
||||
@ -458,133 +360,6 @@ function keyEvent(event) {
|
||||
});
|
||||
}
|
||||
|
||||
function autoNewLine(terminal) {
|
||||
terminal.appendChild(document.createElement("br"));
|
||||
}
|
||||
|
||||
function print(terminal, data) {
|
||||
autoNewLine(terminal);
|
||||
printStructured(terminal, data);
|
||||
autoScroll(terminal);
|
||||
}
|
||||
|
||||
function printSvg(container, data, name, namespace) {
|
||||
var node;
|
||||
if (typeof data == "string") {
|
||||
node = document.createTextNode(data);
|
||||
} else {
|
||||
node = document.createElementNS("http://www.w3.org/2000/svg", name);
|
||||
for (var i in data.attributes) {
|
||||
node.setAttribute(i, data.attributes[i]);
|
||||
}
|
||||
if (data.children) {
|
||||
for (var i in data.children) {
|
||||
node.appendChild(printSvg(node, data.children[i], data.children[i].name));
|
||||
}
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function printStructured(container, data) {
|
||||
if (typeof data == "string") {
|
||||
container.appendChild(document.createTextNode(data));
|
||||
} else if (data && data[0] !== undefined) {
|
||||
for (var i in data) {
|
||||
printStructured(container, data[i]);
|
||||
}
|
||||
} else if (data && data.action == "clear") {
|
||||
while (container.firstChild) {
|
||||
container.removeChild(container.firstChild);
|
||||
}
|
||||
} else if (data) {
|
||||
var node;
|
||||
if (data.href) {
|
||||
node = document.createElement("a");
|
||||
node.setAttribute("href", data.href);
|
||||
node.setAttribute("target", data.target || "_blank");
|
||||
} else if (data.iframe) {
|
||||
node = document.createElement("iframe");
|
||||
if (data.src) {
|
||||
node.setAttribute("src", data.src);
|
||||
} else {
|
||||
node.setAttribute("srcdoc", data.iframe);
|
||||
}
|
||||
node.setAttribute("sandbox", "allow-forms allow-scripts allow-top-navigation allow-same-origin");
|
||||
if (data.width !== null) {
|
||||
node.setAttribute("width", data.width || 320);
|
||||
}
|
||||
if (data.height !== null) {
|
||||
node.setAttribute("height", data.height || 240);
|
||||
}
|
||||
if (data.name) {
|
||||
node.setAttribute("id", "iframe_" + data.name);
|
||||
}
|
||||
} else if (data.svg) {
|
||||
node = printSvg(container, data.svg, "svg");
|
||||
} else if (data.image) {
|
||||
node = document.createElement("img");
|
||||
node.setAttribute("src", data.image);
|
||||
} else if (data.input) {
|
||||
node = document.createElement("input");
|
||||
node.setAttribute("type", data.input);
|
||||
if (data.name) {
|
||||
node.name = data.name;
|
||||
}
|
||||
if (data.input == "submit") {
|
||||
node.onclick = submitButton;
|
||||
}
|
||||
} else {
|
||||
node = document.createElement("span");
|
||||
}
|
||||
|
||||
if (data.style) {
|
||||
node.setAttribute("style", data.style);
|
||||
}
|
||||
if (data.class) {
|
||||
node.setAttribute("class", data.class);
|
||||
}
|
||||
var value = data.value || data.href || data.command || "";
|
||||
if (data.input) {
|
||||
node.value = value;
|
||||
} else if (!value && data.message && data.stackTrace) {
|
||||
printStructured(node, data.message);
|
||||
node.appendChild(document.createElement("br"));
|
||||
printStructured(node, data.fileName + ":" + data.lineNumber + ":");
|
||||
node.appendChild(document.createElement("br"));
|
||||
if (data.stackTrace.length) {
|
||||
for (var i = 0; i < data.stackTrace.length; i++) {
|
||||
printStructured(node, data.stackTrace[i]);
|
||||
node.appendChild(document.createElement("br"));
|
||||
}
|
||||
} else {
|
||||
printStructured(node, data.sourceLine);
|
||||
}
|
||||
} else if (value === undefined) {
|
||||
printStructured(node, JSON.stringify(value));
|
||||
} else {
|
||||
printStructured(node, value);
|
||||
}
|
||||
if (data.command) {
|
||||
node.dataset.command = data.command;
|
||||
node.onclick = commandClick;
|
||||
node.setAttribute("class", "command");
|
||||
}
|
||||
container.appendChild(node);
|
||||
} else {
|
||||
printStructured(container, JSON.stringify(data));
|
||||
}
|
||||
}
|
||||
|
||||
function commandClick() {
|
||||
send(this.dataset.command);
|
||||
document.getElementById("input").focus();
|
||||
}
|
||||
|
||||
function autoScroll(terminal) {
|
||||
terminal.scrollTop = terminal.scrollHeight - terminal.clientHeight;
|
||||
}
|
||||
|
||||
function setStatusMessage(message, color, keep) {
|
||||
var node = document.getElementById("status");
|
||||
if (!keep) {
|
||||
@ -594,18 +369,13 @@ function setStatusMessage(message, color, keep) {
|
||||
}
|
||||
if (message) {
|
||||
node.appendChild(document.createTextNode(message));
|
||||
node.setAttribute("style", "display: inline; color: " + (color || kErrorColor));
|
||||
node.setAttribute("style", "display: inline-block; vertical-align: top; white-space: pre; color: " + (color || kErrorColor));
|
||||
}
|
||||
}
|
||||
|
||||
function send(command) {
|
||||
var value = command;
|
||||
if (!command) {
|
||||
value = document.getElementById("input").value;
|
||||
document.getElementById("input").value = "";
|
||||
}
|
||||
function send(value) {
|
||||
try {
|
||||
gSocket.send(JSON.stringify({action: "command", command: value}));
|
||||
gSocket.send(JSON.stringify(value));
|
||||
} catch (error) {
|
||||
setStatusMessage("Send failed: " + error.toString(), kErrorColor);
|
||||
}
|
||||
@ -620,15 +390,7 @@ function updateLogin() {
|
||||
var a = document.createElement("a");
|
||||
if (gCredentials && gCredentials.session) {
|
||||
a.appendChild(document.createTextNode("logout " + gCredentials.session.name));
|
||||
if (gCredentials.session.google) {
|
||||
gapi.load("auth2", function() {
|
||||
gapi.auth2.init();
|
||||
});
|
||||
a.setAttribute("onclick", "logoutGoogle()");
|
||||
a.setAttribute("href", "#");
|
||||
} else {
|
||||
a.setAttribute("href", "/login/logout?return=" + encodeURIComponent(url() + hash()));
|
||||
}
|
||||
a.setAttribute("href", "/login/logout?return=" + encodeURIComponent(url() + hash()));
|
||||
} else {
|
||||
a.appendChild(document.createTextNode("login"));
|
||||
a.setAttribute("href", "/login?return=" + encodeURIComponent(url() + hash()));
|
||||
@ -636,12 +398,6 @@ function updateLogin() {
|
||||
login.appendChild(a);
|
||||
}
|
||||
|
||||
function logoutGoogle() {
|
||||
gapi.auth2.getAuthInstance().signOut().then(function() {
|
||||
window.location.href = "/login/logout?return=" + encodeURIComponent(url() + hash());
|
||||
});
|
||||
}
|
||||
|
||||
var gOriginalInput;
|
||||
function dragHover(event) {
|
||||
event.stopPropagation();
|
||||
@ -731,7 +487,6 @@ function enableDragDrop() {
|
||||
var body = document.body;
|
||||
body.addEventListener("dragover", dragHover);
|
||||
body.addEventListener("dragleave", dragHover);
|
||||
|
||||
body.addEventListener("drop", fileDrop);
|
||||
}
|
||||
|
||||
@ -753,77 +508,42 @@ function blur() {
|
||||
}
|
||||
}
|
||||
|
||||
function onMessage(event) {
|
||||
function message(event) {
|
||||
if (event.data && event.data.event == "resizeMe" && event.data.width && event.data.height) {
|
||||
var iframe = document.getElementById("iframe_" + event.data.name);
|
||||
iframe.setAttribute("width", event.data.width);
|
||||
iframe.setAttribute("height", event.data.height);
|
||||
var node = iframe.parentElement;
|
||||
while (node && !node.classList.contains("terminal")) {
|
||||
node = node.parentElement;
|
||||
}
|
||||
if (node) {
|
||||
autoScroll(node);
|
||||
}
|
||||
} else {
|
||||
send({event: "onWindowMessage", message: event.data});
|
||||
send({event: "message", message: event.data});
|
||||
}
|
||||
}
|
||||
|
||||
function submitButton() {
|
||||
var inputs = document.getElementsByTagName("input");
|
||||
var data = {};
|
||||
for (var i in inputs) {
|
||||
var input = inputs[i];
|
||||
if (input.name) {
|
||||
data[input.name] = input.value;
|
||||
}
|
||||
}
|
||||
send({event: "submit", value: data});
|
||||
}
|
||||
|
||||
function reconnect() {
|
||||
function reconnect(path) {
|
||||
let oldSocket = gSocket;
|
||||
gSocket = null
|
||||
oldSocket.onclose = function() {}
|
||||
oldSocket.onmessage = function() {}
|
||||
oldSocket.close();
|
||||
split(document.getElementById("terminals"), [{name: "terminal_"}]);
|
||||
connectSocket();
|
||||
connectSocket(path);
|
||||
}
|
||||
|
||||
function connectSocket() {
|
||||
function connectSocket(path) {
|
||||
if (!gSocket || gSocket.readyState == gSocket.CLOSED) {
|
||||
setStatusMessage("Connecting...", kStatusColor, true);
|
||||
gSocket = new WebSocket(
|
||||
(window.location.protocol == "https:" ? "wss://" : "ws://")
|
||||
+ window.location.hostname
|
||||
+ (window.location.port.length ? ":" + window.location.port : "")
|
||||
+ "/terminal/socket");
|
||||
+ "/app/socket");
|
||||
gSocket.onopen = function() {
|
||||
setStatusMessage("...Authenticating...", kStatusColor, true);
|
||||
gSocket.send(JSON.stringify({
|
||||
action: "hello",
|
||||
path: window.location.pathname,
|
||||
terminalApi: [
|
||||
['clear'],
|
||||
['notify', 'title', 'options'],
|
||||
['postMessageToIframe', 'name', 'message'],
|
||||
['setHash', 'value'],
|
||||
['setPassword', 'value'],
|
||||
['setPrompt', 'value'],
|
||||
['setTitle', 'value'],
|
||||
['split', 'options'],
|
||||
['setSendKeyEvents', 'value'],
|
||||
|
||||
['getCurrentPosition', 'options'],
|
||||
['watchPosition', 'options'],
|
||||
['clearWatch'],
|
||||
|
||||
['cork'],
|
||||
['uncork'],
|
||||
|
||||
['setSendDeviceOrientationEvents', 'value'],
|
||||
path: path,
|
||||
api: [
|
||||
['setDocument', 'content'],
|
||||
['postMessage', 'message'],
|
||||
['error', 'error'],
|
||||
],
|
||||
}));
|
||||
}
|
||||
@ -836,18 +556,71 @@ function connectSocket() {
|
||||
}
|
||||
}
|
||||
|
||||
function openFile(name) {
|
||||
var newDoc = (name && gFiles[name]) ? gFiles[name].doc : new CodeMirror.Doc("", guessMode(name));
|
||||
var oldDoc = gEditor.swapDoc(newDoc);
|
||||
if (gFiles[gCurrentFile]) {
|
||||
gFiles[gCurrentFile].doc = oldDoc;
|
||||
}
|
||||
gCurrentFile = name;
|
||||
updateFiles();
|
||||
gEditor.focus();
|
||||
}
|
||||
|
||||
function onFileClicked(event) {
|
||||
openFile(event.target.textContent);
|
||||
}
|
||||
|
||||
function updateFiles() {
|
||||
var node = document.getElementById("files");
|
||||
while (node.firstChild) {
|
||||
node.removeChild(node.firstChild);
|
||||
}
|
||||
|
||||
for (var file of Object.keys(gFiles).sort()) {
|
||||
var li = document.createElement("li");
|
||||
li.onclick = onFileClicked;
|
||||
li.appendChild(document.createTextNode(file));
|
||||
if (file == gCurrentFile) {
|
||||
li.classList.add("current");
|
||||
}
|
||||
node.appendChild(li);
|
||||
}
|
||||
|
||||
gEditor.focus();
|
||||
}
|
||||
|
||||
function makeNewFile(name) {
|
||||
gFiles[name] = {
|
||||
doc: new CodeMirror.Doc("", guessMode(name))
|
||||
};
|
||||
openFile(name);
|
||||
}
|
||||
|
||||
function newFile() {
|
||||
var name = prompt("Name of new file:", "file.js");
|
||||
if (name && !gFiles[name]) {
|
||||
makeNewFile(name);
|
||||
}
|
||||
}
|
||||
|
||||
function removeFile() {
|
||||
if (confirm("Remove " + gCurrentFile + "?")) {
|
||||
delete gFiles[gCurrentFile];
|
||||
openFile(Object.keys(gFiles)[0]);
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("load", function() {
|
||||
if (window.Notification) {
|
||||
Notification.requestPermission();
|
||||
}
|
||||
var input = document.getElementById("input");
|
||||
input.addEventListener("keydown", keydown);
|
||||
input.focus();
|
||||
window.addEventListener("hashchange", hashChange);
|
||||
window.addEventListener("focus", focus);
|
||||
window.addEventListener("blur", blur);
|
||||
window.addEventListener("message", onMessage, false);
|
||||
window.addEventListener("message", message, false);
|
||||
window.addEventListener("online", connectSocket);
|
||||
document.getElementById("name").value = window.location.pathname;
|
||||
enableDragDrop();
|
||||
connectSocket();
|
||||
connectSocket(window.location.pathname);
|
||||
});
|
||||
|
427
core/core.js
427
core/core.js
@ -3,9 +3,8 @@
|
||||
require("encoding-indexes");
|
||||
require("encoding");
|
||||
|
||||
var terminal = require("terminal");
|
||||
var auth = require("auth");
|
||||
var network = require("network");
|
||||
var app = require("app");
|
||||
|
||||
var gProcessIndex = 0;
|
||||
var gProcesses = {};
|
||||
@ -51,11 +50,29 @@ function printError(out, error) {
|
||||
}
|
||||
}
|
||||
|
||||
function invoke(handlers, argv) {
|
||||
var promises = [];
|
||||
if (handlers) {
|
||||
for (var i = 0; i < handlers.length; ++i) {
|
||||
try {
|
||||
promises.push(handlers[i](...argv));
|
||||
} catch (error) {
|
||||
handlers.splice(i, 1);
|
||||
i--;
|
||||
promises.push(new Promise(function(resolve, reject) { reject(error); }));
|
||||
}
|
||||
}
|
||||
}
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
function broadcastEvent(eventName, argv) {
|
||||
var promises = [];
|
||||
for (var i in gProcesses) {
|
||||
var process = gProcesses[i];
|
||||
promises.push(invoke(process.eventHandlers[eventName], argv));
|
||||
if (process.eventHandlers[eventName]) {
|
||||
promises.push(invoke(process.eventHandlers[eventName], argv));
|
||||
}
|
||||
}
|
||||
return Promise.all(promises);
|
||||
}
|
||||
@ -75,53 +92,6 @@ function broadcast(message) {
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
function getDatabase(process) {
|
||||
if (!process.database) {
|
||||
File.makeDirectory("data");
|
||||
File.makeDirectory("data/" + process.packageOwner);
|
||||
File.makeDirectory("data/" + process.packageOwner + "/" + process.packageName);
|
||||
File.makeDirectory("data/" + process.packageOwner + "/" + process.packageName + "/db");
|
||||
process.database = new Database("data/" + process.packageOwner + "/" + process.packageName + "/db");
|
||||
}
|
||||
return process.database;
|
||||
}
|
||||
|
||||
function databaseGet(key) {
|
||||
return getDatabase(this).get(key);
|
||||
}
|
||||
|
||||
function databaseSet(key, value) {
|
||||
return getDatabase(this).set(key, value);
|
||||
}
|
||||
|
||||
function databaseRemove(key) {
|
||||
return getDatabase(this).remove(key);
|
||||
}
|
||||
|
||||
function databaseGetAll() {
|
||||
return getDatabase(this).getAll();
|
||||
}
|
||||
|
||||
async function getPackages() {
|
||||
var packages = [];
|
||||
var packageOwners = File.readDirectory("packages/");
|
||||
for (var i = 0; i < packageOwners.length; i++) {
|
||||
if (packageOwners[i].charAt(0) != ".") {
|
||||
var packageNames = File.readDirectory("packages/" + packageOwners[i] + "/");
|
||||
for (var j = 0; j < packageNames.length; j++) {
|
||||
if (packageNames[j].charAt(0) != ".") {
|
||||
packages.push({
|
||||
owner: packageOwners[i],
|
||||
name: packageNames[j],
|
||||
manifest: await getManifest("packages/" + packageOwners[i] + "/" + packageNames[j] + "/" + packageNames[j] + ".js"),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return packages;
|
||||
}
|
||||
|
||||
function getUser(caller, process) {
|
||||
return {
|
||||
name: process.userName,
|
||||
@ -147,7 +117,9 @@ function getUsers(packageOwner, packageName) {
|
||||
}
|
||||
|
||||
function postMessageInternal(from, to, message) {
|
||||
return invoke(to.eventHandlers['onMessage'], [getUser(from, from), message]);
|
||||
if (to.eventHandlers['message']) {
|
||||
return invoke(to.eventHandlers['message'], [getUser(from, from), message]);
|
||||
}
|
||||
}
|
||||
|
||||
function killProcess(process) {
|
||||
@ -156,47 +128,20 @@ function killProcess(process) {
|
||||
}
|
||||
}
|
||||
|
||||
async function getService(service, packageName) {
|
||||
let process = this;
|
||||
let serviceName = process.packageName + '_' + service;
|
||||
let serviceProcess = await getServiceProcess(process.packageOwner, packageName || process.packageName, serviceName);
|
||||
return serviceProcess.ready.then(function() {
|
||||
return {
|
||||
postMessage: postMessageInternal.bind(process, process, serviceProcess),
|
||||
kill: killProcess.bind(process, serviceProcess),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getSessionProcess(packageOwner, packageName, session, options) {
|
||||
var actualOptions = {terminal: true, timeout: kPingInterval};
|
||||
async function getSessionProcessBlob(blobId, session, options) {
|
||||
var actualOptions = {timeout: kPingInterval};
|
||||
if (options) {
|
||||
for (var i in options) {
|
||||
actualOptions[i] = options[i];
|
||||
}
|
||||
}
|
||||
return getProcess(packageOwner, packageName, 'session_' + session, actualOptions);
|
||||
}
|
||||
|
||||
function getServiceProcess(packageOwner, packageName, service, options) {
|
||||
return getProcess(packageOwner, packageName, 'service_' + packageOwner + '_' + packageName + '_' + service, options || {});
|
||||
}
|
||||
|
||||
function badName(name) {
|
||||
var bad = false;
|
||||
if (name) {
|
||||
for (var i = 0; i < name.length; i++) {
|
||||
if ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890-_".indexOf(name.charAt(i)) == -1) {
|
||||
bad = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bad;
|
||||
return getProcessBlob(blobId, 'session_' + session, actualOptions);
|
||||
}
|
||||
|
||||
function readFileUtf8(fileName) {
|
||||
return new TextDecoder("UTF-8").decode(File.readFile(fileName));
|
||||
let data = File.readFile(fileName);
|
||||
data = utf8Decode(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
let gManifestCache = {};
|
||||
@ -235,33 +180,23 @@ async function getManifest(fileName) {
|
||||
return result;
|
||||
}
|
||||
|
||||
async function getProcess(packageOwner, packageName, key, options) {
|
||||
async function getProcessBlob(blobId, key, options) {
|
||||
var process = gProcesses[key];
|
||||
if (!process
|
||||
&& !(options && "create" in options && !options.create)
|
||||
&& !badName(packageOwner)
|
||||
&& !badName(packageName)) {
|
||||
&& !(options && "create" in options && !options.create)) {
|
||||
try {
|
||||
print("Creating task for " + packageName + " " + key);
|
||||
var fileName = "packages/" + packageOwner + "/" + packageName + "/" + packageName + ".js";
|
||||
var manifest = await getManifest(fileName);
|
||||
print("Creating task for " + blobId + " " + key);
|
||||
process = {};
|
||||
process.key = key;
|
||||
process.index = gProcessIndex++;
|
||||
process.userName = options.userName || ('user' + process.index);
|
||||
process.userName = 'user' + process.index;
|
||||
process.credentials = options.credentials || {};
|
||||
process.task = new Task();
|
||||
process.eventHandlers = {};
|
||||
process.packageOwner = packageOwner;
|
||||
process.packageName = packageName;
|
||||
if (options.terminal) {
|
||||
process.terminal = new Terminal();
|
||||
}
|
||||
process.database = null;
|
||||
process.app = new App();
|
||||
process.lastActive = Date.now();
|
||||
process.lastPing = null;
|
||||
process.timeout = options.timeout;
|
||||
process.connections = [];
|
||||
var resolveReady;
|
||||
var rejectReady;
|
||||
process.ready = new Promise(function(resolve, reject) {
|
||||
@ -271,24 +206,12 @@ async function getProcess(packageOwner, packageName, key, options) {
|
||||
gProcesses[key] = process;
|
||||
process.task.onExit = function(exitCode, terminationSignal) {
|
||||
broadcastEvent('onSessionEnd', [getUser(process, process)]);
|
||||
if (process.terminal) {
|
||||
if (terminationSignal) {
|
||||
process.terminal.print("Process terminated with signal " + terminationSignal + ".");
|
||||
} else {
|
||||
process.terminal.print("Process ended with exit code " + exitCode + ".");
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < process.connections.length; i++) {
|
||||
process.connections[i].close();
|
||||
}
|
||||
process.connections.length = 0;
|
||||
process.task = null;
|
||||
delete gProcesses[key];
|
||||
};
|
||||
var imports = {
|
||||
'core': {
|
||||
'broadcast': broadcast.bind(process),
|
||||
'getService': getService.bind(process),
|
||||
'getPackages': getPackages.bind(process),
|
||||
'getUsers': getUsers.bind(process),
|
||||
'register': function(eventName, handler) {
|
||||
if (!process.eventHandlers[eventName]) {
|
||||
@ -297,7 +220,7 @@ async function getProcess(packageOwner, packageName, key, options) {
|
||||
process.eventHandlers[eventName].push(handler);
|
||||
},
|
||||
'unregister': function(eventHandle, handler) {
|
||||
if (process.eventHandlers(eventName)) {
|
||||
if (process.eventHandlers[eventName]) {
|
||||
let index = process.eventHandlers[eventName].indexOf(handler);
|
||||
if (index != -1) {
|
||||
process.eventHandlers[eventName].splice(index, 1);
|
||||
@ -309,97 +232,62 @@ async function getProcess(packageOwner, packageName, key, options) {
|
||||
},
|
||||
'getUser': getUser.bind(null, process, process),
|
||||
'user': getUser(process, process),
|
||||
},
|
||||
'database': {
|
||||
'get': databaseGet.bind(process),
|
||||
'set': databaseSet.bind(process),
|
||||
'remove': databaseRemove.bind(process),
|
||||
'getAll': databaseGetAll.bind(process),
|
||||
},
|
||||
}
|
||||
};
|
||||
if (options.terminal) {
|
||||
imports.terminal = {
|
||||
'print': process.terminal.print.bind(process.terminal),
|
||||
'readLine': process.terminal.readLine.bind(process.terminal),
|
||||
'setEcho': process.terminal.setEcho.bind(process.terminal),
|
||||
'select': process.terminal.select.bind(process.terminal),
|
||||
if (options.api) {
|
||||
imports.app = {};
|
||||
for (let i in options.api) {
|
||||
let api = options.api[i];
|
||||
imports.app[api[0]] = process.app.makeFunction(api);
|
||||
}
|
||||
}
|
||||
process.task.onError = function(error) {
|
||||
try {
|
||||
process.app.send({action: 'error', error: error});
|
||||
} catch(e) {
|
||||
print(e);
|
||||
}
|
||||
};
|
||||
imports.ssb = Object.fromEntries(Object.keys(ssb).map(key => [key, ssb[key].bind(ssb)]));
|
||||
if (process.credentials &&
|
||||
process.credentials.session &&
|
||||
process.credentials.session.name) {
|
||||
imports.database = function(key) {
|
||||
var db = new Database(process.credentials.session.name + ':' + key);
|
||||
return Object.fromEntries(Object.keys(db).map(x => [x, db[x].bind(db)]));
|
||||
};
|
||||
if (options.terminalApi) {
|
||||
for (let i in options.terminalApi) {
|
||||
let api = options.terminalApi[i];
|
||||
imports.terminal[api[0]] = process.terminal.makeFunction(api);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (manifest
|
||||
&& manifest.permissions
|
||||
&& manifest.permissions.indexOf("administration") != -1) {
|
||||
if (getPermissionsForUser(packageOwner).administration) {
|
||||
imports.administration = {
|
||||
'setGlobalSettings': setGlobalSettings.bind(process),
|
||||
'getGlobalSettings': getGlobalSettings.bind(process),
|
||||
'getStatistics': function() { return statistics; },
|
||||
};
|
||||
} else {
|
||||
throw new Error(packageOwner + " does not have right to permission 'administration'.");
|
||||
}
|
||||
}
|
||||
if (manifest
|
||||
&& manifest.permissions
|
||||
&& manifest.permissions.indexOf("network") != -1) {
|
||||
if (getPermissionsForUser(packageOwner).network) {
|
||||
imports.network = {
|
||||
'newConnection': newConnection.bind(process),
|
||||
};
|
||||
} else {
|
||||
throw new Error(packageOwner + " does not have right to permission 'network'.");
|
||||
}
|
||||
}
|
||||
if (manifest && manifest.require) {
|
||||
let source = {};
|
||||
for (let i in manifest.require) {
|
||||
let name = manifest.require[i];
|
||||
source[name] = readFileUtf8("packages/" + process.packageOwner + "/" + name + "/" + name + ".js");
|
||||
}
|
||||
process.task.setRequires(source);
|
||||
}
|
||||
process.task.setImports(imports);
|
||||
print("Activating task");
|
||||
process.task.activate();
|
||||
print("Executing task");
|
||||
await process.task.execute({name: fileName, source: readFileUtf8(fileName)});
|
||||
print("Task ready");
|
||||
let source = await ssb.blobGet(blobId);
|
||||
var appSource = utf8Decode(source);
|
||||
try {
|
||||
var app = JSON.parse(appSource);
|
||||
if (app.type == "tildefriends-app") {
|
||||
var id = app.files["app.js"];
|
||||
var blob = await ssb.blobGet(id);
|
||||
appSource = utf8Decode(blob);
|
||||
await Promise.all(Object.keys(app.files).map(async function(f) {
|
||||
await process.task.loadFile([f, await ssb.blobGet(app.files[f])]);
|
||||
}));
|
||||
}
|
||||
} catch (e) {
|
||||
printError({print: print}, e);
|
||||
}
|
||||
broadcastEvent('onSessionBegin', [getUser(process, process)]);
|
||||
resolveReady(process);
|
||||
if (process.terminal) {
|
||||
process.terminal.print({action: "ready"});
|
||||
if (process.app) {
|
||||
process.app.send({action: "ready"});
|
||||
}
|
||||
await process.task.execute({name: blobId, source: appSource});
|
||||
} catch (error) {
|
||||
printError(process.terminal, error);
|
||||
printError({print: print}, error);
|
||||
rejectReady();
|
||||
}
|
||||
}
|
||||
return process;
|
||||
}
|
||||
|
||||
function updateProcesses(packageOwner, packageName) {
|
||||
for (var i in gProcesses) {
|
||||
var process = gProcesses[i];
|
||||
if (process.packageOwner == packageOwner
|
||||
&& process.packageName == packageName) {
|
||||
try {
|
||||
if (process.terminal) {
|
||||
process.terminal.notifyUpdate();
|
||||
} else {
|
||||
process.task.kill();
|
||||
}
|
||||
} catch (error) {
|
||||
print(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeDirectoryForFile(fileName) {
|
||||
var parts = fileName.split("/");
|
||||
var path = "";
|
||||
@ -429,6 +317,147 @@ try {
|
||||
print("Error loading settings from " + kGlobalSettingsFile + ": " + error);
|
||||
}
|
||||
|
||||
var kStaticFiles = [
|
||||
{uri: '/', path: 'index.html', type: 'text/html; charset=UTF-8'},
|
||||
{uri: '/style.css', path: 'style.css', type: 'text/css; charset=UTF-8'},
|
||||
{uri: '/favicon.png', path: 'favicon.png', type: 'image/png'},
|
||||
{uri: '/client.js', path: 'client.js', type: 'text/javascript; charset=UTF-8'},
|
||||
{uri: '/robots.txt', path: 'robots.txt', type: 'text/plain; charset=UTF-8'},
|
||||
];
|
||||
|
||||
function startsWithBytes(data, bytes) {
|
||||
if (data.byteLength >= bytes.length) {
|
||||
var dataBytes = new Uint8Array(data.slice(0, bytes.length));
|
||||
for (var i = 0; i < bytes.length; i++) {
|
||||
if (dataBytes[i] != bytes[i] || bytes[i] === null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
async function staticFileHandler(request, response, blobId, uri) {
|
||||
for (var i in kStaticFiles) {
|
||||
if (uri === kStaticFiles[i].uri) {
|
||||
var data = File.readFile("core/" + kStaticFiles[i].path);
|
||||
response.writeHead(200, {"Content-Type": kStaticFiles[i].type, "Content-Length": data.byteLength});
|
||||
response.end(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
response.writeHead(404, {"Content-Type": "text/plain; charset=utf-8", "Content-Length": "File not found".length});
|
||||
response.end("File not found");
|
||||
}
|
||||
|
||||
function sendData(response, data) {
|
||||
if (data) {
|
||||
if (startsWithBytes(data, [0xff, 0xd8, 0xff, 0xdb]) ||
|
||||
startsWithBytes(data, [0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01]) ||
|
||||
startsWithBytes(data, [0xff, 0xd8, 0xff, 0xee]) ||
|
||||
startsWithBytes(data, [0xff, 0xd8, 0xff, 0xe1, null, null, 0x45, 0x78, 0x69, 0x66, 0x00, 0x00])) {
|
||||
response.writeHead(200, {"Content-Type": "image/jpeg", "Content-Length": data.byteLength});
|
||||
response.end(data);
|
||||
} else if (startsWithBytes(data, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])) {
|
||||
response.writeHead(200, {"Content-Type": "image/png", "Content-Length": data.byteLength});
|
||||
response.end(data);
|
||||
} else if (startsWithBytes(data, [0x47, 0x49, 0x46, 0x38, 0x37, 0x61]) ||
|
||||
startsWithBytes(data, [0x47, 0x49, 0x46, 0x38, 0x39, 0x61])) {
|
||||
response.writeHead(200, {"Content-Type": "image/gif", "Content-Length": data.byteLength});
|
||||
response.end(data);
|
||||
} else {
|
||||
response.writeHead(200, {"Content-Type": "text/javascript; charset=utf-8", "Content-Length": data.byteLength});
|
||||
response.end(data);
|
||||
}
|
||||
} else {
|
||||
response.writeHead(404, {"Content-Type": "text/plain; charset=utf-8", "Content-Length": "File not found".length});
|
||||
response.end("File not found");
|
||||
}
|
||||
}
|
||||
|
||||
async function blobHandler(request, response, blobId, uri) {
|
||||
var found = false;
|
||||
if (!found) {
|
||||
for (var i in kStaticFiles) {
|
||||
if (uri === kStaticFiles[i].uri) {
|
||||
found = true;
|
||||
var data = File.readFile("core/" + kStaticFiles[i].path);
|
||||
response.writeHead(200, {"Content-Type": kStaticFiles[i].type, "Content-Length": data.byteLength});
|
||||
response.end(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!uri) {
|
||||
response.writeHead(301, {"Location": blobId + "/"});
|
||||
response.end(data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
var process;
|
||||
if (uri == "/view") {
|
||||
var data;
|
||||
if (match = /^\/\~(\w+)\/(\w+)$/.exec(blobId)) {
|
||||
var id = await new Database(match[1]).get('path:' + match[2]);
|
||||
if (id) {
|
||||
data = await ssb.blobGet(id);
|
||||
if (match[3]) {
|
||||
var app = JSON.parse(data);
|
||||
data = app.files[match[3]];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
data = await ssb.blobGet(blobId);
|
||||
}
|
||||
sendData(response, data);
|
||||
} else if (uri == "/save") {
|
||||
let newBlobId = await ssb.blobStore(request.body);
|
||||
|
||||
var match;
|
||||
if (match = /^\/\~(\w+)\/(\w+)$/.exec(blobId)) {
|
||||
var user = match[1];
|
||||
var app = match[2];
|
||||
var credentials = auth.query(request.headers);
|
||||
if (!credentials || !credentials.session || credentials.session.name != user) {
|
||||
response.writeHead(401, {"Content-Type": "text/plain; charset=utf-8"});
|
||||
response.end("401 Unauthorized");
|
||||
return;
|
||||
}
|
||||
var database = new Database(user);
|
||||
await database.set('path:' + app, newBlobId);
|
||||
}
|
||||
|
||||
response.writeHead(200, {"Content-Type": "text/plain; charset=utf-8"});
|
||||
response.end("/" + newBlobId);
|
||||
} else {
|
||||
var data;
|
||||
if (match = /^\/\~(\w+)\/(\w+)$/.exec(blobId)) {
|
||||
var db = new Database(match[1]);
|
||||
var id = await db.get('path:' + match[2]);
|
||||
if (id) {
|
||||
data = utf8Decode(await ssb.blobGet(id));
|
||||
var app = JSON.parse(data);
|
||||
print(JSON.stringify(app));
|
||||
data = app.files[uri.substring(1)];
|
||||
data = await ssb.blobGet(data);
|
||||
}
|
||||
}
|
||||
sendData(response, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ssb.onBroadcastsChanged = function() {
|
||||
broadcastEvent('onBroadcastsChanged', []);
|
||||
}
|
||||
|
||||
ssb.onConnectionsChanged = function() {
|
||||
broadcastEvent('onConnectionsChanged', []);
|
||||
}
|
||||
|
||||
var auth = require("auth");
|
||||
var httpd = require("httpd");
|
||||
httpd.all("/login", auth.handler);
|
||||
@ -437,12 +466,20 @@ httpd.all("", function(request, response) {
|
||||
if (request.uri === "/" || request.uri === "") {
|
||||
response.writeHead(303, {"Location": gGlobalSettings.index, "Content-Length": "0"});
|
||||
return response.end();
|
||||
} else if (match = /^\/terminal(\/.*)/.exec(request.uri)) {
|
||||
return terminal.handler(request, response, null, null, match[1]);
|
||||
} else if (match = /^\/\~([^\/]+)\/([^\/]+)(.*)/.exec(request.uri)) {
|
||||
return terminal.handler(request, response, match[1], match[2], match[3]);
|
||||
} else if (match = /^(\/~[^\/]+\/[^\/]+)(\/?.*)$/.exec(request.uri)) {
|
||||
return blobHandler(request, response, match[1], match[2]);
|
||||
} else if (match = /^\/(&[^\.]*\.\w+)(\/?.*)/.exec(request.uri)) {
|
||||
return blobHandler(request, response, match[1], match[2]);
|
||||
} else if (match = /^\/static(\/.*)/.exec(request.uri)) {
|
||||
return staticFileHandler(request, response, null, match[1]);
|
||||
} else if (match = /^(.*)(\/save)$/.exec(request.uri)) {
|
||||
return blobHandler(request, response, match[1], match[2]);
|
||||
} else if (match = /^\/trace$/.exec(request.uri)) {
|
||||
var data = trace();
|
||||
response.writeHead(404, {"Content-Type": "application/json; charset=utf-8", "Content-Length": data.length.toString()});
|
||||
return response.end(data);
|
||||
} else if (request.uri == "/robots.txt") {
|
||||
return terminal.handler(request, response, null, null, request.uri);
|
||||
return blobHandler(request, response, null, request.uri);
|
||||
} else if ((match = /^\/.well-known\/(.*)/.exec(request.uri)) && request.uri.indexOf("..") == -1) {
|
||||
var data = File.readFile("data/global/.well-known/" + match[1]);
|
||||
if (data) {
|
||||
@ -458,4 +495,4 @@ httpd.all("", function(request, response) {
|
||||
return response.end(data);
|
||||
}
|
||||
});
|
||||
httpd.registerSocketHandler("/terminal/socket", terminal.socket);
|
||||
httpd.registerSocketHandler("/app/socket", app.socket);
|
||||
|
@ -212,11 +212,17 @@ function handleWebSocketRequest(request, response, client) {
|
||||
packet.push((message.length >> 8) & 0xff);
|
||||
packet.push(message.length & 0xff);
|
||||
} else {
|
||||
var high = 0; //(message.length / (1 ** 32)) & 0xffffffff;
|
||||
var low = message.length & 0xffffffff;
|
||||
packet.push((mask ? (1 << 7) : 0) | 127);
|
||||
packet.push((message.length >> 24) & 0xff);
|
||||
packet.push((message.length >> 16) & 0xff);
|
||||
packet.push((message.length >> 8) & 0xff);
|
||||
packet.push(message.length & 0xff);
|
||||
packet.push((high >> 24) & 0xff);
|
||||
packet.push((high >> 16) & 0xff);
|
||||
packet.push((high >> 8) & 0xff);
|
||||
packet.push((high >> 0) & 0xff);
|
||||
packet.push((low >> 24) & 0xff);
|
||||
packet.push((low >> 16) & 0xff);
|
||||
packet.push((low >> 8) & 0xff);
|
||||
packet.push(low & 0xff);
|
||||
}
|
||||
|
||||
var array = new Uint8Array(packet.length + message.length);
|
||||
@ -235,7 +241,7 @@ function handleWebSocketRequest(request, response, client) {
|
||||
newBuffer.set(data, buffer.length);
|
||||
buffer = newBuffer;
|
||||
|
||||
if (buffer.length >= 2) {
|
||||
while (buffer.length >= 2) {
|
||||
var bits0 = buffer[0];
|
||||
var bits1 = buffer[1];
|
||||
if (bits1 & (1 << 7) == 0) {
|
||||
@ -291,6 +297,8 @@ function handleWebSocketRequest(request, response, client) {
|
||||
}
|
||||
frame = new Uint8Array(0);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -444,24 +452,22 @@ function handleConnection(client) {
|
||||
|
||||
var kBacklog = 8;
|
||||
var kHost = "0.0.0.0"
|
||||
var kHttpPort = gGlobalSettings.httpPort || 12345;
|
||||
var kHttpsPort = gGlobalSettings.httpsPort || null;
|
||||
|
||||
var socket = new Socket();
|
||||
socket.bind(kHost, kHttpPort).then(function() {
|
||||
socket.bind(kHost, tildefriends.http_port).then(function() {
|
||||
var listenResult = socket.listen(kBacklog, function() {
|
||||
socket.accept().then(handleConnection).catch(function(error) {
|
||||
logError("[" + new Date() + "] " + error);
|
||||
logError("[" + new Date() + "] accept error " + error);
|
||||
});
|
||||
});
|
||||
}).catch(function(error) {
|
||||
logError("[" + new Date() + "] " + error);
|
||||
logError("[" + new Date() + "] bind error " + error);
|
||||
});
|
||||
|
||||
if (kHttpsPort) {
|
||||
if (tildefriends.https_port) {
|
||||
var tls = {};
|
||||
var secureSocket = new Socket();
|
||||
secureSocket.bind(kHost, kHttpsPort).then(function() {
|
||||
secureSocket.bind(kHost, tildefriends.https_port).then(function() {
|
||||
return secureSocket.listen(kBacklog, function() {
|
||||
return secureSocket.accept().then(function(client) {
|
||||
handleConnection(client);
|
||||
@ -496,7 +502,7 @@ if (kHttpsPort) {
|
||||
});
|
||||
});
|
||||
}).catch(function(error) {
|
||||
logError("[" + new Date() + "] " + error);
|
||||
logError("[" + new Date() + "] bind error " + error);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Tilde Friends</title>
|
||||
<link type="text/css" rel="stylesheet" href="/terminal/style.css">
|
||||
<link type="image/png" rel="shortcut icon" href="/terminal/favicon.png">
|
||||
<link type="text/css" rel="stylesheet" href="/static/style.css">
|
||||
<link type="image/png" rel="shortcut icon" href="/static/favicon.png">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<!--HEAD-->
|
||||
</head>
|
||||
@ -13,31 +13,39 @@
|
||||
<span id="title">Tilde Friends</span>
|
||||
<a href="/">home</a>
|
||||
<a href="#" onclick="event.preventDefault(); edit()">edit</a>
|
||||
<a href="$(VIEW_SOURCE)">view source</a>
|
||||
<a href="/~cory/about">about</a>
|
||||
<a href="/trace">trace</a>
|
||||
<span id="status"></span>
|
||||
<span id="update">update available! <a href="">refresh</a> to update</span>
|
||||
<span id="login"></span>
|
||||
</div>
|
||||
<div id="content" class="hbox" style="flex: 1 1; width: 100%">
|
||||
<div id="editPane" style="flex: 0 0 50%; display: none; flex-flow: column; overflow: auto">
|
||||
<div id="editPane" class="vbox" style="display: none">
|
||||
<div class="navigation">
|
||||
<input type="button" id="closeEditor" name="closeEditor" value="Close" onclick="closeEditor()">
|
||||
<input type="button" id="save" name="save" value="Save" onclick="save()">
|
||||
<input type="button" id="saveAs" name="saveAs" value="Save As" onclick="saveAs()">
|
||||
<input type="text" id="name" name="name"></input>
|
||||
<input type="checkbox" id="run" name="run" checked><label for="run">Restart after save</label>
|
||||
<input type="button" id="revert" name="revert" value="Revert to Saved" onclick="revert()">
|
||||
<a id="latest" href="">Latest</a>
|
||||
</div>
|
||||
<div class="hbox" style="height: 100%">
|
||||
<div id="filesPane">
|
||||
<ul id="files">
|
||||
</ul>
|
||||
<br>
|
||||
<div><button onclick="newFile()">New File</button></div>
|
||||
<div><button onclick="removeFile()">Remove File</button></div>
|
||||
</div>
|
||||
<div id="docPane" style="display: flex; flex: 1 1 50%; flex-flow: column">
|
||||
<div style="flex: 1 1 50%; position: relative">
|
||||
<textarea id="editor" class="main"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<textarea id="editor" class="main"></textarea>
|
||||
</div>
|
||||
<div class="vbox" style="flex: 1 0 50%; overflow: auto">
|
||||
<div id="terminals" class="vbox"><div id="terminal_" class="terminal" style="flex: 1 1"></div></div>
|
||||
<div class="input">
|
||||
<span id="prompt">></span>
|
||||
<input type='text' id='input'>
|
||||
</div>
|
||||
<iframe id="document" sandbox="allow-forms allow-scripts allow-top-navigation allow-modals" style="width: 100%; height: 100%; border: 0"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/terminal/client.js"></script>
|
||||
<script src="/static/client.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
239
core/isaac.js
239
core/isaac.js
@ -1,239 +0,0 @@
|
||||
/* ----------------------------------------------------------------------
|
||||
* Copyright (c) 2012 Yves-Marie K. Rinquin
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* ISAAC is a cryptographically secure pseudo-random number generator
|
||||
* (or CSPRNG for short) designed by Robert J. Jenkins Jr. in 1996 and
|
||||
* based on RC4. It is designed for speed and security.
|
||||
*
|
||||
* ISAAC's informations & analysis:
|
||||
* http://burtleburtle.net/bob/rand/isaac.html
|
||||
* ISAAC's implementation details:
|
||||
* http://burtleburtle.net/bob/rand/isaacafa.html
|
||||
*
|
||||
* ISAAC succesfully passed TestU01
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* Usage:
|
||||
* <script src="isaac.js"></script>
|
||||
* var random_number = isaac.random();
|
||||
*
|
||||
* Output: [ 0x00000000; 0xffffffff]
|
||||
* [-2147483648; 2147483647]
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* js string (ucs-2/utf16) to a 32-bit integer (utf-8 chars, little-endian) array */
|
||||
String.prototype.toIntArray = function() {
|
||||
var w1, w2, u, r4 = [], r = [], i = 0;
|
||||
var s = this + '\0\0\0'; // pad string to avoid discarding last chars
|
||||
var l = s.length - 1;
|
||||
|
||||
while(i < l) {
|
||||
w1 = s.charCodeAt(i++);
|
||||
w2 = s.charCodeAt(i+1);
|
||||
if (w1 < 0x0080) {
|
||||
// 0x0000 - 0x007f code point: basic ascii
|
||||
r4.push(w1);
|
||||
} else if(w1 < 0x0800) {
|
||||
// 0x0080 - 0x07ff code point
|
||||
r4.push(((w1 >>> 6) & 0x1f) | 0xc0);
|
||||
r4.push(((w1 >>> 0) & 0x3f) | 0x80);
|
||||
} else if((w1 & 0xf800) != 0xd800) {
|
||||
// 0x0800 - 0xd7ff / 0xe000 - 0xffff code point
|
||||
r4.push(((w1 >>> 12) & 0x0f) | 0xe0);
|
||||
r4.push(((w1 >>> 6) & 0x3f) | 0x80);
|
||||
r4.push(((w1 >>> 0) & 0x3f) | 0x80);
|
||||
} else if(((w1 & 0xfc00) == 0xd800)
|
||||
&& ((w2 & 0xfc00) == 0xdc00)) {
|
||||
// 0xd800 - 0xdfff surrogate / 0x10ffff - 0x10000 code point
|
||||
u = ((w2 & 0x3f) | ((w1 & 0x3f) << 10)) + 0x10000;
|
||||
r4.push(((u >>> 18) & 0x07) | 0xf0);
|
||||
r4.push(((u >>> 12) & 0x3f) | 0x80);
|
||||
r4.push(((u >>> 6) & 0x3f) | 0x80);
|
||||
r4.push(((u >>> 0) & 0x3f) | 0x80);
|
||||
i++;
|
||||
} else {
|
||||
// invalid char
|
||||
}
|
||||
/* add integer (four utf-8 value) to array */
|
||||
if(r4.length > 3) {
|
||||
// little endian
|
||||
r.push((r4.shift() << 0) | (r4.shift() << 8) |
|
||||
(r4.shift() << 16) | (r4.shift() << 24));
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* isaac module pattern */
|
||||
var isaac = (function(){
|
||||
|
||||
/* private: internal states */
|
||||
var m = Array(256), // internal memory
|
||||
acc = 0, // accumulator
|
||||
brs = 0, // last result
|
||||
cnt = 0, // counter
|
||||
r = Array(256), // result array
|
||||
gnt = 0; // generation counter
|
||||
|
||||
seed(Math.random() * 0xffffffff);
|
||||
|
||||
/* private: 32-bit integer safe adder */
|
||||
function add(x, y) {
|
||||
var lsb = (x & 0xffff) + (y & 0xffff);
|
||||
var msb = (x >>> 16) + (y >>> 16) + (lsb >>> 16);
|
||||
return (msb << 16) | (lsb & 0xffff);
|
||||
}
|
||||
|
||||
/* public: initialisation */
|
||||
function reset() {
|
||||
acc = brs = cnt = 0;
|
||||
for(var i = 0; i < 256; ++i)
|
||||
m[i] = r[i] = 0;
|
||||
gnt = 0;
|
||||
}
|
||||
|
||||
/* public: seeding function */
|
||||
function seed(s) {
|
||||
var a, b, c, d, e, f, g, h, i;
|
||||
|
||||
/* seeding the seeds of love */
|
||||
a = b = c = d =
|
||||
e = f = g = h = 0x9e3779b9; /* the golden ratio */
|
||||
|
||||
if(s && typeof(s) === 'string')
|
||||
s = s.toIntArray();
|
||||
|
||||
if(s && typeof(s) === 'number') {
|
||||
s = [s];
|
||||
}
|
||||
|
||||
if(s instanceof Array) {
|
||||
reset();
|
||||
for(i = 0; i < s.length; i++)
|
||||
r[i & 0xff] += (typeof(s[i]) === 'number') ? s[i] : 0;
|
||||
}
|
||||
|
||||
/* private: seed mixer */
|
||||
function seed_mix() {
|
||||
a ^= b << 11; d = add(d, a); b = add(b, c);
|
||||
b ^= c >>> 2; e = add(e, b); c = add(c, d);
|
||||
c ^= d << 8; f = add(f, c); d = add(d, e);
|
||||
d ^= e >>> 16; g = add(g, d); e = add(e, f);
|
||||
e ^= f << 10; h = add(h, e); f = add(f, g);
|
||||
f ^= g >>> 4; a = add(a, f); g = add(g, h);
|
||||
g ^= h << 8; b = add(b, g); h = add(h, a);
|
||||
h ^= a >>> 9; c = add(c, h); a = add(a, b);
|
||||
}
|
||||
|
||||
for(i = 0; i < 4; i++) /* scramble it */
|
||||
seed_mix();
|
||||
|
||||
for(i = 0; i < 256; i += 8) {
|
||||
if(s) { /* use all the information in the seed */
|
||||
a = add(a, r[i + 0]); b = add(b, r[i + 1]);
|
||||
c = add(c, r[i + 2]); d = add(d, r[i + 3]);
|
||||
e = add(e, r[i + 4]); f = add(f, r[i + 5]);
|
||||
g = add(g, r[i + 6]); h = add(h, r[i + 7]);
|
||||
}
|
||||
seed_mix();
|
||||
/* fill in m[] with messy stuff */
|
||||
m[i + 0] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d;
|
||||
m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h;
|
||||
}
|
||||
if(s) {
|
||||
/* do a second pass to make all of the seed affect all of m[] */
|
||||
for(i = 0; i < 256; i += 8) {
|
||||
a = add(a, m[i + 0]); b = add(b, m[i + 1]);
|
||||
c = add(c, m[i + 2]); d = add(d, m[i + 3]);
|
||||
e = add(e, m[i + 4]); f = add(f, m[i + 5]);
|
||||
g = add(g, m[i + 6]); h = add(h, m[i + 7]);
|
||||
seed_mix();
|
||||
/* fill in m[] with messy stuff (again) */
|
||||
m[i + 0] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d;
|
||||
m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h;
|
||||
}
|
||||
}
|
||||
|
||||
prng(); /* fill in the first set of results */
|
||||
gnt = 256; /* prepare to use the first set of results */;
|
||||
}
|
||||
|
||||
/* public: isaac generator, n = number of run */
|
||||
function prng(n){
|
||||
var i, x, y;
|
||||
|
||||
n = (n && typeof(n) === 'number')
|
||||
? Math.abs(Math.floor(n)) : 1;
|
||||
|
||||
while(n--) {
|
||||
cnt = add(cnt, 1);
|
||||
brs = add(brs, cnt);
|
||||
|
||||
for(i = 0; i < 256; i++) {
|
||||
switch(i & 3) {
|
||||
case 0: acc ^= acc << 13; break;
|
||||
case 1: acc ^= acc >>> 6; break;
|
||||
case 2: acc ^= acc << 2; break;
|
||||
case 3: acc ^= acc >>> 16; break;
|
||||
}
|
||||
acc = add(m[(i + 128) & 0xff], acc); x = m[i];
|
||||
m[i] = y = add(m[(x >>> 2) & 0xff], add(acc, brs));
|
||||
r[i] = brs = add(m[(y >>> 10) & 0xff], x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* public: return a random number between */
|
||||
function rand() {
|
||||
if(!gnt--) {
|
||||
prng(); gnt = 255;
|
||||
}
|
||||
return r[gnt];
|
||||
}
|
||||
|
||||
/* public: return internals in an object*/
|
||||
function internals(){
|
||||
return {a: acc, b: brs, c: cnt, m: m, r: r};
|
||||
}
|
||||
|
||||
/* return class object */
|
||||
return {
|
||||
'reset': reset,
|
||||
'seed': seed,
|
||||
'prng': prng,
|
||||
'rand': rand,
|
||||
'internals': internals
|
||||
};
|
||||
})(); /* declare and execute */
|
||||
|
||||
/* public: output*/
|
||||
isaac.random = function() {
|
||||
return 0.5 + this.rand() * 2.3283064365386963e-10; // 2^-32
|
||||
}
|
||||
|
||||
exports.rand = isaac.rand;
|
103
core/network.js
103
core/network.js
@ -1,103 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
function Connection() {
|
||||
this.socket = null;
|
||||
this.buffer = null;
|
||||
this.onReadCallback = null;
|
||||
this.onErrorCallback = null;
|
||||
this.tlsContext = null;
|
||||
this._exported = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
Connection.prototype.connect = function(host, port) {
|
||||
let connection = this;
|
||||
connection.close();
|
||||
connection.socket = new Socket();
|
||||
connection.socket.noDelay = true;
|
||||
return connection.socket.connect(host, port).then(function() {
|
||||
connection.buffer = "";
|
||||
return Promise.all([
|
||||
connection.socket.onError(function(error) {
|
||||
if (connection.onErrorCallback) {
|
||||
connection.onErrorCallback(error);
|
||||
}
|
||||
connection.close();
|
||||
}),
|
||||
connection.socket.read(function(data) {
|
||||
if (connection.onReadCallback) {
|
||||
connection.onReadCallback(data);
|
||||
} else {
|
||||
connection.buffer += data;
|
||||
}
|
||||
}),
|
||||
]);
|
||||
});
|
||||
};
|
||||
|
||||
Connection.prototype.isConnected = function() {
|
||||
return this.socket && this.socket.isConnected;
|
||||
};
|
||||
|
||||
Connection.prototype.read = function(callback) {
|
||||
this.onReadCallback = callback;
|
||||
if (this.buffer) {
|
||||
callback(this.buffer);
|
||||
}
|
||||
this.buffer = "";
|
||||
};
|
||||
|
||||
Connection.prototype.onError = function(callback) {
|
||||
this.onErrorCallback = callback;
|
||||
};
|
||||
|
||||
Connection.prototype.write = function(data) {
|
||||
return this.socket.write(data);
|
||||
};
|
||||
|
||||
Connection.prototype.close = function() {
|
||||
let socket = this.socket;
|
||||
this.socket = null;
|
||||
if (socket) {
|
||||
return socket.close();
|
||||
}
|
||||
};
|
||||
|
||||
Connection.prototype.startTls = function() {
|
||||
return this.socket.startTls(this.tlsContext);
|
||||
};
|
||||
|
||||
Connection.prototype.getPeerCertificate = function() {
|
||||
return this.socket.peerCertificate;
|
||||
};
|
||||
|
||||
Connection.prototype.addTrustedCertificate = function(certificate) {
|
||||
if (!this.tlsContext) {
|
||||
this.tlsContext = new TlsContext();
|
||||
}
|
||||
return this.tlsContext.addTrustedCertificate(certificate);
|
||||
};
|
||||
|
||||
Connection.prototype.exported = function() {
|
||||
if (!this._exported) {
|
||||
this._exported = {
|
||||
isConnected: this.isConnected.bind(this),
|
||||
connect: this.connect.bind(this),
|
||||
startTls: this.startTls.bind(this),
|
||||
write: this.write.bind(this),
|
||||
read: this.read.bind(this),
|
||||
onError: this.onError.bind(this),
|
||||
close: this.close.bind(this),
|
||||
getPeerCertificate: this.getPeerCertificate.bind(this),
|
||||
addTrustedCertificate: this.addTrustedCertificate.bind(this),
|
||||
};
|
||||
}
|
||||
return this._exported;
|
||||
};
|
||||
|
||||
function newConnection() {
|
||||
let process = this;
|
||||
let connection = new Connection();
|
||||
process.connections.push(connection);
|
||||
return connection.exported();
|
||||
}
|
@ -20,25 +20,10 @@ body {
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
#terminals {
|
||||
flex: 1;
|
||||
flex-flow: column;
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
#logo {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.terminal {
|
||||
outline: none;
|
||||
white-space: pre-wrap;
|
||||
resize: none;
|
||||
overflow: auto;
|
||||
height: auto;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.hbox {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@ -49,30 +34,6 @@ body {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.terminal > img {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
a:link, .command {
|
||||
color: #268bd2;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a:visited, .command:visited {
|
||||
color: #6c71c4;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a:hover, .command:hover {
|
||||
color: #2aa198;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a:active, .command:active {
|
||||
color: #dc322f;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.input {
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
@ -100,6 +61,11 @@ a:active, .command:active {
|
||||
.CodeMirror {
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.cm-tab {
|
||||
@ -179,3 +145,18 @@ a:active, .command:active {
|
||||
.blue { color: #268bd2; }
|
||||
.cyan { color: #2aa198; }
|
||||
.green { color: #859900; }
|
||||
|
||||
#files {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#files > li {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
#files > li.current {
|
||||
font-weight: bold;
|
||||
background-color: #2aa198;
|
||||
}
|
||||
|
314
core/terminal.js
314
core/terminal.js
@ -1,314 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
var kStaticFiles = [
|
||||
{uri: '', path: 'index.html', type: 'text/html; charset=UTF-8'},
|
||||
{uri: '/style.css', path: 'style.css', type: 'text/css; charset=UTF-8'},
|
||||
{uri: '/favicon.png', path: 'favicon.png', type: 'image/png'},
|
||||
{uri: '/client.js', path: 'client.js', type: 'text/javascript; charset=UTF-8'},
|
||||
{uri: '/robots.txt', path: 'robots.txt', type: 'text/plain; charset=UTF-8'},
|
||||
];
|
||||
|
||||
var auth = require('auth');
|
||||
var form = require('form');
|
||||
|
||||
function Terminal() {
|
||||
this._index = 0;
|
||||
this._firstLine = 0;
|
||||
this._sentIndex = -1;
|
||||
this._lines = [];
|
||||
this._lastRead = null;
|
||||
this._lastWrite = null;
|
||||
this._echo = true;
|
||||
this._readLine = null;
|
||||
this._selected = null;
|
||||
this._onOutput = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
Terminal.kBacklog = 64;
|
||||
|
||||
Terminal.prototype.readOutput = function(callback) {
|
||||
this._onOutput = callback;
|
||||
this.dispatch();
|
||||
}
|
||||
|
||||
Terminal.prototype.dispatch = function(data) {
|
||||
var payload = this._lines.slice(Math.max(0, this._sentIndex + 1 - this._firstLine));
|
||||
if (data) {
|
||||
payload.push(data);
|
||||
}
|
||||
if (this._onOutput && (this._sentIndex < this._index - 1 || data)) {
|
||||
this._sentIndex = this._index - 1;
|
||||
this._onOutput({lines: payload});
|
||||
}
|
||||
}
|
||||
|
||||
Terminal.prototype.print = function() {
|
||||
var data = arguments;
|
||||
if (this._selected) {
|
||||
data = {
|
||||
terminal: this._selected,
|
||||
value: data
|
||||
};
|
||||
}
|
||||
this._lines.push(data);
|
||||
this._index++;
|
||||
if (this._lines.length >= Terminal.kBacklog * 2) {
|
||||
this._firstLine = this._index - Terminal.kBacklog;
|
||||
this._lines = this._lines.slice(this._lines.length - Terminal.kBacklog);
|
||||
}
|
||||
this.dispatch();
|
||||
this._lastWrite = new Date();
|
||||
}
|
||||
|
||||
Terminal.prototype.notifyUpdate = function() {
|
||||
this.print({action: "update"});
|
||||
}
|
||||
|
||||
Terminal.prototype.select = function(name) {
|
||||
this._selected = name;
|
||||
}
|
||||
|
||||
Terminal.prototype.ping = function() {
|
||||
this.dispatch({action: "ping"});
|
||||
}
|
||||
|
||||
Terminal.prototype.setEcho = function(echo) {
|
||||
this._echo = echo;
|
||||
}
|
||||
|
||||
Terminal.prototype.readLine = function() {
|
||||
var self = this;
|
||||
if (self._readLine) {
|
||||
self._readLine[1]();
|
||||
}
|
||||
return new Promise(function(resolve, reject) {
|
||||
self._readLine = [resolve, reject];
|
||||
});
|
||||
}
|
||||
|
||||
Terminal.prototype.makeFunction = function(api) {
|
||||
let self = this;
|
||||
return function() {
|
||||
let message = {action: api[0]};
|
||||
for (let i = 1; i < api.length; i++) {
|
||||
message[api[i]] = arguments[i - 1];
|
||||
}
|
||||
self.print(message);
|
||||
}
|
||||
}
|
||||
|
||||
function invoke(handlers, argv) {
|
||||
var promises = [];
|
||||
if (handlers) {
|
||||
for (var i = 0; i < handlers.length; ++i) {
|
||||
try {
|
||||
promises.push(handlers[i].apply({}, argv));
|
||||
} catch (error) {
|
||||
handlers.splice(i, 1);
|
||||
i--;
|
||||
promises.push(new Promise(function(resolve, reject) { reject(error); }));
|
||||
}
|
||||
}
|
||||
}
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
function socket(request, response, client) {
|
||||
var process;
|
||||
|
||||
var options = {};
|
||||
var credentials = auth.query(request.headers);
|
||||
if (credentials && credentials.session) {
|
||||
options.userName = credentials.session.name;
|
||||
}
|
||||
options.credentials = credentials;
|
||||
|
||||
response.onMessage = async function(event) {
|
||||
if (event.opCode == 0x1 || event.opCode == 0x2) {
|
||||
var message;
|
||||
try {
|
||||
message = JSON.parse(event.data);
|
||||
} catch (error) {
|
||||
print("ERROR", error, event.data, event.data.length, event.opCode);
|
||||
return;
|
||||
}
|
||||
if (message.action == "hello") {
|
||||
var packageOwner;
|
||||
var packageName;
|
||||
var match;
|
||||
if (match = /^\/\~([^\/]+)\/([^\/]+)(.*)/.exec(message.path)) {
|
||||
packageOwner = match[1];
|
||||
packageName = match[2];
|
||||
}
|
||||
response.send(JSON.stringify({lines: [{action: "session", credentials: credentials}]}), 0x1);
|
||||
|
||||
options.terminalApi = message.terminalApi || [];
|
||||
var sessionId = makeSessionId();
|
||||
process = await getSessionProcess(packageOwner, packageName, sessionId, options);
|
||||
process.terminal.readOutput(function(message) {
|
||||
response.send(JSON.stringify(message), 0x1);
|
||||
});
|
||||
|
||||
var ping = function() {
|
||||
var now = Date.now();
|
||||
var again = true;
|
||||
if (now - process.lastActive < process.timeout) {
|
||||
// Active.
|
||||
} else if (process.lastPing > process.lastActive) {
|
||||
// We lost them.
|
||||
process.task.kill();
|
||||
again = false;
|
||||
} else {
|
||||
// Idle. Ping them.
|
||||
response.send("", 0x9);
|
||||
process.lastPing = now;
|
||||
}
|
||||
|
||||
if (again) {
|
||||
setTimeout(ping, process.timeout);
|
||||
}
|
||||
}
|
||||
|
||||
if (process.timeout > 0) {
|
||||
setTimeout(ping, process.timeout);
|
||||
}
|
||||
} else if (message.action == "command") {
|
||||
var command = message.command;
|
||||
var eventName = 'unknown';
|
||||
if (typeof command == "string") {
|
||||
if (process.terminal._echo) {
|
||||
process.terminal.print("> " + command);
|
||||
}
|
||||
if (process.terminal._readLine) {
|
||||
let promise = process.terminal._readLine;
|
||||
process.terminal._readLine = null;
|
||||
promise[0](command);
|
||||
}
|
||||
eventName = 'onInput';
|
||||
} else if (command.event) {
|
||||
eventName = command.event;
|
||||
}
|
||||
return invoke(process.eventHandlers[eventName], [command]).catch(function(error) {
|
||||
process.terminal.print(error);
|
||||
});
|
||||
}
|
||||
} else if (event.opCode == 0x8) {
|
||||
// Close.
|
||||
process.task.kill();
|
||||
response.send(event.data, 0x8);
|
||||
} else if (event.opCode == 0xa) {
|
||||
// PONG
|
||||
}
|
||||
|
||||
if (process) {
|
||||
process.lastActive = Date.now();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function handler(request, response, packageOwner, packageName, uri) {
|
||||
var found = false;
|
||||
|
||||
if (badName(packageOwner) || badName(packageName)) {
|
||||
var data = "File not found";
|
||||
response.writeHead(404, {"Content-Type": "text/plain; charset=utf-8", "Content-Length": data.length});
|
||||
response.end(data);
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
for (var i in kStaticFiles) {
|
||||
if (uri === kStaticFiles[i].uri) {
|
||||
found = true;
|
||||
var data = File.readFile("core/" + kStaticFiles[i].path);
|
||||
if (kStaticFiles[i].type.indexOf("text/") == 0) {
|
||||
data = new TextDecoder("UTF-8").decode(data);
|
||||
if (kStaticFiles[i].uri == "") {
|
||||
if (gGlobalSettings && gGlobalSettings['google-signin-client_id']) {
|
||||
data = data.replace("<!--HEAD-->", `
|
||||
<script src="https://apis.google.com/js/platform.js" async defer></script>
|
||||
<meta name="google-signin-client_id" content="${gGlobalSettings['google-signin-client_id']}">`);
|
||||
}
|
||||
data = data.replace("$(VIEW_SOURCE)", "/~" + packageOwner + "/" + packageName + "/view");
|
||||
}
|
||||
data = new TextEncoder("UTF-8").encode(data);
|
||||
}
|
||||
response.writeHead(200, {"Content-Type": kStaticFiles[i].type, "Content-Length": data.length});
|
||||
response.end(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
var process;
|
||||
if (uri === "/view") {
|
||||
var data = File.readFile("packages/" + packageOwner + "/" + packageName + "/" + packageName + ".js");
|
||||
if (data) {
|
||||
response.writeHead(200, {"Content-Type": "text/javascript; charset=utf-8", "Content-Length": data.length});
|
||||
response.end(data);
|
||||
} else {
|
||||
response.writeHead(404, {"Content-Type": "text/plain; charset=utf-8", "Content-Length": "File not found".length});
|
||||
response.end("File not found");
|
||||
}
|
||||
} else if (uri == "/save") {
|
||||
var credentials = auth.query(request.headers);
|
||||
var userName = credentials && credentials.session && credentials.session.name ? credentials.session.name : "guest";
|
||||
if (badName(packageName)) {
|
||||
response.writeHead(403, {"Content-Type": "text/plain; charset=utf-8"});
|
||||
response.end("Invalid package name: " + packageName);
|
||||
} else if (badName(userName)) {
|
||||
response.writeHead(403, {"Content-Type": "text/plain; charset=utf-8"});
|
||||
response.end("Invalid user name: " + userName);
|
||||
} else {
|
||||
File.makeDirectory("packages/" + userName);
|
||||
File.makeDirectory("packages/" + userName + "/" + packageName);
|
||||
if (!File.writeFile("packages/" + userName + "/" + packageName + "/" + packageName + ".js", request.body || "")) {
|
||||
response.writeHead(200, {"Content-Type": "text/plain; charset=utf-8"});
|
||||
response.end("/~" + userName + "/" + packageName);
|
||||
updateProcesses(userName, packageName);
|
||||
} else {
|
||||
response.writeHead(500, {"Content-Type": "text/plain; charset=utf-8"});
|
||||
response.end("Problem saving: " + packageName);
|
||||
}
|
||||
}
|
||||
} else if (uri === "/submit") {
|
||||
var process = await getServiceProcess(packageOwner, packageName, "submit");
|
||||
process.lastActive = Date.now();
|
||||
return process.ready.then(function() {
|
||||
var payload = form.decodeForm(request.body, form.decodeForm(request.query));
|
||||
return invoke(process.eventHandlers['onSubmit'], [payload]).then(function() {
|
||||
response.writeHead(200, {
|
||||
"Content-Type": "text/plain; charset=utf-8",
|
||||
"Content-Length": "0",
|
||||
"Cache-Control": "no-cache, no-store, must-revalidate",
|
||||
"Pragma": "no-cache",
|
||||
"Expires": "0",
|
||||
});
|
||||
return response.end("");
|
||||
});
|
||||
});
|
||||
} else if (uri === "/atom") {
|
||||
var process = await getServiceProcess(packageOwner, packageName, "atom");
|
||||
process.lastActive = Date.now();
|
||||
return process.ready.then(function() {
|
||||
var payload = form.decodeForm(request.body, form.decodeForm(request.query));
|
||||
return invoke(process.eventHandlers['onAtom'], [payload]).then(function(content) {
|
||||
var atomContent = content.join();
|
||||
response.writeHead(200, {
|
||||
"Content-Type": "application/atom+xml; charset=utf-8",
|
||||
"Content-Length": atomContent.length.toString(),
|
||||
"Cache-Control": "no-cache, no-store, must-revalidate",
|
||||
"Pragma": "no-cache",
|
||||
"Expires": "0",
|
||||
});
|
||||
return response.end(atomContent);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exports.handler = handler;
|
||||
exports.socket = socket;
|
106
deps/base64c/.gitignore
vendored
Normal file
106
deps/base64c/.gitignore
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Linker output
|
||||
*.ilk
|
||||
*.map
|
||||
*.exp
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
*.su
|
||||
*.idb
|
||||
*.pdb
|
||||
|
||||
# Kernel Module Compile Results
|
||||
*.mod*
|
||||
*.cmd
|
||||
.tmp_versions/
|
||||
modules.order
|
||||
Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
|
||||
# http://www.gnu.org/software/automake
|
||||
Makefile
|
||||
Makefile.in
|
||||
/ar-lib
|
||||
/mdate-sh
|
||||
/py-compile
|
||||
/test-driver
|
||||
/ylwrap
|
||||
|
||||
# http://www.gnu.org/software/autoheader
|
||||
config.h
|
||||
# http://www.gnu.org/software/autoconf
|
||||
|
||||
autom4te.cache
|
||||
/autoscan.log
|
||||
/autoscan-*.log
|
||||
/aclocal.m4
|
||||
/compile
|
||||
/config.guess
|
||||
/config.h.in
|
||||
/config.log
|
||||
/config.status
|
||||
/config.sub
|
||||
/configure
|
||||
/configure.scan
|
||||
/depcomp
|
||||
/install-sh
|
||||
/missing
|
||||
/stamp-h1
|
||||
|
||||
# https://www.gnu.org/software/libtool/
|
||||
|
||||
/ltmain.sh
|
||||
|
||||
# http://www.gnu.org/software/texinfo
|
||||
|
||||
/texinfo.tex
|
||||
|
||||
# http://www.gnu.org/software/m4/
|
||||
|
||||
m4/libtool.m4
|
||||
m4/ltoptions.m4
|
||||
m4/ltsugar.m4
|
||||
m4/ltversion.m4
|
||||
m4/lt~obsolete.m4
|
||||
|
||||
# vim
|
||||
*.swp
|
||||
|
||||
# project specific
|
||||
test/gen
|
||||
test/test[0-9]*
|
||||
test/.deps
|
29
deps/base64c/LICENSE
vendored
Normal file
29
deps/base64c/LICENSE
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2018, Sean Hanna
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* 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.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
2
deps/base64c/Makefile.am
vendored
Normal file
2
deps/base64c/Makefile.am
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
SUBDIRS = src test
|
60
deps/base64c/README.md
vendored
Normal file
60
deps/base64c/README.md
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
# base64c
|
||||
This is primarily just a fork of a base64 decoder from the FreeBSD codebase. It has received a few modifications:
|
||||
* removed all allocations, you are expected to pass in a buffer that has sufficient space and you will get an error (-1) if you run out of space
|
||||
* replaced a dynamically generated lookup table with a hardcoded lookup table
|
||||
* wrote my own unit tests, i'm sure there are tests for freebsd somewhere but i didn't find them
|
||||
|
||||
# Embedding
|
||||
This code is primarily intended to be dropped into an existing code base ( or perhaps using submodules). To do that:
|
||||
|
||||
* grab include/base64c.h
|
||||
* grab src/base64c.h
|
||||
|
||||
# Usage
|
||||
|
||||
Call base64c_encoding_length() to calculate how big a buffer you need to encode a string. It's somewhere around 4 times the size of the input string. This length includes a null terminator.
|
||||
|
||||
```c
|
||||
char input_string[256];
|
||||
|
||||
size_t new_len = base64c_encoding_length( strlen(input_string));
|
||||
|
||||
unsigned char *buffer = (unsigned char*)malloc(new_len);
|
||||
```
|
||||
|
||||
Call base64c_encode() to actually encode your input string as base64. It will write to the buffer and return how many characters were written. If there was an error it will return -1.
|
||||
|
||||
```c
|
||||
size_t output_length = base64c_encode(input_string, strlen(input_string), buffer, new_len);
|
||||
|
||||
if (output_length == -1) {
|
||||
int x = 1/0; // ERROR!
|
||||
}
|
||||
```
|
||||
|
||||
Call base64c_decoding_length() to calculate how big a buffer you need to decode. It comes out to about half the size. This number isn't always exact, but it is close to within a byte or two.
|
||||
|
||||
```c
|
||||
size_t decode_len = base64c_decoding_length( strlen(buffer) );
|
||||
|
||||
unsigned char *decoded = (unsigned char*)malloc( decode_len );
|
||||
```
|
||||
|
||||
Call base64c_decode() to decode an encoded base64 string. It will write to the buffer and return how many characters were written. IF there was an error it will return -1. If the string contains invalid number of characters, or has any characters that are not part of the base64 character set an error will be returned.
|
||||
|
||||
# Building
|
||||
|
||||
You need to bootstrap all the autoconf tools by running ./autogen.sh
|
||||
|
||||
You need to have autoconf installed to do this.
|
||||
|
||||
Once bootstrapped run ./configure
|
||||
|
||||
# Tests
|
||||
|
||||
There are tests in the test/ subfolder. They will be built automatically. There is no special test runner. You can run each of the test cases manually to check whether the code is working properly.
|
||||
|
||||
# References
|
||||
|
||||
(http://web.mit.edu/freebsd/head/contrib/wpa/src/utils/base64.c)
|
||||
(https://github.com/freebsd/freebsd/blob/master/contrib/wpa/src/utils/base64.c)
|
3
deps/base64c/autogen.sh
vendored
Normal file
3
deps/base64c/autogen.sh
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
aclocal && automake --gnu --add-missing && autoconf
|
22
deps/base64c/configure.ac
vendored
Normal file
22
deps/base64c/configure.ac
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
BASE64C_VERSION=0.5
|
||||
AC_PREREQ([2.69])
|
||||
AC_INIT(base64c, 0.5, hannasm@gmail.com)
|
||||
AM_INIT_AUTOMAKE(base64c, 0.5)
|
||||
AC_CONFIG_SRCDIR([include/base64c.h])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
|
||||
# Checks for libraries.
|
||||
|
||||
# Checks for header files.
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_TYPE_SIZE_T
|
||||
|
||||
# Checks for library functions.
|
||||
|
||||
AC_OUTPUT(Makefile src/Makefile test/Makefile)
|
42
deps/base64c/include/base64c.h
vendored
Normal file
42
deps/base64c/include/base64c.h
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef base64cC_H
|
||||
#define base64cC_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* base64c_encoding_length - calculate length to allocate for encode
|
||||
* @len: Length of input string
|
||||
* Returns: number of bytes required to base64c encode, this includes room for '\0' terminator
|
||||
*/
|
||||
size_t base64c_encoding_length(size_t len);
|
||||
|
||||
/**
|
||||
* base64c_decoding_length - calculate length to allocate for decode
|
||||
* @len: Length of (base64 encoded) input string
|
||||
* Returns: maximum number of bytes required to decode
|
||||
*/
|
||||
size_t base64c_decoding_length(size_t inlen);
|
||||
|
||||
/**
|
||||
* base64c_encode - base64c encode
|
||||
* @src: Data to be encoded
|
||||
* @len: Length of the data to be encoded
|
||||
* @out: Mutable output buffer destination, all encoded bytes will be written to the destination
|
||||
* @out_len: length of output buffer
|
||||
* Returns: number of bytes written, or -1 if there was an error
|
||||
*/
|
||||
size_t base64c_encode(const unsigned char *src, size_t len, unsigned char* out, const size_t out_len);
|
||||
|
||||
/**
|
||||
* base64c_decode - base64c decode
|
||||
* @src: Data to be decoded
|
||||
* @len: Length of the data to be decoded
|
||||
* @out_len: Pointer to output length variable
|
||||
* Returns: Allocated buffer of out_len bytes of decoded data,
|
||||
* or %NULL on failure
|
||||
*
|
||||
* Caller is responsible for freeing the returned buffer.
|
||||
*/
|
||||
size_t base64c_decode(const unsigned char *src, size_t len, unsigned char *out, const size_t out_len);
|
||||
#endif
|
3
deps/base64c/src/Makefile.am
vendored
Normal file
3
deps/base64c/src/Makefile.am
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
CFLAGS = --pednatic -Wall -stdc99 -O2
|
||||
LDFLAGS =
|
||||
|
139
deps/base64c/src/base64c.c
vendored
Normal file
139
deps/base64c/src/base64c.c
vendored
Normal file
@ -0,0 +1,139 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* Base64 encoding/decoding (RFC1341)
|
||||
* Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
static const unsigned char base64c_table[65] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
static const unsigned char base64c_dtable[256] = {
|
||||
/*000*/0x80,/*001*/0x80,/*002*/0x80,/*003*/0x80,/*004*/0x80,/*005*/0x80,/*006*/0x80,/*007*/0x80,/*008*/0x80,/*009*/0x80,/*010*/0x80,/*011*/0x80,/*012*/0x80,/*013*/0x80,/*014*/0x80,/*015*/0x80,/*016*/0x80,/*017*/0x80,/*018*/0x80,/*019*/0x80,
|
||||
/*020*/0x80,/*021*/0x80,/*022*/0x80,/*023*/0x80,/*024*/0x80,/*025*/0x80,/*026*/0x80,/*027*/0x80,/*028*/0x80,/*029*/0x80,/*030*/0x80,/*031*/0x80,/*032*/0x80,/*033*/0x80,/*034*/0x80,/*035*/0x80,/*036*/0x80,/*037*/0x80,/*038*/0x80,/*039*/0x80,
|
||||
/*040*/0x80,/*041*/0x80,/*042*/0x80,/*043*/0x3e,/*044*/0x80,/*045*/0x80,/*046*/0x80,/*047*/0x3f,/*048*/0x34,/*049*/0x35,/*050*/0x36,/*051*/0x37,/*052*/0x38,/*053*/0x39,/*054*/0x3a,/*055*/0x3b,/*056*/0x3c,/*057*/0x3d,/*058*/0x80,/*059*/0x80,
|
||||
/*060*/0x80,/*061*/0x00,/*062*/0x80,/*063*/0x80,/*064*/0x80,/*065*/0x00,/*066*/0x01,/*067*/0x02,/*068*/0x03,/*069*/0x04,/*070*/0x05,/*071*/0x06,/*072*/0x07,/*073*/0x08,/*074*/0x09,/*075*/0x0a,/*076*/0x0b,/*077*/0x0c,/*078*/0x0d,/*079*/0x0e,
|
||||
/*080*/0x0f,/*081*/0x10,/*082*/0x11,/*083*/0x12,/*084*/0x13,/*085*/0x14,/*086*/0x15,/*087*/0x16,/*088*/0x17,/*089*/0x18,/*090*/0x19,/*091*/0x80,/*092*/0x80,/*093*/0x80,/*094*/0x80,/*095*/0x80,/*096*/0x80,/*097*/0x1a,/*098*/0x1b,/*099*/0x1c,
|
||||
/*100*/0x1d,/*101*/0x1e,/*102*/0x1f,/*103*/0x20,/*104*/0x21,/*105*/0x22,/*106*/0x23,/*107*/0x24,/*108*/0x25,/*109*/0x26,/*110*/0x27,/*111*/0x28,/*112*/0x29,/*113*/0x2a,/*114*/0x2b,/*115*/0x2c,/*116*/0x2d,/*117*/0x2e,/*118*/0x2f,/*119*/0x30,
|
||||
/*120*/0x31,/*121*/0x32,/*122*/0x33,/*123*/0x80,/*124*/0x80,/*125*/0x80,/*126*/0x80,/*127*/0x80,/*128*/0x80,/*129*/0x80,/*130*/0x80,/*131*/0x80,/*132*/0x80,/*133*/0x80,/*134*/0x80,/*135*/0x80,/*136*/0x80,/*137*/0x80,/*138*/0x80,/*139*/0x80,
|
||||
/*140*/0x80,/*141*/0x80,/*142*/0x80,/*143*/0x80,/*144*/0x80,/*145*/0x80,/*146*/0x80,/*147*/0x80,/*148*/0x80,/*149*/0x80,/*150*/0x80,/*151*/0x80,/*152*/0x80,/*153*/0x80,/*154*/0x80,/*155*/0x80,/*156*/0x80,/*157*/0x80,/*158*/0x80,/*159*/0x80,
|
||||
/*160*/0x80,/*161*/0x80,/*162*/0x80,/*163*/0x80,/*164*/0x80,/*165*/0x80,/*166*/0x80,/*167*/0x80,/*168*/0x80,/*169*/0x80,/*170*/0x80,/*171*/0x80,/*172*/0x80,/*173*/0x80,/*174*/0x80,/*175*/0x80,/*176*/0x80,/*177*/0x80,/*178*/0x80,/*179*/0x80,
|
||||
/*180*/0x80,/*181*/0x80,/*182*/0x80,/*183*/0x80,/*184*/0x80,/*185*/0x80,/*186*/0x80,/*187*/0x80,/*188*/0x80,/*189*/0x80,/*190*/0x80,/*191*/0x80,/*192*/0x80,/*193*/0x80,/*194*/0x80,/*195*/0x80,/*196*/0x80,/*197*/0x80,/*198*/0x80,/*199*/0x80,
|
||||
/*200*/0x80,/*201*/0x80,/*202*/0x80,/*203*/0x80,/*204*/0x80,/*205*/0x80,/*206*/0x80,/*207*/0x80,/*208*/0x80,/*209*/0x80,/*210*/0x80,/*211*/0x80,/*212*/0x80,/*213*/0x80,/*214*/0x80,/*215*/0x80,/*216*/0x80,/*217*/0x80,/*218*/0x80,/*219*/0x80,
|
||||
/*220*/0x80,/*221*/0x80,/*222*/0x80,/*223*/0x80,/*224*/0x80,/*225*/0x80,/*226*/0x80,/*227*/0x80,/*228*/0x80,/*229*/0x80,/*230*/0x80,/*231*/0x80,/*232*/0x80,/*233*/0x80,/*234*/0x80,/*235*/0x80,/*236*/0x80,/*237*/0x80,/*238*/0x80,/*239*/0x80,
|
||||
/*240*/0x80,/*241*/0x80,/*242*/0x80,/*243*/0x80,/*244*/0x80,/*245*/0x80,/*246*/0x80,/*247*/0x80,/*248*/0x80,/*249*/0x80,/*250*/0x80,/*251*/0x80,/*252*/0x80,/*253*/0x80,/*254*/0x80,/*255*/0x00,
|
||||
};
|
||||
|
||||
size_t base64c_encoding_length(size_t len) {
|
||||
size_t olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */
|
||||
olen++; /* nul termination */
|
||||
if (olen < len)
|
||||
return 0; /* integer overflow */
|
||||
return olen;
|
||||
}
|
||||
|
||||
size_t base64c_encode(const unsigned char *src, size_t len,
|
||||
unsigned char* out, const size_t out_len)
|
||||
{
|
||||
unsigned char *pos;
|
||||
const unsigned char *end, *in;
|
||||
const unsigned char *out_end = out + out_len;
|
||||
|
||||
end = src + len;
|
||||
in = src;
|
||||
pos = out;
|
||||
|
||||
if (out_len < base64c_encoding_length(len)) { return -1; }
|
||||
|
||||
while (end - in >= 3 ) {
|
||||
*pos++ = base64c_table[in[0] >> 2];
|
||||
*pos++ = base64c_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
|
||||
*pos++ = base64c_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
|
||||
*pos++ = base64c_table[in[2] & 0x3f];
|
||||
in += 3;
|
||||
}
|
||||
|
||||
if (end - in) {
|
||||
*pos++ = base64c_table[in[0] >> 2];
|
||||
|
||||
if (end - in == 1) {
|
||||
*pos++ = base64c_table[(in[0] & 0x03) << 4];
|
||||
*pos++ = '=';
|
||||
} else {
|
||||
*pos++ = base64c_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
|
||||
*pos++ = base64c_table[(in[1] & 0x0f) << 2];
|
||||
}
|
||||
*pos++ = '=';
|
||||
}
|
||||
|
||||
*pos = '\0';
|
||||
|
||||
return out_len - (out_end-pos);
|
||||
}
|
||||
|
||||
size_t base64c_decoding_length(size_t inlen) {
|
||||
return inlen / 4 * 3;
|
||||
}
|
||||
|
||||
size_t base64c_decode(const unsigned char *src, size_t len, unsigned char *out, const size_t out_len)
|
||||
{
|
||||
if (out == NULL) { return 0; }
|
||||
if (out_len <= 0) { return 0; }
|
||||
|
||||
unsigned char *pos, block[4], tmp;
|
||||
size_t i, count;
|
||||
int pad = 0;
|
||||
|
||||
if (len == 0 ){
|
||||
*out = '\0';
|
||||
return 1;
|
||||
}
|
||||
if (len % 4) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pos = out;
|
||||
count = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (src[i] == '=') { pad++; }
|
||||
tmp = base64c_dtable[src[i]];
|
||||
|
||||
if (tmp == 0x80) { return -1; }
|
||||
|
||||
block[count] = tmp;
|
||||
count++;
|
||||
if (count == 4) {
|
||||
switch (pad) {
|
||||
case 0:
|
||||
if ((pos - out) + 3 > out_len) {
|
||||
return -1;
|
||||
}
|
||||
*pos++ = (block[0] << 2) | (block[1] >> 4);
|
||||
*pos++ = (block[1] << 4) | (block[2] >> 2);
|
||||
*pos++ = (block[2] << 6) | block[3];
|
||||
break;
|
||||
case 1:
|
||||
if ((pos - out) + 2 > out_len || i + 1 > len) {
|
||||
return -1;
|
||||
}
|
||||
*pos++ = (block[0] << 2) | (block[1] >> 4);
|
||||
*pos++ = (block[1] << 4) | (block[2] >> 2);
|
||||
break;
|
||||
case 2:
|
||||
if ((pos - out) + 1 > out_len || i + 1 > len) {
|
||||
return -1;
|
||||
}
|
||||
*pos++ = (block[0] << 2) | (block[1] >> 4);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return pos - out;
|
||||
}
|
16
deps/base64c/test/Makefile.am
vendored
Normal file
16
deps/base64c/test/Makefile.am
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
CFLAGS = --pedantic -Wall -std=c99 -g -ggdb
|
||||
LDFLAGS =
|
||||
|
||||
bin_PROGRAMS = test001 test002 test003 test004 \
|
||||
test005 test006 test007 test008 \
|
||||
gen
|
||||
|
||||
test001_SOURCES = test001.c ../src/base64c.c
|
||||
test002_SOURCES = test002.c ../src/base64c.c
|
||||
test003_SOURCES = test003.c ../src/base64c.c
|
||||
test004_SOURCES = test004.c ../src/base64c.c
|
||||
test005_SOURCES = test005.c ../src/base64c.c
|
||||
test006_SOURCES = test006.c ../src/base64c.c
|
||||
test007_SOURCES = test007.c ../src/base64c.c
|
||||
test008_SOURCES = test008.c ../src/base64c.c
|
||||
gen_SOURCES = gen.c
|
22
deps/base64c/test/gen.c
vendored
Normal file
22
deps/base64c/test/gen.c
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static const unsigned char base64_table[65] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
int main() {
|
||||
unsigned char out[256];
|
||||
|
||||
memset(out, 0x80, 255);
|
||||
for (int i = 0; i < 64; i++) {
|
||||
out[base64_table[i]] = i;
|
||||
}
|
||||
out['='] = 0;
|
||||
|
||||
printf("static const unsigned char base64c_dtable[256] = {");
|
||||
for (int i = 0; i < 256; i++) {
|
||||
if (i% 20==0) { printf("\n"); }
|
||||
printf("/*%03d*/0x%02x,", i, out[i]);
|
||||
}
|
||||
printf("\n};");
|
||||
}
|
36
deps/base64c/test/test001.c
vendored
Normal file
36
deps/base64c/test/test001.c
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
#include "../include/base64c.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
unsigned char in[12] = "Hello World";
|
||||
size_t in_len = 11;
|
||||
unsigned char enc[32];
|
||||
size_t enc_len = 32;
|
||||
unsigned char out[12];
|
||||
size_t out_len = 12;
|
||||
|
||||
printf("Encoding %lu - %s\n", in_len, in);
|
||||
|
||||
size_t enc_result = base64c_encode(in, in_len, enc, enc_len);
|
||||
|
||||
printf("Encoded %lu - %s\n", enc_result, enc);
|
||||
|
||||
size_t dec_result = base64c_decode(enc, enc_result, out, out_len);
|
||||
|
||||
if ((long)dec_result < 0) {
|
||||
printf("Decode failed with code %ld\n", (long)dec_result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Decoded %lu - %s\n", dec_result, out);
|
||||
|
||||
if (dec_result != in_len) {
|
||||
printf("in length %ld not equal to out length %ld", in_len, dec_result);
|
||||
return 3;
|
||||
}
|
||||
if (strncmp((char*)in, (char*)out, in_len)) {
|
||||
printf("roundtrip encoding failed\n");
|
||||
return 2;
|
||||
}
|
||||
}
|
37
deps/base64c/test/test002.c
vendored
Normal file
37
deps/base64c/test/test002.c
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
#include "../include/base64c.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
unsigned char in[11] = "Hello Worl";
|
||||
size_t in_len = 10;
|
||||
unsigned char enc[32];
|
||||
size_t enc_len = 32;
|
||||
unsigned char out[12];
|
||||
size_t out_len = 12;
|
||||
|
||||
printf("Encoding %lu - %s\n", in_len, in);
|
||||
|
||||
size_t enc_result = base64c_encode(in, in_len, enc, enc_len);
|
||||
|
||||
printf("Encoded %lu - %s\n", enc_result, enc);
|
||||
|
||||
size_t dec_result = base64c_decode(enc, enc_result, out, out_len);
|
||||
|
||||
if ((long)dec_result < 0) {
|
||||
printf("Decode failed with code %ld\n", (long)dec_result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Decoded %lu - %s\n", dec_result, out);
|
||||
|
||||
if (dec_result != in_len) {
|
||||
printf("in length %ld not equal to out length %ld", in_len, dec_result);
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (strncmp((char*)in, (char*)out, in_len)) {
|
||||
printf("roundtrip encoding failed\n");
|
||||
return 2;
|
||||
}
|
||||
}
|
37
deps/base64c/test/test003.c
vendored
Normal file
37
deps/base64c/test/test003.c
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
#include "../include/base64c.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
unsigned char in[10] = "Hello Wor";
|
||||
size_t in_len = 9;
|
||||
unsigned char enc[32];
|
||||
size_t enc_len = 32;
|
||||
unsigned char out[12];
|
||||
size_t out_len = 12;
|
||||
|
||||
printf("Encoding %lu - %s\n", in_len, in);
|
||||
|
||||
size_t enc_result = base64c_encode(in, in_len, enc, enc_len);
|
||||
|
||||
printf("Encoded %lu - %s\n", enc_result, enc);
|
||||
|
||||
size_t dec_result = base64c_decode(enc, enc_result, out, out_len);
|
||||
|
||||
if ((long)dec_result < 0) {
|
||||
printf("Decode failed with code %ld\n", (long)dec_result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Decoded %lu - %s\n", dec_result, out);
|
||||
|
||||
if (dec_result != in_len) {
|
||||
printf("in length %ld not equal to out length %ld", in_len, dec_result);
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (strncmp((char*)in, (char*)out, in_len)) {
|
||||
printf("roundtrip encoding failed\n");
|
||||
return 2;
|
||||
}
|
||||
}
|
37
deps/base64c/test/test004.c
vendored
Normal file
37
deps/base64c/test/test004.c
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
#include "../include/base64c.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
unsigned char in[10] = "Hello Wo";
|
||||
size_t in_len = 8;
|
||||
unsigned char enc[32];
|
||||
size_t enc_len = 32;
|
||||
unsigned char out[12];
|
||||
size_t out_len = 12;
|
||||
|
||||
printf("Encoding %lu - %s\n", in_len, in);
|
||||
|
||||
size_t enc_result = base64c_encode(in, in_len, enc, enc_len);
|
||||
|
||||
printf("Encoded %lu - %s\n", enc_result, enc);
|
||||
|
||||
size_t dec_result = base64c_decode(enc, enc_result, out, out_len);
|
||||
|
||||
if ((long)dec_result < 0) {
|
||||
printf("Decode failed with code %ld\n", (long)dec_result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Decoded %lu - %s\n", dec_result, out);
|
||||
|
||||
if (dec_result != in_len) {
|
||||
printf("in length %ld not equal to out length %ld", in_len, dec_result);
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (strncmp((char*)in, (char*)out, in_len)) {
|
||||
printf("roundtrip encoding failed\n");
|
||||
return 2;
|
||||
}
|
||||
}
|
36
deps/base64c/test/test005.c
vendored
Normal file
36
deps/base64c/test/test005.c
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
#include "../include/base64c.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
unsigned char in[13] = "Hello Worlds";
|
||||
size_t in_len = 12;
|
||||
unsigned char enc[32];
|
||||
size_t enc_len = 32;
|
||||
unsigned char out[13];
|
||||
size_t out_len = 13;
|
||||
|
||||
printf("Encoding %lu - %s\n", in_len, in);
|
||||
|
||||
size_t enc_result = base64c_encode(in, in_len, enc, enc_len);
|
||||
|
||||
printf("Encoded %lu - %s\n", enc_result, enc);
|
||||
|
||||
size_t dec_result = base64c_decode(enc, enc_result, out, out_len);
|
||||
|
||||
if ((long)dec_result < 0) {
|
||||
printf("Decode failed with code %ld\n", (long)dec_result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Decoded %lu - %s\n", dec_result, out);
|
||||
|
||||
if (dec_result != in_len) {
|
||||
printf("in length %ld not equal to out length %ld", in_len, dec_result);
|
||||
return 3;
|
||||
}
|
||||
if (strncmp((char*)in, (char*)out, in_len)) {
|
||||
printf("roundtrip encoding failed\n");
|
||||
return 2;
|
||||
}
|
||||
}
|
36
deps/base64c/test/test006.c
vendored
Normal file
36
deps/base64c/test/test006.c
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
#include "../include/base64c.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
unsigned char in[14] = "Hello Worldsy";
|
||||
size_t in_len = 13;
|
||||
unsigned char enc[32];
|
||||
size_t enc_len = 32;
|
||||
unsigned char out[15];
|
||||
size_t out_len = 15;
|
||||
|
||||
printf("Encoding %lu - %s\n", in_len, in);
|
||||
|
||||
size_t enc_result = base64c_encode(in, in_len, enc, enc_len);
|
||||
|
||||
printf("Encoded %lu - %s\n", enc_result, enc);
|
||||
|
||||
size_t dec_result = base64c_decode(enc, enc_result, out, out_len);
|
||||
|
||||
if ((long)dec_result < 0) {
|
||||
printf("Decode failed with code %ld\n", (long)dec_result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Decoded %lu - %s\n", dec_result, out);
|
||||
|
||||
if (dec_result != in_len) {
|
||||
printf("in length %ld not equal to out length %ld", in_len, dec_result);
|
||||
return 3;
|
||||
}
|
||||
if (strncmp((char*)in, (char*)out, in_len)) {
|
||||
printf("roundtrip encoding failed\n");
|
||||
return 2;
|
||||
}
|
||||
}
|
36
deps/base64c/test/test007.c
vendored
Normal file
36
deps/base64c/test/test007.c
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
#include "../include/base64c.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
unsigned char in[15] = "Hello World of";
|
||||
size_t in_len = 14;
|
||||
unsigned char enc[32];
|
||||
size_t enc_len = 32;
|
||||
unsigned char out[15];
|
||||
size_t out_len = 15;
|
||||
|
||||
printf("Encoding %lu - %s\n", in_len, in);
|
||||
|
||||
size_t enc_result = base64c_encode(in, in_len, enc, enc_len);
|
||||
|
||||
printf("Encoded %lu - %s\n", enc_result, enc);
|
||||
|
||||
size_t dec_result = base64c_decode(enc, enc_result, out, out_len);
|
||||
|
||||
if ((long)dec_result < 0) {
|
||||
printf("Decode failed with code %ld\n", (long)dec_result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Decoded %lu - %s\n", dec_result, out);
|
||||
|
||||
if (dec_result != in_len) {
|
||||
printf("in length %ld not equal to out length %ld", in_len, dec_result);
|
||||
return 3;
|
||||
}
|
||||
if (strncmp((char*)in, (char*)out, in_len)) {
|
||||
printf("roundtrip encoding failed\n");
|
||||
return 2;
|
||||
}
|
||||
}
|
37
deps/base64c/test/test008.c
vendored
Normal file
37
deps/base64c/test/test008.c
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
#include "../include/base64c.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
unsigned char in[10] = "H";
|
||||
size_t in_len = 1;
|
||||
unsigned char enc[32];
|
||||
size_t enc_len = 32;
|
||||
unsigned char out[12];
|
||||
size_t out_len = 12;
|
||||
|
||||
printf("Encoding %lu - %s\n", in_len, in);
|
||||
|
||||
size_t enc_result = base64c_encode(in, in_len, enc, enc_len);
|
||||
|
||||
printf("Encoded %lu - %s\n", enc_result, enc);
|
||||
|
||||
size_t dec_result = base64c_decode(enc, enc_result, out, out_len);
|
||||
|
||||
if ((long)dec_result < 0) {
|
||||
printf("Decode failed with code %ld\n", (long)dec_result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Decoded %lu - %s\n", dec_result, out);
|
||||
|
||||
if (dec_result != in_len) {
|
||||
printf("in length %ld not equal to out length %ld", in_len, dec_result);
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (strncmp((char*)in, (char*)out, in_len)) {
|
||||
printf("roundtrip encoding failed\n");
|
||||
return 2;
|
||||
}
|
||||
}
|
29
deps/crypt_blowfish/LINKS
vendored
Normal file
29
deps/crypt_blowfish/LINKS
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
New versions of this package (crypt_blowfish):
|
||||
|
||||
http://www.openwall.com/crypt/
|
||||
|
||||
A paper on the algorithm that explains its design decisions:
|
||||
|
||||
http://www.usenix.org/events/usenix99/provos.html
|
||||
|
||||
Unix Seventh Edition Manual, Volume 2: the password scheme (1978):
|
||||
|
||||
http://plan9.bell-labs.com/7thEdMan/vol2/password
|
||||
|
||||
The Openwall GNU/*/Linux (Owl) tcb suite implementing the alternative
|
||||
password shadowing scheme. This includes a PAM module which
|
||||
supersedes pam_unix and uses the password hashing framework provided
|
||||
with crypt_blowfish when setting new passwords.
|
||||
|
||||
http://www.openwall.com/tcb/
|
||||
|
||||
pam_passwdqc, a password strength checking and policy enforcement
|
||||
module for PAM-aware password changing programs:
|
||||
|
||||
http://www.openwall.com/passwdqc/
|
||||
|
||||
John the Ripper password cracker:
|
||||
|
||||
http://www.openwall.com/john/
|
||||
|
||||
$Owl: Owl/packages/glibc/crypt_blowfish/LINKS,v 1.4 2005/11/16 13:09:47 solar Exp $
|
77
deps/crypt_blowfish/Makefile
vendored
Normal file
77
deps/crypt_blowfish/Makefile
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
#
|
||||
# Written and revised by Solar Designer <solar at openwall.com> in 2000-2011.
|
||||
# No copyright is claimed, and the software is hereby placed in the public
|
||||
# domain. In case this attempt to disclaim copyright and place the software
|
||||
# in the public domain is deemed null and void, then the software is
|
||||
# Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
|
||||
# general public under the following terms:
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted.
|
||||
#
|
||||
# There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
#
|
||||
# See crypt_blowfish.c for more information.
|
||||
#
|
||||
|
||||
CC = gcc
|
||||
AS = $(CC)
|
||||
LD = $(CC)
|
||||
RM = rm -f
|
||||
CFLAGS = -W -Wall -Wbad-function-cast -Wcast-align -Wcast-qual -Wmissing-prototypes -Wstrict-prototypes -Wshadow -Wundef -Wpointer-arith -O2 -fomit-frame-pointer -funroll-loops
|
||||
ASFLAGS = -c
|
||||
LDFLAGS = -s
|
||||
|
||||
BLOWFISH_OBJS = \
|
||||
crypt_blowfish.o x86.o
|
||||
|
||||
CRYPT_OBJS = \
|
||||
$(BLOWFISH_OBJS) crypt_gensalt.o wrapper.o
|
||||
|
||||
TEST_OBJS = \
|
||||
$(BLOWFISH_OBJS) crypt_gensalt.o crypt_test.o
|
||||
|
||||
TEST_THREADS_OBJS = \
|
||||
$(BLOWFISH_OBJS) crypt_gensalt.o crypt_test_threads.o
|
||||
|
||||
EXTRA_MANS = \
|
||||
crypt_r.3 crypt_rn.3 crypt_ra.3 \
|
||||
crypt_gensalt.3 crypt_gensalt_rn.3 crypt_gensalt_ra.3
|
||||
|
||||
all: $(CRYPT_OBJS) man
|
||||
|
||||
check: crypt_test
|
||||
./crypt_test
|
||||
|
||||
crypt_test: $(TEST_OBJS)
|
||||
$(LD) $(LDFLAGS) $(TEST_OBJS) -o $@
|
||||
|
||||
crypt_test.o: wrapper.c ow-crypt.h crypt_blowfish.h crypt_gensalt.h
|
||||
$(CC) -c $(CFLAGS) wrapper.c -DTEST -o $@
|
||||
|
||||
check_threads: crypt_test_threads
|
||||
./crypt_test_threads
|
||||
|
||||
crypt_test_threads: $(TEST_THREADS_OBJS)
|
||||
$(LD) $(LDFLAGS) $(TEST_THREADS_OBJS) -lpthread -o $@
|
||||
|
||||
crypt_test_threads.o: wrapper.c ow-crypt.h crypt_blowfish.h crypt_gensalt.h
|
||||
$(CC) -c $(CFLAGS) wrapper.c -DTEST -DTEST_THREADS=4 -o $@
|
||||
|
||||
man: $(EXTRA_MANS)
|
||||
|
||||
$(EXTRA_MANS):
|
||||
echo '.so man3/crypt.3' > $@
|
||||
|
||||
crypt_blowfish.o: crypt_blowfish.h
|
||||
crypt_gensalt.o: crypt_gensalt.h
|
||||
wrapper.o: crypt.h ow-crypt.h crypt_blowfish.h crypt_gensalt.h
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $*.c
|
||||
|
||||
.S.o:
|
||||
$(AS) $(ASFLAGS) $*.S
|
||||
|
||||
clean:
|
||||
$(RM) crypt_test crypt_test_threads *.o $(EXTRA_MANS) core
|
30
deps/crypt_blowfish/PERFORMANCE
vendored
Normal file
30
deps/crypt_blowfish/PERFORMANCE
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
These numbers are for 32 iterations ("$2a$05"):
|
||||
|
||||
OpenBSD 3.0 bcrypt(*) crypt_blowfish 0.4.4
|
||||
Pentium III, 840 MHz 99 c/s 121 c/s (+22%)
|
||||
Alpha 21164PC, 533 MHz 55.5 c/s 76.9 c/s (+38%)
|
||||
UltraSparc IIi, 400 MHz 49.9 c/s 52.5 c/s (+5%)
|
||||
Pentium, 120 MHz 8.8 c/s 20.1 c/s (+128%)
|
||||
PA-RISC 7100LC, 80 MHz 8.5 c/s 16.3 c/s (+92%)
|
||||
|
||||
(*) built with -fomit-frame-pointer -funroll-loops, which I don't
|
||||
think happens for libcrypt.
|
||||
|
||||
Starting with version 1.1 released in June 2011, default builds of
|
||||
crypt_blowfish invoke a quick self-test on every hash computation.
|
||||
This has roughly a 4.8% performance impact at "$2a$05", but only a 0.6%
|
||||
impact at a more typical setting of "$2a$08".
|
||||
|
||||
The large speedup for the original Pentium is due to the assembly
|
||||
code and the weird optimizations this processor requires.
|
||||
|
||||
The numbers for password cracking are 2 to 10% higher than those for
|
||||
crypt_blowfish as certain things may be done out of the loop and the
|
||||
code doesn't need to be reentrant.
|
||||
|
||||
Recent versions of John the Ripper (1.6.25-dev and newer) achieve an
|
||||
additional 15% speedup on the Pentium Pro family of processors (which
|
||||
includes Pentium III) with a separate version of the assembly code and
|
||||
run-time CPU detection.
|
||||
|
||||
$Owl: Owl/packages/glibc/crypt_blowfish/PERFORMANCE,v 1.6 2011/06/21 12:09:20 solar Exp $
|
68
deps/crypt_blowfish/README
vendored
Normal file
68
deps/crypt_blowfish/README
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
This is an implementation of a password hashing method, provided via the
|
||||
crypt(3) and a reentrant interface. It is fully compatible with
|
||||
OpenBSD's bcrypt.c for prefix "$2b$", originally by Niels Provos and
|
||||
David Mazieres. (Please refer to the included crypt(3) man page for
|
||||
information on minor compatibility issues for other bcrypt prefixes.)
|
||||
|
||||
I've placed this code in the public domain, with fallback to a
|
||||
permissive license. Please see the comment in crypt_blowfish.c for
|
||||
more information.
|
||||
|
||||
You can use the provided routines in your own packages, or link them
|
||||
into a C library. I've provided hooks for linking into GNU libc, but
|
||||
it shouldn't be too hard to get this into another C library. Note
|
||||
that simply adding this code into your libc is probably not enough to
|
||||
make your system use the new password hashing algorithm. Changes to
|
||||
passwd(1), PAM modules, or whatever else your system uses will likely
|
||||
be needed as well. These are not a part of this package, but see
|
||||
LINKS for a pointer to our tcb suite.
|
||||
|
||||
Instructions on using the routines in one of the two common ways are
|
||||
given below. It is recommended that you test the routines on your
|
||||
system before you start. Type "make check" or "make check_threads"
|
||||
(if you have the POSIX threads library), then "make clean".
|
||||
|
||||
|
||||
1. Using the routines in your programs.
|
||||
|
||||
The available interfaces are in ow-crypt.h, and this is the file you
|
||||
should include. You won't need crypt.h. When linking, add all of the
|
||||
C files and x86.S (you can compile and link it even on a non-x86, it
|
||||
will produce no code in this case).
|
||||
|
||||
|
||||
2. Building the routines into GNU C library.
|
||||
|
||||
For versions 2.13 and 2.14 (and likely other nearby ones), extract the
|
||||
library sources as usual. Apply the patch for glibc 2.14 provided in
|
||||
this package. Enter crypt/ and rename crypt.h to gnu-crypt.h within
|
||||
that directory. Copy the C sources, header, and assembly (x86.S) files
|
||||
from this package in there as well (but be sure you don't overwrite the
|
||||
Makefile). Configure, build, and install the library as usual.
|
||||
|
||||
For versions 2.2 to 2.3.6 (and likely also for some newer ones),
|
||||
extract the library sources and maybe its optional add-ons as usual.
|
||||
Apply the patch for glibc 2.3.6 provided in this package. Enter
|
||||
crypt/ and rename crypt.h to gnu-crypt.h within that directory. Copy
|
||||
the C sources, header, and assembly (x86.S) files from this package in
|
||||
there as well (but be sure you don't overwrite the Makefile).
|
||||
Configure, build, and install the library as usual.
|
||||
|
||||
For versions 2.1 to 2.1.3, extract the library sources and the crypt
|
||||
and linuxthreads add-ons as usual. Apply the patch for glibc 2.1.3
|
||||
provided in this package. Enter crypt/sysdeps/unix/, and rename
|
||||
crypt.h to gnu-crypt.h within that directory. Copy C sources, header,
|
||||
and assembly (x86.S) files from this package in there as well (but be
|
||||
sure you don't overwrite the Makefile). Configure, build, and install
|
||||
the library as usual.
|
||||
|
||||
Programs that want to use the provided interfaces will need to include
|
||||
crypt.h (but not ow-crypt.h directly). By default, prototypes for the
|
||||
new routines aren't defined (but the extra functionality of crypt(3)
|
||||
is indeed available). You need to define _OW_SOURCE to obtain the new
|
||||
routines as well.
|
||||
|
||||
--
|
||||
Solar Designer <solar at openwall.com>
|
||||
|
||||
$Owl: Owl/packages/glibc/crypt_blowfish/README,v 1.10 2014/07/07 15:19:04 solar Exp $
|
575
deps/crypt_blowfish/crypt.3
vendored
Normal file
575
deps/crypt_blowfish/crypt.3
vendored
Normal file
@ -0,0 +1,575 @@
|
||||
.\" Written and revised by Solar Designer <solar at openwall.com> in 2000-2011.
|
||||
.\" No copyright is claimed, and this man page is hereby placed in the public
|
||||
.\" domain. In case this attempt to disclaim copyright and place the man page
|
||||
.\" in the public domain is deemed null and void, then the man page is
|
||||
.\" Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
|
||||
.\" general public under the following terms:
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted.
|
||||
.\"
|
||||
.\" There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
.\"
|
||||
.\" This manual page in its current form is intended for use on systems
|
||||
.\" based on the GNU C Library with crypt_blowfish patched into libcrypt.
|
||||
.\"
|
||||
.TH CRYPT 3 "July 7, 2014" "Openwall Project" "Library functions"
|
||||
.ad l
|
||||
.\" No macros in NAME to keep makewhatis happy.
|
||||
.SH NAME
|
||||
\fBcrypt\fR, \fBcrypt_r\fR, \fBcrypt_rn\fR, \fBcrypt_ra\fR,
|
||||
\fBcrypt_gensalt\fR, \fBcrypt_gensalt_rn\fR, \fBcrypt_gensalt_ra\fR
|
||||
\- password hashing
|
||||
.SH SYNOPSIS
|
||||
.B #define _XOPEN_SOURCE
|
||||
.br
|
||||
.B #include <unistd.h>
|
||||
.sp
|
||||
.in +8
|
||||
.ti -8
|
||||
.BI "char *crypt(const char *" key ", const char *" setting );
|
||||
.in -8
|
||||
.sp
|
||||
.B #define _GNU_SOURCE
|
||||
.br
|
||||
.B #include <crypt.h>
|
||||
.sp
|
||||
.in +8
|
||||
.ti -8
|
||||
.BI "char *crypt_r(const char *" key ", const char *" setting ", struct crypt_data *" data );
|
||||
.in -8
|
||||
.sp
|
||||
.B #define _OW_SOURCE
|
||||
.br
|
||||
.B #include <crypt.h>
|
||||
.sp
|
||||
.in +8
|
||||
.ti -8
|
||||
.BI "char *crypt_rn(const char *" key ", const char *" setting ", void *" data ", int " size );
|
||||
.ti -8
|
||||
.BI "char *crypt_ra(const char *" key ", const char *" setting ", void **" data ", int *" size );
|
||||
.ti -8
|
||||
.BI "char *crypt_gensalt(const char *" prefix ", unsigned long " count ", const char *" input ", int " size );
|
||||
.ti -8
|
||||
.BI "char *crypt_gensalt_rn(const char *" prefix ", unsigned long " count ", const char *" input ", int " size ", char *" output ", int " output_size );
|
||||
.ti -8
|
||||
.BI "char *crypt_gensalt_ra(const char *" prefix ", unsigned long " count ", const char *" input ", int " size );
|
||||
.ad b
|
||||
.de crypt
|
||||
.BR crypt ,
|
||||
.BR crypt_r ,
|
||||
.BR crypt_rn ", \\$1"
|
||||
.ie "\\$2"" .B crypt_ra
|
||||
.el .BR crypt_ra "\\$2"
|
||||
..
|
||||
.de crypt_gensalt
|
||||
.BR crypt_gensalt ,
|
||||
.BR crypt_gensalt_rn ", \\$1"
|
||||
.ie "\\$2"" .B crypt_gensalt_ra
|
||||
.el .BR crypt_gensalt_ra "\\$2"
|
||||
..
|
||||
.SH DESCRIPTION
|
||||
The
|
||||
.crypt and
|
||||
functions calculate a cryptographic hash function of
|
||||
.I key
|
||||
with one of a number of supported methods as requested with
|
||||
.IR setting ,
|
||||
which is also used to pass a salt and possibly other parameters to
|
||||
the chosen method.
|
||||
The hashing methods are explained below.
|
||||
.PP
|
||||
Unlike
|
||||
.BR crypt ,
|
||||
the functions
|
||||
.BR crypt_r ,
|
||||
.BR crypt_rn " and"
|
||||
.B crypt_ra
|
||||
are reentrant.
|
||||
They place their result and possibly their private data in a
|
||||
.I data
|
||||
area of
|
||||
.I size
|
||||
bytes as passed to them by an application and/or in memory they
|
||||
allocate dynamically. Some hashing algorithms may use the data area to
|
||||
cache precomputed intermediate values across calls. Thus, applications
|
||||
must properly initialize the data area before its first use.
|
||||
.B crypt_r
|
||||
requires that only
|
||||
.I data->initialized
|
||||
be reset to zero;
|
||||
.BR crypt_rn " and " crypt_ra
|
||||
require that either the entire data area is zeroed or, in the case of
|
||||
.BR crypt_ra ,
|
||||
.I *data
|
||||
is NULL. When called with a NULL
|
||||
.I *data
|
||||
or insufficient
|
||||
.I *size
|
||||
for the requested hashing algorithm,
|
||||
.B crypt_ra
|
||||
uses
|
||||
.BR realloc (3)
|
||||
to allocate the required amount of memory dynamically. Thus,
|
||||
.B crypt_ra
|
||||
has the additional requirement that
|
||||
.IR *data ,
|
||||
when non-NULL, must point to an area allocated either with a previous
|
||||
call to
|
||||
.B crypt_ra
|
||||
or with a
|
||||
.BR malloc (3)
|
||||
family call.
|
||||
The memory allocated by
|
||||
.B crypt_ra
|
||||
should be freed with
|
||||
.BR free "(3)."
|
||||
.PP
|
||||
The
|
||||
.crypt_gensalt and
|
||||
functions compile a string for use as
|
||||
.I setting
|
||||
\- with the given
|
||||
.I prefix
|
||||
(used to choose a hashing method), the iteration
|
||||
.I count
|
||||
(if supported by the chosen method) and up to
|
||||
.I size
|
||||
cryptographically random
|
||||
.I input
|
||||
bytes for use as the actual salt.
|
||||
If
|
||||
.I count
|
||||
is 0, a low default will be picked.
|
||||
The random bytes may be obtained from
|
||||
.BR /dev/urandom .
|
||||
Unlike
|
||||
.BR crypt_gensalt ,
|
||||
the functions
|
||||
.BR crypt_gensalt_rn " and " crypt_gensalt_ra
|
||||
are reentrant.
|
||||
.B crypt_gensalt_rn
|
||||
places its result in the
|
||||
.I output
|
||||
buffer of
|
||||
.I output_size
|
||||
bytes.
|
||||
.B crypt_gensalt_ra
|
||||
allocates memory for its result dynamically. The memory should be
|
||||
freed with
|
||||
.BR free "(3)."
|
||||
.SH RETURN VALUE
|
||||
Upon successful completion, the functions
|
||||
.crypt and
|
||||
return a pointer to a string containing the setting that was actually used
|
||||
and a printable encoding of the hash function value.
|
||||
The entire string is directly usable as
|
||||
.I setting
|
||||
with other calls to
|
||||
.crypt and
|
||||
and as
|
||||
.I prefix
|
||||
with calls to
|
||||
.crypt_gensalt and .
|
||||
.PP
|
||||
The behavior of
|
||||
.B crypt
|
||||
on errors isn't well standardized. Some implementations simply can't fail
|
||||
(unless the process dies, in which case they obviously can't return),
|
||||
others return NULL or a fixed string. Most implementations don't set
|
||||
.IR errno ,
|
||||
but some do. SUSv2 specifies only returning NULL and setting
|
||||
.I errno
|
||||
as a valid behavior, and defines only one possible error
|
||||
.RB "(" ENOSYS ,
|
||||
"The functionality is not supported on this implementation.")
|
||||
Unfortunately, most existing applications aren't prepared to handle
|
||||
NULL returns from
|
||||
.BR crypt .
|
||||
The description below corresponds to this implementation of
|
||||
.BR crypt " and " crypt_r
|
||||
only, and to
|
||||
.BR crypt_rn " and " crypt_ra .
|
||||
The behavior may change to match standards, other implementations or
|
||||
existing applications.
|
||||
.PP
|
||||
.BR crypt " and " crypt_r
|
||||
may only fail (and return) when passed an invalid or unsupported
|
||||
.IR setting ,
|
||||
in which case they return a pointer to a magic string that is
|
||||
shorter than 13 characters and is guaranteed to differ from
|
||||
.IR setting .
|
||||
This behavior is safe for older applications which assume that
|
||||
.B crypt
|
||||
can't fail, when both setting new passwords and authenticating against
|
||||
existing password hashes.
|
||||
.BR crypt_rn " and " crypt_ra
|
||||
return NULL to indicate failure. All four functions set
|
||||
.I errno
|
||||
when they fail.
|
||||
.PP
|
||||
The functions
|
||||
.crypt_gensalt and
|
||||
return a pointer to the compiled string for
|
||||
.IR setting ,
|
||||
or NULL on error in which case
|
||||
.I errno
|
||||
is set.
|
||||
.SH ERRORS
|
||||
.TP
|
||||
.B EINVAL
|
||||
.crypt "" :
|
||||
.I setting
|
||||
is invalid or not supported by this implementation;
|
||||
.sp
|
||||
.crypt_gensalt "" :
|
||||
.I prefix
|
||||
is invalid or not supported by this implementation;
|
||||
.I count
|
||||
is invalid for the requested
|
||||
.IR prefix ;
|
||||
the input
|
||||
.I size
|
||||
is insufficient for the smallest valid salt with the requested
|
||||
.IR prefix ;
|
||||
.I input
|
||||
is NULL.
|
||||
.TP
|
||||
.B ERANGE
|
||||
.BR crypt_rn :
|
||||
the provided data area
|
||||
.I size
|
||||
is insufficient for the requested hashing algorithm;
|
||||
.sp
|
||||
.BR crypt_gensalt_rn :
|
||||
.I output_size
|
||||
is too small to hold the compiled
|
||||
.I setting
|
||||
string.
|
||||
.TP
|
||||
.B ENOMEM
|
||||
.B crypt
|
||||
(original glibc only):
|
||||
failed to allocate memory for the output buffer (which subsequent calls
|
||||
would re-use);
|
||||
.sp
|
||||
.BR crypt_ra :
|
||||
.I *data
|
||||
is NULL or
|
||||
.I *size
|
||||
is insufficient for the requested hashing algorithm and
|
||||
.BR realloc (3)
|
||||
failed;
|
||||
.sp
|
||||
.BR crypt_gensalt_ra :
|
||||
failed to allocate memory for the compiled
|
||||
.I setting
|
||||
string.
|
||||
.TP
|
||||
.B ENOSYS
|
||||
.B crypt
|
||||
(SUSv2):
|
||||
the functionality is not supported on this implementation;
|
||||
.sp
|
||||
.BR crypt ,
|
||||
.B crypt_r
|
||||
(glibc 2.0 to 2.0.1 only):
|
||||
.de no-crypt-add-on
|
||||
the crypt add-on is not compiled in and
|
||||
.I setting
|
||||
requests something other than the MD5-based algorithm.
|
||||
..
|
||||
.no-crypt-add-on
|
||||
.TP
|
||||
.B EOPNOTSUPP
|
||||
.BR crypt ,
|
||||
.B crypt_r
|
||||
(glibc 2.0.2 to 2.1.3 only):
|
||||
.no-crypt-add-on
|
||||
.SH HASHING METHODS
|
||||
The implemented hashing methods are intended specifically for processing
|
||||
user passwords for storage and authentication;
|
||||
they are at best inefficient for most other purposes.
|
||||
.PP
|
||||
It is important to understand that password hashing is not a replacement
|
||||
for strong passwords.
|
||||
It is always possible for an attacker with access to password hashes
|
||||
to try guessing candidate passwords against the hashes.
|
||||
There are, however, certain properties a password hashing method may have
|
||||
which make these key search attacks somewhat harder.
|
||||
.PP
|
||||
All of the hashing methods use salts such that the same
|
||||
.I key
|
||||
may produce many possible hashes.
|
||||
Proper use of salts may defeat a number of attacks, including:
|
||||
.TP
|
||||
1.
|
||||
The ability to try candidate passwords against multiple hashes at the
|
||||
price of one.
|
||||
.TP
|
||||
2.
|
||||
The use of pre-hashed lists of candidate passwords.
|
||||
.TP
|
||||
3.
|
||||
The ability to determine whether two users (or two accounts of one user)
|
||||
have the same or different passwords without actually having to guess
|
||||
one of the passwords.
|
||||
.PP
|
||||
The key search attacks depend on computing hashes of large numbers of
|
||||
candidate passwords.
|
||||
Thus, the computational cost of a good password hashing method must be
|
||||
high \- but of course not too high to render it impractical.
|
||||
.PP
|
||||
All hashing methods implemented within the
|
||||
.crypt and
|
||||
interfaces use multiple iterations of an underlying cryptographic
|
||||
primitive specifically in order to increase the cost of trying a
|
||||
candidate password.
|
||||
Unfortunately, due to hardware improvements, the hashing methods which
|
||||
have a fixed cost become increasingly less secure over time.
|
||||
.PP
|
||||
In addition to salts, modern password hashing methods accept a variable
|
||||
iteration
|
||||
.IR count .
|
||||
This makes it possible to adapt their cost to the hardware improvements
|
||||
while still maintaining compatibility.
|
||||
.PP
|
||||
The following hashing methods are or may be implemented within the
|
||||
described interfaces:
|
||||
.PP
|
||||
.de hash
|
||||
.ad l
|
||||
.TP
|
||||
.I prefix
|
||||
.ie "\\$1"" \{\
|
||||
"" (empty string);
|
||||
.br
|
||||
a string matching ^[./0-9A-Za-z]{2} (see
|
||||
.BR regex (7))
|
||||
.\}
|
||||
.el "\\$1"
|
||||
.TP
|
||||
.B Encoding syntax
|
||||
\\$2
|
||||
.TP
|
||||
.B Maximum password length
|
||||
\\$3 (uses \\$4-bit characters)
|
||||
.TP
|
||||
.B Effective key size
|
||||
.ie "\\$5"" limited by the hash size only
|
||||
.el up to \\$5 bits
|
||||
.TP
|
||||
.B Hash size
|
||||
\\$6 bits
|
||||
.TP
|
||||
.B Salt size
|
||||
\\$7 bits
|
||||
.TP
|
||||
.B Iteration count
|
||||
\\$8
|
||||
.ad b
|
||||
..
|
||||
.ti -2
|
||||
.B Traditional DES-based
|
||||
.br
|
||||
This method is supported by almost all implementations of
|
||||
.BR crypt .
|
||||
Unfortunately, it no longer offers adequate security because of its many
|
||||
limitations.
|
||||
Thus, it should not be used for new passwords unless you absolutely have
|
||||
to be able to migrate the password hashes to other systems.
|
||||
.hash "" "[./0-9A-Za-z]{13}" 8 7 56 64 12 25
|
||||
.PP
|
||||
.ti -2
|
||||
.B Extended BSDI-style DES-based
|
||||
.br
|
||||
This method is used on BSDI and is also available on at least NetBSD,
|
||||
OpenBSD, and FreeBSD due to the use of David Burren's FreeSec library.
|
||||
.hash _ "_[./0-9A-Za-z]{19}" unlimited 7 56 64 24 "1 to 2**24-1 (must be odd)"
|
||||
.PP
|
||||
.ti -2
|
||||
.B FreeBSD-style MD5-based
|
||||
.br
|
||||
This is Poul-Henning Kamp's MD5-based password hashing method originally
|
||||
developed for FreeBSD.
|
||||
It is currently supported on many free Unix-like systems, on Solaris 10
|
||||
and newer, and it is part of the official glibc.
|
||||
Its main disadvantage is the fixed iteration count, which is already
|
||||
too low for the currently available hardware.
|
||||
.hash "$1$" "\e$1\e$[^$]{1,8}\e$[./0-9A-Za-z]{22}" unlimited 8 "" 128 "6 to 48" 1000
|
||||
.PP
|
||||
.ti -2
|
||||
.BR "OpenBSD-style Blowfish-based" " (" bcrypt )
|
||||
.br
|
||||
.B bcrypt
|
||||
was originally developed by Niels Provos and David Mazieres for OpenBSD
|
||||
and is also supported on recent versions of FreeBSD and NetBSD,
|
||||
on Solaris 10 and newer, and on several GNU/*/Linux distributions.
|
||||
It is, however, not part of the official glibc.
|
||||
.PP
|
||||
While both
|
||||
.B bcrypt
|
||||
and the BSDI-style DES-based hashing offer a variable iteration count,
|
||||
.B bcrypt
|
||||
may scale to even faster hardware, doesn't allow for certain optimizations
|
||||
specific to password cracking only, doesn't have the effective key size
|
||||
limitation, and uses 8-bit characters in passwords.
|
||||
.hash "$2b$" "\e$2[abxy]\e$[0-9]{2}\e$[./A-Za-z0-9]{53}" 72 8 "" 184 128 "2**4 to 2**99 (current implementations are limited to 2**31 iterations)"
|
||||
.PP
|
||||
With
|
||||
.BR bcrypt ,
|
||||
the
|
||||
.I count
|
||||
passed to
|
||||
.crypt_gensalt and
|
||||
is the base-2 logarithm of the actual iteration count.
|
||||
.PP
|
||||
.B bcrypt
|
||||
hashes used the "$2a$" prefix since 1997.
|
||||
However, in 2011 an implementation bug was discovered in crypt_blowfish
|
||||
(versions up to 1.0.4 inclusive) affecting handling of password characters with
|
||||
the 8th bit set.
|
||||
Besides fixing the bug,
|
||||
to provide for upgrade strategies for existing systems, two new prefixes were
|
||||
introduced: "$2x$", which fully re-introduces the bug, and "$2y$", which
|
||||
guarantees correct handling of both 7- and 8-bit characters.
|
||||
OpenBSD 5.5 introduced the "$2b$" prefix for behavior that exactly matches
|
||||
crypt_blowfish's "$2y$", and current crypt_blowfish supports it as well.
|
||||
Unfortunately, the behavior of "$2a$" on password characters with the 8th bit
|
||||
set has to be considered system-specific.
|
||||
When generating new password hashes, the "$2b$" or "$2y$" prefix should be used.
|
||||
(If such hashes ever need to be migrated to a system that does not yet support
|
||||
these new prefixes, the prefix in migrated copies of the already-generated
|
||||
hashes may be changed to "$2a$".)
|
||||
.PP
|
||||
.crypt_gensalt and
|
||||
support the "$2b$", "$2y$", and "$2a$" prefixes (the latter for legacy programs
|
||||
or configurations), but not "$2x$" (which must not be used for new hashes).
|
||||
.crypt and
|
||||
support all four of these prefixes.
|
||||
.SH PORTABILITY NOTES
|
||||
Programs using any of these functions on a glibc 2.x system must be
|
||||
linked against
|
||||
.BR libcrypt .
|
||||
However, many Unix-like operating systems and older versions of the
|
||||
GNU C Library include the
|
||||
.BR crypt " function in " libc .
|
||||
.PP
|
||||
The
|
||||
.BR crypt_r ,
|
||||
.BR crypt_rn ,
|
||||
.BR crypt_ra ,
|
||||
.crypt_gensalt and
|
||||
functions are very non-portable.
|
||||
.PP
|
||||
The set of supported hashing methods is implementation-dependent.
|
||||
.SH CONFORMING TO
|
||||
The
|
||||
.B crypt
|
||||
function conforms to SVID, X/OPEN, and is available on BSD 4.3.
|
||||
The strings returned by
|
||||
.B crypt
|
||||
are not required to be portable among conformant systems.
|
||||
.PP
|
||||
.B crypt_r
|
||||
is a GNU extension.
|
||||
There's also a
|
||||
.B crypt_r
|
||||
function on HP-UX and MKS Toolkit, but the prototypes and semantics differ.
|
||||
.PP
|
||||
.B crypt_gensalt
|
||||
is an Openwall extension.
|
||||
There's also a
|
||||
.B crypt_gensalt
|
||||
function on Solaris 10 and newer, but the prototypes and semantics differ.
|
||||
.PP
|
||||
.BR crypt_rn ,
|
||||
.BR crypt_ra ,
|
||||
.BR crypt_gensalt_rn ,
|
||||
and
|
||||
.B crypt_gensalt_ra
|
||||
are Openwall extensions.
|
||||
.SH HISTORY
|
||||
A rotor-based
|
||||
.B crypt
|
||||
function appeared in Version 6 AT&T UNIX.
|
||||
The "traditional"
|
||||
.B crypt
|
||||
first appeared in Version 7 AT&T UNIX.
|
||||
.PP
|
||||
The
|
||||
.B crypt_r
|
||||
function was introduced during glibc 2.0 development.
|
||||
.SH BUGS
|
||||
The return values of
|
||||
.BR crypt " and " crypt_gensalt
|
||||
point to static buffers that are overwritten by subsequent calls.
|
||||
These functions are not thread-safe.
|
||||
.RB ( crypt
|
||||
on recent versions of Solaris uses thread-specific data and actually is
|
||||
thread-safe.)
|
||||
.PP
|
||||
The strings returned by certain other implementations of
|
||||
.B crypt
|
||||
on error may be stored in read-only locations or only initialized once,
|
||||
which makes it unsafe to always attempt to zero out the buffer normally
|
||||
pointed to by the
|
||||
.B crypt
|
||||
return value as it would otherwise be preferable for security reasons.
|
||||
The problem could be avoided with the use of
|
||||
.BR crypt_r ,
|
||||
.BR crypt_rn ,
|
||||
or
|
||||
.B crypt_ra
|
||||
where the application has full control over output buffers of these functions
|
||||
(and often over some of their private data as well).
|
||||
Unfortunately, the functions aren't (yet?) available on platforms where
|
||||
.B crypt
|
||||
has this undesired property.
|
||||
.PP
|
||||
Applications using the thread-safe
|
||||
.B crypt_r
|
||||
need to allocate address space for the large (over 128 KB)
|
||||
.I struct crypt_data
|
||||
structure. Each thread needs a separate instance of the structure. The
|
||||
.B crypt_r
|
||||
interface makes it impossible to implement a hashing algorithm which
|
||||
would need to keep an even larger amount of private data, without breaking
|
||||
binary compatibility.
|
||||
.B crypt_ra
|
||||
allows for dynamically increasing the allocation size as required by the
|
||||
hashing algorithm that is actually used. Unfortunately,
|
||||
.B crypt_ra
|
||||
is even more non-portable than
|
||||
.BR crypt_r .
|
||||
.PP
|
||||
Multi-threaded applications or library functions which are meant to be
|
||||
thread-safe should use
|
||||
.BR crypt_gensalt_rn " or " crypt_gensalt_ra
|
||||
rather than
|
||||
.BR crypt_gensalt .
|
||||
.SH SEE ALSO
|
||||
.BR login (1),
|
||||
.BR passwd (1),
|
||||
.BR crypto (3),
|
||||
.BR encrypt (3),
|
||||
.BR free (3),
|
||||
.BR getpass (3),
|
||||
.BR getpwent (3),
|
||||
.BR malloc (3),
|
||||
.BR realloc (3),
|
||||
.BR shadow (3),
|
||||
.BR passwd (5),
|
||||
.BR shadow (5),
|
||||
.BR regex (7),
|
||||
.BR pam (8)
|
||||
.sp
|
||||
Niels Provos and David Mazieres. A Future-Adaptable Password Scheme.
|
||||
Proceedings of the 1999 USENIX Annual Technical Conference, June 1999.
|
||||
.br
|
||||
http://www.usenix.org/events/usenix99/provos.html
|
||||
.sp
|
||||
Robert Morris and Ken Thompson. Password Security: A Case History.
|
||||
Unix Seventh Edition Manual, Volume 2, April 1978.
|
||||
.br
|
||||
http://plan9.bell-labs.com/7thEdMan/vol2/password
|
24
deps/crypt_blowfish/crypt.h
vendored
Normal file
24
deps/crypt_blowfish/crypt.h
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Written by Solar Designer <solar at openwall.com> in 2000-2002.
|
||||
* No copyright is claimed, and the software is hereby placed in the public
|
||||
* domain. In case this attempt to disclaim copyright and place the software
|
||||
* in the public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2000-2002 Solar Designer and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* See crypt_blowfish.c for more information.
|
||||
*/
|
||||
|
||||
#include <gnu-crypt.h>
|
||||
|
||||
#if defined(_OW_SOURCE) || defined(__USE_OW)
|
||||
#define __SKIP_GNU
|
||||
#undef __SKIP_OW
|
||||
#include <ow-crypt.h>
|
||||
#undef __SKIP_GNU
|
||||
#endif
|
907
deps/crypt_blowfish/crypt_blowfish.c
vendored
Normal file
907
deps/crypt_blowfish/crypt_blowfish.c
vendored
Normal file
@ -0,0 +1,907 @@
|
||||
/*
|
||||
* The crypt_blowfish homepage is:
|
||||
*
|
||||
* http://www.openwall.com/crypt/
|
||||
*
|
||||
* This code comes from John the Ripper password cracker, with reentrant
|
||||
* and crypt(3) interfaces added, but optimizations specific to password
|
||||
* cracking removed.
|
||||
*
|
||||
* Written by Solar Designer <solar at openwall.com> in 1998-2014.
|
||||
* No copyright is claimed, and the software is hereby placed in the public
|
||||
* domain. In case this attempt to disclaim copyright and place the software
|
||||
* in the public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 1998-2014 Solar Designer and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* It is my intent that you should be able to use this on your system,
|
||||
* as part of a software package, or anywhere else to improve security,
|
||||
* ensure compatibility, or for any other purpose. I would appreciate
|
||||
* it if you give credit where it is due and keep your modifications in
|
||||
* the public domain as well, but I don't require that in order to let
|
||||
* you place this code and any modifications you make under a license
|
||||
* of your choice.
|
||||
*
|
||||
* This implementation is fully compatible with OpenBSD's bcrypt.c for prefix
|
||||
* "$2b$", originally by Niels Provos <provos at citi.umich.edu>, and it uses
|
||||
* some of his ideas. The password hashing algorithm was designed by David
|
||||
* Mazieres <dm at lcs.mit.edu>. For information on the level of
|
||||
* compatibility for bcrypt hash prefixes other than "$2b$", please refer to
|
||||
* the comments in BF_set_key() below and to the included crypt(3) man page.
|
||||
*
|
||||
* There's a paper on the algorithm that explains its design decisions:
|
||||
*
|
||||
* http://www.usenix.org/events/usenix99/provos.html
|
||||
*
|
||||
* Some of the tricks in BF_ROUND might be inspired by Eric Young's
|
||||
* Blowfish library (I can't be sure if I would think of something if I
|
||||
* hadn't seen his code).
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef __set_errno
|
||||
#define __set_errno(val) errno = (val)
|
||||
#endif
|
||||
|
||||
/* Just to make sure the prototypes match the actual definitions */
|
||||
#include "crypt_blowfish.h"
|
||||
|
||||
#ifdef __i386__
|
||||
#define BF_ASM 1
|
||||
#define BF_SCALE 1
|
||||
#elif defined(__x86_64__) || defined(__alpha__) || defined(__hppa__)
|
||||
#define BF_ASM 0
|
||||
#define BF_SCALE 1
|
||||
#else
|
||||
#define BF_ASM 0
|
||||
#define BF_SCALE 0
|
||||
#endif
|
||||
|
||||
typedef unsigned int BF_word;
|
||||
typedef signed int BF_word_signed;
|
||||
|
||||
/* Number of Blowfish rounds, this is also hardcoded into a few places */
|
||||
#define BF_N 16
|
||||
|
||||
typedef BF_word BF_key[BF_N + 2];
|
||||
|
||||
typedef struct {
|
||||
BF_word S[4][0x100];
|
||||
BF_key P;
|
||||
} BF_ctx;
|
||||
|
||||
/*
|
||||
* Magic IV for 64 Blowfish encryptions that we do at the end.
|
||||
* The string is "OrpheanBeholderScryDoubt" on big-endian.
|
||||
*/
|
||||
static BF_word BF_magic_w[6] = {
|
||||
0x4F727068, 0x65616E42, 0x65686F6C,
|
||||
0x64657253, 0x63727944, 0x6F756274
|
||||
};
|
||||
|
||||
/*
|
||||
* P-box and S-box tables initialized with digits of Pi.
|
||||
*/
|
||||
static BF_ctx BF_init_state = {
|
||||
{
|
||||
{
|
||||
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
|
||||
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
|
||||
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
|
||||
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
|
||||
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
|
||||
0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
|
||||
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
|
||||
0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
|
||||
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
|
||||
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
|
||||
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
|
||||
0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
|
||||
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
|
||||
0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
|
||||
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
|
||||
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
|
||||
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
|
||||
0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
|
||||
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
|
||||
0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
|
||||
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
|
||||
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
|
||||
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
|
||||
0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
|
||||
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
|
||||
0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
|
||||
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
|
||||
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
|
||||
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
|
||||
0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
|
||||
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
|
||||
0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
|
||||
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
|
||||
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
|
||||
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
|
||||
0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
|
||||
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
|
||||
0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
|
||||
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
|
||||
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
|
||||
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
|
||||
0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
|
||||
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
|
||||
0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
|
||||
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
|
||||
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
|
||||
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
|
||||
0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
|
||||
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
|
||||
0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
|
||||
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
|
||||
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
|
||||
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
|
||||
0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
|
||||
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
|
||||
0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
|
||||
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
|
||||
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
|
||||
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
|
||||
0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
|
||||
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
|
||||
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
|
||||
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
|
||||
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
|
||||
}, {
|
||||
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
|
||||
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
|
||||
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
|
||||
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
|
||||
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
|
||||
0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
|
||||
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
|
||||
0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
|
||||
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
|
||||
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
|
||||
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
|
||||
0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
|
||||
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
|
||||
0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
|
||||
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
|
||||
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
|
||||
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
|
||||
0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
|
||||
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
|
||||
0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
|
||||
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
|
||||
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
|
||||
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
|
||||
0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
|
||||
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
|
||||
0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
|
||||
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
|
||||
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
|
||||
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
|
||||
0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
|
||||
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
|
||||
0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
|
||||
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
|
||||
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
|
||||
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
|
||||
0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
|
||||
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
|
||||
0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
|
||||
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
|
||||
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
|
||||
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
|
||||
0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
|
||||
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
|
||||
0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
|
||||
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
|
||||
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
|
||||
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
|
||||
0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
|
||||
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
|
||||
0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
|
||||
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
|
||||
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
|
||||
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
|
||||
0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
|
||||
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
|
||||
0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
|
||||
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
|
||||
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
|
||||
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
|
||||
0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
|
||||
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
|
||||
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
|
||||
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
|
||||
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
|
||||
}, {
|
||||
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
|
||||
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
|
||||
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
|
||||
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
|
||||
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
|
||||
0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
|
||||
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
|
||||
0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
|
||||
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
|
||||
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
|
||||
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
|
||||
0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
|
||||
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
|
||||
0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
|
||||
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
|
||||
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
|
||||
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
|
||||
0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
|
||||
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
|
||||
0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
|
||||
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
|
||||
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
|
||||
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
|
||||
0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
|
||||
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
|
||||
0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
|
||||
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
|
||||
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
|
||||
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
|
||||
0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
|
||||
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
|
||||
0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
|
||||
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
|
||||
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
|
||||
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
|
||||
0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
|
||||
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
|
||||
0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
|
||||
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
|
||||
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
|
||||
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
|
||||
0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
|
||||
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
|
||||
0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
|
||||
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
|
||||
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
|
||||
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
|
||||
0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
|
||||
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
|
||||
0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
|
||||
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
|
||||
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
|
||||
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
|
||||
0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
|
||||
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
|
||||
0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
|
||||
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
|
||||
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
|
||||
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
|
||||
0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
|
||||
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
|
||||
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
|
||||
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
|
||||
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
|
||||
}, {
|
||||
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
|
||||
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
|
||||
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
|
||||
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
|
||||
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
|
||||
0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
|
||||
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
|
||||
0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
|
||||
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
|
||||
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
|
||||
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
|
||||
0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
|
||||
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
|
||||
0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
|
||||
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
|
||||
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
|
||||
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
|
||||
0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
|
||||
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
|
||||
0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
|
||||
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
|
||||
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
|
||||
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
|
||||
0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
|
||||
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
|
||||
0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
|
||||
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
|
||||
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
|
||||
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
|
||||
0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
|
||||
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
|
||||
0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
|
||||
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
|
||||
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
|
||||
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
|
||||
0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
|
||||
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
|
||||
0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
|
||||
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
|
||||
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
|
||||
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
|
||||
0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
|
||||
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
|
||||
0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
|
||||
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
|
||||
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
|
||||
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
|
||||
0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
|
||||
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
|
||||
0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
|
||||
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
|
||||
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
|
||||
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
|
||||
0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
|
||||
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
|
||||
0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
|
||||
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
|
||||
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
|
||||
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
|
||||
0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
|
||||
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
|
||||
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
|
||||
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
|
||||
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
|
||||
}
|
||||
}, {
|
||||
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
|
||||
0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
|
||||
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
|
||||
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
|
||||
0x9216d5d9, 0x8979fb1b
|
||||
}
|
||||
};
|
||||
|
||||
static unsigned char BF_itoa64[64 + 1] =
|
||||
"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
static unsigned char BF_atoi64[0x60] = {
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1,
|
||||
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64,
|
||||
64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 64, 64, 64, 64, 64,
|
||||
64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
|
||||
43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64
|
||||
};
|
||||
|
||||
#define BF_safe_atoi64(dst, src) \
|
||||
{ \
|
||||
tmp = (unsigned char)(src); \
|
||||
if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \
|
||||
tmp = BF_atoi64[tmp]; \
|
||||
if (tmp > 63) return -1; \
|
||||
(dst) = tmp; \
|
||||
}
|
||||
|
||||
static int BF_decode(BF_word *dst, const char *src, int size)
|
||||
{
|
||||
unsigned char *dptr = (unsigned char *)dst;
|
||||
unsigned char *end = dptr + size;
|
||||
const unsigned char *sptr = (const unsigned char *)src;
|
||||
unsigned int tmp, c1, c2, c3, c4;
|
||||
|
||||
do {
|
||||
BF_safe_atoi64(c1, *sptr++);
|
||||
BF_safe_atoi64(c2, *sptr++);
|
||||
*dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4);
|
||||
if (dptr >= end) break;
|
||||
|
||||
BF_safe_atoi64(c3, *sptr++);
|
||||
*dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2);
|
||||
if (dptr >= end) break;
|
||||
|
||||
BF_safe_atoi64(c4, *sptr++);
|
||||
*dptr++ = ((c3 & 0x03) << 6) | c4;
|
||||
} while (dptr < end);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void BF_encode(char *dst, const BF_word *src, int size)
|
||||
{
|
||||
const unsigned char *sptr = (const unsigned char *)src;
|
||||
const unsigned char *end = sptr + size;
|
||||
unsigned char *dptr = (unsigned char *)dst;
|
||||
unsigned int c1, c2;
|
||||
|
||||
do {
|
||||
c1 = *sptr++;
|
||||
*dptr++ = BF_itoa64[c1 >> 2];
|
||||
c1 = (c1 & 0x03) << 4;
|
||||
if (sptr >= end) {
|
||||
*dptr++ = BF_itoa64[c1];
|
||||
break;
|
||||
}
|
||||
|
||||
c2 = *sptr++;
|
||||
c1 |= c2 >> 4;
|
||||
*dptr++ = BF_itoa64[c1];
|
||||
c1 = (c2 & 0x0f) << 2;
|
||||
if (sptr >= end) {
|
||||
*dptr++ = BF_itoa64[c1];
|
||||
break;
|
||||
}
|
||||
|
||||
c2 = *sptr++;
|
||||
c1 |= c2 >> 6;
|
||||
*dptr++ = BF_itoa64[c1];
|
||||
*dptr++ = BF_itoa64[c2 & 0x3f];
|
||||
} while (sptr < end);
|
||||
}
|
||||
|
||||
static void BF_swap(BF_word *x, int count)
|
||||
{
|
||||
static int endianness_check = 1;
|
||||
char *is_little_endian = (char *)&endianness_check;
|
||||
BF_word tmp;
|
||||
|
||||
if (*is_little_endian)
|
||||
do {
|
||||
tmp = *x;
|
||||
tmp = (tmp << 16) | (tmp >> 16);
|
||||
*x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF);
|
||||
} while (--count);
|
||||
}
|
||||
|
||||
#if BF_SCALE
|
||||
/* Architectures which can shift addresses left by 2 bits with no extra cost */
|
||||
#define BF_ROUND(L, R, N) \
|
||||
tmp1 = L & 0xFF; \
|
||||
tmp2 = L >> 8; \
|
||||
tmp2 &= 0xFF; \
|
||||
tmp3 = L >> 16; \
|
||||
tmp3 &= 0xFF; \
|
||||
tmp4 = L >> 24; \
|
||||
tmp1 = data.ctx.S[3][tmp1]; \
|
||||
tmp2 = data.ctx.S[2][tmp2]; \
|
||||
tmp3 = data.ctx.S[1][tmp3]; \
|
||||
tmp3 += data.ctx.S[0][tmp4]; \
|
||||
tmp3 ^= tmp2; \
|
||||
R ^= data.ctx.P[N + 1]; \
|
||||
tmp3 += tmp1; \
|
||||
R ^= tmp3;
|
||||
#else
|
||||
/* Architectures with no complicated addressing modes supported */
|
||||
#define BF_INDEX(S, i) \
|
||||
(*((BF_word *)(((unsigned char *)S) + (i))))
|
||||
#define BF_ROUND(L, R, N) \
|
||||
tmp1 = L & 0xFF; \
|
||||
tmp1 <<= 2; \
|
||||
tmp2 = L >> 6; \
|
||||
tmp2 &= 0x3FC; \
|
||||
tmp3 = L >> 14; \
|
||||
tmp3 &= 0x3FC; \
|
||||
tmp4 = L >> 22; \
|
||||
tmp4 &= 0x3FC; \
|
||||
tmp1 = BF_INDEX(data.ctx.S[3], tmp1); \
|
||||
tmp2 = BF_INDEX(data.ctx.S[2], tmp2); \
|
||||
tmp3 = BF_INDEX(data.ctx.S[1], tmp3); \
|
||||
tmp3 += BF_INDEX(data.ctx.S[0], tmp4); \
|
||||
tmp3 ^= tmp2; \
|
||||
R ^= data.ctx.P[N + 1]; \
|
||||
tmp3 += tmp1; \
|
||||
R ^= tmp3;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Encrypt one block, BF_N is hardcoded here.
|
||||
*/
|
||||
#define BF_ENCRYPT \
|
||||
L ^= data.ctx.P[0]; \
|
||||
BF_ROUND(L, R, 0); \
|
||||
BF_ROUND(R, L, 1); \
|
||||
BF_ROUND(L, R, 2); \
|
||||
BF_ROUND(R, L, 3); \
|
||||
BF_ROUND(L, R, 4); \
|
||||
BF_ROUND(R, L, 5); \
|
||||
BF_ROUND(L, R, 6); \
|
||||
BF_ROUND(R, L, 7); \
|
||||
BF_ROUND(L, R, 8); \
|
||||
BF_ROUND(R, L, 9); \
|
||||
BF_ROUND(L, R, 10); \
|
||||
BF_ROUND(R, L, 11); \
|
||||
BF_ROUND(L, R, 12); \
|
||||
BF_ROUND(R, L, 13); \
|
||||
BF_ROUND(L, R, 14); \
|
||||
BF_ROUND(R, L, 15); \
|
||||
tmp4 = R; \
|
||||
R = L; \
|
||||
L = tmp4 ^ data.ctx.P[BF_N + 1];
|
||||
|
||||
#if BF_ASM
|
||||
#define BF_body() \
|
||||
_BF_body_r(&data.ctx);
|
||||
#else
|
||||
#define BF_body() \
|
||||
L = R = 0; \
|
||||
ptr = data.ctx.P; \
|
||||
do { \
|
||||
ptr += 2; \
|
||||
BF_ENCRYPT; \
|
||||
*(ptr - 2) = L; \
|
||||
*(ptr - 1) = R; \
|
||||
} while (ptr < &data.ctx.P[BF_N + 2]); \
|
||||
\
|
||||
ptr = data.ctx.S[0]; \
|
||||
do { \
|
||||
ptr += 2; \
|
||||
BF_ENCRYPT; \
|
||||
*(ptr - 2) = L; \
|
||||
*(ptr - 1) = R; \
|
||||
} while (ptr < &data.ctx.S[3][0xFF]);
|
||||
#endif
|
||||
|
||||
static void BF_set_key(const char *key, BF_key expanded, BF_key initial,
|
||||
unsigned char flags)
|
||||
{
|
||||
const char *ptr = key;
|
||||
unsigned int bug, i, j;
|
||||
BF_word safety, sign, diff, tmp[2];
|
||||
|
||||
/*
|
||||
* There was a sign extension bug in older revisions of this function. While
|
||||
* we would have liked to simply fix the bug and move on, we have to provide
|
||||
* a backwards compatibility feature (essentially the bug) for some systems and
|
||||
* a safety measure for some others. The latter is needed because for certain
|
||||
* multiple inputs to the buggy algorithm there exist easily found inputs to
|
||||
* the correct algorithm that produce the same hash. Thus, we optionally
|
||||
* deviate from the correct algorithm just enough to avoid such collisions.
|
||||
* While the bug itself affected the majority of passwords containing
|
||||
* characters with the 8th bit set (although only a percentage of those in a
|
||||
* collision-producing way), the anti-collision safety measure affects
|
||||
* only a subset of passwords containing the '\xff' character (not even all of
|
||||
* those passwords, just some of them). This character is not found in valid
|
||||
* UTF-8 sequences and is rarely used in popular 8-bit character encodings.
|
||||
* Thus, the safety measure is unlikely to cause much annoyance, and is a
|
||||
* reasonable tradeoff to use when authenticating against existing hashes that
|
||||
* are not reliably known to have been computed with the correct algorithm.
|
||||
*
|
||||
* We use an approach that tries to minimize side-channel leaks of password
|
||||
* information - that is, we mostly use fixed-cost bitwise operations instead
|
||||
* of branches or table lookups. (One conditional branch based on password
|
||||
* length remains. It is not part of the bug aftermath, though, and is
|
||||
* difficult and possibly unreasonable to avoid given the use of C strings by
|
||||
* the caller, which results in similar timing leaks anyway.)
|
||||
*
|
||||
* For actual implementation, we set an array index in the variable "bug"
|
||||
* (0 means no bug, 1 means sign extension bug emulation) and a flag in the
|
||||
* variable "safety" (bit 16 is set when the safety measure is requested).
|
||||
* Valid combinations of settings are:
|
||||
*
|
||||
* Prefix "$2a$": bug = 0, safety = 0x10000
|
||||
* Prefix "$2b$": bug = 0, safety = 0
|
||||
* Prefix "$2x$": bug = 1, safety = 0
|
||||
* Prefix "$2y$": bug = 0, safety = 0
|
||||
*/
|
||||
bug = (unsigned int)flags & 1;
|
||||
safety = ((BF_word)flags & 2) << 15;
|
||||
|
||||
sign = diff = 0;
|
||||
|
||||
for (i = 0; i < BF_N + 2; i++) {
|
||||
tmp[0] = tmp[1] = 0;
|
||||
for (j = 0; j < 4; j++) {
|
||||
tmp[0] <<= 8;
|
||||
tmp[0] |= (unsigned char)*ptr; /* correct */
|
||||
tmp[1] <<= 8;
|
||||
tmp[1] |= (BF_word_signed)(signed char)*ptr; /* bug */
|
||||
/*
|
||||
* Sign extension in the first char has no effect - nothing to overwrite yet,
|
||||
* and those extra 24 bits will be fully shifted out of the 32-bit word. For
|
||||
* chars 2, 3, 4 in each four-char block, we set bit 7 of "sign" if sign
|
||||
* extension in tmp[1] occurs. Once this flag is set, it remains set.
|
||||
*/
|
||||
if (j)
|
||||
sign |= tmp[1] & 0x80;
|
||||
if (!*ptr)
|
||||
ptr = key;
|
||||
else
|
||||
ptr++;
|
||||
}
|
||||
diff |= tmp[0] ^ tmp[1]; /* Non-zero on any differences */
|
||||
|
||||
expanded[i] = tmp[bug];
|
||||
initial[i] = BF_init_state.P[i] ^ tmp[bug];
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, "diff" is zero iff the correct and buggy algorithms produced
|
||||
* exactly the same result. If so and if "sign" is non-zero, which indicates
|
||||
* that there was a non-benign sign extension, this means that we have a
|
||||
* collision between the correctly computed hash for this password and a set of
|
||||
* passwords that could be supplied to the buggy algorithm. Our safety measure
|
||||
* is meant to protect from such many-buggy to one-correct collisions, by
|
||||
* deviating from the correct algorithm in such cases. Let's check for this.
|
||||
*/
|
||||
diff |= diff >> 16; /* still zero iff exact match */
|
||||
diff &= 0xffff; /* ditto */
|
||||
diff += 0xffff; /* bit 16 set iff "diff" was non-zero (on non-match) */
|
||||
sign <<= 9; /* move the non-benign sign extension flag to bit 16 */
|
||||
sign &= ~diff & safety; /* action needed? */
|
||||
|
||||
/*
|
||||
* If we have determined that we need to deviate from the correct algorithm,
|
||||
* flip bit 16 in initial expanded key. (The choice of 16 is arbitrary, but
|
||||
* let's stick to it now. It came out of the approach we used above, and it's
|
||||
* not any worse than any other choice we could make.)
|
||||
*
|
||||
* It is crucial that we don't do the same to the expanded key used in the main
|
||||
* Eksblowfish loop. By doing it to only one of these two, we deviate from a
|
||||
* state that could be directly specified by a password to the buggy algorithm
|
||||
* (and to the fully correct one as well, but that's a side-effect).
|
||||
*/
|
||||
initial[0] ^= sign;
|
||||
}
|
||||
|
||||
static const unsigned char flags_by_subtype[26] =
|
||||
{2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0};
|
||||
|
||||
static char *BF_crypt(const char *key, const char *setting,
|
||||
char *output, int size,
|
||||
BF_word min)
|
||||
{
|
||||
#if BF_ASM
|
||||
extern void _BF_body_r(BF_ctx *ctx);
|
||||
#endif
|
||||
struct {
|
||||
BF_ctx ctx;
|
||||
BF_key expanded_key;
|
||||
union {
|
||||
BF_word salt[4];
|
||||
BF_word output[6];
|
||||
} binary;
|
||||
} data;
|
||||
BF_word L, R;
|
||||
BF_word tmp1, tmp2, tmp3, tmp4;
|
||||
BF_word *ptr;
|
||||
BF_word count;
|
||||
int i;
|
||||
|
||||
if (size < 7 + 22 + 31 + 1) {
|
||||
__set_errno(ERANGE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (setting[0] != '$' ||
|
||||
setting[1] != '2' ||
|
||||
setting[2] < 'a' || setting[2] > 'z' ||
|
||||
!flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a'] ||
|
||||
setting[3] != '$' ||
|
||||
setting[4] < '0' || setting[4] > '3' ||
|
||||
setting[5] < '0' || setting[5] > '9' ||
|
||||
(setting[4] == '3' && setting[5] > '1') ||
|
||||
setting[6] != '$') {
|
||||
__set_errno(EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
|
||||
if (count < min || BF_decode(data.binary.salt, &setting[7], 16)) {
|
||||
__set_errno(EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
BF_swap(data.binary.salt, 4);
|
||||
|
||||
BF_set_key(key, data.expanded_key, data.ctx.P,
|
||||
flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a']);
|
||||
|
||||
memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S));
|
||||
|
||||
L = R = 0;
|
||||
for (i = 0; i < BF_N + 2; i += 2) {
|
||||
L ^= data.binary.salt[i & 2];
|
||||
R ^= data.binary.salt[(i & 2) + 1];
|
||||
BF_ENCRYPT;
|
||||
data.ctx.P[i] = L;
|
||||
data.ctx.P[i + 1] = R;
|
||||
}
|
||||
|
||||
ptr = data.ctx.S[0];
|
||||
do {
|
||||
ptr += 4;
|
||||
L ^= data.binary.salt[(BF_N + 2) & 3];
|
||||
R ^= data.binary.salt[(BF_N + 3) & 3];
|
||||
BF_ENCRYPT;
|
||||
*(ptr - 4) = L;
|
||||
*(ptr - 3) = R;
|
||||
|
||||
L ^= data.binary.salt[(BF_N + 4) & 3];
|
||||
R ^= data.binary.salt[(BF_N + 5) & 3];
|
||||
BF_ENCRYPT;
|
||||
*(ptr - 2) = L;
|
||||
*(ptr - 1) = R;
|
||||
} while (ptr < &data.ctx.S[3][0xFF]);
|
||||
|
||||
do {
|
||||
int done;
|
||||
|
||||
for (i = 0; i < BF_N + 2; i += 2) {
|
||||
data.ctx.P[i] ^= data.expanded_key[i];
|
||||
data.ctx.P[i + 1] ^= data.expanded_key[i + 1];
|
||||
}
|
||||
|
||||
done = 0;
|
||||
do {
|
||||
BF_body();
|
||||
if (done)
|
||||
break;
|
||||
done = 1;
|
||||
|
||||
tmp1 = data.binary.salt[0];
|
||||
tmp2 = data.binary.salt[1];
|
||||
tmp3 = data.binary.salt[2];
|
||||
tmp4 = data.binary.salt[3];
|
||||
for (i = 0; i < BF_N; i += 4) {
|
||||
data.ctx.P[i] ^= tmp1;
|
||||
data.ctx.P[i + 1] ^= tmp2;
|
||||
data.ctx.P[i + 2] ^= tmp3;
|
||||
data.ctx.P[i + 3] ^= tmp4;
|
||||
}
|
||||
data.ctx.P[16] ^= tmp1;
|
||||
data.ctx.P[17] ^= tmp2;
|
||||
} while (1);
|
||||
} while (--count);
|
||||
|
||||
for (i = 0; i < 6; i += 2) {
|
||||
L = BF_magic_w[i];
|
||||
R = BF_magic_w[i + 1];
|
||||
|
||||
count = 64;
|
||||
do {
|
||||
BF_ENCRYPT;
|
||||
} while (--count);
|
||||
|
||||
data.binary.output[i] = L;
|
||||
data.binary.output[i + 1] = R;
|
||||
}
|
||||
|
||||
memcpy(output, setting, 7 + 22 - 1);
|
||||
output[7 + 22 - 1] = BF_itoa64[(int)
|
||||
BF_atoi64[(int)setting[7 + 22 - 1] - 0x20] & 0x30];
|
||||
|
||||
/* This has to be bug-compatible with the original implementation, so
|
||||
* only encode 23 of the 24 bytes. :-) */
|
||||
BF_swap(data.binary.output, 6);
|
||||
BF_encode(&output[7 + 22], data.binary.output, 23);
|
||||
output[7 + 22 + 31] = '\0';
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
int _crypt_output_magic(const char *setting, char *output, int size)
|
||||
{
|
||||
if (size < 3)
|
||||
return -1;
|
||||
|
||||
output[0] = '*';
|
||||
output[1] = '0';
|
||||
output[2] = '\0';
|
||||
|
||||
if (setting[0] == '*' && setting[1] == '0')
|
||||
output[1] = '1';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Please preserve the runtime self-test. It serves two purposes at once:
|
||||
*
|
||||
* 1. We really can't afford the risk of producing incompatible hashes e.g.
|
||||
* when there's something like gcc bug 26587 again, whereas an application or
|
||||
* library integrating this code might not also integrate our external tests or
|
||||
* it might not run them after every build. Even if it does, the miscompile
|
||||
* might only occur on the production build, but not on a testing build (such
|
||||
* as because of different optimization settings). It is painful to recover
|
||||
* from incorrectly-computed hashes - merely fixing whatever broke is not
|
||||
* enough. Thus, a proactive measure like this self-test is needed.
|
||||
*
|
||||
* 2. We don't want to leave sensitive data from our actual password hash
|
||||
* computation on the stack or in registers. Previous revisions of the code
|
||||
* would do explicit cleanups, but simply running the self-test after hash
|
||||
* computation is more reliable.
|
||||
*
|
||||
* The performance cost of this quick self-test is around 0.6% at the "$2a$08"
|
||||
* setting.
|
||||
*/
|
||||
char *_crypt_blowfish_rn(const char *key, const char *setting,
|
||||
char *output, int size)
|
||||
{
|
||||
const char *test_key = "8b \xd0\xc1\xd2\xcf\xcc\xd8";
|
||||
const char *test_setting = "$2a$00$abcdefghijklmnopqrstuu";
|
||||
static const char * const test_hashes[2] =
|
||||
{"i1D709vfamulimlGcq0qq3UvuUasvEa\0\x55", /* 'a', 'b', 'y' */
|
||||
"VUrPmXD6q/nVSSp7pNDhCR9071IfIRe\0\x55"}; /* 'x' */
|
||||
const char *test_hash = test_hashes[0];
|
||||
char *retval;
|
||||
const char *p;
|
||||
int save_errno, ok;
|
||||
struct {
|
||||
char s[7 + 22 + 1];
|
||||
char o[7 + 22 + 31 + 1 + 1 + 1];
|
||||
} buf;
|
||||
|
||||
/* Hash the supplied password */
|
||||
_crypt_output_magic(setting, output, size);
|
||||
retval = BF_crypt(key, setting, output, size, 16);
|
||||
save_errno = errno;
|
||||
|
||||
/*
|
||||
* Do a quick self-test. It is important that we make both calls to BF_crypt()
|
||||
* from the same scope such that they likely use the same stack locations,
|
||||
* which makes the second call overwrite the first call's sensitive data on the
|
||||
* stack and makes it more likely that any alignment related issues would be
|
||||
* detected by the self-test.
|
||||
*/
|
||||
memcpy(buf.s, test_setting, sizeof(buf.s));
|
||||
if (retval) {
|
||||
unsigned int flags = flags_by_subtype[
|
||||
(unsigned int)(unsigned char)setting[2] - 'a'];
|
||||
test_hash = test_hashes[flags & 1];
|
||||
buf.s[2] = setting[2];
|
||||
}
|
||||
memset(buf.o, 0x55, sizeof(buf.o));
|
||||
buf.o[sizeof(buf.o) - 1] = 0;
|
||||
p = BF_crypt(test_key, buf.s, buf.o, sizeof(buf.o) - (1 + 1), 1);
|
||||
|
||||
ok = (p == buf.o &&
|
||||
!memcmp(p, buf.s, 7 + 22) &&
|
||||
!memcmp(p + (7 + 22), test_hash, 31 + 1 + 1 + 1));
|
||||
|
||||
{
|
||||
const char *k = "\xff\xa3" "34" "\xff\xff\xff\xa3" "345";
|
||||
BF_key ae, ai, ye, yi;
|
||||
BF_set_key(k, ae, ai, 2); /* $2a$ */
|
||||
BF_set_key(k, ye, yi, 4); /* $2y$ */
|
||||
ai[0] ^= 0x10000; /* undo the safety (for comparison) */
|
||||
ok = ok && ai[0] == 0xdb9c59bc && ye[17] == 0x33343500 &&
|
||||
!memcmp(ae, ye, sizeof(ae)) &&
|
||||
!memcmp(ai, yi, sizeof(ai));
|
||||
}
|
||||
|
||||
__set_errno(save_errno);
|
||||
if (ok)
|
||||
return retval;
|
||||
|
||||
/* Should not happen */
|
||||
_crypt_output_magic(setting, output, size);
|
||||
__set_errno(EINVAL); /* pretend we don't support this hash type */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *_crypt_gensalt_blowfish_rn(const char *prefix, unsigned long count,
|
||||
const char *input, int size, char *output, int output_size)
|
||||
{
|
||||
if (size < 16 || output_size < 7 + 22 + 1 ||
|
||||
(count && (count < 4 || count > 31)) ||
|
||||
prefix[0] != '$' || prefix[1] != '2' ||
|
||||
(prefix[2] != 'a' && prefix[2] != 'b' && prefix[2] != 'y')) {
|
||||
if (output_size > 0) output[0] = '\0';
|
||||
__set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!count) count = 5;
|
||||
|
||||
output[0] = '$';
|
||||
output[1] = '2';
|
||||
output[2] = prefix[2];
|
||||
output[3] = '$';
|
||||
output[4] = '0' + count / 10;
|
||||
output[5] = '0' + count % 10;
|
||||
output[6] = '$';
|
||||
|
||||
BF_encode(&output[7], (const BF_word *)input, 16);
|
||||
output[7 + 22] = '\0';
|
||||
|
||||
return output;
|
||||
}
|
27
deps/crypt_blowfish/crypt_blowfish.h
vendored
Normal file
27
deps/crypt_blowfish/crypt_blowfish.h
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Written by Solar Designer <solar at openwall.com> in 2000-2011.
|
||||
* No copyright is claimed, and the software is hereby placed in the public
|
||||
* domain. In case this attempt to disclaim copyright and place the software
|
||||
* in the public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* See crypt_blowfish.c for more information.
|
||||
*/
|
||||
|
||||
#ifndef _CRYPT_BLOWFISH_H
|
||||
#define _CRYPT_BLOWFISH_H
|
||||
|
||||
extern int _crypt_output_magic(const char *setting, char *output, int size);
|
||||
extern char *_crypt_blowfish_rn(const char *key, const char *setting,
|
||||
char *output, int size);
|
||||
extern char *_crypt_gensalt_blowfish_rn(const char *prefix,
|
||||
unsigned long count,
|
||||
const char *input, int size, char *output, int output_size);
|
||||
|
||||
#endif
|
124
deps/crypt_blowfish/crypt_gensalt.c
vendored
Normal file
124
deps/crypt_blowfish/crypt_gensalt.c
vendored
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Written by Solar Designer <solar at openwall.com> in 2000-2011.
|
||||
* No copyright is claimed, and the software is hereby placed in the public
|
||||
* domain. In case this attempt to disclaim copyright and place the software
|
||||
* in the public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* See crypt_blowfish.c for more information.
|
||||
*
|
||||
* This file contains salt generation functions for the traditional and
|
||||
* other common crypt(3) algorithms, except for bcrypt which is defined
|
||||
* entirely in crypt_blowfish.c.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef __set_errno
|
||||
#define __set_errno(val) errno = (val)
|
||||
#endif
|
||||
|
||||
/* Just to make sure the prototypes match the actual definitions */
|
||||
#include "crypt_gensalt.h"
|
||||
|
||||
unsigned char _crypt_itoa64[64 + 1] =
|
||||
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
char *_crypt_gensalt_traditional_rn(const char *prefix, unsigned long count,
|
||||
const char *input, int size, char *output, int output_size)
|
||||
{
|
||||
(void) prefix;
|
||||
|
||||
if (size < 2 || output_size < 2 + 1 || (count && count != 25)) {
|
||||
if (output_size > 0) output[0] = '\0';
|
||||
__set_errno((output_size < 2 + 1) ? ERANGE : EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
output[0] = _crypt_itoa64[(unsigned int)input[0] & 0x3f];
|
||||
output[1] = _crypt_itoa64[(unsigned int)input[1] & 0x3f];
|
||||
output[2] = '\0';
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
char *_crypt_gensalt_extended_rn(const char *prefix, unsigned long count,
|
||||
const char *input, int size, char *output, int output_size)
|
||||
{
|
||||
unsigned long value;
|
||||
|
||||
(void) prefix;
|
||||
|
||||
/* Even iteration counts make it easier to detect weak DES keys from a look
|
||||
* at the hash, so they should be avoided */
|
||||
if (size < 3 || output_size < 1 + 4 + 4 + 1 ||
|
||||
(count && (count > 0xffffff || !(count & 1)))) {
|
||||
if (output_size > 0) output[0] = '\0';
|
||||
__set_errno((output_size < 1 + 4 + 4 + 1) ? ERANGE : EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!count) count = 725;
|
||||
|
||||
output[0] = '_';
|
||||
output[1] = _crypt_itoa64[count & 0x3f];
|
||||
output[2] = _crypt_itoa64[(count >> 6) & 0x3f];
|
||||
output[3] = _crypt_itoa64[(count >> 12) & 0x3f];
|
||||
output[4] = _crypt_itoa64[(count >> 18) & 0x3f];
|
||||
value = (unsigned long)(unsigned char)input[0] |
|
||||
((unsigned long)(unsigned char)input[1] << 8) |
|
||||
((unsigned long)(unsigned char)input[2] << 16);
|
||||
output[5] = _crypt_itoa64[value & 0x3f];
|
||||
output[6] = _crypt_itoa64[(value >> 6) & 0x3f];
|
||||
output[7] = _crypt_itoa64[(value >> 12) & 0x3f];
|
||||
output[8] = _crypt_itoa64[(value >> 18) & 0x3f];
|
||||
output[9] = '\0';
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
char *_crypt_gensalt_md5_rn(const char *prefix, unsigned long count,
|
||||
const char *input, int size, char *output, int output_size)
|
||||
{
|
||||
unsigned long value;
|
||||
|
||||
(void) prefix;
|
||||
|
||||
if (size < 3 || output_size < 3 + 4 + 1 || (count && count != 1000)) {
|
||||
if (output_size > 0) output[0] = '\0';
|
||||
__set_errno((output_size < 3 + 4 + 1) ? ERANGE : EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
output[0] = '$';
|
||||
output[1] = '1';
|
||||
output[2] = '$';
|
||||
value = (unsigned long)(unsigned char)input[0] |
|
||||
((unsigned long)(unsigned char)input[1] << 8) |
|
||||
((unsigned long)(unsigned char)input[2] << 16);
|
||||
output[3] = _crypt_itoa64[value & 0x3f];
|
||||
output[4] = _crypt_itoa64[(value >> 6) & 0x3f];
|
||||
output[5] = _crypt_itoa64[(value >> 12) & 0x3f];
|
||||
output[6] = _crypt_itoa64[(value >> 18) & 0x3f];
|
||||
output[7] = '\0';
|
||||
|
||||
if (size >= 6 && output_size >= 3 + 4 + 4 + 1) {
|
||||
value = (unsigned long)(unsigned char)input[3] |
|
||||
((unsigned long)(unsigned char)input[4] << 8) |
|
||||
((unsigned long)(unsigned char)input[5] << 16);
|
||||
output[7] = _crypt_itoa64[value & 0x3f];
|
||||
output[8] = _crypt_itoa64[(value >> 6) & 0x3f];
|
||||
output[9] = _crypt_itoa64[(value >> 12) & 0x3f];
|
||||
output[10] = _crypt_itoa64[(value >> 18) & 0x3f];
|
||||
output[11] = '\0';
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
30
deps/crypt_blowfish/crypt_gensalt.h
vendored
Normal file
30
deps/crypt_blowfish/crypt_gensalt.h
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Written by Solar Designer <solar at openwall.com> in 2000-2011.
|
||||
* No copyright is claimed, and the software is hereby placed in the public
|
||||
* domain. In case this attempt to disclaim copyright and place the software
|
||||
* in the public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* See crypt_blowfish.c for more information.
|
||||
*/
|
||||
|
||||
#ifndef _CRYPT_GENSALT_H
|
||||
#define _CRYPT_GENSALT_H
|
||||
|
||||
extern unsigned char _crypt_itoa64[];
|
||||
extern char *_crypt_gensalt_traditional_rn(const char *prefix,
|
||||
unsigned long count,
|
||||
const char *input, int size, char *output, int output_size);
|
||||
extern char *_crypt_gensalt_extended_rn(const char *prefix,
|
||||
unsigned long count,
|
||||
const char *input, int size, char *output, int output_size);
|
||||
extern char *_crypt_gensalt_md5_rn(const char *prefix, unsigned long count,
|
||||
const char *input, int size, char *output, int output_size);
|
||||
|
||||
#endif
|
53
deps/crypt_blowfish/glibc-2.1.3-crypt.diff
vendored
Normal file
53
deps/crypt_blowfish/glibc-2.1.3-crypt.diff
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
--- glibc-2.1.3.orig/crypt/sysdeps/unix/Makefile 1997-03-05 00:33:59 +0000
|
||||
+++ glibc-2.1.3/crypt/sysdeps/unix/Makefile 2000-06-11 03:13:41 +0000
|
||||
@@ -1,4 +1,4 @@
|
||||
ifeq ($(subdir),md5-crypt)
|
||||
-libcrypt-routines += crypt crypt_util
|
||||
-dont_distribute += crypt.c crypt_util.c
|
||||
+libcrypt-routines += crypt crypt_util crypt_blowfish x86 crypt_gensalt wrapper
|
||||
+dont_distribute += crypt.c crypt_util.c crypt_blowfish.c x86.S crypt_gensalt.c wrapper.c
|
||||
endif
|
||||
--- glibc-2.1.3.orig/crypt/sysdeps/unix/crypt-entry.c 1998-12-10 12:49:04 +0000
|
||||
+++ glibc-2.1.3/crypt/sysdeps/unix/crypt-entry.c 2000-06-11 03:14:57 +0000
|
||||
@@ -70,7 +70,7 @@ extern struct crypt_data _ufc_foobar;
|
||||
*/
|
||||
|
||||
char *
|
||||
-__crypt_r (key, salt, data)
|
||||
+__des_crypt_r (key, salt, data)
|
||||
const char *key;
|
||||
const char *salt;
|
||||
struct crypt_data * __restrict data;
|
||||
@@ -115,6 +115,7 @@ __crypt_r (key, salt, data)
|
||||
_ufc_output_conversion_r (res[0], res[1], salt, data);
|
||||
return data->crypt_3_buf;
|
||||
}
|
||||
+#if 0
|
||||
weak_alias (__crypt_r, crypt_r)
|
||||
|
||||
char *
|
||||
@@ -147,3 +148,4 @@ __fcrypt (key, salt)
|
||||
return crypt (key, salt);
|
||||
}
|
||||
#endif
|
||||
+#endif
|
||||
--- glibc-2.1.3.orig/md5-crypt/Makefile 1998-07-02 22:46:47 +0000
|
||||
+++ glibc-2.1.3/md5-crypt/Makefile 2000-06-11 03:12:34 +0000
|
||||
@@ -21,7 +21,7 @@
|
||||
#
|
||||
subdir := md5-crypt
|
||||
|
||||
-headers := crypt.h
|
||||
+headers := crypt.h gnu-crypt.h ow-crypt.h
|
||||
|
||||
distribute := md5.h
|
||||
|
||||
--- glibc-2.1.3.orig/md5-crypt/Versions 1998-07-02 22:32:07 +0000
|
||||
+++ glibc-2.1.3/md5-crypt/Versions 2000-06-11 09:11:03 +0000
|
||||
@@ -1,5 +1,6 @@
|
||||
libcrypt {
|
||||
GLIBC_2.0 {
|
||||
crypt; crypt_r; encrypt; encrypt_r; fcrypt; setkey; setkey_r;
|
||||
+ crypt_rn; crypt_ra; crypt_gensalt; crypt_gensalt_rn; crypt_gensalt_ra;
|
||||
}
|
||||
}
|
55
deps/crypt_blowfish/glibc-2.14-crypt.diff
vendored
Normal file
55
deps/crypt_blowfish/glibc-2.14-crypt.diff
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
diff -urp glibc-2.14.orig/crypt/Makefile glibc-2.14/crypt/Makefile
|
||||
--- glibc-2.14.orig/crypt/Makefile 2011-05-31 04:12:33 +0000
|
||||
+++ glibc-2.14/crypt/Makefile 2011-07-16 21:40:56 +0000
|
||||
@@ -22,6 +22,7 @@
|
||||
subdir := crypt
|
||||
|
||||
headers := crypt.h
|
||||
+headers += gnu-crypt.h ow-crypt.h
|
||||
|
||||
extra-libs := libcrypt
|
||||
extra-libs-others := $(extra-libs)
|
||||
@@ -29,6 +30,8 @@ extra-libs-others := $(extra-libs)
|
||||
libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt crypt \
|
||||
crypt_util
|
||||
|
||||
+libcrypt-routines += crypt_blowfish x86 crypt_gensalt wrapper
|
||||
+
|
||||
tests := cert md5c-test sha256c-test sha512c-test
|
||||
|
||||
distribute := ufc-crypt.h crypt-private.h ufc.c speeds.c README.ufc-crypt \
|
||||
diff -urp glibc-2.14.orig/crypt/Versions glibc-2.14/crypt/Versions
|
||||
--- glibc-2.14.orig/crypt/Versions 2011-05-31 04:12:33 +0000
|
||||
+++ glibc-2.14/crypt/Versions 2011-07-16 21:40:56 +0000
|
||||
@@ -1,5 +1,6 @@
|
||||
libcrypt {
|
||||
GLIBC_2.0 {
|
||||
crypt; crypt_r; encrypt; encrypt_r; fcrypt; setkey; setkey_r;
|
||||
+ crypt_rn; crypt_ra; crypt_gensalt; crypt_gensalt_rn; crypt_gensalt_ra;
|
||||
}
|
||||
}
|
||||
diff -urp glibc-2.14.orig/crypt/crypt-entry.c glibc-2.14/crypt/crypt-entry.c
|
||||
--- glibc-2.14.orig/crypt/crypt-entry.c 2011-05-31 04:12:33 +0000
|
||||
+++ glibc-2.14/crypt/crypt-entry.c 2011-07-16 21:40:56 +0000
|
||||
@@ -82,7 +82,7 @@ extern struct crypt_data _ufc_foobar;
|
||||
*/
|
||||
|
||||
char *
|
||||
-__crypt_r (key, salt, data)
|
||||
+__des_crypt_r (key, salt, data)
|
||||
const char *key;
|
||||
const char *salt;
|
||||
struct crypt_data * __restrict data;
|
||||
@@ -137,6 +137,7 @@ __crypt_r (key, salt, data)
|
||||
_ufc_output_conversion_r (res[0], res[1], salt, data);
|
||||
return data->crypt_3_buf;
|
||||
}
|
||||
+#if 0
|
||||
weak_alias (__crypt_r, crypt_r)
|
||||
|
||||
char *
|
||||
@@ -177,3 +178,4 @@ __fcrypt (key, salt)
|
||||
return crypt (key, salt);
|
||||
}
|
||||
#endif
|
||||
+#endif
|
52
deps/crypt_blowfish/glibc-2.3.6-crypt.diff
vendored
Normal file
52
deps/crypt_blowfish/glibc-2.3.6-crypt.diff
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
--- glibc-2.3.6.orig/crypt/Makefile 2001-07-06 04:54:45 +0000
|
||||
+++ glibc-2.3.6/crypt/Makefile 2004-02-27 00:23:48 +0000
|
||||
@@ -21,14 +21,14 @@
|
||||
#
|
||||
subdir := crypt
|
||||
|
||||
-headers := crypt.h
|
||||
+headers := crypt.h gnu-crypt.h ow-crypt.h
|
||||
|
||||
distribute := md5.h
|
||||
|
||||
extra-libs := libcrypt
|
||||
extra-libs-others := $(extra-libs)
|
||||
|
||||
-libcrypt-routines := crypt-entry md5-crypt md5 crypt crypt_util
|
||||
+libcrypt-routines := crypt-entry md5-crypt md5 crypt crypt_util crypt_blowfish x86 crypt_gensalt wrapper
|
||||
|
||||
tests = cert md5test md5c-test
|
||||
|
||||
--- glibc-2.3.6.orig/crypt/Versions 2000-03-04 00:47:30 +0000
|
||||
+++ glibc-2.3.6/crypt/Versions 2004-02-27 00:25:15 +0000
|
||||
@@ -1,5 +1,6 @@
|
||||
libcrypt {
|
||||
GLIBC_2.0 {
|
||||
crypt; crypt_r; encrypt; encrypt_r; fcrypt; setkey; setkey_r;
|
||||
+ crypt_rn; crypt_ra; crypt_gensalt; crypt_gensalt_rn; crypt_gensalt_ra;
|
||||
}
|
||||
}
|
||||
--- glibc-2.3.6.orig/crypt/crypt-entry.c 2001-07-06 05:18:49 +0000
|
||||
+++ glibc-2.3.6/crypt/crypt-entry.c 2004-02-27 00:12:32 +0000
|
||||
@@ -70,7 +70,7 @@ extern struct crypt_data _ufc_foobar;
|
||||
*/
|
||||
|
||||
char *
|
||||
-__crypt_r (key, salt, data)
|
||||
+__des_crypt_r (key, salt, data)
|
||||
const char *key;
|
||||
const char *salt;
|
||||
struct crypt_data * __restrict data;
|
||||
@@ -115,6 +115,7 @@ __crypt_r (key, salt, data)
|
||||
_ufc_output_conversion_r (res[0], res[1], salt, data);
|
||||
return data->crypt_3_buf;
|
||||
}
|
||||
+#if 0
|
||||
weak_alias (__crypt_r, crypt_r)
|
||||
|
||||
char *
|
||||
@@ -147,3 +148,4 @@ __fcrypt (key, salt)
|
||||
return crypt (key, salt);
|
||||
}
|
||||
#endif
|
||||
+#endif
|
43
deps/crypt_blowfish/ow-crypt.h
vendored
Normal file
43
deps/crypt_blowfish/ow-crypt.h
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Written by Solar Designer <solar at openwall.com> in 2000-2011.
|
||||
* No copyright is claimed, and the software is hereby placed in the public
|
||||
* domain. In case this attempt to disclaim copyright and place the software
|
||||
* in the public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2000-2011 Solar Designer and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* See crypt_blowfish.c for more information.
|
||||
*/
|
||||
|
||||
#ifndef _OW_CRYPT_H
|
||||
#define _OW_CRYPT_H
|
||||
|
||||
#ifndef __GNUC__
|
||||
#undef __const
|
||||
#define __const const
|
||||
#endif
|
||||
|
||||
#ifndef __SKIP_GNU
|
||||
extern char *crypt(__const char *key, __const char *setting);
|
||||
extern char *crypt_r(__const char *key, __const char *setting, void *data);
|
||||
#endif
|
||||
|
||||
#ifndef __SKIP_OW
|
||||
extern char *crypt_rn(__const char *key, __const char *setting,
|
||||
void *data, int size);
|
||||
extern char *crypt_ra(__const char *key, __const char *setting,
|
||||
void **data, int *size);
|
||||
extern char *crypt_gensalt(__const char *prefix, unsigned long count,
|
||||
__const char *input, int size);
|
||||
extern char *crypt_gensalt_rn(__const char *prefix, unsigned long count,
|
||||
__const char *input, int size, char *output, int output_size);
|
||||
extern char *crypt_gensalt_ra(__const char *prefix, unsigned long count,
|
||||
__const char *input, int size);
|
||||
#endif
|
||||
|
||||
#endif
|
551
deps/crypt_blowfish/wrapper.c
vendored
Normal file
551
deps/crypt_blowfish/wrapper.c
vendored
Normal file
@ -0,0 +1,551 @@
|
||||
/*
|
||||
* Written by Solar Designer <solar at openwall.com> in 2000-2014.
|
||||
* No copyright is claimed, and the software is hereby placed in the public
|
||||
* domain. In case this attempt to disclaim copyright and place the software
|
||||
* in the public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 2000-2014 Solar Designer and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* See crypt_blowfish.c for more information.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
#ifndef __set_errno
|
||||
#define __set_errno(val) errno = (val)
|
||||
#endif
|
||||
|
||||
#ifdef TEST
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/times.h>
|
||||
#ifdef TEST_THREADS
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define CRYPT_OUTPUT_SIZE (7 + 22 + 31 + 1)
|
||||
#define CRYPT_GENSALT_OUTPUT_SIZE (7 + 22 + 1)
|
||||
|
||||
#if defined(__GLIBC__) && defined(_LIBC)
|
||||
#define __SKIP_GNU
|
||||
#endif
|
||||
#include "ow-crypt.h"
|
||||
|
||||
#include "crypt_blowfish.h"
|
||||
#include "crypt_gensalt.h"
|
||||
|
||||
#if defined(__GLIBC__) && defined(_LIBC)
|
||||
/* crypt.h from glibc-crypt-2.1 will define struct crypt_data for us */
|
||||
#include "crypt.h"
|
||||
extern char *__md5_crypt_r(const char *key, const char *salt,
|
||||
char *buffer, int buflen);
|
||||
/* crypt-entry.c needs to be patched to define __des_crypt_r rather than
|
||||
* __crypt_r, and not define crypt_r and crypt at all */
|
||||
extern char *__des_crypt_r(const char *key, const char *salt,
|
||||
struct crypt_data *data);
|
||||
extern struct crypt_data _ufc_foobar;
|
||||
#endif
|
||||
|
||||
static int _crypt_data_alloc(void **data, int *size, int need)
|
||||
{
|
||||
void *updated;
|
||||
|
||||
if (*data && *size >= need) return 0;
|
||||
|
||||
updated = realloc(*data, need);
|
||||
|
||||
if (!updated) {
|
||||
#ifndef __GLIBC__
|
||||
/* realloc(3) on glibc sets errno, so we don't need to bother */
|
||||
__set_errno(ENOMEM);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(__GLIBC__) && defined(_LIBC)
|
||||
if (need >= sizeof(struct crypt_data))
|
||||
((struct crypt_data *)updated)->initialized = 0;
|
||||
#endif
|
||||
|
||||
*data = updated;
|
||||
*size = need;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *_crypt_retval_magic(char *retval, const char *setting,
|
||||
char *output, int size)
|
||||
{
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
if (_crypt_output_magic(setting, output, size))
|
||||
return NULL; /* shouldn't happen */
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#if defined(__GLIBC__) && defined(_LIBC)
|
||||
/*
|
||||
* Applications may re-use the same instance of struct crypt_data without
|
||||
* resetting the initialized field in order to let crypt_r() skip some of
|
||||
* its initialization code. Thus, it is important that our multiple hashing
|
||||
* algorithms either don't conflict with each other in their use of the
|
||||
* data area or reset the initialized field themselves whenever required.
|
||||
* Currently, the hashing algorithms simply have no conflicts: the first
|
||||
* field of struct crypt_data is the 128-byte large DES key schedule which
|
||||
* __des_crypt_r() calculates each time it is called while the two other
|
||||
* hashing algorithms use less than 128 bytes of the data area.
|
||||
*/
|
||||
|
||||
char *__crypt_rn(__const char *key, __const char *setting,
|
||||
void *data, int size)
|
||||
{
|
||||
if (setting[0] == '$' && setting[1] == '2')
|
||||
return _crypt_blowfish_rn(key, setting, (char *)data, size);
|
||||
if (setting[0] == '$' && setting[1] == '1')
|
||||
return __md5_crypt_r(key, setting, (char *)data, size);
|
||||
if (setting[0] == '$' || setting[0] == '_') {
|
||||
__set_errno(EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
if (size >= sizeof(struct crypt_data))
|
||||
return __des_crypt_r(key, setting, (struct crypt_data *)data);
|
||||
__set_errno(ERANGE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *__crypt_ra(__const char *key, __const char *setting,
|
||||
void **data, int *size)
|
||||
{
|
||||
if (setting[0] == '$' && setting[1] == '2') {
|
||||
if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE))
|
||||
return NULL;
|
||||
return _crypt_blowfish_rn(key, setting, (char *)*data, *size);
|
||||
}
|
||||
if (setting[0] == '$' && setting[1] == '1') {
|
||||
if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE))
|
||||
return NULL;
|
||||
return __md5_crypt_r(key, setting, (char *)*data, *size);
|
||||
}
|
||||
if (setting[0] == '$' || setting[0] == '_') {
|
||||
__set_errno(EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
if (_crypt_data_alloc(data, size, sizeof(struct crypt_data)))
|
||||
return NULL;
|
||||
return __des_crypt_r(key, setting, (struct crypt_data *)*data);
|
||||
}
|
||||
|
||||
char *__crypt_r(__const char *key, __const char *setting,
|
||||
struct crypt_data *data)
|
||||
{
|
||||
return _crypt_retval_magic(
|
||||
__crypt_rn(key, setting, data, sizeof(*data)),
|
||||
setting, (char *)data, sizeof(*data));
|
||||
}
|
||||
|
||||
char *__crypt(__const char *key, __const char *setting)
|
||||
{
|
||||
return _crypt_retval_magic(
|
||||
__crypt_rn(key, setting, &_ufc_foobar, sizeof(_ufc_foobar)),
|
||||
setting, (char *)&_ufc_foobar, sizeof(_ufc_foobar));
|
||||
}
|
||||
#else
|
||||
char *crypt_rn(const char *key, const char *setting, void *data, int size)
|
||||
{
|
||||
return _crypt_blowfish_rn(key, setting, (char *)data, size);
|
||||
}
|
||||
|
||||
char *crypt_ra(const char *key, const char *setting,
|
||||
void **data, int *size)
|
||||
{
|
||||
if (_crypt_data_alloc(data, size, CRYPT_OUTPUT_SIZE))
|
||||
return NULL;
|
||||
return _crypt_blowfish_rn(key, setting, (char *)*data, *size);
|
||||
}
|
||||
|
||||
char *crypt_r(const char *key, const char *setting, void *data)
|
||||
{
|
||||
return _crypt_retval_magic(
|
||||
crypt_rn(key, setting, data, CRYPT_OUTPUT_SIZE),
|
||||
setting, (char *)data, CRYPT_OUTPUT_SIZE);
|
||||
}
|
||||
|
||||
char *crypt(const char *key, const char *setting)
|
||||
{
|
||||
static char output[CRYPT_OUTPUT_SIZE];
|
||||
|
||||
return _crypt_retval_magic(
|
||||
crypt_rn(key, setting, output, sizeof(output)),
|
||||
setting, output, sizeof(output));
|
||||
}
|
||||
|
||||
#define __crypt_gensalt_rn crypt_gensalt_rn
|
||||
#define __crypt_gensalt_ra crypt_gensalt_ra
|
||||
#define __crypt_gensalt crypt_gensalt
|
||||
#endif
|
||||
|
||||
char *__crypt_gensalt_rn(const char *prefix, unsigned long count,
|
||||
const char *input, int size, char *output, int output_size)
|
||||
{
|
||||
char *(*use)(const char *_prefix, unsigned long _count,
|
||||
const char *_input, int _size,
|
||||
char *_output, int _output_size);
|
||||
|
||||
/* This may be supported on some platforms in the future */
|
||||
if (!input) {
|
||||
__set_errno(EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!strncmp(prefix, "$2a$", 4) || !strncmp(prefix, "$2b$", 4) ||
|
||||
!strncmp(prefix, "$2y$", 4))
|
||||
use = _crypt_gensalt_blowfish_rn;
|
||||
else
|
||||
if (!strncmp(prefix, "$1$", 3))
|
||||
use = _crypt_gensalt_md5_rn;
|
||||
else
|
||||
if (prefix[0] == '_')
|
||||
use = _crypt_gensalt_extended_rn;
|
||||
else
|
||||
if (!prefix[0] ||
|
||||
(prefix[0] && prefix[1] &&
|
||||
memchr(_crypt_itoa64, prefix[0], 64) &&
|
||||
memchr(_crypt_itoa64, prefix[1], 64)))
|
||||
use = _crypt_gensalt_traditional_rn;
|
||||
else {
|
||||
__set_errno(EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return use(prefix, count, input, size, output, output_size);
|
||||
}
|
||||
|
||||
char *__crypt_gensalt_ra(const char *prefix, unsigned long count,
|
||||
const char *input, int size)
|
||||
{
|
||||
char output[CRYPT_GENSALT_OUTPUT_SIZE];
|
||||
char *retval;
|
||||
|
||||
retval = __crypt_gensalt_rn(prefix, count,
|
||||
input, size, output, sizeof(output));
|
||||
|
||||
if (retval) {
|
||||
retval = strdup(retval);
|
||||
#ifndef __GLIBC__
|
||||
/* strdup(3) on glibc sets errno, so we don't need to bother */
|
||||
if (!retval)
|
||||
__set_errno(ENOMEM);
|
||||
#endif
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
char *__crypt_gensalt(const char *prefix, unsigned long count,
|
||||
const char *input, int size)
|
||||
{
|
||||
static char output[CRYPT_GENSALT_OUTPUT_SIZE];
|
||||
|
||||
return __crypt_gensalt_rn(prefix, count,
|
||||
input, size, output, sizeof(output));
|
||||
}
|
||||
|
||||
#if defined(__GLIBC__) && defined(_LIBC)
|
||||
weak_alias(__crypt_rn, crypt_rn)
|
||||
weak_alias(__crypt_ra, crypt_ra)
|
||||
weak_alias(__crypt_r, crypt_r)
|
||||
weak_alias(__crypt, crypt)
|
||||
weak_alias(__crypt_gensalt_rn, crypt_gensalt_rn)
|
||||
weak_alias(__crypt_gensalt_ra, crypt_gensalt_ra)
|
||||
weak_alias(__crypt_gensalt, crypt_gensalt)
|
||||
weak_alias(crypt, fcrypt)
|
||||
#endif
|
||||
|
||||
#ifdef TEST
|
||||
static const char *tests[][3] = {
|
||||
{"$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW",
|
||||
"U*U"},
|
||||
{"$2a$05$CCCCCCCCCCCCCCCCCCCCC.VGOzA784oUp/Z0DY336zx7pLYAy0lwK",
|
||||
"U*U*"},
|
||||
{"$2a$05$XXXXXXXXXXXXXXXXXXXXXOAcXxm9kjPGEMsLznoKqmqw7tc8WCx4a",
|
||||
"U*U*U"},
|
||||
{"$2a$05$abcdefghijklmnopqrstuu5s2v8.iXieOjg/.AySBTTZIIVFJeBui",
|
||||
"0123456789abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
"chars after 72 are ignored"},
|
||||
{"$2x$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e",
|
||||
"\xa3"},
|
||||
{"$2x$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e",
|
||||
"\xff\xff\xa3"},
|
||||
{"$2y$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e",
|
||||
"\xff\xff\xa3"},
|
||||
{"$2a$05$/OK.fbVrR/bpIqNJ5ianF.nqd1wy.pTMdcvrRWxyiGL2eMz.2a85.",
|
||||
"\xff\xff\xa3"},
|
||||
{"$2b$05$/OK.fbVrR/bpIqNJ5ianF.CE5elHaaO4EbggVDjb8P19RukzXSM3e",
|
||||
"\xff\xff\xa3"},
|
||||
{"$2y$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq",
|
||||
"\xa3"},
|
||||
{"$2a$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq",
|
||||
"\xa3"},
|
||||
{"$2b$05$/OK.fbVrR/bpIqNJ5ianF.Sa7shbm4.OzKpvFnX1pQLmQW96oUlCq",
|
||||
"\xa3"},
|
||||
{"$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi",
|
||||
"1\xa3" "345"},
|
||||
{"$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi",
|
||||
"\xff\xa3" "345"},
|
||||
{"$2x$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi",
|
||||
"\xff\xa3" "34" "\xff\xff\xff\xa3" "345"},
|
||||
{"$2y$05$/OK.fbVrR/bpIqNJ5ianF.o./n25XVfn6oAPaUvHe.Csk4zRfsYPi",
|
||||
"\xff\xa3" "34" "\xff\xff\xff\xa3" "345"},
|
||||
{"$2a$05$/OK.fbVrR/bpIqNJ5ianF.ZC1JEJ8Z4gPfpe1JOr/oyPXTWl9EFd.",
|
||||
"\xff\xa3" "34" "\xff\xff\xff\xa3" "345"},
|
||||
{"$2y$05$/OK.fbVrR/bpIqNJ5ianF.nRht2l/HRhr6zmCp9vYUvvsqynflf9e",
|
||||
"\xff\xa3" "345"},
|
||||
{"$2a$05$/OK.fbVrR/bpIqNJ5ianF.nRht2l/HRhr6zmCp9vYUvvsqynflf9e",
|
||||
"\xff\xa3" "345"},
|
||||
{"$2a$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS",
|
||||
"\xa3" "ab"},
|
||||
{"$2x$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS",
|
||||
"\xa3" "ab"},
|
||||
{"$2y$05$/OK.fbVrR/bpIqNJ5ianF.6IflQkJytoRVc1yuaNtHfiuq.FRlSIS",
|
||||
"\xa3" "ab"},
|
||||
{"$2x$05$6bNw2HLQYeqHYyBfLMsv/OiwqTymGIGzFsA4hOTWebfehXHNprcAS",
|
||||
"\xd1\x91"},
|
||||
{"$2x$05$6bNw2HLQYeqHYyBfLMsv/O9LIGgn8OMzuDoHfof8AQimSGfcSWxnS",
|
||||
"\xd0\xc1\xd2\xcf\xcc\xd8"},
|
||||
{"$2a$05$/OK.fbVrR/bpIqNJ5ianF.swQOIzjOiJ9GHEPuhEkvqrUyvWhEMx6",
|
||||
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
|
||||
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
|
||||
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
|
||||
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
|
||||
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
|
||||
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
|
||||
"chars after 72 are ignored as usual"},
|
||||
{"$2a$05$/OK.fbVrR/bpIqNJ5ianF.R9xrDjiycxMbQE2bp.vgqlYpW5wx2yy",
|
||||
"\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55"
|
||||
"\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55"
|
||||
"\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55"
|
||||
"\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55"
|
||||
"\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55"
|
||||
"\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55\xaa\x55"},
|
||||
{"$2a$05$/OK.fbVrR/bpIqNJ5ianF.9tQZzcJfm3uj2NvJ/n5xkhpqLrMpWCe",
|
||||
"\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff"
|
||||
"\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff"
|
||||
"\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff"
|
||||
"\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff"
|
||||
"\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff"
|
||||
"\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff\x55\xaa\xff"},
|
||||
{"$2a$05$CCCCCCCCCCCCCCCCCCCCC.7uG0VCzI2bS7j6ymqJi9CdcdxiRTWNy",
|
||||
""},
|
||||
{"*0", "", "$2a$03$CCCCCCCCCCCCCCCCCCCCC."},
|
||||
{"*0", "", "$2a$32$CCCCCCCCCCCCCCCCCCCCC."},
|
||||
{"*0", "", "$2c$05$CCCCCCCCCCCCCCCCCCCCC."},
|
||||
{"*0", "", "$2z$05$CCCCCCCCCCCCCCCCCCCCC."},
|
||||
{"*0", "", "$2`$05$CCCCCCCCCCCCCCCCCCCCC."},
|
||||
{"*0", "", "$2{$05$CCCCCCCCCCCCCCCCCCCCC."},
|
||||
{"*1", "", "*0"},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
#define which tests[0]
|
||||
|
||||
static volatile sig_atomic_t running;
|
||||
|
||||
static void handle_timer(int signum)
|
||||
{
|
||||
(void) signum;
|
||||
running = 0;
|
||||
}
|
||||
|
||||
static void *run(void *arg)
|
||||
{
|
||||
unsigned long count = 0;
|
||||
int i = 0;
|
||||
void *data = NULL;
|
||||
int size = 0x12345678;
|
||||
|
||||
do {
|
||||
const char *hash = tests[i][0];
|
||||
const char *key = tests[i][1];
|
||||
const char *setting = tests[i][2];
|
||||
|
||||
if (!tests[++i][0])
|
||||
i = 0;
|
||||
|
||||
if (setting && strlen(hash) < 30) /* not for benchmark */
|
||||
continue;
|
||||
|
||||
if (strcmp(crypt_ra(key, hash, &data, &size), hash)) {
|
||||
printf("%d: FAILED (crypt_ra/%d/%lu)\n",
|
||||
(int)((char *)arg - (char *)0), i, count);
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
count++;
|
||||
} while (running);
|
||||
|
||||
free(data);
|
||||
return count + (char *)0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct itimerval it;
|
||||
struct tms buf;
|
||||
clock_t clk_tck, start_real, start_virtual, end_real, end_virtual;
|
||||
unsigned long count;
|
||||
void *data;
|
||||
int size;
|
||||
char *setting1, *setting2;
|
||||
int i;
|
||||
#ifdef TEST_THREADS
|
||||
pthread_t t[TEST_THREADS];
|
||||
void *t_retval;
|
||||
#endif
|
||||
|
||||
data = NULL;
|
||||
size = 0x12345678;
|
||||
|
||||
for (i = 0; tests[i][0]; i++) {
|
||||
const char *hash = tests[i][0];
|
||||
const char *key = tests[i][1];
|
||||
const char *setting = tests[i][2];
|
||||
const char *p;
|
||||
int ok = !setting || strlen(hash) >= 30;
|
||||
int o_size;
|
||||
char s_buf[30], o_buf[61];
|
||||
if (!setting) {
|
||||
memcpy(s_buf, hash, sizeof(s_buf) - 1);
|
||||
s_buf[sizeof(s_buf) - 1] = 0;
|
||||
setting = s_buf;
|
||||
}
|
||||
|
||||
__set_errno(0);
|
||||
p = crypt(key, setting);
|
||||
if ((!ok && !errno) || strcmp(p, hash)) {
|
||||
printf("FAILED (crypt/%d)\n", i);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ok && strcmp(crypt(key, hash), hash)) {
|
||||
printf("FAILED (crypt/%d)\n", i);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (o_size = -1; o_size <= (int)sizeof(o_buf); o_size++) {
|
||||
int ok_n = ok && o_size == (int)sizeof(o_buf);
|
||||
const char *x = "abc";
|
||||
strcpy(o_buf, x);
|
||||
if (o_size >= 3) {
|
||||
x = "*0";
|
||||
if (setting[0] == '*' && setting[1] == '0')
|
||||
x = "*1";
|
||||
}
|
||||
__set_errno(0);
|
||||
p = crypt_rn(key, setting, o_buf, o_size);
|
||||
if ((ok_n && (!p || strcmp(p, hash))) ||
|
||||
(!ok_n && (!errno || p || strcmp(o_buf, x)))) {
|
||||
printf("FAILED (crypt_rn/%d)\n", i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
__set_errno(0);
|
||||
p = crypt_ra(key, setting, &data, &size);
|
||||
if ((ok && (!p || strcmp(p, hash))) ||
|
||||
(!ok && (!errno || p || strcmp((char *)data, hash)))) {
|
||||
printf("FAILED (crypt_ra/%d)\n", i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
setting1 = crypt_gensalt(which[0], 12, data, size);
|
||||
if (!setting1 || strncmp(setting1, "$2a$12$", 7)) {
|
||||
puts("FAILED (crypt_gensalt)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
setting2 = crypt_gensalt_ra(setting1, 12, data, size);
|
||||
if (strcmp(setting1, setting2)) {
|
||||
puts("FAILED (crypt_gensalt_ra/1)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
(*(char *)data)++;
|
||||
setting1 = crypt_gensalt_ra(setting2, 12, data, size);
|
||||
if (!strcmp(setting1, setting2)) {
|
||||
puts("FAILED (crypt_gensalt_ra/2)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
free(setting1);
|
||||
free(setting2);
|
||||
free(data);
|
||||
|
||||
#if defined(_SC_CLK_TCK) || !defined(CLK_TCK)
|
||||
clk_tck = sysconf(_SC_CLK_TCK);
|
||||
#else
|
||||
clk_tck = CLK_TCK;
|
||||
#endif
|
||||
|
||||
running = 1;
|
||||
signal(SIGALRM, handle_timer);
|
||||
|
||||
memset(&it, 0, sizeof(it));
|
||||
it.it_value.tv_sec = 5;
|
||||
setitimer(ITIMER_REAL, &it, NULL);
|
||||
|
||||
start_real = times(&buf);
|
||||
start_virtual = buf.tms_utime + buf.tms_stime;
|
||||
|
||||
count = (char *)run((char *)0) - (char *)0;
|
||||
|
||||
end_real = times(&buf);
|
||||
end_virtual = buf.tms_utime + buf.tms_stime;
|
||||
if (end_virtual == start_virtual) end_virtual++;
|
||||
|
||||
printf("%.1f c/s real, %.1f c/s virtual\n",
|
||||
(float)count * clk_tck / (end_real - start_real),
|
||||
(float)count * clk_tck / (end_virtual - start_virtual));
|
||||
|
||||
#ifdef TEST_THREADS
|
||||
running = 1;
|
||||
it.it_value.tv_sec = 60;
|
||||
setitimer(ITIMER_REAL, &it, NULL);
|
||||
start_real = times(&buf);
|
||||
|
||||
for (i = 0; i < TEST_THREADS; i++)
|
||||
if (pthread_create(&t[i], NULL, run, i + (char *)0)) {
|
||||
perror("pthread_create");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < TEST_THREADS; i++) {
|
||||
if (pthread_join(t[i], &t_retval)) {
|
||||
perror("pthread_join");
|
||||
continue;
|
||||
}
|
||||
if (!t_retval) continue;
|
||||
count = (char *)t_retval - (char *)0;
|
||||
end_real = times(&buf);
|
||||
printf("%d: %.1f c/s real\n", i,
|
||||
(float)count * clk_tck / (end_real - start_real));
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
203
deps/crypt_blowfish/x86.S
vendored
Normal file
203
deps/crypt_blowfish/x86.S
vendored
Normal file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Written by Solar Designer <solar at openwall.com> in 1998-2010.
|
||||
* No copyright is claimed, and the software is hereby placed in the public
|
||||
* domain. In case this attempt to disclaim copyright and place the software
|
||||
* in the public domain is deemed null and void, then the software is
|
||||
* Copyright (c) 1998-2010 Solar Designer and it is hereby released to the
|
||||
* general public under the following terms:
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted.
|
||||
*
|
||||
* There's ABSOLUTELY NO WARRANTY, express or implied.
|
||||
*
|
||||
* See crypt_blowfish.c for more information.
|
||||
*/
|
||||
|
||||
#ifdef __i386__
|
||||
|
||||
#if defined(__OpenBSD__) && !defined(__ELF__)
|
||||
#define UNDERSCORES
|
||||
#define ALIGN_LOG
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN32__) || defined(__MINGW32__)
|
||||
#define UNDERSCORES
|
||||
#endif
|
||||
|
||||
#ifdef __DJGPP__
|
||||
#define UNDERSCORES
|
||||
#define ALIGN_LOG
|
||||
#endif
|
||||
|
||||
#ifdef UNDERSCORES
|
||||
#define _BF_body_r __BF_body_r
|
||||
#endif
|
||||
|
||||
#ifdef ALIGN_LOG
|
||||
#define DO_ALIGN(log) .align (log)
|
||||
#elif defined(DUMBAS)
|
||||
#define DO_ALIGN(log) .align 1 << log
|
||||
#else
|
||||
#define DO_ALIGN(log) .align (1 << (log))
|
||||
#endif
|
||||
|
||||
#define BF_FRAME 0x200
|
||||
#define ctx %esp
|
||||
|
||||
#define BF_ptr (ctx)
|
||||
|
||||
#define S(N, r) N+BF_FRAME(ctx,r,4)
|
||||
#ifdef DUMBAS
|
||||
#define P(N) 0x1000+N+N+N+N+BF_FRAME(ctx)
|
||||
#else
|
||||
#define P(N) 0x1000+4*N+BF_FRAME(ctx)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This version of the assembly code is optimized primarily for the original
|
||||
* Intel Pentium but is also careful to avoid partial register stalls on the
|
||||
* Pentium Pro family of processors (tested up to Pentium III Coppermine).
|
||||
*
|
||||
* It is possible to do 15% faster on the Pentium Pro family and probably on
|
||||
* many non-Intel x86 processors, but, unfortunately, that would make things
|
||||
* twice slower for the original Pentium.
|
||||
*
|
||||
* An additional 2% speedup may be achieved with non-reentrant code.
|
||||
*/
|
||||
|
||||
#define L %esi
|
||||
#define R %edi
|
||||
#define tmp1 %eax
|
||||
#define tmp1_lo %al
|
||||
#define tmp2 %ecx
|
||||
#define tmp2_hi %ch
|
||||
#define tmp3 %edx
|
||||
#define tmp3_lo %dl
|
||||
#define tmp4 %ebx
|
||||
#define tmp4_hi %bh
|
||||
#define tmp5 %ebp
|
||||
|
||||
.text
|
||||
|
||||
#define BF_ROUND(L, R, N) \
|
||||
xorl L,tmp2; \
|
||||
xorl tmp1,tmp1; \
|
||||
movl tmp2,L; \
|
||||
shrl $16,tmp2; \
|
||||
movl L,tmp4; \
|
||||
movb tmp2_hi,tmp1_lo; \
|
||||
andl $0xFF,tmp2; \
|
||||
movb tmp4_hi,tmp3_lo; \
|
||||
andl $0xFF,tmp4; \
|
||||
movl S(0,tmp1),tmp1; \
|
||||
movl S(0x400,tmp2),tmp5; \
|
||||
addl tmp5,tmp1; \
|
||||
movl S(0x800,tmp3),tmp5; \
|
||||
xorl tmp5,tmp1; \
|
||||
movl S(0xC00,tmp4),tmp5; \
|
||||
addl tmp1,tmp5; \
|
||||
movl 4+P(N),tmp2; \
|
||||
xorl tmp5,R
|
||||
|
||||
#define BF_ENCRYPT_START \
|
||||
BF_ROUND(L, R, 0); \
|
||||
BF_ROUND(R, L, 1); \
|
||||
BF_ROUND(L, R, 2); \
|
||||
BF_ROUND(R, L, 3); \
|
||||
BF_ROUND(L, R, 4); \
|
||||
BF_ROUND(R, L, 5); \
|
||||
BF_ROUND(L, R, 6); \
|
||||
BF_ROUND(R, L, 7); \
|
||||
BF_ROUND(L, R, 8); \
|
||||
BF_ROUND(R, L, 9); \
|
||||
BF_ROUND(L, R, 10); \
|
||||
BF_ROUND(R, L, 11); \
|
||||
BF_ROUND(L, R, 12); \
|
||||
BF_ROUND(R, L, 13); \
|
||||
BF_ROUND(L, R, 14); \
|
||||
BF_ROUND(R, L, 15); \
|
||||
movl BF_ptr,tmp5; \
|
||||
xorl L,tmp2; \
|
||||
movl P(17),L
|
||||
|
||||
#define BF_ENCRYPT_END \
|
||||
xorl R,L; \
|
||||
movl tmp2,R
|
||||
|
||||
DO_ALIGN(5)
|
||||
.globl _BF_body_r
|
||||
_BF_body_r:
|
||||
movl 4(%esp),%eax
|
||||
pushl %ebp
|
||||
pushl %ebx
|
||||
pushl %esi
|
||||
pushl %edi
|
||||
subl $BF_FRAME-8,%eax
|
||||
xorl L,L
|
||||
cmpl %esp,%eax
|
||||
ja BF_die
|
||||
xchgl %eax,%esp
|
||||
xorl R,R
|
||||
pushl %eax
|
||||
leal 0x1000+BF_FRAME-4(ctx),%eax
|
||||
movl 0x1000+BF_FRAME-4(ctx),tmp2
|
||||
pushl %eax
|
||||
xorl tmp3,tmp3
|
||||
BF_loop_P:
|
||||
BF_ENCRYPT_START
|
||||
addl $8,tmp5
|
||||
BF_ENCRYPT_END
|
||||
leal 0x1000+18*4+BF_FRAME(ctx),tmp1
|
||||
movl tmp5,BF_ptr
|
||||
cmpl tmp5,tmp1
|
||||
movl L,-8(tmp5)
|
||||
movl R,-4(tmp5)
|
||||
movl P(0),tmp2
|
||||
ja BF_loop_P
|
||||
leal BF_FRAME(ctx),tmp5
|
||||
xorl tmp3,tmp3
|
||||
movl tmp5,BF_ptr
|
||||
BF_loop_S:
|
||||
BF_ENCRYPT_START
|
||||
BF_ENCRYPT_END
|
||||
movl P(0),tmp2
|
||||
movl L,(tmp5)
|
||||
movl R,4(tmp5)
|
||||
BF_ENCRYPT_START
|
||||
BF_ENCRYPT_END
|
||||
movl P(0),tmp2
|
||||
movl L,8(tmp5)
|
||||
movl R,12(tmp5)
|
||||
BF_ENCRYPT_START
|
||||
BF_ENCRYPT_END
|
||||
movl P(0),tmp2
|
||||
movl L,16(tmp5)
|
||||
movl R,20(tmp5)
|
||||
BF_ENCRYPT_START
|
||||
addl $32,tmp5
|
||||
BF_ENCRYPT_END
|
||||
leal 0x1000+BF_FRAME(ctx),tmp1
|
||||
movl tmp5,BF_ptr
|
||||
cmpl tmp5,tmp1
|
||||
movl P(0),tmp2
|
||||
movl L,-8(tmp5)
|
||||
movl R,-4(tmp5)
|
||||
ja BF_loop_S
|
||||
movl 4(%esp),%esp
|
||||
popl %edi
|
||||
popl %esi
|
||||
popl %ebx
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
BF_die:
|
||||
/* Oops, need to re-compile with a larger BF_FRAME. */
|
||||
hlt
|
||||
jmp BF_die
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__ELF__) && defined(__linux__)
|
||||
.section .note.GNU-stack,"",@progbits
|
||||
#endif
|
1
deps/libuv/.gitattributes
vendored
Normal file
1
deps/libuv/.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
test/fixtures/lorem_ipsum.txt text eol=lf
|
13
deps/libuv/.github/ISSUE_TEMPLATE.md
vendored
Normal file
13
deps/libuv/.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
<!--
|
||||
If you want to report a bug, you are in the right place!
|
||||
|
||||
If you need help or have a question, go here:
|
||||
https://github.com/libuv/help/issues/new
|
||||
|
||||
If you are reporting a libuv test failure, please ensure that you are not
|
||||
running the test as root.
|
||||
|
||||
Please include code that demonstrates the bug and keep it short and simple.
|
||||
-->
|
||||
* **Version**: <!-- libuv version -->
|
||||
* **Platform**: <!-- `uname -a` (UNIX), or Windows version and machine type -->
|
24
deps/libuv/.github/stale.yml
vendored
Normal file
24
deps/libuv/.github/stale.yml
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 21
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
# Set to false to disable. If disabled, issues still need to be closed
|
||||
# manually, but will remain marked as stale.
|
||||
daysUntilClose: 120
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- v2
|
||||
- enhancement
|
||||
- good first issue
|
||||
- feature-request
|
||||
- doc
|
||||
- bug
|
||||
- not-stale
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
69
deps/libuv/.github/workflows/CI.yml
vendored
Normal file
69
deps/libuv/.github/workflows/CI.yml
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
name: CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build-android:
|
||||
runs-on: ubuntu-latest
|
||||
container: reactnativecommunity/react-native-android:2020-5-20
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Envinfo
|
||||
run: npx envinfo
|
||||
- name: Build android arm64
|
||||
# see build options you can use in https://developer.android.com/ndk/guides/cmake
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
$ANDROID_HOME/cmake/3.10.2.4988404/bin/cmake -DCMAKE_TOOLCHAIN_FILE=$ANDROID_HOME/ndk/20.0.5594570/build/cmake/android.toolchain.cmake -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="arm64-v8a" -DANDROID_PLATFORM=android-21 ..
|
||||
$ANDROID_HOME/cmake/3.10.2.4988404/bin/cmake --build .
|
||||
|
||||
build-cross-qemu:
|
||||
runs-on: ubuntu-latest
|
||||
name: build-cross-qemu-${{ matrix.config.target }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {target: arm, toolchain: gcc-arm-linux-gnueabi, cc: arm-linux-gnueabi-gcc, qemu: qemu-arm-static }
|
||||
- {target: armhf, toolchain: gcc-arm-linux-gnueabihf, cc: arm-linux-gnueabihf-gcc, qemu: qemu-arm-static }
|
||||
- {target: aarch64, toolchain: gcc-aarch64-linux-gnu, cc: aarch64-linux-gnu-gcc, qemu: qemu-aarch64-static }
|
||||
- {target: riscv64, toolchain: gcc-riscv64-linux-gnu, cc: riscv64-linux-gnu-gcc, qemu: qemu-riscv64-static }
|
||||
- {target: ppc, toolchain: gcc-powerpc-linux-gnu, cc: powerpc-linux-gnu-gcc, qemu: qemu-ppc-static }
|
||||
- {target: ppc64, toolchain: gcc-powerpc64-linux-gnu, cc: powerpc64-linux-gnu-gcc, qemu: qemu-ppc64-static }
|
||||
- {target: ppc64le, toolchain: gcc-powerpc64le-linux-gnu, cc: powerpc64le-linux-gnu-gcc, qemu: qemu-ppc64le-static }
|
||||
- {target: s390x, toolchain: gcc-s390x-linux-gnu, cc: s390x-linux-gnu-gcc, qemu: qemu-s390x-static }
|
||||
- {target: mips, toolchain: gcc-mips-linux-gnu, cc: mips-linux-gnu-gcc, qemu: qemu-mips-static }
|
||||
- {target: mips64, toolchain: gcc-mips64-linux-gnuabi64, cc: mips64-linux-gnuabi64-gcc, qemu: qemu-mips64-static }
|
||||
- {target: mipsel, toolchain: gcc-mipsel-linux-gnu, cc: mipsel-linux-gnu-gcc, qemu: qemu-mipsel-static }
|
||||
- {target: mips64el,toolchain: gcc-mips64el-linux-gnuabi64, cc: mips64el-linux-gnuabi64-gcc,qemu: qemu-mips64el-static }
|
||||
- {target: alpha, toolchain: gcc-alpha-linux-gnu, cc: alpha-linux-gnu-gcc, qemu: qemu-alpha-static }
|
||||
- {target: arm (u64 slots), toolchain: gcc-arm-linux-gnueabi, cc: arm-linux-gnueabi-gcc, qemu: qemu-arm-static}
|
||||
- {target: aarch64 (u64 slots), toolchain: gcc-aarch64-linux-gnu, cc: aarch64-linux-gnu-gcc, qemu: qemu-aarch64-static}
|
||||
- {target: ppc (u64 slots), toolchain: gcc-powerpc-linux-gnu, cc: powerpc-linux-gnu-gcc, qemu: qemu-ppc-static}
|
||||
- {target: ppc64 (u64 slots), toolchain: gcc-powerpc64-linux-gnu, cc: powerpc64-linux-gnu-gcc, qemu: qemu-ppc64-static}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install QEMU
|
||||
# this ensure install latest qemu on ubuntu, apt get version is old
|
||||
env:
|
||||
QEMU_SRC: "http://archive.ubuntu.com/ubuntu/pool/universe/q/qemu"
|
||||
QEMU_VER: "qemu-user-static_4\\.2-.*_amd64.deb$"
|
||||
run: |
|
||||
DEB=`curl -s $QEMU_SRC/ | grep -o -E 'href="([^"#]+)"' | cut -d'"' -f2 | grep $QEMU_VER | tail -1`
|
||||
wget $QEMU_SRC/$DEB
|
||||
sudo dpkg -i $DEB
|
||||
- name: Install ${{ matrix.config.toolchain }}
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install ${{ matrix.config.toolchain }} -y
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build && cmake .. -DBUILD_TESTING=ON -DQEMU=ON -DCMAKE_C_COMPILER=${{ matrix.config.cc }}
|
||||
cmake --build .
|
||||
ls -lh
|
||||
- name: Test
|
||||
run: |
|
||||
${{ matrix.config.qemu }} build/uv_run_tests_a
|
76
deps/libuv/.gitignore
vendored
Normal file
76
deps/libuv/.gitignore
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
*.swp
|
||||
*.[oa]
|
||||
*.l[oa]
|
||||
*.opensdf
|
||||
*.orig
|
||||
*.pyc
|
||||
*.sdf
|
||||
*.suo
|
||||
.vs/
|
||||
*.VC.db
|
||||
*.VC.opendb
|
||||
core
|
||||
vgcore.*
|
||||
.buildstamp
|
||||
.dirstamp
|
||||
.deps/
|
||||
/.libs/
|
||||
/aclocal.m4
|
||||
/ar-lib
|
||||
/autom4te.cache/
|
||||
/compile
|
||||
/config.guess
|
||||
/config.log
|
||||
/config.status
|
||||
/config.sub
|
||||
/configure
|
||||
/depcomp
|
||||
/install-sh
|
||||
/libtool
|
||||
/libuv.a
|
||||
/libuv.dylib
|
||||
/libuv.pc
|
||||
/libuv.so
|
||||
/ltmain.sh
|
||||
/missing
|
||||
/test-driver
|
||||
Makefile
|
||||
Makefile.in
|
||||
|
||||
/build/
|
||||
|
||||
/test/.libs/
|
||||
/test/run-tests
|
||||
/test/run-tests.exe
|
||||
/test/run-tests.dSYM
|
||||
/test/run-benchmarks
|
||||
/test/run-benchmarks.exe
|
||||
/test/run-benchmarks.dSYM
|
||||
test_file_*
|
||||
|
||||
*.sln
|
||||
*.sln.cache
|
||||
*.ncb
|
||||
*.vcproj
|
||||
*.vcproj*.user
|
||||
*.vcxproj
|
||||
*.vcxproj.filters
|
||||
*.vcxproj.user
|
||||
_UpgradeReport_Files/
|
||||
UpgradeLog*.XML
|
||||
Debug
|
||||
Release
|
||||
ipch
|
||||
|
||||
# sphinx generated files
|
||||
/docs/build/
|
||||
|
||||
# Clion / IntelliJ project files
|
||||
/.idea/
|
||||
cmake-build-debug/
|
||||
|
||||
*.xcodeproj
|
||||
*.xcworkspace
|
||||
|
||||
# make dist output
|
||||
libuv-*.tar.*
|
54
deps/libuv/.mailmap
vendored
Normal file
54
deps/libuv/.mailmap
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
A. Hauptmann <andreashauptmann@t-online.de>
|
||||
Aaron Bieber <qbit@deftly.net> <deftly@gmail.com>
|
||||
Alan Gutierrez <alan@prettyrobots.com> <alan@blogometer.com>
|
||||
Andrius Bentkus <andrius.bentkus@gmail.com> <toxedvirus@gmail.com>
|
||||
Bert Belder <bertbelder@gmail.com> <i@bertbelder.com>
|
||||
Bert Belder <bertbelder@gmail.com> <info@2bs.nl>
|
||||
Bert Belder <bertbelder@gmail.com> <user@ChrUbuntu.(none)>
|
||||
Brandon Philips <brandon.philips@rackspace.com> <brandon@ifup.org>
|
||||
Brian White <mscdex@mscdex.net>
|
||||
Brian White <mscdex@mscdex.net> <mscdex@gmail.com>
|
||||
Caleb James DeLisle <cjd@hyperboria.ca> <cjd@cjdns.fr>
|
||||
Christoph Iserlohn <christoph.iserlohn@innoq.com>
|
||||
Devchandra Meetei Leishangthem <dlmeetei@gmail.com>
|
||||
Fedor Indutny <fedor.indutny@gmail.com> <fedor@indutny.com>
|
||||
Frank Denis <github@pureftpd.org>
|
||||
Imran Iqbal <imrani@ca.ibm.com> <imran@imraniqbal.org>
|
||||
Isaac Z. Schlueter <i@izs.me>
|
||||
Jason Williams <necmon@yahoo.com>
|
||||
Jesse Gorzinski <jgorzinski@gmail.com>
|
||||
Jesse Gorzinski <jgorzinski@gmail.com> <jgorzins@us.ibm.com>
|
||||
Justin Venus <justin.venus@gmail.com> <justin.venus@orbitz.com>
|
||||
Keno Fischer <kenof@stanford.edu> <kfischer+github@college.harvard.edu>
|
||||
Keno Fischer <kenof@stanford.edu> <kfischer@college.harvard.edu>
|
||||
Leith Bade <leith@leithalweapon.geek.nz> <leith@mapbox.com>
|
||||
Leonard Hecker <leonard.hecker91@gmail.com> <leonard@hecker.io>
|
||||
Maciej Małecki <maciej.malecki@notimplemented.org> <me@mmalecki.com>
|
||||
Marc Schlaich <marc.schlaich@googlemail.com> <marc.schlaich@gmail.com>
|
||||
Michael <michael_dawson@ca.ibm.com>
|
||||
Michael Neumann <mneumann@think.localnet> <mneumann@ntecs.de>
|
||||
Michael Penick <michael.penick@datastax.com> <mpenick@users.noreply.github.com>
|
||||
Nicholas Vavilov <vvnicholas@gmail.com>
|
||||
Nick Logan <ugexe@cpan.org> <nlogan@gmail.com>
|
||||
Rasmus Christian Pedersen <zerhacken@yahoo.com>
|
||||
Rasmus Christian Pedersen <zerhacken@yahoo.com> <ruysch@outlook.com>
|
||||
Robert Mustacchi <rm@joyent.com> <rm@fingolfin.org>
|
||||
Ryan Dahl <ryan@joyent.com> <ry@tinyclouds.org>
|
||||
Ryan Emery <seebees@gmail.com>
|
||||
Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
|
||||
Sam Roberts <vieuxtech@gmail.com> <sam@strongloop.com>
|
||||
San-Tai Hsu <vanilla@fatpipi.com>
|
||||
Santiago Gimeno <santiago.gimeno@quantion.es> <santiago.gimeno@gmail.com>
|
||||
Saúl Ibarra Corretgé <saghul@gmail.com>
|
||||
Saúl Ibarra Corretgé <saghul@gmail.com> <s@saghul.net>
|
||||
Shigeki Ohtsu <ohtsu@iij.ad.jp> <ohtsu@ohtsu.org>
|
||||
TK-one <tk5641@naver.com>
|
||||
Timothy J. Fontaine <tjfontaine@gmail.com>
|
||||
Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
Yazhong Liu <yorkiefixer@gmail.com>
|
||||
Yuki Okumura <mjt@cltn.org>
|
||||
gengjiawen <technicalcute@gmail.com>
|
||||
jBarz <jBarz@users.noreply.github.com> <jbarboza@ca.ibm.com>
|
||||
jBarz <jBarz@users.noreply.github.com> <jbarz@users.noreply.github.com>
|
||||
ptlomholt <pt@lomholt.com>
|
||||
zlargon <zlargon1988@gmail.com>
|
450
deps/libuv/AUTHORS
vendored
Normal file
450
deps/libuv/AUTHORS
vendored
Normal file
@ -0,0 +1,450 @@
|
||||
# Authors ordered by first contribution.
|
||||
Ryan Dahl <ryan@joyent.com>
|
||||
Bert Belder <bertbelder@gmail.com>
|
||||
Josh Roesslein <jroesslein@gmail.com>
|
||||
Alan Gutierrez <alan@prettyrobots.com>
|
||||
Joshua Peek <josh@joshpeek.com>
|
||||
Igor Zinkovsky <igorzi@microsoft.com>
|
||||
San-Tai Hsu <vanilla@fatpipi.com>
|
||||
Ben Noordhuis <info@bnoordhuis.nl>
|
||||
Henry Rawas <henryr@schakra.com>
|
||||
Robert Mustacchi <rm@joyent.com>
|
||||
Matt Stevens <matt@alloysoft.com>
|
||||
Paul Querna <pquerna@apache.org>
|
||||
Shigeki Ohtsu <ohtsu@iij.ad.jp>
|
||||
Tom Hughes <tom.hughes@palm.com>
|
||||
Peter Bright <drpizza@quiscalusmexicanus.org>
|
||||
Jeroen Janssen <jeroen.janssen@gmail.com>
|
||||
Andrea Lattuada <ndr.lattuada@gmail.com>
|
||||
Augusto Henrique Hentz <ahhentz@gmail.com>
|
||||
Clifford Heath <clifford.heath@gmail.com>
|
||||
Jorge Chamorro Bieling <jorge@jorgechamorro.com>
|
||||
Luis Lavena <luislavena@gmail.com>
|
||||
Matthew Sporleder <msporleder@gmail.com>
|
||||
Erick Tryzelaar <erick.tryzelaar@gmail.com>
|
||||
Isaac Z. Schlueter <i@izs.me>
|
||||
Pieter Noordhuis <pcnoordhuis@gmail.com>
|
||||
Marek Jelen <marek@jelen.biz>
|
||||
Fedor Indutny <fedor.indutny@gmail.com>
|
||||
Saúl Ibarra Corretgé <saghul@gmail.com>
|
||||
Felix Geisendörfer <felix@debuggable.com>
|
||||
Yuki Okumura <mjt@cltn.org>
|
||||
Roman Shtylman <shtylman@gmail.com>
|
||||
Frank Denis <github@pureftpd.org>
|
||||
Carter Allen <CarterA@opt-6.com>
|
||||
Tj Holowaychuk <tj@vision-media.ca>
|
||||
Shimon Doodkin <helpmepro1@gmail.com>
|
||||
Ryan Emery <seebees@gmail.com>
|
||||
Bruce Mitchener <bruce.mitchener@gmail.com>
|
||||
Maciej Małecki <maciej.malecki@notimplemented.org>
|
||||
Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
Daisuke Murase <typester@cpan.org>
|
||||
Paddy Byers <paddy.byers@gmail.com>
|
||||
Dan VerWeire <dverweire@gmail.com>
|
||||
Brandon Benvie <brandon@bbenvie.com>
|
||||
Brandon Philips <brandon.philips@rackspace.com>
|
||||
Nathan Rajlich <nathan@tootallnate.net>
|
||||
Charlie McConnell <charlie@charlieistheman.com>
|
||||
Vladimir Dronnikov <dronnikov@gmail.com>
|
||||
Aaron Bieber <qbit@deftly.net>
|
||||
Bulat Shakirzyanov <mallluhuct@gmail.com>
|
||||
Brian White <mscdex@mscdex.net>
|
||||
Erik Dubbelboer <erik@dubbelboer.com>
|
||||
Keno Fischer <kenof@stanford.edu>
|
||||
Ira Cooper <Ira.Cooper@mathworks.com>
|
||||
Andrius Bentkus <andrius.bentkus@gmail.com>
|
||||
Iñaki Baz Castillo <ibc@aliax.net>
|
||||
Mark Cavage <mark.cavage@joyent.com>
|
||||
George Yohng <georgegh@oss3d.com>
|
||||
Xidorn Quan <quanxunzhen@gmail.com>
|
||||
Roman Neuhauser <rneuhauser@suse.cz>
|
||||
Shuhei Tanuma <shuhei.tanuma@gmail.com>
|
||||
Bryan Cantrill <bcantrill@acm.org>
|
||||
Trond Norbye <trond.norbye@gmail.com>
|
||||
Tim Holy <holy@wustl.edu>
|
||||
Prancesco Pertugio <meh@schizofreni.co>
|
||||
Leonard Hecker <leonard.hecker91@gmail.com>
|
||||
Andrew Paprocki <andrew@ishiboo.com>
|
||||
Luigi Grilli <luigi.grilli@gmail.com>
|
||||
Shannen Saez <shannenlaptop@gmail.com>
|
||||
Artur Adib <arturadib@gmail.com>
|
||||
Hiroaki Nakamura <hnakamur@gmail.com>
|
||||
Ting-Yu Lin <ph.minamo@cytisan.com>
|
||||
Stephen Gallagher <sgallagh@redhat.com>
|
||||
Shane Holloway <shane.holloway@ieee.org>
|
||||
Andrew Shaffer <darawk@gmail.com>
|
||||
Vlad Tudose <vlad.tudose@intel.com>
|
||||
Ben Leslie <benno@benno.id.au>
|
||||
Tim Bradshaw <tfb@cley.com>
|
||||
Timothy J. Fontaine <tjfontaine@gmail.com>
|
||||
Marc Schlaich <marc.schlaich@googlemail.com>
|
||||
Brian Mazza <louseman@gmail.com>
|
||||
Elliot Saba <staticfloat@gmail.com>
|
||||
Ben Kelly <ben@wanderview.com>
|
||||
Nils Maier <maierman@web.de>
|
||||
Nicholas Vavilov <vvnicholas@gmail.com>
|
||||
Miroslav Bajtoš <miro.bajtos@gmail.com>
|
||||
Sean Silva <chisophugis@gmail.com>
|
||||
Wynn Wilkes <wynnw@movenetworks.com>
|
||||
Andrei Sedoi <bsnote@gmail.com>
|
||||
Alex Crichton <alex@alexcrichton.com>
|
||||
Brent Cook <brent@boundary.com>
|
||||
Brian Kaisner <bkize1@gmail.com>
|
||||
Luca Bruno <lucab@debian.org>
|
||||
Reini Urban <rurban@cpanel.net>
|
||||
Maks Naumov <maksqwe1@ukr.net>
|
||||
Sean Farrell <sean.farrell@rioki.org>
|
||||
Chris Bank <cbank@adobe.com>
|
||||
Geert Jansen <geertj@gmail.com>
|
||||
Christoph Iserlohn <christoph.iserlohn@innoq.com>
|
||||
Steven Kabbes <stevenkabbes@gmail.com>
|
||||
Alex Gaynor <alex.gaynor@gmail.com>
|
||||
huxingyi <huxingyi@msn.com>
|
||||
Tenor Biel <tenorbiel@gmail.com>
|
||||
Andrej Manduch <AManduch@gmail.com>
|
||||
Joshua Neuheisel <joshua@neuheisel.us>
|
||||
Alexis Campailla <alexis@janeasystems.com>
|
||||
Yazhong Liu <yorkiefixer@gmail.com>
|
||||
Sam Roberts <vieuxtech@gmail.com>
|
||||
River Tarnell <river@loreley.flyingparchment.org.uk>
|
||||
Nathan Sweet <nathanjsweet@gmail.com>
|
||||
Trevor Norris <trev.norris@gmail.com>
|
||||
Oguz Bastemur <obastemur@gmail.com>
|
||||
Dylan Cali <calid1984@gmail.com>
|
||||
Austin Foxley <austinf@cetoncorp.com>
|
||||
Benjamin Saunders <ben.e.saunders@gmail.com>
|
||||
Geoffry Song <goffrie@gmail.com>
|
||||
Rasmus Christian Pedersen <ruysch@outlook.com>
|
||||
William Light <wrl@illest.net>
|
||||
Oleg Efimov <o.efimov@corp.badoo.com>
|
||||
Lars Gierth <larsg@systemli.org>
|
||||
Rasmus Christian Pedersen <zerhacken@yahoo.com>
|
||||
Justin Venus <justin.venus@gmail.com>
|
||||
Kristian Evensen <kristian.evensen@gmail.com>
|
||||
Linus Mårtensson <linus.martensson@sonymobile.com>
|
||||
Navaneeth Kedaram Nambiathan <navaneethkn@gmail.com>
|
||||
Yorkie <yorkiefixer@gmail.com>
|
||||
StarWing <weasley.wx@gmail.com>
|
||||
thierry-FreeBSD <thierry@FreeBSD.org>
|
||||
Isaiah Norton <isaiah.norton@gmail.com>
|
||||
Raul Martins <raulms.martins@gmail.com>
|
||||
David Capello <davidcapello@gmail.com>
|
||||
Paul Tan <pyokagan@gmail.com>
|
||||
Javier Hernández <jhernandez@emergya.com>
|
||||
Tonis Tiigi <tonistiigi@gmail.com>
|
||||
Norio Kobota <nori.0428@gmail.com>
|
||||
李港平 <chopdown@gmail.com>
|
||||
Chernyshev Viacheslav <astellar@ro.ru>
|
||||
Stephen von Takach <steve@advancedcontrol.com.au>
|
||||
JD Ballard <jd@pixelandline.com>
|
||||
Luka Perkov <luka.perkov@sartura.hr>
|
||||
Ryan Cole <ryan@rycole.com>
|
||||
HungMingWu <u9089000@gmail.com>
|
||||
Jay Satiro <raysatiro@yahoo.com>
|
||||
Leith Bade <leith@leithalweapon.geek.nz>
|
||||
Peter Atashian <retep998@gmail.com>
|
||||
Tim Cooper <tim.cooper@layeh.com>
|
||||
Caleb James DeLisle <cjd@hyperboria.ca>
|
||||
Jameson Nash <vtjnash@gmail.com>
|
||||
Graham Lee <ghmlee@ghmlee.com>
|
||||
Andrew Low <Andrew_Low@ca.ibm.com>
|
||||
Pavel Platto <hinidu@gmail.com>
|
||||
Tony Kelman <tony@kelman.net>
|
||||
John Firebaugh <john.firebaugh@gmail.com>
|
||||
lilohuang <lilohuang@hotmail.com>
|
||||
Paul Goldsmith <paul.goldsmith@aplink.net>
|
||||
Julien Gilli <julien.gilli@joyent.com>
|
||||
Michael Hudson-Doyle <michael.hudson@linaro.org>
|
||||
Recep ASLANTAS <m@recp.me>
|
||||
Rob Adams <readams@readams.net>
|
||||
Zachary Newman <znewman01@gmail.com>
|
||||
Robin Hahling <robin.hahling@gw-computing.net>
|
||||
Jeff Widman <jeff@jeffwidman.com>
|
||||
cjihrig <cjihrig@gmail.com>
|
||||
Tomasz Kołodziejski <tkolodziejski@mozilla.com>
|
||||
Unknown W. Brackets <checkins@unknownbrackets.org>
|
||||
Emmanuel Odeke <odeke@ualberta.ca>
|
||||
Mikhail Mukovnikov <yndi@me.com>
|
||||
Thorsten Lorenz <thlorenz@gmx.de>
|
||||
Yuri D'Elia <yuri.delia@eurac.edu>
|
||||
Manos Nikolaidis <manos@shadowrobot.com>
|
||||
Elijah Andrews <elijah@busbud.com>
|
||||
Michael Ira Krufky <m.krufky@samsung.com>
|
||||
Helge Deller <deller@gmx.de>
|
||||
Joey Geralnik <jgeralnik@gmail.com>
|
||||
Tim Caswell <tim@creationix.com>
|
||||
Logan Rosen <loganrosen@gmail.com>
|
||||
Kenneth Perry <thothonegan@gmail.com>
|
||||
John Marino <marino@FreeBSD.org>
|
||||
Alexey Melnichuk <mimir@newmail.ru>
|
||||
Johan Bergström <bugs@bergstroem.nu>
|
||||
Alex Mo <almosnow@gmail.com>
|
||||
Luis Martinez de Bartolome <lasote@gmail.com>
|
||||
Michael Penick <michael.penick@datastax.com>
|
||||
Michael <michael_dawson@ca.ibm.com>
|
||||
Massimiliano Torromeo <massimiliano.torromeo@gmail.com>
|
||||
TomCrypto <thomas.beneteau@yahoo.fr>
|
||||
Brett Vickers <brett@beevik.com>
|
||||
Ole André Vadla Ravnås <oleavr@gmail.com>
|
||||
Kazuho Oku <kazuhooku@gmail.com>
|
||||
Ryan Phillips <ryan.phillips@rackspace.com>
|
||||
Brian Green <briangreenery@gmail.com>
|
||||
Devchandra Meetei Leishangthem <dlmeetei@gmail.com>
|
||||
Corey Farrell <git@cfware.com>
|
||||
Per Nilsson <pni@qlik.com>
|
||||
Alan Rogers <alanjrogers@me.com>
|
||||
Daryl Haresign <github@daryl.haresign.com>
|
||||
Rui Abreu Ferreira <raf-ep@gmx.com>
|
||||
João Reis <reis@janeasystems.com>
|
||||
farblue68 <farblue68@gmail.com>
|
||||
Jason Williams <necmon@yahoo.com>
|
||||
Igor Soarez <igorsoarez@gmail.com>
|
||||
Miodrag Milanovic <mmicko@gmail.com>
|
||||
Cheng Zhao <zcbenz@gmail.com>
|
||||
Michael Neumann <mneumann@think.localnet>
|
||||
Stefano Cristiano <stefanocristiano82@gmail.com>
|
||||
heshamsafi <hesham.safi.eldeen@gmail.com>
|
||||
A. Hauptmann <andreashauptmann@t-online.de>
|
||||
John McNamee <jpm@microwiz.com>
|
||||
Yosuke Furukawa <yosuke.furukawa@gmail.com>
|
||||
Santiago Gimeno <santiago.gimeno@quantion.es>
|
||||
guworks <ground.up.works@gmail.com>
|
||||
RossBencina <rossb@audiomulch.com>
|
||||
Roger A. Light <roger@atchoo.org>
|
||||
chenttuuvv <chenttuuvv@yahoo.com>
|
||||
Richard Lau <riclau@uk.ibm.com>
|
||||
ronkorving <rkorving@wizcorp.jp>
|
||||
Corbin Simpson <MostAwesomeDude@gmail.com>
|
||||
Zachary Hamm <zsh@imipolexg.org>
|
||||
Karl Skomski <karl@skomski.com>
|
||||
Jeremy Whitlock <jwhitlock@apache.org>
|
||||
Willem Thiart <himself@willemthiart.com>
|
||||
Ben Trask <bentrask@comcast.net>
|
||||
Jianghua Yang <jianghua.yjh@alibaba-inc.com>
|
||||
Colin Snover <github.com@zetafleet.com>
|
||||
Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
|
||||
Eli Skeggs <skeggse@gmail.com>
|
||||
nmushell <nmushell@bloomberg.net>
|
||||
Gireesh Punathil <gpunathi@in.ibm.com>
|
||||
Ryan Johnston <ryan@mediapixel.co.nz>
|
||||
Adam Stylinski <stylinae@mail.uc.edu>
|
||||
Nathan Corvino <nathan@corvino.com>
|
||||
Wink Saville <wink@saville.com>
|
||||
Angel Leon <gubatron@gmail.com>
|
||||
Louis DeJardin <lodejard@microsoft.com>
|
||||
Imran Iqbal <imrani@ca.ibm.com>
|
||||
Petka Antonov <petka_antonov@hotmail.com>
|
||||
Ian Kronquist <iankronquist@teleport.com>
|
||||
kkdaemon <kkdaemon@gmail.com>
|
||||
Yuval Brik <yuval@brik.org.il>
|
||||
Joran Dirk Greef <joran@ronomon.com>
|
||||
Andrey Mazo <andrey.mazo@fidelissecurity.com>
|
||||
sztomi <hello.sztomi@gmail.com>
|
||||
Martin Bark <martin@barkynet.com>
|
||||
Dave <dave@jut.io>
|
||||
Alexis Murzeau <amubtdx@gmail.com>
|
||||
Didiet <lynxluna@gmail.com>
|
||||
Nan Xiang <514580344@qq.com>
|
||||
Samuel Lorétan <sloretan@riotgames.com>
|
||||
Nándor István Krácser <bonifaido@gmail.com>
|
||||
Katsutoshi Horie <mps299792458@gmail.com>
|
||||
Lukasz Jagiello <lukasz@wikia-inc.com>
|
||||
Robert Chiras <robert.chiras@intel.com>
|
||||
Kári Tristan Helgason <kthelgason@gmail.com>
|
||||
Krishnaraj Bhat <krrishnarraj@gmail.com>
|
||||
Enno Boland <g@s01.de>
|
||||
Michael Fero <michael.fero@datastax.com>
|
||||
Robert Jefe Lindstaedt <robert.lindstaedt@gmail.com>
|
||||
Myles Borins <myles.borins@gmail.com>
|
||||
Tony Theodore <tonyt@logyst.com>
|
||||
Jason Ginchereau <jasongin@microsoft.com>
|
||||
Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
|
||||
Pierre-Marie de Rodat <pmderodat@kawie.fr>
|
||||
Brian Maher <brian@brimworks.com>
|
||||
neevek <i@neevek.net>
|
||||
John Barboza <jbarboza@ca.ibm.com>
|
||||
liuxiaobo <icexile@qq.com>
|
||||
Michele Caini <michele.caini@gmail.com>
|
||||
Bartosz Sosnowski <bartosz@janeasystems.com>
|
||||
Matej Knopp <matej.knopp@gmail.com>
|
||||
sunjin.lee <kod21236@gmail.com>
|
||||
Matt Clarkson <mattyclarkson@gmail.com>
|
||||
Jeffrey Clark <dude@zaplabs.com>
|
||||
Bart Robinson <bartarr@gmail.com>
|
||||
Vit Gottwald <vit.gottwald@gmail.com>
|
||||
Vladimír Čunát <vladimir.cunat@nic.cz>
|
||||
Alex Hultman <alexhultman@gmail.com>
|
||||
Brad King <brad.king@kitware.com>
|
||||
Philippe Laferriere <laferriere.phil@gmail.com>
|
||||
Will Speak <lithiumflame@gmail.com>
|
||||
Hitesh Kanwathirtha <digitalinfinity@gmail.com>
|
||||
Eric Sciple <ersciple@microsoft.com>
|
||||
jBarz <jBarz@users.noreply.github.com>
|
||||
muflub <admin@lodle.net>
|
||||
Daniel Bevenius <daniel.bevenius@gmail.com>
|
||||
Howard Hellyer <hhellyer@uk.ibm.com>
|
||||
Chris Araman <chris.araman@fuze.com>
|
||||
Vladimir Matveev <vladima@microsoft.com>
|
||||
Jason Madden <jamadden@gmail.com>
|
||||
Jamie Davis <davisjam@vt.edu>
|
||||
Daniel Kahn Gillmor <dkg@fifthhorseman.net>
|
||||
Keane <erich.keane@intel.com>
|
||||
James McCoy <jamessan@jamessan.com>
|
||||
Bernardo Ramos <berna.gensis@gmail.com>
|
||||
Juan Cruz Viotti <jviotti@openmailbox.org>
|
||||
Gemini Wen <geminiwen@aliyun.com>
|
||||
Sebastian Wiedenroth <wiedi@frubar.net>
|
||||
Sai Ke WANG <swang304@bloomberg.net>
|
||||
Barnabas Gema <gema.barnabas@gmail.com>
|
||||
Romain Caire <romain@blade-group.com>
|
||||
Robert Ayrapetyan <robert.ayrapetyan@gmail.com>
|
||||
Refael Ackermann <refack@gmail.com>
|
||||
André Klitzing <aklitzing@gmail.com>
|
||||
Matthew Taylor <mstaveleytaylor@gmail.com>
|
||||
CurlyMoo <curlymoo1@gmail.com>
|
||||
XadillaX <admin@xcoder.in>
|
||||
Anticrisis <anticrisisg@gmail.com>
|
||||
Jacob Segal <jacob.e.segal@gmail.com>
|
||||
Maciej Szeptuch (Neverous) <neverous@neverous.info>
|
||||
Joel Winarske <joel.winarske@inrix.com>
|
||||
Gergely Nagy <ngg@tresorit.com>
|
||||
Kamil Rytarowski <n54@gmx.com>
|
||||
tux.uudiin <77389867@qq.com>
|
||||
Nick Logan <ugexe@cpan.org>
|
||||
darobs <darobs@microsoft.com>
|
||||
Zheng, Lei <realthunder.dev@gmail.com>
|
||||
Carlo Marcelo Arenas Belón <carenas@gmail.com>
|
||||
Scott Parker <scott.parker087@gmail.com>
|
||||
Wade Brainerd <Wade.Brainerd@activision.com>
|
||||
rayrase <rmartinez2175@eagle.fgcu.edu>
|
||||
Pekka Nikander <pekka.nikander@iki.fi>
|
||||
Ed Schouten <ed@nuxi.nl>
|
||||
Xu Meng <mengxumx@cn.ibm.com>
|
||||
Matt Harrison <hi@matt-harrison.com>
|
||||
Anna Henningsen <anna@addaleax.net>
|
||||
Jérémy Lal <kapouer@melix.org>
|
||||
Ben Wijen <ben@wijen.net>
|
||||
elephantp <elephantp@elephantp.blog>
|
||||
Felix Yan <felixonmars@archlinux.org>
|
||||
Mason X <me@masonx.ca>
|
||||
Jesse Gorzinski <jgorzinski@gmail.com>
|
||||
Ryuichi KAWAMATA <ryuichi.kawamata@dena.jp>
|
||||
Joyee Cheung <joyeec9h3@gmail.com>
|
||||
Michael Kilburn <crusader.mike@gmail.com>
|
||||
Ruslan Bekenev <furyinbox@gmail.com>
|
||||
Bob Burger <rgburger@beckman.com>
|
||||
Thomas Versteeg <thomasversteeg@gmx.com>
|
||||
zzzjim <zzzjim@users.noreply.github.com>
|
||||
Alex Arslan <ararslan@comcast.net>
|
||||
Kyle Farnung <kfarnung@microsoft.com>
|
||||
ssrlive <30760636+ssrlive@users.noreply.github.com>
|
||||
Tobias Nießen <tniessen@tnie.de>
|
||||
Björn Linse <bjorn.linse@gmail.com>
|
||||
zyxwvu Shi <i@shiyc.cn>
|
||||
Peter Johnson <johnson.peter@gmail.com>
|
||||
Paolo Greppi <paolo.greppi@libpf.com>
|
||||
Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Ujjwal Sharma <usharma1998@gmail.com>
|
||||
Michał Kozakiewicz <michalkozakiewicz3@gmail.com>
|
||||
Emil Bay <github@tixz.dk>
|
||||
Jeremiah Senkpiel <fishrock123@rocketmail.com>
|
||||
Andy Zhang <zhangyong232@gmail.com>
|
||||
dmabupt <dmabupt@gmail.com>
|
||||
Ryan Liptak <squeek502@hotmail.com>
|
||||
Ali Ijaz Sheikh <ofrobots@google.com>
|
||||
hitesh <sainihitesh.scientist@gmail.com>
|
||||
Svante Signell <svante.signell@gmail.com>
|
||||
Samuel Thibault <sthibault@debian.org>
|
||||
Jeremy Studer <studerj1.mail@gmail.com>
|
||||
damon-kwok <563066990@qq.com>
|
||||
Damon Kwok <MedusaIDE@outlook.com>
|
||||
Ashe Connor <ashe@kivikakk.ee>
|
||||
Rick <lcw0622@163.com>
|
||||
Ivan Krylov <krylov.r00t@gmail.com>
|
||||
Michael Meier <michael.meier@leica-geosystems.com>
|
||||
ptlomholt <pt@lomholt.com>
|
||||
Victor Costan <pwnall@chromium.org>
|
||||
sid <sidyhe@hotmail.com>
|
||||
Kevin Adler <kadler@us.ibm.com>
|
||||
Stephen Belanger <admin@stephenbelanger.com>
|
||||
yeyuanfeng <yeyuanfeng@bytedance.com>
|
||||
erw7 <erw7.github@gmail.com>
|
||||
Thomas Karl Pietrowski <thopiekar@gmail.com>
|
||||
evgley <evgley@gmail.com>
|
||||
Andreas Rohner <andreas.rohner@gmx.net>
|
||||
Rich Trott <rtrott@gmail.com>
|
||||
Milad Farazmand <miladfar@ca.ibm.com>
|
||||
zlargon <zlargon1988@gmail.com>
|
||||
Yury Selivanov <yury@magic.io>
|
||||
Oscar Waddell <owaddell@beckman.com>
|
||||
FX Coudert <fxcoudert@gmail.com>
|
||||
George Zhao <zhaozg@gmail.com>
|
||||
Kyle Edwards <kyle.edwards@kitware.com>
|
||||
ken-cunningham-webuse <ken.cunningham.webuse@gmail.com>
|
||||
Kelvin Jin <kelvinjin@google.com>
|
||||
Leorize <leorize+oss@disroot.org>
|
||||
Vlad A <vladmore@gmail.com>
|
||||
Niels Lohmann <mail@nlohmann.me>
|
||||
Jenil Christo <jenilchristo5@gmail.com>
|
||||
Evgeny Ermakov <evgeny.v.ermakov@gmail.com>
|
||||
gengjiawen <technicalcute@gmail.com>
|
||||
Leo Chung <gewalalb@gmail.com>
|
||||
Javier Blazquez <jblazquez@riotgames.com>
|
||||
Mustafa M <mus-m@outlook.com>
|
||||
Zach Bjornson <zbbjornson@gmail.com>
|
||||
Nan Xiao <nan@chinadtrace.org>
|
||||
Ben Davies <kaiepi@outlook.com>
|
||||
Nhan Khong <knhana7@gmail.com>
|
||||
Crunkle <justcrunkle@hotmail.co.uk>
|
||||
Tomas Krizek <tomas.krizek@nic.cz>
|
||||
Konstantin Podsvirov <konstantin@podsvirov.pro>
|
||||
seny <arseny.vakhrushev@gmail.com>
|
||||
Vladimir Karnushin <v.karnushin@mail.ru>
|
||||
MaYuming <maym@appexnetworks.com>
|
||||
Eneas U de Queiroz <cotequeiroz@gmail.com>
|
||||
Daniel Hahler <git@thequod.de>
|
||||
Yang Yu <yang.yu@disigma.org>
|
||||
David Carlier <devnexen@gmail.com>
|
||||
Calvin Hill <calvin@hakobaito.co.uk>
|
||||
Isabella Muerte <63051+slurps-mad-rips@users.noreply.github.com>
|
||||
Ouyang Yadong <oyydoibh@gmail.com>
|
||||
ZYSzys <zyszys98@gmail.com>
|
||||
Carl Lei <xecycle@gmail.com>
|
||||
Stefan Bender <stefan.bender@ntnu.no>
|
||||
nia <nia@NetBSD.org>
|
||||
virtualyw <virtualyw@gmail.com>
|
||||
Witold Kręcicki <wpk@isc.org>
|
||||
Dominique Dumont <dod@debian.org>
|
||||
Manuel BACHMANN <tarnyko@tarnyko.net>
|
||||
Marek Vavrusa <marek@vavrusa.com>
|
||||
TK-one <tk5641@naver.com>
|
||||
Irek Fakhrutdinov <ifakhrutdinov@rocketsoftware.com>
|
||||
Lin Zhang <linroid@gmail.com>
|
||||
毛毛 <srayuws@users.noreply.github.com>
|
||||
Sk Sajidul Kadir <sheikh.sajid522@gmail.com>
|
||||
twosee <twose@qq.com>
|
||||
Rikard Falkeborn <rikard.falkeborn@gmail.com>
|
||||
Yash Ladha <yashladhapankajladha123@gmail.com>
|
||||
James Ross <git@james-ross.co.uk>
|
||||
Colin Finck <colin@reactos.org>
|
||||
Shohei YOSHIDA <syohex@gmail.com>
|
||||
Philip Chimento <philip.chimento@gmail.com>
|
||||
Michal Artazov <michal@artazov.cz>
|
||||
Jeroen Roovers <jer@gentoo.org>
|
||||
MasterDuke17 <MasterDuke17@users.noreply.github.com>
|
||||
Alexander Tokmakov <avtokmakov@yandex-team.ru>
|
||||
Arenoros <arenoros@gmail.com>
|
||||
lander0s <dh.landeros08@gmail.com>
|
||||
Turbinya <wownucleos@gmail.com>
|
||||
OleksandrKvl <oleksandrdvl@gmail.com>
|
||||
Carter Li <carter.li@eoitek.com>
|
||||
Juan Sebastian velez Posada <jvelezpo@users.noreply.github.com>
|
||||
escherstair <ernestviga@gmail.com>
|
||||
Evan Lucas <evanlucas@me.com>
|
||||
tjarlama <59913901+tjarlama@users.noreply.github.com>
|
||||
司徒玟琅 <sanjusss@qq.com>
|
||||
YuMeiJie <yumeijie@huawei.com>
|
||||
Aleksej Lebedev <root@zta.lk>
|
||||
Nikolay Mitev <github@hmel.org>
|
||||
Ulrik Strid <ulrik.strid@outlook.com>
|
||||
Elad Lahav <elahav@qnx.com>
|
619
deps/libuv/CMakeLists.txt
vendored
Normal file
619
deps/libuv/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,619 @@
|
||||
cmake_minimum_required(VERSION 3.4)
|
||||
project(libuv LANGUAGES C)
|
||||
|
||||
cmake_policy(SET CMP0057 NEW) # Enable IN_LIST operator
|
||||
cmake_policy(SET CMP0064 NEW) # Support if (TEST) operator
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(CMakeDependentOption)
|
||||
include(CheckCCompilerFlag)
|
||||
include(GNUInstallDirs)
|
||||
include(CTest)
|
||||
|
||||
set(CMAKE_C_VISIBILITY_PRESET hidden)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_C_EXTENSIONS ON)
|
||||
set(CMAKE_C_STANDARD 90)
|
||||
|
||||
cmake_dependent_option(LIBUV_BUILD_TESTS
|
||||
"Build the unit tests when BUILD_TESTING is enabled and we are the root project" ON
|
||||
"BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||
cmake_dependent_option(LIBUV_BUILD_BENCH
|
||||
"Build the benchmarks when building unit tests and we are the root project" ON
|
||||
"LIBUV_BUILD_TESTS" OFF)
|
||||
|
||||
# Qemu Build
|
||||
option(QEMU "build for qemu" OFF)
|
||||
if(QEMU)
|
||||
add_definitions(-D__QEMU__=1)
|
||||
endif()
|
||||
|
||||
# Compiler check
|
||||
string(CONCAT is-msvc $<OR:
|
||||
$<C_COMPILER_ID:MSVC>,
|
||||
$<STREQUAL:${CMAKE_C_COMPILER_FRONTEND_VARIANT},MSVC>
|
||||
>)
|
||||
|
||||
check_c_compiler_flag(/W4 UV_LINT_W4)
|
||||
check_c_compiler_flag(/wd4100 UV_LINT_NO_UNUSED_PARAMETER_MSVC)
|
||||
check_c_compiler_flag(/wd4127 UV_LINT_NO_CONDITIONAL_CONSTANT_MSVC)
|
||||
check_c_compiler_flag(/wd4201 UV_LINT_NO_NONSTANDARD_MSVC)
|
||||
check_c_compiler_flag(/wd4206 UV_LINT_NO_NONSTANDARD_EMPTY_TU_MSVC)
|
||||
check_c_compiler_flag(/wd4210 UV_LINT_NO_NONSTANDARD_FILE_SCOPE_MSVC)
|
||||
check_c_compiler_flag(/wd4232 UV_LINT_NO_NONSTANDARD_NONSTATIC_DLIMPORT_MSVC)
|
||||
check_c_compiler_flag(/wd4456 UV_LINT_NO_HIDES_LOCAL)
|
||||
check_c_compiler_flag(/wd4457 UV_LINT_NO_HIDES_PARAM)
|
||||
check_c_compiler_flag(/wd4459 UV_LINT_NO_HIDES_GLOBAL)
|
||||
check_c_compiler_flag(/wd4706 UV_LINT_NO_CONDITIONAL_ASSIGNMENT_MSVC)
|
||||
check_c_compiler_flag(/wd4996 UV_LINT_NO_UNSAFE_MSVC)
|
||||
|
||||
check_c_compiler_flag(-Wall UV_LINT_WALL) # DO NOT use this under MSVC
|
||||
|
||||
# TODO: Place these into its own function
|
||||
check_c_compiler_flag(-Wno-unused-parameter UV_LINT_NO_UNUSED_PARAMETER)
|
||||
check_c_compiler_flag(-Wstrict-prototypes UV_LINT_STRICT_PROTOTYPES)
|
||||
check_c_compiler_flag(-Wextra UV_LINT_EXTRA)
|
||||
|
||||
check_c_compiler_flag(/utf-8 UV_LINT_UTF8_MSVC)
|
||||
|
||||
set(lint-no-unused-parameter $<$<BOOL:${UV_LINT_NO_UNUSED_PARAMETER}>:-Wno-unused-parameter>)
|
||||
set(lint-strict-prototypes $<$<BOOL:${UV_LINT_STRICT_PROTOTYPES}>:-Wstrict-prototypes>)
|
||||
set(lint-extra $<$<BOOL:${UV_LINT_EXTRA}>:-Wextra>)
|
||||
set(lint-w4 $<$<BOOL:${UV_LINT_W4}>:/W4>)
|
||||
set(lint-no-unused-parameter-msvc $<$<BOOL:${UV_LINT_NO_UNUSED_PARAMETER_MSVC}>:/wd4100>)
|
||||
set(lint-no-conditional-constant-msvc $<$<BOOL:${UV_LINT_NO_CONDITIONAL_CONSTANT_MSVC}>:/wd4127>)
|
||||
set(lint-no-nonstandard-msvc $<$<BOOL:${UV_LINT_NO_NONSTANDARD_MSVC}>:/wd4201>)
|
||||
set(lint-no-nonstandard-empty-tu-msvc $<$<BOOL:${UV_LINT_NO_NONSTANDARD_EMPTY_TU_MSVC}>:/wd4206>)
|
||||
set(lint-no-nonstandard-file-scope-msvc $<$<BOOL:${UV_LINT_NO_NONSTANDARD_FILE_SCOPE_MSVC}>:/wd4210>)
|
||||
set(lint-no-nonstandard-nonstatic-dlimport-msvc $<$<BOOL:${UV_LINT_NO_NONSTANDARD_NONSTATIC_DLIMPORT_MSVC}>:/wd4232>)
|
||||
set(lint-no-hides-local-msvc $<$<BOOL:${UV_LINT_NO_HIDES_LOCAL}>:/wd4456>)
|
||||
set(lint-no-hides-param-msvc $<$<BOOL:${UV_LINT_NO_HIDES_PARAM}>:/wd4457>)
|
||||
set(lint-no-hides-global-msvc $<$<BOOL:${UV_LINT_NO_HIDES_GLOBAL}>:/wd4459>)
|
||||
set(lint-no-conditional-assignment-msvc $<$<BOOL:${UV_LINT_NO_CONDITIONAL_ASSIGNMENT_MSVC}>:/wd4706>)
|
||||
set(lint-no-unsafe-msvc $<$<BOOL:${UV_LINT_NO_UNSAFE_MSVC}>:/wd4996>)
|
||||
# Unfortunately, this one is complicated because MSVC and clang-cl support -Wall
|
||||
# but using it is like calling -Weverything
|
||||
string(CONCAT lint-default $<
|
||||
$<AND:$<BOOL:${UV_LINT_WALL}>,$<NOT:${is-msvc}>>:-Wall
|
||||
>)
|
||||
set(lint-utf8-msvc $<$<BOOL:${UV_LINT_UTF8_MSVC}>:/utf-8>)
|
||||
|
||||
list(APPEND uv_cflags ${lint-strict-prototypes} ${lint-extra} ${lint-default} ${lint-w4})
|
||||
list(APPEND uv_cflags ${lint-no-unused-parameter})
|
||||
list(APPEND uv_cflags ${lint-no-unused-parameter-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-conditional-constant-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-nonstandard-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-nonstandard-empty-tu-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-nonstandard-file-scope-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-nonstandard-nonstatic-dlimport-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-hides-local-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-hides-param-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-hides-global-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-conditional-assignment-msvc})
|
||||
list(APPEND uv_cflags ${lint-no-unsafe-msvc})
|
||||
list(APPEND uv_cflags ${lint-utf8-msvc} )
|
||||
|
||||
set(uv_sources
|
||||
src/fs-poll.c
|
||||
src/idna.c
|
||||
src/inet.c
|
||||
src/random.c
|
||||
src/strscpy.c
|
||||
src/threadpool.c
|
||||
src/timer.c
|
||||
src/uv-common.c
|
||||
src/uv-data-getter-setters.c
|
||||
src/version.c)
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND uv_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0600)
|
||||
list(APPEND uv_libraries
|
||||
psapi
|
||||
user32
|
||||
advapi32
|
||||
iphlpapi
|
||||
userenv
|
||||
ws2_32)
|
||||
list(APPEND uv_sources
|
||||
src/win/async.c
|
||||
src/win/core.c
|
||||
src/win/detect-wakeup.c
|
||||
src/win/dl.c
|
||||
src/win/error.c
|
||||
src/win/fs.c
|
||||
src/win/fs-event.c
|
||||
src/win/getaddrinfo.c
|
||||
src/win/getnameinfo.c
|
||||
src/win/handle.c
|
||||
src/win/loop-watcher.c
|
||||
src/win/pipe.c
|
||||
src/win/thread.c
|
||||
src/win/poll.c
|
||||
src/win/process.c
|
||||
src/win/process-stdio.c
|
||||
src/win/signal.c
|
||||
src/win/snprintf.c
|
||||
src/win/stream.c
|
||||
src/win/tcp.c
|
||||
src/win/tty.c
|
||||
src/win/udp.c
|
||||
src/win/util.c
|
||||
src/win/winapi.c
|
||||
src/win/winsock.c)
|
||||
list(APPEND uv_test_libraries ws2_32)
|
||||
list(APPEND uv_test_sources src/win/snprintf.c test/runner-win.c)
|
||||
else()
|
||||
list(APPEND uv_defines _FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE)
|
||||
if(NOT CMAKE_SYSTEM_NAME MATCHES "Android|OS390|QNX")
|
||||
# TODO: This should be replaced with find_package(Threads) if possible
|
||||
# Android has pthread as part of its c library, not as a separate
|
||||
# libpthread.so.
|
||||
list(APPEND uv_libraries pthread)
|
||||
endif()
|
||||
list(APPEND uv_sources
|
||||
src/unix/async.c
|
||||
src/unix/core.c
|
||||
src/unix/dl.c
|
||||
src/unix/fs.c
|
||||
src/unix/getaddrinfo.c
|
||||
src/unix/getnameinfo.c
|
||||
src/unix/loop-watcher.c
|
||||
src/unix/loop.c
|
||||
src/unix/pipe.c
|
||||
src/unix/poll.c
|
||||
src/unix/process.c
|
||||
src/unix/random-devurandom.c
|
||||
src/unix/signal.c
|
||||
src/unix/stream.c
|
||||
src/unix/tcp.c
|
||||
src/unix/thread.c
|
||||
src/unix/tty.c
|
||||
src/unix/udp.c)
|
||||
list(APPEND uv_test_sources test/runner-unix.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
|
||||
list(APPEND uv_defines
|
||||
_ALL_SOURCE
|
||||
_LINUX_SOURCE_COMPAT
|
||||
_THREAD_SAFE
|
||||
_XOPEN_SOURCE=500
|
||||
HAVE_SYS_AHAFS_EVPRODS_H)
|
||||
list(APPEND uv_libraries perfstat)
|
||||
list(APPEND uv_sources
|
||||
src/unix/aix.c
|
||||
src/unix/aix-common.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
list(APPEND uv_defines _GNU_SOURCE)
|
||||
list(APPEND uv_libraries dl)
|
||||
list(APPEND uv_sources
|
||||
src/unix/android-ifaddrs.c
|
||||
src/unix/linux-core.c
|
||||
src/unix/linux-inotify.c
|
||||
src/unix/linux-syscalls.c
|
||||
src/unix/procfs-exepath.c
|
||||
src/unix/pthread-fixes.c
|
||||
src/unix/random-getentropy.c
|
||||
src/unix/random-getrandom.c
|
||||
src/unix/random-sysctl-linux.c)
|
||||
endif()
|
||||
|
||||
if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "Android|Linux|OS390")
|
||||
list(APPEND uv_sources src/unix/proctitle.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD")
|
||||
list(APPEND uv_sources src/unix/freebsd.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|NetBSD|OpenBSD")
|
||||
list(APPEND uv_sources src/unix/posix-hrtime.c src/unix/bsd-proctitle.c)
|
||||
endif()
|
||||
|
||||
if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|NetBSD|OpenBSD")
|
||||
list(APPEND uv_sources src/unix/bsd-ifaddrs.c src/unix/kqueue.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||
list(APPEND uv_sources src/unix/random-getrandom.c)
|
||||
endif()
|
||||
|
||||
if(APPLE OR CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
|
||||
list(APPEND uv_sources src/unix/random-getentropy.c)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
list(APPEND uv_defines _DARWIN_UNLIMITED_SELECT=1 _DARWIN_USE_64_BIT_INODE=1)
|
||||
list(APPEND uv_sources
|
||||
src/unix/darwin-proctitle.c
|
||||
src/unix/darwin.c
|
||||
src/unix/fsevents.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
list(APPEND uv_defines _GNU_SOURCE _POSIX_C_SOURCE=200112)
|
||||
list(APPEND uv_libraries dl rt)
|
||||
list(APPEND uv_sources
|
||||
src/unix/linux-core.c
|
||||
src/unix/linux-inotify.c
|
||||
src/unix/linux-syscalls.c
|
||||
src/unix/procfs-exepath.c
|
||||
src/unix/random-getrandom.c
|
||||
src/unix/random-sysctl-linux.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
|
||||
list(APPEND uv_sources src/unix/netbsd.c)
|
||||
list(APPEND uv_libraries kvm)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
|
||||
list(APPEND uv_sources src/unix/openbsd.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
|
||||
list(APPEND uv_defines PATH_MAX=255)
|
||||
list(APPEND uv_defines _AE_BIMODAL)
|
||||
list(APPEND uv_defines _ALL_SOURCE)
|
||||
list(APPEND uv_defines _ISOC99_SOURCE)
|
||||
list(APPEND uv_defines _LARGE_TIME_API)
|
||||
list(APPEND uv_defines _OPEN_MSGQ_EXT)
|
||||
list(APPEND uv_defines _OPEN_SYS_FILE_EXT)
|
||||
list(APPEND uv_defines _OPEN_SYS_IF_EXT)
|
||||
list(APPEND uv_defines _OPEN_SYS_SOCK_EXT3)
|
||||
list(APPEND uv_defines _OPEN_SYS_SOCK_IPV6)
|
||||
list(APPEND uv_defines _UNIX03_SOURCE)
|
||||
list(APPEND uv_defines _UNIX03_THREADS)
|
||||
list(APPEND uv_defines _UNIX03_WITHDRAWN)
|
||||
list(APPEND uv_defines _XOPEN_SOURCE_EXTENDED)
|
||||
list(APPEND uv_sources
|
||||
src/unix/pthread-fixes.c
|
||||
src/unix/os390.c
|
||||
src/unix/os390-syscalls.c)
|
||||
list(APPEND uv_cflags -Wc,DLL -Wc,exportall -Wc,xplink)
|
||||
list(APPEND uv_libraries -Wl,xplink)
|
||||
list(APPEND uv_test_libraries -Wl,xplink)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "OS400")
|
||||
list(APPEND uv_defines
|
||||
_ALL_SOURCE
|
||||
_LINUX_SOURCE_COMPAT
|
||||
_THREAD_SAFE
|
||||
_XOPEN_SOURCE=500)
|
||||
list(APPEND uv_sources
|
||||
src/unix/aix-common.c
|
||||
src/unix/ibmi.c
|
||||
src/unix/no-fsevents.c
|
||||
src/unix/posix-poll.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
|
||||
list(APPEND uv_defines __EXTENSIONS__ _XOPEN_SOURCE=500)
|
||||
list(APPEND uv_libraries kstat nsl sendfile socket)
|
||||
list(APPEND uv_sources src/unix/no-proctitle.c src/unix/sunos.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Haiku")
|
||||
list(APPEND uv_defines _BSD_SOURCE)
|
||||
list(APPEND uv_libraries bsd network)
|
||||
list(APPEND uv_sources
|
||||
src/unix/haiku.c
|
||||
src/unix/bsd-ifaddrs.c
|
||||
src/unix/no-fsevents.c
|
||||
src/unix/no-proctitle.c
|
||||
src/unix/posix-hrtime.c
|
||||
src/unix/posix-poll.c)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "QNX")
|
||||
list(APPEND uv_sources
|
||||
src/unix/posix-hrtime.c
|
||||
src/unix/posix-poll.c
|
||||
src/unix/qnx.c
|
||||
src/unix/bsd-ifaddrs.c
|
||||
src/unix/no-proctitle.c
|
||||
src/unix/no-fsevents.c)
|
||||
list(APPEND uv_cflags -fno-strict-aliasing)
|
||||
list(APPEND uv_libraries socket)
|
||||
endif()
|
||||
|
||||
if(APPLE OR CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|Linux|NetBSD|OpenBSD")
|
||||
list(APPEND uv_test_libraries util)
|
||||
endif()
|
||||
|
||||
add_library(uv SHARED ${uv_sources})
|
||||
target_compile_definitions(uv
|
||||
INTERFACE
|
||||
USING_UV_SHARED=1
|
||||
PRIVATE
|
||||
BUILDING_UV_SHARED=1
|
||||
${uv_defines})
|
||||
target_compile_options(uv PRIVATE ${uv_cflags})
|
||||
target_include_directories(uv
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
|
||||
target_link_libraries(uv ${uv_libraries})
|
||||
|
||||
add_library(uv_a STATIC ${uv_sources})
|
||||
target_compile_definitions(uv_a PRIVATE ${uv_defines})
|
||||
target_compile_options(uv_a PRIVATE ${uv_cflags})
|
||||
target_include_directories(uv_a
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
PRIVATE
|
||||
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
|
||||
target_link_libraries(uv_a ${uv_libraries})
|
||||
|
||||
if(LIBUV_BUILD_TESTS)
|
||||
# Small hack: use ${uv_test_sources} now to get the runner skeleton,
|
||||
# before the actual tests are added.
|
||||
add_executable(
|
||||
uv_run_benchmarks_a
|
||||
${uv_test_sources}
|
||||
test/benchmark-async-pummel.c
|
||||
test/benchmark-async.c
|
||||
test/benchmark-fs-stat.c
|
||||
test/benchmark-getaddrinfo.c
|
||||
test/benchmark-loop-count.c
|
||||
test/benchmark-million-async.c
|
||||
test/benchmark-million-timers.c
|
||||
test/benchmark-multi-accept.c
|
||||
test/benchmark-ping-pongs.c
|
||||
test/benchmark-ping-udp.c
|
||||
test/benchmark-pound.c
|
||||
test/benchmark-pump.c
|
||||
test/benchmark-sizes.c
|
||||
test/benchmark-spawn.c
|
||||
test/benchmark-tcp-write-batch.c
|
||||
test/benchmark-thread.c
|
||||
test/benchmark-udp-pummel.c
|
||||
test/blackhole-server.c
|
||||
test/dns-server.c
|
||||
test/echo-server.c
|
||||
test/run-benchmarks.c
|
||||
test/runner.c)
|
||||
target_compile_definitions(uv_run_benchmarks_a PRIVATE ${uv_defines})
|
||||
target_compile_options(uv_run_benchmarks_a PRIVATE ${uv_cflags})
|
||||
target_link_libraries(uv_run_benchmarks_a uv_a ${uv_test_libraries})
|
||||
|
||||
list(APPEND uv_test_sources
|
||||
test/blackhole-server.c
|
||||
test/echo-server.c
|
||||
test/run-tests.c
|
||||
test/runner.c
|
||||
test/test-active.c
|
||||
test/test-async-null-cb.c
|
||||
test/test-async.c
|
||||
test/test-barrier.c
|
||||
test/test-callback-order.c
|
||||
test/test-callback-stack.c
|
||||
test/test-close-fd.c
|
||||
test/test-close-order.c
|
||||
test/test-condvar.c
|
||||
test/test-connect-unspecified.c
|
||||
test/test-connection-fail.c
|
||||
test/test-cwd-and-chdir.c
|
||||
test/test-default-loop-close.c
|
||||
test/test-delayed-accept.c
|
||||
test/test-dlerror.c
|
||||
test/test-eintr-handling.c
|
||||
test/test-embed.c
|
||||
test/test-emfile.c
|
||||
test/test-env-vars.c
|
||||
test/test-error.c
|
||||
test/test-fail-always.c
|
||||
test/test-fork.c
|
||||
test/test-fs-copyfile.c
|
||||
test/test-fs-event.c
|
||||
test/test-fs-poll.c
|
||||
test/test-fs.c
|
||||
test/test-fs-readdir.c
|
||||
test/test-fs-fd-hash.c
|
||||
test/test-fs-open-flags.c
|
||||
test/test-get-currentexe.c
|
||||
test/test-get-loadavg.c
|
||||
test/test-get-memory.c
|
||||
test/test-get-passwd.c
|
||||
test/test-getaddrinfo.c
|
||||
test/test-gethostname.c
|
||||
test/test-getnameinfo.c
|
||||
test/test-getsockname.c
|
||||
test/test-getters-setters.c
|
||||
test/test-gettimeofday.c
|
||||
test/test-handle-fileno.c
|
||||
test/test-homedir.c
|
||||
test/test-hrtime.c
|
||||
test/test-idle.c
|
||||
test/test-idna.c
|
||||
test/test-ip4-addr.c
|
||||
test/test-ip6-addr.c
|
||||
test/test-ipc-heavy-traffic-deadlock-bug.c
|
||||
test/test-ipc-send-recv.c
|
||||
test/test-ipc.c
|
||||
test/test-loop-alive.c
|
||||
test/test-loop-close.c
|
||||
test/test-loop-configure.c
|
||||
test/test-loop-handles.c
|
||||
test/test-loop-stop.c
|
||||
test/test-loop-time.c
|
||||
test/test-metrics.c
|
||||
test/test-multiple-listen.c
|
||||
test/test-mutexes.c
|
||||
test/test-osx-select.c
|
||||
test/test-pass-always.c
|
||||
test/test-ping-pong.c
|
||||
test/test-pipe-bind-error.c
|
||||
test/test-pipe-close-stdout-read-stdin.c
|
||||
test/test-pipe-connect-error.c
|
||||
test/test-pipe-connect-multiple.c
|
||||
test/test-pipe-connect-prepare.c
|
||||
test/test-pipe-getsockname.c
|
||||
test/test-pipe-pending-instances.c
|
||||
test/test-pipe-sendmsg.c
|
||||
test/test-pipe-server-close.c
|
||||
test/test-pipe-set-fchmod.c
|
||||
test/test-pipe-set-non-blocking.c
|
||||
test/test-platform-output.c
|
||||
test/test-poll-close-doesnt-corrupt-stack.c
|
||||
test/test-poll-close.c
|
||||
test/test-poll-closesocket.c
|
||||
test/test-poll-oob.c
|
||||
test/test-poll.c
|
||||
test/test-process-priority.c
|
||||
test/test-process-title-threadsafe.c
|
||||
test/test-process-title.c
|
||||
test/test-queue-foreach-delete.c
|
||||
test/test-random.c
|
||||
test/test-ref.c
|
||||
test/test-run-nowait.c
|
||||
test/test-run-once.c
|
||||
test/test-semaphore.c
|
||||
test/test-shutdown-close.c
|
||||
test/test-shutdown-eof.c
|
||||
test/test-shutdown-twice.c
|
||||
test/test-signal-multiple-loops.c
|
||||
test/test-signal-pending-on-close.c
|
||||
test/test-signal.c
|
||||
test/test-socket-buffer-size.c
|
||||
test/test-spawn.c
|
||||
test/test-stdio-over-pipes.c
|
||||
test/test-strscpy.c
|
||||
test/test-tcp-alloc-cb-fail.c
|
||||
test/test-tcp-bind-error.c
|
||||
test/test-tcp-bind6-error.c
|
||||
test/test-tcp-close-accept.c
|
||||
test/test-tcp-close-while-connecting.c
|
||||
test/test-tcp-close.c
|
||||
test/test-tcp-close-reset.c
|
||||
test/test-tcp-connect-error-after-write.c
|
||||
test/test-tcp-connect-error.c
|
||||
test/test-tcp-connect-timeout.c
|
||||
test/test-tcp-connect6-error.c
|
||||
test/test-tcp-create-socket-early.c
|
||||
test/test-tcp-flags.c
|
||||
test/test-tcp-oob.c
|
||||
test/test-tcp-open.c
|
||||
test/test-tcp-read-stop.c
|
||||
test/test-tcp-read-stop-start.c
|
||||
test/test-tcp-shutdown-after-write.c
|
||||
test/test-tcp-try-write.c
|
||||
test/test-tcp-try-write-error.c
|
||||
test/test-tcp-unexpected-read.c
|
||||
test/test-tcp-write-after-connect.c
|
||||
test/test-tcp-write-fail.c
|
||||
test/test-tcp-write-queue-order.c
|
||||
test/test-tcp-write-to-half-open-connection.c
|
||||
test/test-tcp-writealot.c
|
||||
test/test-test-macros.c
|
||||
test/test-thread-equal.c
|
||||
test/test-thread.c
|
||||
test/test-threadpool-cancel.c
|
||||
test/test-threadpool.c
|
||||
test/test-timer-again.c
|
||||
test/test-timer-from-check.c
|
||||
test/test-timer.c
|
||||
test/test-tmpdir.c
|
||||
test/test-tty-duplicate-key.c
|
||||
test/test-tty-escape-sequence-processing.c
|
||||
test/test-tty.c
|
||||
test/test-udp-alloc-cb-fail.c
|
||||
test/test-udp-bind.c
|
||||
test/test-udp-connect.c
|
||||
test/test-udp-create-socket-early.c
|
||||
test/test-udp-dgram-too-big.c
|
||||
test/test-udp-ipv6.c
|
||||
test/test-udp-mmsg.c
|
||||
test/test-udp-multicast-interface.c
|
||||
test/test-udp-multicast-interface6.c
|
||||
test/test-udp-multicast-join.c
|
||||
test/test-udp-multicast-join6.c
|
||||
test/test-udp-multicast-ttl.c
|
||||
test/test-udp-open.c
|
||||
test/test-udp-options.c
|
||||
test/test-udp-send-and-recv.c
|
||||
test/test-udp-send-hang-loop.c
|
||||
test/test-udp-send-immediate.c
|
||||
test/test-udp-sendmmsg-error.c
|
||||
test/test-udp-send-unreachable.c
|
||||
test/test-udp-try-send.c
|
||||
test/test-uname.c
|
||||
test/test-walk-handles.c
|
||||
test/test-watcher-cross-stop.c)
|
||||
|
||||
add_executable(uv_run_tests ${uv_test_sources} uv_win_longpath.manifest)
|
||||
target_compile_definitions(uv_run_tests
|
||||
PRIVATE ${uv_defines} USING_UV_SHARED=1)
|
||||
target_compile_options(uv_run_tests PRIVATE ${uv_cflags})
|
||||
target_link_libraries(uv_run_tests uv ${uv_test_libraries})
|
||||
add_test(NAME uv_test
|
||||
COMMAND uv_run_tests
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "OS390")
|
||||
set_tests_properties(uv_test PROPERTIES ENVIRONMENT
|
||||
"LIBPATH=${CMAKE_BINARY_DIR}:$ENV{LIBPATH}")
|
||||
endif()
|
||||
add_executable(uv_run_tests_a ${uv_test_sources} uv_win_longpath.manifest)
|
||||
target_compile_definitions(uv_run_tests_a PRIVATE ${uv_defines})
|
||||
target_compile_options(uv_run_tests_a PRIVATE ${uv_cflags})
|
||||
if(QEMU)
|
||||
target_link_libraries(uv_run_tests_a uv_a ${uv_test_libraries} -static)
|
||||
else()
|
||||
target_link_libraries(uv_run_tests_a uv_a ${uv_test_libraries})
|
||||
endif()
|
||||
add_test(NAME uv_test_a
|
||||
COMMAND uv_run_tests_a
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
if(UNIX OR MINGW)
|
||||
# Now for some gibbering horrors from beyond the stars...
|
||||
foreach(lib IN LISTS uv_libraries)
|
||||
list(APPEND LIBS "-l${lib}")
|
||||
endforeach()
|
||||
string(REPLACE ";" " " LIBS "${LIBS}")
|
||||
# Consider setting project version via project() call?
|
||||
file(STRINGS configure.ac configure_ac REGEX ^AC_INIT)
|
||||
string(REGEX MATCH "([0-9]+)[.][0-9]+[.][0-9]+" PACKAGE_VERSION "${configure_ac}")
|
||||
set(UV_VERSION_MAJOR "${CMAKE_MATCH_1}")
|
||||
# The version in the filename is mirroring the behaviour of autotools.
|
||||
set_target_properties(uv PROPERTIES
|
||||
VERSION ${UV_VERSION_MAJOR}.0.0
|
||||
SOVERSION ${UV_VERSION_MAJOR})
|
||||
set(includedir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR})
|
||||
set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
|
||||
set(prefix ${CMAKE_INSTALL_PREFIX})
|
||||
configure_file(libuv.pc.in libuv.pc @ONLY)
|
||||
configure_file(libuv-static.pc.in libuv-static.pc @ONLY)
|
||||
|
||||
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||
install(FILES ${PROJECT_BINARY_DIR}/libuv.pc ${PROJECT_BINARY_DIR}/libuv-static.pc
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
install(TARGETS uv LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(TARGETS uv_a ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
install(DIRECTORY include/ DESTINATION include)
|
||||
install(FILES LICENSE DESTINATION .)
|
||||
install(TARGETS uv uv_a
|
||||
RUNTIME DESTINATION lib/$<CONFIG>
|
||||
ARCHIVE DESTINATION lib/$<CONFIG>)
|
||||
endif()
|
||||
|
||||
message(STATUS "summary of build options:
|
||||
Install prefix: ${CMAKE_INSTALL_PREFIX}
|
||||
Target system: ${CMAKE_SYSTEM_NAME}
|
||||
Compiler:
|
||||
C compiler: ${CMAKE_C_COMPILER}
|
||||
CFLAGS: ${CMAKE_C_FLAGS_${_build_type}} ${CMAKE_C_FLAGS}
|
||||
")
|
171
deps/libuv/CONTRIBUTING.md
vendored
Normal file
171
deps/libuv/CONTRIBUTING.md
vendored
Normal file
@ -0,0 +1,171 @@
|
||||
# CONTRIBUTING
|
||||
|
||||
The libuv project welcomes new contributors. This document will guide you
|
||||
through the process.
|
||||
|
||||
|
||||
### FORK
|
||||
|
||||
Fork the project [on GitHub](https://github.com/libuv/libuv) and check out
|
||||
your copy.
|
||||
|
||||
```
|
||||
$ git clone https://github.com/username/libuv.git
|
||||
$ cd libuv
|
||||
$ git remote add upstream https://github.com/libuv/libuv.git
|
||||
```
|
||||
|
||||
Now decide if you want your feature or bug fix to go into the master branch
|
||||
or the stable branch. As a rule of thumb, bug fixes go into the stable branch
|
||||
while new features go into the master branch.
|
||||
|
||||
The stable branch is effectively frozen; patches that change the libuv
|
||||
API/ABI or affect the run-time behavior of applications get rejected.
|
||||
|
||||
In case of doubt, open an issue in the [issue tracker][], post your question
|
||||
to the [libuv mailing list], or contact one of [project maintainers][] on [IRC][].
|
||||
|
||||
Especially do so if you plan to work on something big. Nothing is more
|
||||
frustrating than seeing your hard work go to waste because your vision
|
||||
does not align with that of a project maintainers.
|
||||
|
||||
|
||||
### BRANCH
|
||||
|
||||
Okay, so you have decided on the proper branch. Create a feature branch
|
||||
and start hacking:
|
||||
|
||||
```
|
||||
$ git checkout -b my-feature-branch -t origin/v1.x
|
||||
```
|
||||
|
||||
(Where v1.x is the latest stable branch as of this writing.)
|
||||
|
||||
### CODE
|
||||
|
||||
Please adhere to libuv's code style. In general it follows the conventions from
|
||||
the [Google C/C++ style guide]. Some of the key points, as well as some
|
||||
additional guidelines, are enumerated below.
|
||||
|
||||
* Code that is specific to unix-y platforms should be placed in `src/unix`, and
|
||||
declarations go into `include/uv/unix.h`.
|
||||
|
||||
* Source code that is Windows-specific goes into `src/win`, and related
|
||||
publicly exported types, functions and macro declarations should generally
|
||||
be declared in `include/uv/win.h`.
|
||||
|
||||
* Names should be descriptive and concise.
|
||||
|
||||
* All the symbols and types that libuv makes available publicly should be
|
||||
prefixed with `uv_` (or `UV_` in case of macros).
|
||||
|
||||
* Internal, non-static functions should be prefixed with `uv__`.
|
||||
|
||||
* Use two spaces and no tabs.
|
||||
|
||||
* Lines should be wrapped at 80 characters.
|
||||
|
||||
* Ensure that lines have no trailing whitespace, and use unix-style (LF) line
|
||||
endings.
|
||||
|
||||
* Use C89-compliant syntax. In other words, variables can only be declared at
|
||||
the top of a scope (function, if/for/while-block).
|
||||
|
||||
* When writing comments, use properly constructed sentences, including
|
||||
punctuation.
|
||||
|
||||
* When documenting APIs and/or source code, don't make assumptions or make
|
||||
implications about race, gender, religion, political orientation or anything
|
||||
else that isn't relevant to the project.
|
||||
|
||||
* Remember that source code usually gets written once and read often: ensure
|
||||
the reader doesn't have to make guesses. Make sure that the purpose and inner
|
||||
logic are either obvious to a reasonably skilled professional, or add a
|
||||
comment that explains it.
|
||||
|
||||
|
||||
### COMMIT
|
||||
|
||||
Make sure git knows your name and email address:
|
||||
|
||||
```
|
||||
$ git config --global user.name "J. Random User"
|
||||
$ git config --global user.email "j.random.user@example.com"
|
||||
```
|
||||
|
||||
Writing good commit logs is important. A commit log should describe what
|
||||
changed and why. Follow these guidelines when writing one:
|
||||
|
||||
1. The first line should be 50 characters or less and contain a short
|
||||
description of the change prefixed with the name of the changed
|
||||
subsystem (e.g. "net: add localAddress and localPort to Socket").
|
||||
2. Keep the second line blank.
|
||||
3. Wrap all other lines at 72 columns.
|
||||
|
||||
A good commit log looks like this:
|
||||
|
||||
```
|
||||
subsystem: explaining the commit in one line
|
||||
|
||||
Body of commit message is a few lines of text, explaining things
|
||||
in more detail, possibly giving some background about the issue
|
||||
being fixed, etc etc.
|
||||
|
||||
The body of the commit message can be several paragraphs, and
|
||||
please do proper word-wrap and keep columns shorter than about
|
||||
72 characters or so. That way `git log` will show things
|
||||
nicely even when it is indented.
|
||||
```
|
||||
|
||||
The header line should be meaningful; it is what other people see when they
|
||||
run `git shortlog` or `git log --oneline`.
|
||||
|
||||
Check the output of `git log --oneline files_that_you_changed` to find out
|
||||
what subsystem (or subsystems) your changes touch.
|
||||
|
||||
|
||||
### REBASE
|
||||
|
||||
Use `git rebase` (not `git merge`) to sync your work from time to time.
|
||||
|
||||
```
|
||||
$ git fetch upstream
|
||||
$ git rebase upstream/v1.x # or upstream/master
|
||||
```
|
||||
|
||||
|
||||
### TEST
|
||||
|
||||
Bug fixes and features should come with tests. Add your tests in the
|
||||
`test/` directory. Each new test needs to be registered in `test/test-list.h`.
|
||||
|
||||
If you add a new test file, it needs to be registered in three places:
|
||||
- `CMakeLists.txt`: add the file's name to the `uv_test_sources` list.
|
||||
- `Makefile.am`: add the file's name to the `test_run_tests_SOURCES` list.
|
||||
|
||||
Look at other tests to see how they should be structured (license boilerplate,
|
||||
the way entry points are declared, etc.).
|
||||
|
||||
Check README.md file to find out how to run the test suite and make sure that
|
||||
there are no test regressions.
|
||||
|
||||
### PUSH
|
||||
|
||||
```
|
||||
$ git push origin my-feature-branch
|
||||
```
|
||||
|
||||
Go to https://github.com/username/libuv and select your feature branch. Click
|
||||
the 'Pull Request' button and fill out the form.
|
||||
|
||||
Pull requests are usually reviewed within a few days. If there are comments
|
||||
to address, apply your changes in a separate commit and push that to your
|
||||
feature branch. Post a comment in the pull request afterwards; GitHub does
|
||||
not send out notifications when you add commits.
|
||||
|
||||
|
||||
[issue tracker]: https://github.com/libuv/libuv/issues
|
||||
[libuv mailing list]: http://groups.google.com/group/libuv
|
||||
[IRC]: http://webchat.freenode.net/?channels=libuv
|
||||
[Google C/C++ style guide]: https://google.github.io/styleguide/cppguide.html
|
||||
[project maintainers]: https://github.com/libuv/libuv/blob/master/MAINTAINERS.md
|
4975
deps/libuv/ChangeLog
vendored
Normal file
4975
deps/libuv/ChangeLog
vendored
Normal file
File diff suppressed because it is too large
Load Diff
70
deps/libuv/LICENSE
vendored
Normal file
70
deps/libuv/LICENSE
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
libuv is licensed for use as follows:
|
||||
|
||||
====
|
||||
Copyright (c) 2015-present libuv project contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
====
|
||||
|
||||
This license applies to parts of libuv originating from the
|
||||
https://github.com/joyent/libuv repository:
|
||||
|
||||
====
|
||||
|
||||
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
|
||||
====
|
||||
|
||||
This license applies to all parts of libuv that are not externally
|
||||
maintained libraries.
|
||||
|
||||
The externally maintained libraries used by libuv are:
|
||||
|
||||
- tree.h (from FreeBSD), copyright Niels Provos. Two clause BSD license.
|
||||
|
||||
- inet_pton and inet_ntop implementations, contained in src/inet.c, are
|
||||
copyright the Internet Systems Consortium, Inc., and licensed under the ISC
|
||||
license.
|
||||
|
||||
- stdint-msvc2008.h (from msinttypes), copyright Alexander Chemeris. Three
|
||||
clause BSD license.
|
||||
|
||||
- pthread-fixes.c, copyright Google Inc. and Sony Mobile Communications AB.
|
||||
Three clause BSD license.
|
||||
|
||||
- android-ifaddrs.h, android-ifaddrs.c, copyright Berkeley Software Design
|
||||
Inc, Kenneth MacKay and Emergya (Cloud4all, FP7/2007-2013, grant agreement
|
||||
n° 289016). Three clause BSD license.
|
396
deps/libuv/LICENSE-docs
vendored
Normal file
396
deps/libuv/LICENSE-docs
vendored
Normal file
@ -0,0 +1,396 @@
|
||||
Attribution 4.0 International
|
||||
|
||||
=======================================================================
|
||||
|
||||
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
||||
does not provide legal services or legal advice. Distribution of
|
||||
Creative Commons public licenses does not create a lawyer-client or
|
||||
other relationship. Creative Commons makes its licenses and related
|
||||
information available on an "as-is" basis. Creative Commons gives no
|
||||
warranties regarding its licenses, any material licensed under their
|
||||
terms and conditions, or any related information. Creative Commons
|
||||
disclaims all liability for damages resulting from their use to the
|
||||
fullest extent possible.
|
||||
|
||||
Using Creative Commons Public Licenses
|
||||
|
||||
Creative Commons public licenses provide a standard set of terms and
|
||||
conditions that creators and other rights holders may use to share
|
||||
original works of authorship and other material subject to copyright
|
||||
and certain other rights specified in the public license below. The
|
||||
following considerations are for informational purposes only, are not
|
||||
exhaustive, and do not form part of our licenses.
|
||||
|
||||
Considerations for licensors: Our public licenses are
|
||||
intended for use by those authorized to give the public
|
||||
permission to use material in ways otherwise restricted by
|
||||
copyright and certain other rights. Our licenses are
|
||||
irrevocable. Licensors should read and understand the terms
|
||||
and conditions of the license they choose before applying it.
|
||||
Licensors should also secure all rights necessary before
|
||||
applying our licenses so that the public can reuse the
|
||||
material as expected. Licensors should clearly mark any
|
||||
material not subject to the license. This includes other CC-
|
||||
licensed material, or material used under an exception or
|
||||
limitation to copyright. More considerations for licensors:
|
||||
wiki.creativecommons.org/Considerations_for_licensors
|
||||
|
||||
Considerations for the public: By using one of our public
|
||||
licenses, a licensor grants the public permission to use the
|
||||
licensed material under specified terms and conditions. If
|
||||
the licensor's permission is not necessary for any reason--for
|
||||
example, because of any applicable exception or limitation to
|
||||
copyright--then that use is not regulated by the license. Our
|
||||
licenses grant only permissions under copyright and certain
|
||||
other rights that a licensor has authority to grant. Use of
|
||||
the licensed material may still be restricted for other
|
||||
reasons, including because others have copyright or other
|
||||
rights in the material. A licensor may make special requests,
|
||||
such as asking that all changes be marked or described.
|
||||
Although not required by our licenses, you are encouraged to
|
||||
respect those requests where reasonable. More_considerations
|
||||
for the public:
|
||||
wiki.creativecommons.org/Considerations_for_licensees
|
||||
|
||||
=======================================================================
|
||||
|
||||
Creative Commons Attribution 4.0 International Public License
|
||||
|
||||
By exercising the Licensed Rights (defined below), You accept and agree
|
||||
to be bound by the terms and conditions of this Creative Commons
|
||||
Attribution 4.0 International Public License ("Public License"). To the
|
||||
extent this Public License may be interpreted as a contract, You are
|
||||
granted the Licensed Rights in consideration of Your acceptance of
|
||||
these terms and conditions, and the Licensor grants You such rights in
|
||||
consideration of benefits the Licensor receives from making the
|
||||
Licensed Material available under these terms and conditions.
|
||||
|
||||
|
||||
Section 1 -- Definitions.
|
||||
|
||||
a. Adapted Material means material subject to Copyright and Similar
|
||||
Rights that is derived from or based upon the Licensed Material
|
||||
and in which the Licensed Material is translated, altered,
|
||||
arranged, transformed, or otherwise modified in a manner requiring
|
||||
permission under the Copyright and Similar Rights held by the
|
||||
Licensor. For purposes of this Public License, where the Licensed
|
||||
Material is a musical work, performance, or sound recording,
|
||||
Adapted Material is always produced where the Licensed Material is
|
||||
synched in timed relation with a moving image.
|
||||
|
||||
b. Adapter's License means the license You apply to Your Copyright
|
||||
and Similar Rights in Your contributions to Adapted Material in
|
||||
accordance with the terms and conditions of this Public License.
|
||||
|
||||
c. Copyright and Similar Rights means copyright and/or similar rights
|
||||
closely related to copyright including, without limitation,
|
||||
performance, broadcast, sound recording, and Sui Generis Database
|
||||
Rights, without regard to how the rights are labeled or
|
||||
categorized. For purposes of this Public License, the rights
|
||||
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
||||
Rights.
|
||||
|
||||
d. Effective Technological Measures means those measures that, in the
|
||||
absence of proper authority, may not be circumvented under laws
|
||||
fulfilling obligations under Article 11 of the WIPO Copyright
|
||||
Treaty adopted on December 20, 1996, and/or similar international
|
||||
agreements.
|
||||
|
||||
e. Exceptions and Limitations means fair use, fair dealing, and/or
|
||||
any other exception or limitation to Copyright and Similar Rights
|
||||
that applies to Your use of the Licensed Material.
|
||||
|
||||
f. Licensed Material means the artistic or literary work, database,
|
||||
or other material to which the Licensor applied this Public
|
||||
License.
|
||||
|
||||
g. Licensed Rights means the rights granted to You subject to the
|
||||
terms and conditions of this Public License, which are limited to
|
||||
all Copyright and Similar Rights that apply to Your use of the
|
||||
Licensed Material and that the Licensor has authority to license.
|
||||
|
||||
h. Licensor means the individual(s) or entity(ies) granting rights
|
||||
under this Public License.
|
||||
|
||||
i. Share means to provide material to the public by any means or
|
||||
process that requires permission under the Licensed Rights, such
|
||||
as reproduction, public display, public performance, distribution,
|
||||
dissemination, communication, or importation, and to make material
|
||||
available to the public including in ways that members of the
|
||||
public may access the material from a place and at a time
|
||||
individually chosen by them.
|
||||
|
||||
j. Sui Generis Database Rights means rights other than copyright
|
||||
resulting from Directive 96/9/EC of the European Parliament and of
|
||||
the Council of 11 March 1996 on the legal protection of databases,
|
||||
as amended and/or succeeded, as well as other essentially
|
||||
equivalent rights anywhere in the world.
|
||||
|
||||
k. You means the individual or entity exercising the Licensed Rights
|
||||
under this Public License. Your has a corresponding meaning.
|
||||
|
||||
|
||||
Section 2 -- Scope.
|
||||
|
||||
a. License grant.
|
||||
|
||||
1. Subject to the terms and conditions of this Public License,
|
||||
the Licensor hereby grants You a worldwide, royalty-free,
|
||||
non-sublicensable, non-exclusive, irrevocable license to
|
||||
exercise the Licensed Rights in the Licensed Material to:
|
||||
|
||||
a. reproduce and Share the Licensed Material, in whole or
|
||||
in part; and
|
||||
|
||||
b. produce, reproduce, and Share Adapted Material.
|
||||
|
||||
2. Exceptions and Limitations. For the avoidance of doubt, where
|
||||
Exceptions and Limitations apply to Your use, this Public
|
||||
License does not apply, and You do not need to comply with
|
||||
its terms and conditions.
|
||||
|
||||
3. Term. The term of this Public License is specified in Section
|
||||
6(a).
|
||||
|
||||
4. Media and formats; technical modifications allowed. The
|
||||
Licensor authorizes You to exercise the Licensed Rights in
|
||||
all media and formats whether now known or hereafter created,
|
||||
and to make technical modifications necessary to do so. The
|
||||
Licensor waives and/or agrees not to assert any right or
|
||||
authority to forbid You from making technical modifications
|
||||
necessary to exercise the Licensed Rights, including
|
||||
technical modifications necessary to circumvent Effective
|
||||
Technological Measures. For purposes of this Public License,
|
||||
simply making modifications authorized by this Section 2(a)
|
||||
(4) never produces Adapted Material.
|
||||
|
||||
5. Downstream recipients.
|
||||
|
||||
a. Offer from the Licensor -- Licensed Material. Every
|
||||
recipient of the Licensed Material automatically
|
||||
receives an offer from the Licensor to exercise the
|
||||
Licensed Rights under the terms and conditions of this
|
||||
Public License.
|
||||
|
||||
b. No downstream restrictions. You may not offer or impose
|
||||
any additional or different terms or conditions on, or
|
||||
apply any Effective Technological Measures to, the
|
||||
Licensed Material if doing so restricts exercise of the
|
||||
Licensed Rights by any recipient of the Licensed
|
||||
Material.
|
||||
|
||||
6. No endorsement. Nothing in this Public License constitutes or
|
||||
may be construed as permission to assert or imply that You
|
||||
are, or that Your use of the Licensed Material is, connected
|
||||
with, or sponsored, endorsed, or granted official status by,
|
||||
the Licensor or others designated to receive attribution as
|
||||
provided in Section 3(a)(1)(A)(i).
|
||||
|
||||
b. Other rights.
|
||||
|
||||
1. Moral rights, such as the right of integrity, are not
|
||||
licensed under this Public License, nor are publicity,
|
||||
privacy, and/or other similar personality rights; however, to
|
||||
the extent possible, the Licensor waives and/or agrees not to
|
||||
assert any such rights held by the Licensor to the limited
|
||||
extent necessary to allow You to exercise the Licensed
|
||||
Rights, but not otherwise.
|
||||
|
||||
2. Patent and trademark rights are not licensed under this
|
||||
Public License.
|
||||
|
||||
3. To the extent possible, the Licensor waives any right to
|
||||
collect royalties from You for the exercise of the Licensed
|
||||
Rights, whether directly or through a collecting society
|
||||
under any voluntary or waivable statutory or compulsory
|
||||
licensing scheme. In all other cases the Licensor expressly
|
||||
reserves any right to collect such royalties.
|
||||
|
||||
|
||||
Section 3 -- License Conditions.
|
||||
|
||||
Your exercise of the Licensed Rights is expressly made subject to the
|
||||
following conditions.
|
||||
|
||||
a. Attribution.
|
||||
|
||||
1. If You Share the Licensed Material (including in modified
|
||||
form), You must:
|
||||
|
||||
a. retain the following if it is supplied by the Licensor
|
||||
with the Licensed Material:
|
||||
|
||||
i. identification of the creator(s) of the Licensed
|
||||
Material and any others designated to receive
|
||||
attribution, in any reasonable manner requested by
|
||||
the Licensor (including by pseudonym if
|
||||
designated);
|
||||
|
||||
ii. a copyright notice;
|
||||
|
||||
iii. a notice that refers to this Public License;
|
||||
|
||||
iv. a notice that refers to the disclaimer of
|
||||
warranties;
|
||||
|
||||
v. a URI or hyperlink to the Licensed Material to the
|
||||
extent reasonably practicable;
|
||||
|
||||
b. indicate if You modified the Licensed Material and
|
||||
retain an indication of any previous modifications; and
|
||||
|
||||
c. indicate the Licensed Material is licensed under this
|
||||
Public License, and include the text of, or the URI or
|
||||
hyperlink to, this Public License.
|
||||
|
||||
2. You may satisfy the conditions in Section 3(a)(1) in any
|
||||
reasonable manner based on the medium, means, and context in
|
||||
which You Share the Licensed Material. For example, it may be
|
||||
reasonable to satisfy the conditions by providing a URI or
|
||||
hyperlink to a resource that includes the required
|
||||
information.
|
||||
|
||||
3. If requested by the Licensor, You must remove any of the
|
||||
information required by Section 3(a)(1)(A) to the extent
|
||||
reasonably practicable.
|
||||
|
||||
4. If You Share Adapted Material You produce, the Adapter's
|
||||
License You apply must not prevent recipients of the Adapted
|
||||
Material from complying with this Public License.
|
||||
|
||||
|
||||
Section 4 -- Sui Generis Database Rights.
|
||||
|
||||
Where the Licensed Rights include Sui Generis Database Rights that
|
||||
apply to Your use of the Licensed Material:
|
||||
|
||||
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
||||
to extract, reuse, reproduce, and Share all or a substantial
|
||||
portion of the contents of the database;
|
||||
|
||||
b. if You include all or a substantial portion of the database
|
||||
contents in a database in which You have Sui Generis Database
|
||||
Rights, then the database in which You have Sui Generis Database
|
||||
Rights (but not its individual contents) is Adapted Material; and
|
||||
|
||||
c. You must comply with the conditions in Section 3(a) if You Share
|
||||
all or a substantial portion of the contents of the database.
|
||||
|
||||
For the avoidance of doubt, this Section 4 supplements and does not
|
||||
replace Your obligations under this Public License where the Licensed
|
||||
Rights include other Copyright and Similar Rights.
|
||||
|
||||
|
||||
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
||||
|
||||
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
||||
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
||||
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
||||
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
||||
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
||||
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
||||
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
||||
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
||||
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
||||
|
||||
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
||||
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
||||
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
||||
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
||||
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
||||
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
||||
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
||||
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
||||
|
||||
c. The disclaimer of warranties and limitation of liability provided
|
||||
above shall be interpreted in a manner that, to the extent
|
||||
possible, most closely approximates an absolute disclaimer and
|
||||
waiver of all liability.
|
||||
|
||||
|
||||
Section 6 -- Term and Termination.
|
||||
|
||||
a. This Public License applies for the term of the Copyright and
|
||||
Similar Rights licensed here. However, if You fail to comply with
|
||||
this Public License, then Your rights under this Public License
|
||||
terminate automatically.
|
||||
|
||||
b. Where Your right to use the Licensed Material has terminated under
|
||||
Section 6(a), it reinstates:
|
||||
|
||||
1. automatically as of the date the violation is cured, provided
|
||||
it is cured within 30 days of Your discovery of the
|
||||
violation; or
|
||||
|
||||
2. upon express reinstatement by the Licensor.
|
||||
|
||||
For the avoidance of doubt, this Section 6(b) does not affect any
|
||||
right the Licensor may have to seek remedies for Your violations
|
||||
of this Public License.
|
||||
|
||||
c. For the avoidance of doubt, the Licensor may also offer the
|
||||
Licensed Material under separate terms or conditions or stop
|
||||
distributing the Licensed Material at any time; however, doing so
|
||||
will not terminate this Public License.
|
||||
|
||||
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
||||
License.
|
||||
|
||||
|
||||
Section 7 -- Other Terms and Conditions.
|
||||
|
||||
a. The Licensor shall not be bound by any additional or different
|
||||
terms or conditions communicated by You unless expressly agreed.
|
||||
|
||||
b. Any arrangements, understandings, or agreements regarding the
|
||||
Licensed Material not stated herein are separate from and
|
||||
independent of the terms and conditions of this Public License.
|
||||
|
||||
|
||||
Section 8 -- Interpretation.
|
||||
|
||||
a. For the avoidance of doubt, this Public License does not, and
|
||||
shall not be interpreted to, reduce, limit, restrict, or impose
|
||||
conditions on any use of the Licensed Material that could lawfully
|
||||
be made without permission under this Public License.
|
||||
|
||||
b. To the extent possible, if any provision of this Public License is
|
||||
deemed unenforceable, it shall be automatically reformed to the
|
||||
minimum extent necessary to make it enforceable. If the provision
|
||||
cannot be reformed, it shall be severed from this Public License
|
||||
without affecting the enforceability of the remaining terms and
|
||||
conditions.
|
||||
|
||||
c. No term or condition of this Public License will be waived and no
|
||||
failure to comply consented to unless expressly agreed to by the
|
||||
Licensor.
|
||||
|
||||
d. Nothing in this Public License constitutes or may be interpreted
|
||||
as a limitation upon, or waiver of, any privileges and immunities
|
||||
that apply to the Licensor or You, including from the legal
|
||||
processes of any jurisdiction or authority.
|
||||
|
||||
|
||||
=======================================================================
|
||||
|
||||
Creative Commons is not a party to its public
|
||||
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
||||
its public licenses to material it publishes and in those instances
|
||||
will be considered the “Licensor.” The text of the Creative Commons
|
||||
public licenses is dedicated to the public domain under the CC0 Public
|
||||
Domain Dedication. Except for the limited purpose of indicating that
|
||||
material is shared under a Creative Commons public license or as
|
||||
otherwise permitted by the Creative Commons policies published at
|
||||
creativecommons.org/policies, Creative Commons does not authorize the
|
||||
use of the trademark "Creative Commons" or any other trademark or logo
|
||||
of Creative Commons without its prior written consent including,
|
||||
without limitation, in connection with any unauthorized modifications
|
||||
to any of its public licenses or any other arrangements,
|
||||
understandings, or agreements concerning use of licensed material. For
|
||||
the avoidance of doubt, this paragraph does not form part of the
|
||||
public licenses.
|
||||
|
||||
Creative Commons may be contacted at creativecommons.org.
|
||||
|
50
deps/libuv/MAINTAINERS.md
vendored
Normal file
50
deps/libuv/MAINTAINERS.md
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
|
||||
# Project Maintainers
|
||||
|
||||
libuv is currently managed by the following individuals:
|
||||
|
||||
* **Anna Henningsen** ([@addaleax](https://github.com/addaleax))
|
||||
* **Bartosz Sosnowski** ([@bzoz](https://github.com/bzoz))
|
||||
* **Ben Noordhuis** ([@bnoordhuis](https://github.com/bnoordhuis))
|
||||
- GPG key: D77B 1E34 243F BAF0 5F8E 9CC3 4F55 C8C8 46AB 89B9 (pubkey-bnoordhuis)
|
||||
* **Bert Belder** ([@piscisaureus](https://github.com/piscisaureus))
|
||||
* **Colin Ihrig** ([@cjihrig](https://github.com/cjihrig))
|
||||
- GPG key: 94AE 3667 5C46 4D64 BAFA 68DD 7434 390B DBE9 B9C5 (pubkey-cjihrig)
|
||||
- GPG key: 5735 3E0D BDAA A7E8 39B6 6A1A FF47 D5E4 AD8B 4FDC (pubkey-cjihrig-kb)
|
||||
* **Fedor Indutny** ([@indutny](https://github.com/indutny))
|
||||
- GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny)
|
||||
* **Imran Iqbal** ([@imran-iq](https://github.com/imran-iq))
|
||||
- GPG key: 9DFE AA5F 481B BF77 2D90 03CE D592 4925 2F8E C41A (pubkey-iwuzhere)
|
||||
* **Jameson Nash** ([@vtjnash](https://github.com/vtjnash))
|
||||
* **John Barboza** ([@jbarz](https://github.com/jbarz))
|
||||
* **Kaoru Takanashi** ([@erw7](https://github.com/erw7))
|
||||
- GPG Key: 5804 F999 8A92 2AFB A398 47A0 7183 5090 6134 887F (pubkey-erw7)
|
||||
* **Richard Lau** ([@richardlau](https://github.com/richardlau))
|
||||
- GPG key: C82F A3AE 1CBE DC6B E46B 9360 C43C EC45 C17A B93C (pubkey-richardlau)
|
||||
* **Santiago Gimeno** ([@santigimeno](https://github.com/santigimeno))
|
||||
- GPG key: 612F 0EAD 9401 6223 79DF 4402 F28C 3C8D A33C 03BE (pubkey-santigimeno)
|
||||
* **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul))
|
||||
- GPG key: FDF5 1936 4458 319F A823 3DC9 410E 5553 AE9B C059 (pubkey-saghul)
|
||||
|
||||
## Storing a maintainer key in Git
|
||||
|
||||
It's quite handy to store a maintainer's signature as a git blob, and have
|
||||
that object tagged and signed with such key.
|
||||
|
||||
Export your public key:
|
||||
|
||||
$ gpg --armor --export saghul@gmail.com > saghul.asc
|
||||
|
||||
Store it as a blob on the repo:
|
||||
|
||||
$ git hash-object -w saghul.asc
|
||||
|
||||
The previous command returns a hash, copy it. For the sake of this explanation,
|
||||
we'll assume it's 'abcd1234'. Storing the blob in git is not enough, it could
|
||||
be garbage collected since nothing references it, so we'll create a tag for it:
|
||||
|
||||
$ git tag -s pubkey-saghul abcd1234
|
||||
|
||||
Commit the changes and push:
|
||||
|
||||
$ git push origin pubkey-saghul
|
546
deps/libuv/Makefile.am
vendored
Normal file
546
deps/libuv/Makefile.am
vendored
Normal file
@ -0,0 +1,546 @@
|
||||
# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/src
|
||||
|
||||
include_HEADERS=include/uv.h
|
||||
|
||||
uvincludedir = $(includedir)/uv
|
||||
uvinclude_HEADERS = include/uv/errno.h \
|
||||
include/uv/threadpool.h \
|
||||
include/uv/version.h
|
||||
|
||||
CLEANFILES =
|
||||
|
||||
lib_LTLIBRARIES = libuv.la
|
||||
libuv_la_CFLAGS = @CFLAGS@
|
||||
libuv_la_LDFLAGS = -no-undefined -version-info 1:0:0
|
||||
libuv_la_SOURCES = src/fs-poll.c \
|
||||
src/heap-inl.h \
|
||||
src/idna.c \
|
||||
src/idna.h \
|
||||
src/inet.c \
|
||||
src/queue.h \
|
||||
src/random.c \
|
||||
src/strscpy.c \
|
||||
src/strscpy.h \
|
||||
src/threadpool.c \
|
||||
src/timer.c \
|
||||
src/uv-data-getter-setters.c \
|
||||
src/uv-common.c \
|
||||
src/uv-common.h \
|
||||
src/version.c
|
||||
|
||||
if SUNOS
|
||||
# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers
|
||||
# on other platforms complain that the argument is unused during compilation.
|
||||
libuv_la_CFLAGS += -pthreads
|
||||
endif
|
||||
|
||||
if WINNT
|
||||
|
||||
uvinclude_HEADERS += include/uv/win.h include/uv/tree.h
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/src/win \
|
||||
-DWIN32_LEAN_AND_MEAN \
|
||||
-D_WIN32_WINNT=0x0600
|
||||
libuv_la_SOURCES += src/win/async.c \
|
||||
src/win/atomicops-inl.h \
|
||||
src/win/core.c \
|
||||
src/win/detect-wakeup.c \
|
||||
src/win/dl.c \
|
||||
src/win/error.c \
|
||||
src/win/fs-event.c \
|
||||
src/win/fs.c \
|
||||
src/win/getaddrinfo.c \
|
||||
src/win/getnameinfo.c \
|
||||
src/win/handle.c \
|
||||
src/win/handle-inl.h \
|
||||
src/win/internal.h \
|
||||
src/win/loop-watcher.c \
|
||||
src/win/pipe.c \
|
||||
src/win/poll.c \
|
||||
src/win/process-stdio.c \
|
||||
src/win/process.c \
|
||||
src/win/req-inl.h \
|
||||
src/win/signal.c \
|
||||
src/win/stream.c \
|
||||
src/win/stream-inl.h \
|
||||
src/win/tcp.c \
|
||||
src/win/thread.c \
|
||||
src/win/tty.c \
|
||||
src/win/udp.c \
|
||||
src/win/util.c \
|
||||
src/win/winapi.c \
|
||||
src/win/winapi.h \
|
||||
src/win/winsock.c \
|
||||
src/win/winsock.h
|
||||
|
||||
else # WINNT
|
||||
|
||||
uvinclude_HEADERS += include/uv/unix.h
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/src/unix
|
||||
libuv_la_SOURCES += src/unix/async.c \
|
||||
src/unix/atomic-ops.h \
|
||||
src/unix/core.c \
|
||||
src/unix/dl.c \
|
||||
src/unix/fs.c \
|
||||
src/unix/getaddrinfo.c \
|
||||
src/unix/getnameinfo.c \
|
||||
src/unix/internal.h \
|
||||
src/unix/loop-watcher.c \
|
||||
src/unix/loop.c \
|
||||
src/unix/pipe.c \
|
||||
src/unix/poll.c \
|
||||
src/unix/process.c \
|
||||
src/unix/random-devurandom.c \
|
||||
src/unix/signal.c \
|
||||
src/unix/spinlock.h \
|
||||
src/unix/stream.c \
|
||||
src/unix/tcp.c \
|
||||
src/unix/thread.c \
|
||||
src/unix/tty.c \
|
||||
src/unix/udp.c
|
||||
|
||||
endif # WINNT
|
||||
|
||||
EXTRA_DIST = test/fixtures/empty_file \
|
||||
test/fixtures/load_error.node \
|
||||
test/fixtures/lorem_ipsum.txt \
|
||||
include \
|
||||
docs \
|
||||
img \
|
||||
CONTRIBUTING.md \
|
||||
LICENSE \
|
||||
README.md
|
||||
|
||||
|
||||
|
||||
TESTS = test/run-tests
|
||||
check_PROGRAMS = test/run-tests
|
||||
test_run_tests_CFLAGS =
|
||||
|
||||
if SUNOS
|
||||
# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers
|
||||
# on other platforms complain that the argument is unused during compilation.
|
||||
test_run_tests_CFLAGS += -pthreads
|
||||
endif
|
||||
|
||||
test_run_tests_LDFLAGS =
|
||||
test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/dns-server.c \
|
||||
test/echo-server.c \
|
||||
test/run-tests.c \
|
||||
test/runner.c \
|
||||
test/runner.h \
|
||||
test/task.h \
|
||||
test/test-active.c \
|
||||
test/test-async.c \
|
||||
test/test-async-null-cb.c \
|
||||
test/test-barrier.c \
|
||||
test/test-callback-order.c \
|
||||
test/test-callback-stack.c \
|
||||
test/test-close-fd.c \
|
||||
test/test-close-order.c \
|
||||
test/test-condvar.c \
|
||||
test/test-connect-unspecified.c \
|
||||
test/test-connection-fail.c \
|
||||
test/test-cwd-and-chdir.c \
|
||||
test/test-default-loop-close.c \
|
||||
test/test-delayed-accept.c \
|
||||
test/test-dlerror.c \
|
||||
test/test-eintr-handling.c \
|
||||
test/test-embed.c \
|
||||
test/test-emfile.c \
|
||||
test/test-env-vars.c \
|
||||
test/test-error.c \
|
||||
test/test-fail-always.c \
|
||||
test/test-fs-copyfile.c \
|
||||
test/test-fs-event.c \
|
||||
test/test-fs-poll.c \
|
||||
test/test-fs.c \
|
||||
test/test-fs-readdir.c \
|
||||
test/test-fs-fd-hash.c \
|
||||
test/test-fs-open-flags.c \
|
||||
test/test-fork.c \
|
||||
test/test-getters-setters.c \
|
||||
test/test-get-currentexe.c \
|
||||
test/test-get-loadavg.c \
|
||||
test/test-get-memory.c \
|
||||
test/test-get-passwd.c \
|
||||
test/test-getaddrinfo.c \
|
||||
test/test-gethostname.c \
|
||||
test/test-getnameinfo.c \
|
||||
test/test-getsockname.c \
|
||||
test/test-gettimeofday.c \
|
||||
test/test-handle-fileno.c \
|
||||
test/test-homedir.c \
|
||||
test/test-hrtime.c \
|
||||
test/test-idle.c \
|
||||
test/test-idna.c \
|
||||
test/test-ip4-addr.c \
|
||||
test/test-ip6-addr.c \
|
||||
test/test-ipc-heavy-traffic-deadlock-bug.c \
|
||||
test/test-ipc-send-recv.c \
|
||||
test/test-ipc.c \
|
||||
test/test-list.h \
|
||||
test/test-loop-handles.c \
|
||||
test/test-loop-alive.c \
|
||||
test/test-loop-close.c \
|
||||
test/test-loop-stop.c \
|
||||
test/test-loop-time.c \
|
||||
test/test-loop-configure.c \
|
||||
test/test-metrics.c \
|
||||
test/test-multiple-listen.c \
|
||||
test/test-mutexes.c \
|
||||
test/test-osx-select.c \
|
||||
test/test-pass-always.c \
|
||||
test/test-ping-pong.c \
|
||||
test/test-pipe-bind-error.c \
|
||||
test/test-pipe-connect-error.c \
|
||||
test/test-pipe-connect-multiple.c \
|
||||
test/test-pipe-connect-prepare.c \
|
||||
test/test-pipe-getsockname.c \
|
||||
test/test-pipe-pending-instances.c \
|
||||
test/test-pipe-sendmsg.c \
|
||||
test/test-pipe-server-close.c \
|
||||
test/test-pipe-close-stdout-read-stdin.c \
|
||||
test/test-pipe-set-non-blocking.c \
|
||||
test/test-pipe-set-fchmod.c \
|
||||
test/test-platform-output.c \
|
||||
test/test-poll.c \
|
||||
test/test-poll-close.c \
|
||||
test/test-poll-close-doesnt-corrupt-stack.c \
|
||||
test/test-poll-closesocket.c \
|
||||
test/test-poll-oob.c \
|
||||
test/test-process-priority.c \
|
||||
test/test-process-title.c \
|
||||
test/test-process-title-threadsafe.c \
|
||||
test/test-queue-foreach-delete.c \
|
||||
test/test-random.c \
|
||||
test/test-ref.c \
|
||||
test/test-run-nowait.c \
|
||||
test/test-run-once.c \
|
||||
test/test-semaphore.c \
|
||||
test/test-shutdown-close.c \
|
||||
test/test-shutdown-eof.c \
|
||||
test/test-shutdown-twice.c \
|
||||
test/test-signal-multiple-loops.c \
|
||||
test/test-signal-pending-on-close.c \
|
||||
test/test-signal.c \
|
||||
test/test-socket-buffer-size.c \
|
||||
test/test-spawn.c \
|
||||
test/test-stdio-over-pipes.c \
|
||||
test/test-strscpy.c \
|
||||
test/test-tcp-alloc-cb-fail.c \
|
||||
test/test-tcp-bind-error.c \
|
||||
test/test-tcp-bind6-error.c \
|
||||
test/test-tcp-close-accept.c \
|
||||
test/test-tcp-close-while-connecting.c \
|
||||
test/test-tcp-close.c \
|
||||
test/test-tcp-close-reset.c \
|
||||
test/test-tcp-create-socket-early.c \
|
||||
test/test-tcp-connect-error-after-write.c \
|
||||
test/test-tcp-connect-error.c \
|
||||
test/test-tcp-connect-timeout.c \
|
||||
test/test-tcp-connect6-error.c \
|
||||
test/test-tcp-flags.c \
|
||||
test/test-tcp-open.c \
|
||||
test/test-tcp-read-stop.c \
|
||||
test/test-tcp-read-stop-start.c \
|
||||
test/test-tcp-shutdown-after-write.c \
|
||||
test/test-tcp-unexpected-read.c \
|
||||
test/test-tcp-oob.c \
|
||||
test/test-tcp-write-to-half-open-connection.c \
|
||||
test/test-tcp-write-after-connect.c \
|
||||
test/test-tcp-writealot.c \
|
||||
test/test-tcp-write-fail.c \
|
||||
test/test-tcp-try-write.c \
|
||||
test/test-tcp-try-write-error.c \
|
||||
test/test-tcp-write-queue-order.c \
|
||||
test/test-test-macros.c \
|
||||
test/test-thread-equal.c \
|
||||
test/test-thread.c \
|
||||
test/test-threadpool-cancel.c \
|
||||
test/test-threadpool.c \
|
||||
test/test-timer-again.c \
|
||||
test/test-timer-from-check.c \
|
||||
test/test-timer.c \
|
||||
test/test-tmpdir.c \
|
||||
test/test-tty-duplicate-key.c \
|
||||
test/test-tty-escape-sequence-processing.c \
|
||||
test/test-tty.c \
|
||||
test/test-udp-alloc-cb-fail.c \
|
||||
test/test-udp-bind.c \
|
||||
test/test-udp-connect.c \
|
||||
test/test-udp-create-socket-early.c \
|
||||
test/test-udp-dgram-too-big.c \
|
||||
test/test-udp-ipv6.c \
|
||||
test/test-udp-mmsg.c \
|
||||
test/test-udp-multicast-interface.c \
|
||||
test/test-udp-multicast-interface6.c \
|
||||
test/test-udp-multicast-join.c \
|
||||
test/test-udp-multicast-join6.c \
|
||||
test/test-udp-multicast-ttl.c \
|
||||
test/test-udp-open.c \
|
||||
test/test-udp-options.c \
|
||||
test/test-udp-send-and-recv.c \
|
||||
test/test-udp-send-hang-loop.c \
|
||||
test/test-udp-send-immediate.c \
|
||||
test/test-udp-sendmmsg-error.c \
|
||||
test/test-udp-send-unreachable.c \
|
||||
test/test-udp-try-send.c \
|
||||
test/test-uname.c \
|
||||
test/test-walk-handles.c \
|
||||
test/test-watcher-cross-stop.c
|
||||
test_run_tests_LDADD = libuv.la
|
||||
|
||||
if WINNT
|
||||
test_run_tests_SOURCES += test/runner-win.c \
|
||||
test/runner-win.h
|
||||
else
|
||||
test_run_tests_SOURCES += test/runner-unix.c \
|
||||
test/runner-unix.h
|
||||
endif
|
||||
|
||||
if AIX
|
||||
test_run_tests_CFLAGS += -D_ALL_SOURCE \
|
||||
-D_XOPEN_SOURCE=500 \
|
||||
-D_LINUX_SOURCE_COMPAT
|
||||
endif
|
||||
|
||||
if OS400
|
||||
test_run_tests_CFLAGS += -D_ALL_SOURCE \
|
||||
-D_XOPEN_SOURCE=500 \
|
||||
-D_LINUX_SOURCE_COMPAT
|
||||
endif
|
||||
|
||||
if HAIKU
|
||||
test_run_tests_CFLAGS += -D_BSD_SOURCE
|
||||
endif
|
||||
|
||||
if LINUX
|
||||
test_run_tests_CFLAGS += -D_GNU_SOURCE
|
||||
endif
|
||||
|
||||
if SUNOS
|
||||
test_run_tests_CFLAGS += -D__EXTENSIONS__ \
|
||||
-D_XOPEN_SOURCE=500 \
|
||||
-D_REENTRANT
|
||||
endif
|
||||
|
||||
if OS390
|
||||
test_run_tests_CFLAGS += -D_ISOC99_SOURCE \
|
||||
-D_UNIX03_THREADS \
|
||||
-D_UNIX03_SOURCE \
|
||||
-D_OPEN_SYS_IF_EXT=1 \
|
||||
-D_OPEN_SYS_SOCK_IPV6 \
|
||||
-D_OPEN_MSGQ_EXT \
|
||||
-D_XOPEN_SOURCE_EXTENDED \
|
||||
-D_ALL_SOURCE \
|
||||
-D_LARGE_TIME_API \
|
||||
-D_OPEN_SYS_FILE_EXT \
|
||||
-DPATH_MAX=255 \
|
||||
-qCHARS=signed \
|
||||
-qXPLINK \
|
||||
-qFLOAT=IEEE
|
||||
endif
|
||||
|
||||
if AIX
|
||||
libuv_la_CFLAGS += -D_ALL_SOURCE \
|
||||
-D_XOPEN_SOURCE=500 \
|
||||
-D_LINUX_SOURCE_COMPAT \
|
||||
-D_THREAD_SAFE \
|
||||
-DHAVE_SYS_AHAFS_EVPRODS_H
|
||||
uvinclude_HEADERS += include/uv/aix.h
|
||||
libuv_la_SOURCES += src/unix/aix.c src/unix/aix-common.c
|
||||
endif
|
||||
|
||||
if OS400
|
||||
libuv_la_CFLAGS += -D_ALL_SOURCE \
|
||||
-D_XOPEN_SOURCE=500 \
|
||||
-D_LINUX_SOURCE_COMPAT \
|
||||
-D_THREAD_SAFE
|
||||
uvinclude_HEADERS += include/uv/posix.h
|
||||
libuv_la_SOURCES += src/unix/aix-common.c \
|
||||
src/unix/ibmi.c \
|
||||
src/unix/posix-poll.c \
|
||||
src/unix/no-fsevents.c
|
||||
endif
|
||||
|
||||
if ANDROID
|
||||
uvinclude_HEADERS += include/uv/android-ifaddrs.h
|
||||
libuv_la_CFLAGS += -D_GNU_SOURCE
|
||||
libuv_la_SOURCES += src/unix/android-ifaddrs.c \
|
||||
src/unix/linux-core.c \
|
||||
src/unix/linux-inotify.c \
|
||||
src/unix/linux-syscalls.c \
|
||||
src/unix/procfs-exepath.c \
|
||||
src/unix/pthread-fixes.c \
|
||||
src/unix/random-getrandom.c \
|
||||
src/unix/random-sysctl-linux.c
|
||||
endif
|
||||
|
||||
if CYGWIN
|
||||
uvinclude_HEADERS += include/uv/posix.h
|
||||
libuv_la_CFLAGS += -D_GNU_SOURCE
|
||||
libuv_la_SOURCES += src/unix/cygwin.c \
|
||||
src/unix/bsd-ifaddrs.c \
|
||||
src/unix/no-fsevents.c \
|
||||
src/unix/no-proctitle.c \
|
||||
src/unix/posix-hrtime.c \
|
||||
src/unix/posix-poll.c \
|
||||
src/unix/procfs-exepath.c \
|
||||
src/unix/sysinfo-loadavg.c \
|
||||
src/unix/sysinfo-memory.c
|
||||
endif
|
||||
|
||||
if DARWIN
|
||||
uvinclude_HEADERS += include/uv/darwin.h
|
||||
libuv_la_CFLAGS += -D_DARWIN_USE_64_BIT_INODE=1
|
||||
libuv_la_CFLAGS += -D_DARWIN_UNLIMITED_SELECT=1
|
||||
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
|
||||
src/unix/darwin-proctitle.c \
|
||||
src/unix/darwin-stub.h \
|
||||
src/unix/darwin.c \
|
||||
src/unix/fsevents.c \
|
||||
src/unix/kqueue.c \
|
||||
src/unix/proctitle.c \
|
||||
src/unix/random-getentropy.c
|
||||
test_run_tests_LDFLAGS += -lutil
|
||||
endif
|
||||
|
||||
if DRAGONFLY
|
||||
uvinclude_HEADERS += include/uv/bsd.h
|
||||
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
|
||||
src/unix/bsd-proctitle.c \
|
||||
src/unix/freebsd.c \
|
||||
src/unix/kqueue.c \
|
||||
src/unix/posix-hrtime.c
|
||||
test_run_tests_LDFLAGS += -lutil
|
||||
endif
|
||||
|
||||
if FREEBSD
|
||||
uvinclude_HEADERS += include/uv/bsd.h
|
||||
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
|
||||
src/unix/bsd-proctitle.c \
|
||||
src/unix/freebsd.c \
|
||||
src/unix/kqueue.c \
|
||||
src/unix/posix-hrtime.c \
|
||||
src/unix/random-getrandom.c
|
||||
test_run_tests_LDFLAGS += -lutil
|
||||
endif
|
||||
|
||||
if HAIKU
|
||||
uvinclude_HEADERS += include/uv/posix.h
|
||||
libuv_la_CFLAGS += -D_BSD_SOURCE
|
||||
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
|
||||
src/unix/haiku.c \
|
||||
src/unix/no-fsevents.c \
|
||||
src/unix/no-proctitle.c \
|
||||
src/unix/posix-hrtime.c \
|
||||
src/unix/posix-poll.c
|
||||
endif
|
||||
|
||||
if HURD
|
||||
uvinclude_HEADERS += include/uv/posix.h
|
||||
libuv_la_SOURCES += src/unix/no-fsevents.c \
|
||||
src/unix/posix-hrtime.c \
|
||||
src/unix/posix-poll.c
|
||||
endif
|
||||
|
||||
if LINUX
|
||||
uvinclude_HEADERS += include/uv/linux.h
|
||||
libuv_la_CFLAGS += -D_GNU_SOURCE
|
||||
libuv_la_SOURCES += src/unix/linux-core.c \
|
||||
src/unix/linux-inotify.c \
|
||||
src/unix/linux-syscalls.c \
|
||||
src/unix/linux-syscalls.h \
|
||||
src/unix/procfs-exepath.c \
|
||||
src/unix/proctitle.c \
|
||||
src/unix/random-getrandom.c \
|
||||
src/unix/random-sysctl-linux.c
|
||||
test_run_tests_LDFLAGS += -lutil
|
||||
endif
|
||||
|
||||
if MSYS
|
||||
libuv_la_CFLAGS += -D_GNU_SOURCE
|
||||
libuv_la_SOURCES += src/unix/cygwin.c \
|
||||
src/unix/bsd-ifaddrs.c \
|
||||
src/unix/no-fsevents.c \
|
||||
src/unix/no-proctitle.c \
|
||||
src/unix/posix-hrtime.c \
|
||||
src/unix/posix-poll.c \
|
||||
src/unix/procfs-exepath.c \
|
||||
src/unix/sysinfo-loadavg.c \
|
||||
src/unix/sysinfo-memory.c
|
||||
endif
|
||||
|
||||
if NETBSD
|
||||
uvinclude_HEADERS += include/uv/bsd.h
|
||||
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
|
||||
src/unix/bsd-proctitle.c \
|
||||
src/unix/kqueue.c \
|
||||
src/unix/netbsd.c \
|
||||
src/unix/posix-hrtime.c
|
||||
test_run_tests_LDFLAGS += -lutil
|
||||
endif
|
||||
|
||||
if OPENBSD
|
||||
uvinclude_HEADERS += include/uv/bsd.h
|
||||
libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \
|
||||
src/unix/bsd-proctitle.c \
|
||||
src/unix/kqueue.c \
|
||||
src/unix/openbsd.c \
|
||||
src/unix/posix-hrtime.c \
|
||||
src/unix/random-getentropy.c
|
||||
test_run_tests_LDFLAGS += -lutil
|
||||
endif
|
||||
|
||||
if SUNOS
|
||||
uvinclude_HEADERS += include/uv/sunos.h
|
||||
libuv_la_CFLAGS += -D__EXTENSIONS__ \
|
||||
-D_XOPEN_SOURCE=500 \
|
||||
-D_REENTRANT
|
||||
libuv_la_SOURCES += src/unix/no-proctitle.c \
|
||||
src/unix/sunos.c
|
||||
endif
|
||||
|
||||
if OS390
|
||||
libuv_la_CFLAGS += -D_UNIX03_THREADS \
|
||||
-D_UNIX03_SOURCE \
|
||||
-D_OPEN_SYS_IF_EXT=1 \
|
||||
-D_OPEN_MSGQ_EXT \
|
||||
-D_XOPEN_SOURCE_EXTENDED \
|
||||
-D_ALL_SOURCE \
|
||||
-D_LARGE_TIME_API \
|
||||
-D_OPEN_SYS_SOCK_EXT3 \
|
||||
-D_OPEN_SYS_SOCK_IPV6 \
|
||||
-D_OPEN_SYS_FILE_EXT \
|
||||
-DUV_PLATFORM_SEM_T=int \
|
||||
-DPATH_MAX=255 \
|
||||
-qCHARS=signed \
|
||||
-qXPLINK \
|
||||
-qFLOAT=IEEE
|
||||
libuv_la_LDFLAGS += -qXPLINK
|
||||
libuv_la_SOURCES += src/unix/pthread-fixes.c \
|
||||
src/unix/os390.c \
|
||||
src/unix/os390-syscalls.c \
|
||||
src/unix/proctitle.c
|
||||
endif
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = @PACKAGE_NAME@.pc
|
317
deps/libuv/README.md
vendored
Normal file
317
deps/libuv/README.md
vendored
Normal file
@ -0,0 +1,317 @@
|
||||
![libuv][libuv_banner]
|
||||
|
||||
## Overview
|
||||
|
||||
libuv is a multi-platform support library with a focus on asynchronous I/O. It
|
||||
was primarily developed for use by [Node.js][], but it's also
|
||||
used by [Luvit](http://luvit.io/), [Julia](http://julialang.org/),
|
||||
[pyuv](https://github.com/saghul/pyuv), and [others](https://github.com/libuv/libuv/wiki/Projects-that-use-libuv).
|
||||
|
||||
## Feature highlights
|
||||
|
||||
* Full-featured event loop backed by epoll, kqueue, IOCP, event ports.
|
||||
|
||||
* Asynchronous TCP and UDP sockets
|
||||
|
||||
* Asynchronous DNS resolution
|
||||
|
||||
* Asynchronous file and file system operations
|
||||
|
||||
* File system events
|
||||
|
||||
* ANSI escape code controlled TTY
|
||||
|
||||
* IPC with socket sharing, using Unix domain sockets or named pipes (Windows)
|
||||
|
||||
* Child processes
|
||||
|
||||
* Thread pool
|
||||
|
||||
* Signal handling
|
||||
|
||||
* High resolution clock
|
||||
|
||||
* Threading and synchronization primitives
|
||||
|
||||
## Versioning
|
||||
|
||||
Starting with version 1.0.0 libuv follows the [semantic versioning](http://semver.org/)
|
||||
scheme. The API change and backwards compatibility rules are those indicated by
|
||||
SemVer. libuv will keep a stable ABI across major releases.
|
||||
|
||||
The ABI/API changes can be tracked [here](http://abi-laboratory.pro/tracker/timeline/libuv/).
|
||||
|
||||
## Licensing
|
||||
|
||||
libuv is licensed under the MIT license. Check the [LICENSE file](LICENSE).
|
||||
The documentation is licensed under the CC BY 4.0 license. Check the [LICENSE-docs file](LICENSE-docs).
|
||||
|
||||
## Community
|
||||
|
||||
* [Support](https://github.com/libuv/help)
|
||||
* [Mailing list](http://groups.google.com/group/libuv)
|
||||
* [IRC chatroom (#libuv@irc.freenode.org)](http://webchat.freenode.net?channels=libuv&uio=d4)
|
||||
|
||||
## Documentation
|
||||
|
||||
### Official documentation
|
||||
|
||||
Located in the docs/ subdirectory. It uses the [Sphinx](http://sphinx-doc.org/)
|
||||
framework, which makes it possible to build the documentation in multiple
|
||||
formats.
|
||||
|
||||
Show different supported building options:
|
||||
|
||||
```bash
|
||||
$ make help
|
||||
```
|
||||
|
||||
Build documentation as HTML:
|
||||
|
||||
```bash
|
||||
$ make html
|
||||
```
|
||||
|
||||
Build documentation as HTML and live reload it when it changes (this requires
|
||||
sphinx-autobuild to be installed and is only supported on Unix):
|
||||
|
||||
```bash
|
||||
$ make livehtml
|
||||
```
|
||||
|
||||
Build documentation as man pages:
|
||||
|
||||
```bash
|
||||
$ make man
|
||||
```
|
||||
|
||||
Build documentation as ePub:
|
||||
|
||||
```bash
|
||||
$ make epub
|
||||
```
|
||||
|
||||
NOTE: Windows users need to use make.bat instead of plain 'make'.
|
||||
|
||||
Documentation can be browsed online [here](http://docs.libuv.org).
|
||||
|
||||
The [tests and benchmarks](https://github.com/libuv/libuv/tree/master/test)
|
||||
also serve as API specification and usage examples.
|
||||
|
||||
### Other resources
|
||||
|
||||
* [LXJS 2012 talk](http://www.youtube.com/watch?v=nGn60vDSxQ4)
|
||||
— High-level introductory talk about libuv.
|
||||
* [libuv-dox](https://github.com/thlorenz/libuv-dox)
|
||||
— Documenting types and methods of libuv, mostly by reading uv.h.
|
||||
* [learnuv](https://github.com/thlorenz/learnuv)
|
||||
— Learn uv for fun and profit, a self guided workshop to libuv.
|
||||
|
||||
These resources are not handled by libuv maintainers and might be out of
|
||||
date. Please verify it before opening new issues.
|
||||
|
||||
## Downloading
|
||||
|
||||
libuv can be downloaded either from the
|
||||
[GitHub repository](https://github.com/libuv/libuv)
|
||||
or from the [downloads site](http://dist.libuv.org/dist/).
|
||||
|
||||
Before verifying the git tags or signature files, importing the relevant keys
|
||||
is necessary. Key IDs are listed in the
|
||||
[MAINTAINERS](https://github.com/libuv/libuv/blob/master/MAINTAINERS.md)
|
||||
file, but are also available as git blob objects for easier use.
|
||||
|
||||
Importing a key the usual way:
|
||||
|
||||
```bash
|
||||
$ gpg --keyserver pool.sks-keyservers.net --recv-keys AE9BC059
|
||||
```
|
||||
|
||||
Importing a key from a git blob object:
|
||||
|
||||
```bash
|
||||
$ git show pubkey-saghul | gpg --import
|
||||
```
|
||||
|
||||
### Verifying releases
|
||||
|
||||
Git tags are signed with the developer's key, they can be verified as follows:
|
||||
|
||||
```bash
|
||||
$ git verify-tag v1.6.1
|
||||
```
|
||||
|
||||
Starting with libuv 1.7.0, the tarballs stored in the
|
||||
[downloads site](http://dist.libuv.org/dist/) are signed and an accompanying
|
||||
signature file sit alongside each. Once both the release tarball and the
|
||||
signature file are downloaded, the file can be verified as follows:
|
||||
|
||||
```bash
|
||||
$ gpg --verify libuv-1.7.0.tar.gz.sign
|
||||
```
|
||||
|
||||
## Build Instructions
|
||||
|
||||
For UNIX-like platforms, including macOS, there are two build methods:
|
||||
autotools or [CMake][].
|
||||
|
||||
For Windows, [CMake][] is the only supported build method and has the
|
||||
following prerequisites:
|
||||
|
||||
<details>
|
||||
|
||||
* One of:
|
||||
* [Visual C++ Build Tools][]
|
||||
* [Visual Studio 2015 Update 3][], all editions
|
||||
including the Community edition (remember to select
|
||||
"Common Tools for Visual C++ 2015" feature during installation).
|
||||
* [Visual Studio 2017][], any edition (including the Build Tools SKU).
|
||||
**Required Components:** "MSbuild", "VC++ 2017 v141 toolset" and one of the
|
||||
Windows SDKs (10 or 8.1).
|
||||
* Basic Unix tools required for some tests,
|
||||
[Git for Windows][] includes Git Bash
|
||||
and tools which can be included in the global `PATH`.
|
||||
|
||||
</details>
|
||||
|
||||
To build with autotools:
|
||||
|
||||
```bash
|
||||
$ sh autogen.sh
|
||||
$ ./configure
|
||||
$ make
|
||||
$ make check
|
||||
$ make install
|
||||
```
|
||||
|
||||
To build with [CMake][]:
|
||||
|
||||
```bash
|
||||
$ mkdir -p build
|
||||
|
||||
$ (cd build && cmake .. -DBUILD_TESTING=ON) # generate project with tests
|
||||
$ cmake --build build # add `-j <n>` with cmake >= 3.12
|
||||
|
||||
# Run tests:
|
||||
$ (cd build && ctest -C Debug --output-on-failure)
|
||||
|
||||
# Or manually run tests:
|
||||
$ build/uv_run_tests # shared library build
|
||||
$ build/uv_run_tests_a # static library build
|
||||
```
|
||||
|
||||
To cross-compile with [CMake][] (unsupported but generally works):
|
||||
|
||||
```bash
|
||||
$ cmake ../.. \
|
||||
-DCMAKE_SYSTEM_NAME=Windows \
|
||||
-DCMAKE_SYSTEM_VERSION=6.1 \
|
||||
-DCMAKE_C_COMPILER=i686-w64-mingw32-gcc
|
||||
```
|
||||
|
||||
### Install with Homebrew
|
||||
|
||||
```bash
|
||||
$ brew install --HEAD libuv
|
||||
```
|
||||
|
||||
Note to OS X users:
|
||||
|
||||
Make sure that you specify the architecture you wish to build for in the
|
||||
"ARCHS" flag. You can specify more than one by delimiting with a space
|
||||
(e.g. "x86_64 i386").
|
||||
|
||||
### Running tests
|
||||
|
||||
Some tests are timing sensitive. Relaxing test timeouts may be necessary
|
||||
on slow or overloaded machines:
|
||||
|
||||
```bash
|
||||
$ env UV_TEST_TIMEOUT_MULTIPLIER=2 build/uv_run_tests # 10s instead of 5s
|
||||
```
|
||||
|
||||
#### Run one test
|
||||
|
||||
The list of all tests is in `test/test-list.h`.
|
||||
|
||||
This invocation will cause the test driver to fork and execute `TEST_NAME` in
|
||||
a child process:
|
||||
|
||||
```bash
|
||||
$ build/uv_run_tests_a TEST_NAME
|
||||
```
|
||||
|
||||
This invocation will cause the test driver to execute the test in
|
||||
the same process:
|
||||
|
||||
```bash
|
||||
$ build/uv_run_tests_a TEST_NAME TEST_NAME
|
||||
```
|
||||
|
||||
#### Debugging tools
|
||||
|
||||
When running the test from within the test driver process
|
||||
(`build/uv_run_tests_a TEST_NAME TEST_NAME`), tools like gdb and valgrind
|
||||
work normally.
|
||||
|
||||
When running the test from a child of the test driver process
|
||||
(`build/uv_run_tests_a TEST_NAME`), use these tools in a fork-aware manner.
|
||||
|
||||
##### Fork-aware gdb
|
||||
|
||||
Use the [follow-fork-mode](https://sourceware.org/gdb/onlinedocs/gdb/Forks.html) setting:
|
||||
|
||||
```
|
||||
$ gdb --args build/uv_run_tests_a TEST_NAME
|
||||
|
||||
(gdb) set follow-fork-mode child
|
||||
...
|
||||
```
|
||||
|
||||
##### Fork-aware valgrind
|
||||
|
||||
Use the `--trace-children=yes` parameter:
|
||||
|
||||
```bash
|
||||
$ valgrind --trace-children=yes -v --tool=memcheck --leak-check=full --track-origins=yes --leak-resolution=high --show-reachable=yes --log-file=memcheck-%p.log build/uv_run_tests_a TEST_NAME
|
||||
```
|
||||
|
||||
### Running benchmarks
|
||||
|
||||
See the section on running tests.
|
||||
The benchmark driver is `./uv_run_benchmarks_a` and the benchmarks are
|
||||
listed in `test/benchmark-list.h`.
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
Check the [SUPPORTED_PLATFORMS file](SUPPORTED_PLATFORMS.md).
|
||||
|
||||
### AIX Notes
|
||||
|
||||
AIX compilation using IBM XL C/C++ requires version 12.1 or greater.
|
||||
|
||||
AIX support for filesystem events requires the non-default IBM `bos.ahafs`
|
||||
package to be installed. This package provides the AIX Event Infrastructure
|
||||
that is detected by `autoconf`.
|
||||
[IBM documentation](http://www.ibm.com/developerworks/aix/library/au-aix_event_infrastructure/)
|
||||
describes the package in more detail.
|
||||
|
||||
### z/OS Notes
|
||||
|
||||
z/OS creates System V semaphores and message queues. These persist on the system
|
||||
after the process terminates unless the event loop is closed.
|
||||
|
||||
Use the `ipcrm` command to manually clear up System V resources.
|
||||
|
||||
## Patches
|
||||
|
||||
See the [guidelines for contributing][].
|
||||
|
||||
[CMake]: https://cmake.org/
|
||||
[node.js]: http://nodejs.org/
|
||||
[guidelines for contributing]: https://github.com/libuv/libuv/blob/master/CONTRIBUTING.md
|
||||
[libuv_banner]: https://raw.githubusercontent.com/libuv/libuv/master/img/banner.png
|
||||
[Visual C++ Build Tools]: https://visualstudio.microsoft.com/visual-cpp-build-tools/
|
||||
[Visual Studio 2015 Update 3]: https://www.visualstudio.com/vs/older-downloads/
|
||||
[Visual Studio 2017]: https://www.visualstudio.com/downloads/
|
||||
[Git for Windows]: http://git-scm.com/download/win
|
69
deps/libuv/SUPPORTED_PLATFORMS.md
vendored
Normal file
69
deps/libuv/SUPPORTED_PLATFORMS.md
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
# Supported platforms
|
||||
|
||||
| System | Support type | Supported versions | Notes |
|
||||
|---|---|---|---|
|
||||
| GNU/Linux | Tier 1 | Linux >= 2.6.32 with glibc >= 2.12 | |
|
||||
| macOS | Tier 1 | macOS >= 10.7 | |
|
||||
| Windows | Tier 1 | >= Windows 7 | MSVC 2008 and later are supported |
|
||||
| FreeBSD | Tier 1 | >= 10 | |
|
||||
| AIX | Tier 2 | >= 6 | Maintainers: @libuv/aix |
|
||||
| z/OS | Tier 2 | >= V2R2 | Maintainers: @libuv/zos |
|
||||
| Linux with musl | Tier 2 | musl >= 1.0 | |
|
||||
| SmartOS | Tier 2 | >= 14.4 | Maintainers: @libuv/smartos |
|
||||
| Android | Tier 3 | NDK >= r15b | |
|
||||
| IBM i | Tier 3 | >= IBM i 7.2 | Maintainers: @libuv/ibmi |
|
||||
| MinGW | Tier 3 | MinGW32 and MinGW-w64 | |
|
||||
| SunOS | Tier 3 | Solaris 121 and later | |
|
||||
| Other | Tier 3 | N/A | |
|
||||
|
||||
## Support types
|
||||
|
||||
* **Tier 1**: Officially supported and tested with CI. Any contributed patch
|
||||
MUST NOT break such systems. These are supported by @libuv/collaborators.
|
||||
|
||||
* **Tier 2**: Officially supported, but not necessarily tested with CI. These
|
||||
systems are maintained to the best of @libuv/collaborators ability,
|
||||
without being a top priority.
|
||||
|
||||
* **Tier 3**: Community maintained. These systems may inadvertently break and the
|
||||
community and interested parties are expected to help with the maintenance.
|
||||
|
||||
## Adding support for a new platform
|
||||
|
||||
**IMPORTANT**: Before attempting to add support for a new platform please open
|
||||
an issue about it for discussion.
|
||||
|
||||
### Unix
|
||||
|
||||
I/O handling is abstracted by an internal `uv__io_t` handle. The new platform
|
||||
will need to implement some of the functions, the prototypes are in
|
||||
``src/unix/internal.h``.
|
||||
|
||||
If the new platform requires extra fields for any handle structure, create a
|
||||
new include file in ``include/`` with the name ``uv-theplatform.h`` and add
|
||||
the appropriate defines there.
|
||||
|
||||
All functionality related to the new platform must be implemented in its own
|
||||
file inside ``src/unix/`` unless it's already done in a common file, in which
|
||||
case adding an `ifdef` is fine.
|
||||
|
||||
Two build systems are supported: autotools and cmake. Ideally both need to be
|
||||
supported, but if one of the two does not support the new platform it can be
|
||||
left out.
|
||||
|
||||
### Windows
|
||||
|
||||
Windows is treated as a single platform, so adding support for a new platform
|
||||
would mean adding support for a new version.
|
||||
|
||||
Compilation and runtime must succeed for the minimum supported version. If a
|
||||
new API is to be used, it must be done optionally, only in supported versions.
|
||||
|
||||
### Common
|
||||
|
||||
Some common notes when adding support for new platforms:
|
||||
|
||||
* Generally libuv tries to avoid compile time checks. Do not add any to the
|
||||
autotools based build system or use version checking macros.
|
||||
Dynamically load functions and symbols if they are not supported by the
|
||||
minimum supported version.
|
46
deps/libuv/autogen.sh
vendored
Executable file
46
deps/libuv/autogen.sh
vendored
Executable file
@ -0,0 +1,46 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
cd `dirname "$0"`
|
||||
|
||||
if [ "$LIBTOOLIZE" = "" ] && [ "`uname`" = "Darwin" ]; then
|
||||
LIBTOOLIZE=glibtoolize
|
||||
fi
|
||||
|
||||
ACLOCAL=${ACLOCAL:-aclocal}
|
||||
AUTOCONF=${AUTOCONF:-autoconf}
|
||||
AUTOMAKE=${AUTOMAKE:-automake}
|
||||
LIBTOOLIZE=${LIBTOOLIZE:-libtoolize}
|
||||
|
||||
automake_version=`"$AUTOMAKE" --version | head -n 1 | sed 's/[^.0-9]//g'`
|
||||
automake_version_major=`echo "$automake_version" | cut -d. -f1`
|
||||
automake_version_minor=`echo "$automake_version" | cut -d. -f2`
|
||||
|
||||
UV_EXTRA_AUTOMAKE_FLAGS=
|
||||
if test "$automake_version_major" -gt 1 || \
|
||||
test "$automake_version_major" -eq 1 && \
|
||||
test "$automake_version_minor" -gt 11; then
|
||||
# serial-tests is available in v1.12 and newer.
|
||||
UV_EXTRA_AUTOMAKE_FLAGS="$UV_EXTRA_AUTOMAKE_FLAGS serial-tests"
|
||||
fi
|
||||
echo "m4_define([UV_EXTRA_AUTOMAKE_FLAGS], [$UV_EXTRA_AUTOMAKE_FLAGS])" \
|
||||
> m4/libuv-extra-automake-flags.m4
|
||||
|
||||
set -ex
|
||||
"$LIBTOOLIZE" --copy
|
||||
"$ACLOCAL" -I m4
|
||||
"$AUTOCONF"
|
||||
"$AUTOMAKE" --add-missing --copy
|
84
deps/libuv/configure.ac
vendored
Normal file
84
deps/libuv/configure.ac
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
AC_PREREQ(2.57)
|
||||
AC_INIT([libuv], [1.40.0], [https://github.com/libuv/libuv/issues])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
m4_include([m4/libuv-extra-automake-flags.m4])
|
||||
m4_include([m4/as_case.m4])
|
||||
m4_include([m4/libuv-check-flags.m4])
|
||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects] UV_EXTRA_AUTOMAKE_FLAGS)
|
||||
AC_CANONICAL_HOST
|
||||
AC_ENABLE_SHARED
|
||||
AC_ENABLE_STATIC
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
CC_FLAG_VISIBILITY #[-fvisibility=hidden]
|
||||
CC_CHECK_CFLAGS_APPEND([-g])
|
||||
CC_CHECK_CFLAGS_APPEND([-std=gnu89])
|
||||
CC_CHECK_CFLAGS_APPEND([-Wall])
|
||||
CC_CHECK_CFLAGS_APPEND([-Wextra])
|
||||
CC_CHECK_CFLAGS_APPEND([-Wno-long-long])
|
||||
CC_CHECK_CFLAGS_APPEND([-Wno-unused-parameter])
|
||||
CC_CHECK_CFLAGS_APPEND([-Wstrict-prototypes])
|
||||
# AM_PROG_AR is not available in automake v0.11 but it's essential in v0.12.
|
||||
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
|
||||
# autoconf complains if AC_PROG_LIBTOOL precedes AM_PROG_AR.
|
||||
AC_PROG_LIBTOOL
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
LT_INIT
|
||||
AX_PTHREAD([
|
||||
LIBS="$LIBS $PTHREAD_LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
])
|
||||
AC_CHECK_LIB([dl], [dlopen])
|
||||
AC_SEARCH_LIBS([kstat_lookup], [kstat])
|
||||
AC_SEARCH_LIBS([gethostbyname], [nsl])
|
||||
AC_SEARCH_LIBS([perfstat_cpu], [perfstat])
|
||||
AC_SEARCH_LIBS([clock_gettime], [rt])
|
||||
AC_SEARCH_LIBS([sendfile], [sendfile])
|
||||
AC_SEARCH_LIBS([socket], [socket])
|
||||
AC_SYS_LARGEFILE
|
||||
AM_CONDITIONAL([AIX], [AS_CASE([$host_os],[aix*], [true], [false])])
|
||||
AM_CONDITIONAL([ANDROID], [AS_CASE([$host_os],[linux-android*],[true], [false])])
|
||||
AM_CONDITIONAL([CYGWIN], [AS_CASE([$host_os],[cygwin*], [true], [false])])
|
||||
AM_CONDITIONAL([DARWIN], [AS_CASE([$host_os],[darwin*], [true], [false])])
|
||||
AM_CONDITIONAL([DRAGONFLY],[AS_CASE([$host_os],[dragonfly*], [true], [false])])
|
||||
AM_CONDITIONAL([FREEBSD], [AS_CASE([$host_os],[*freebsd*], [true], [false])])
|
||||
AM_CONDITIONAL([HAIKU], [AS_CASE([$host_os],[haiku], [true], [false])])
|
||||
AM_CONDITIONAL([HURD], [AS_CASE([$host_os],[gnu*], [true], [false])])
|
||||
AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])])
|
||||
AM_CONDITIONAL([MSYS], [AS_CASE([$host_os],[msys*], [true], [false])])
|
||||
AM_CONDITIONAL([NETBSD], [AS_CASE([$host_os],[netbsd*], [true], [false])])
|
||||
AM_CONDITIONAL([OPENBSD], [AS_CASE([$host_os],[openbsd*], [true], [false])])
|
||||
AM_CONDITIONAL([OS390], [AS_CASE([$host_os],[openedition*], [true], [false])])
|
||||
AM_CONDITIONAL([OS400], [AS_CASE([$host_os],[os400], [true], [false])])
|
||||
AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])])
|
||||
AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])])
|
||||
AS_CASE([$host_os],[mingw*], [
|
||||
LIBS="$LIBS -lws2_32 -lpsapi -liphlpapi -lshell32 -luserenv -luser32"
|
||||
])
|
||||
AS_CASE([$host_os], [netbsd*], [AC_CHECK_LIB([kvm], [kvm_open])])
|
||||
AS_CASE([$host_os], [kfreebsd*], [
|
||||
LIBS="$LIBS -lfreebsd-glue"
|
||||
])
|
||||
AS_CASE([$host_os], [haiku], [
|
||||
LIBS="$LIBS -lnetwork"
|
||||
])
|
||||
AC_CHECK_HEADERS([sys/ahafs_evProds.h])
|
||||
AC_CONFIG_FILES([Makefile libuv.pc])
|
||||
AC_CONFIG_LINKS([test/fixtures/empty_file:test/fixtures/empty_file])
|
||||
AC_CONFIG_LINKS([test/fixtures/load_error.node:test/fixtures/load_error.node])
|
||||
AC_CONFIG_LINKS([test/fixtures/lorem_ipsum.txt:test/fixtures/lorem_ipsum.txt])
|
||||
AC_OUTPUT
|
183
deps/libuv/docs/Makefile
vendored
Normal file
183
deps/libuv/docs/Makefile
vendored
Normal file
@ -0,0 +1,183 @@
|
||||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
SPHINXAUTOBUILD = sphinx-autobuild
|
||||
PAPER =
|
||||
BUILDDIR = build
|
||||
SRCDIR = src
|
||||
|
||||
# User-friendly check for sphinx-build
|
||||
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
|
||||
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
|
||||
endif
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SRCDIR)
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SRCDIR)
|
||||
|
||||
.PHONY: help clean html livehtml dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " livehtml to make standalone HTML files and live reload them"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " texinfo to make Texinfo files"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " gettext to make PO message catalogs"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " xml to make Docutils-native XML files"
|
||||
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
livehtml: html
|
||||
$(SPHINXAUTOBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/libuv.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/libuv.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/libuv"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/libuv"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
latexpdfja:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through platex and dvipdfmx..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
texinfo:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo
|
||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||
"(use \`make info' here to do that automatically)."
|
||||
|
||||
info:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo "Running Texinfo files through makeinfo..."
|
||||
make -C $(BUILDDIR)/texinfo info
|
||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||
|
||||
gettext:
|
||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||
@echo
|
||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
|
||||
xml:
|
||||
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
|
||||
@echo
|
||||
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
|
||||
|
||||
pseudoxml:
|
||||
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
|
||||
@echo
|
||||
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
81
deps/libuv/docs/code/cgi/main.c
vendored
Normal file
81
deps/libuv/docs/code/cgi/main.c
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <uv.h>
|
||||
|
||||
uv_loop_t *loop;
|
||||
uv_process_t child_req;
|
||||
uv_process_options_t options;
|
||||
|
||||
void cleanup_handles(uv_process_t *req, int64_t exit_status, int term_signal) {
|
||||
fprintf(stderr, "Process exited with status %" PRId64 ", signal %d\n", exit_status, term_signal);
|
||||
uv_close((uv_handle_t*) req->data, NULL);
|
||||
uv_close((uv_handle_t*) req, NULL);
|
||||
}
|
||||
|
||||
void invoke_cgi_script(uv_tcp_t *client) {
|
||||
size_t size = 500;
|
||||
char path[size];
|
||||
uv_exepath(path, &size);
|
||||
strcpy(path + (strlen(path) - strlen("cgi")), "tick");
|
||||
|
||||
char* args[2];
|
||||
args[0] = path;
|
||||
args[1] = NULL;
|
||||
|
||||
/* ... finding the executable path and setting up arguments ... */
|
||||
|
||||
options.stdio_count = 3;
|
||||
uv_stdio_container_t child_stdio[3];
|
||||
child_stdio[0].flags = UV_IGNORE;
|
||||
child_stdio[1].flags = UV_INHERIT_STREAM;
|
||||
child_stdio[1].data.stream = (uv_stream_t*) client;
|
||||
child_stdio[2].flags = UV_IGNORE;
|
||||
options.stdio = child_stdio;
|
||||
|
||||
options.exit_cb = cleanup_handles;
|
||||
options.file = args[0];
|
||||
options.args = args;
|
||||
|
||||
// Set this so we can close the socket after the child process exits.
|
||||
child_req.data = (void*) client;
|
||||
int r;
|
||||
if ((r = uv_spawn(loop, &child_req, &options))) {
|
||||
fprintf(stderr, "%s\n", uv_strerror(r));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void on_new_connection(uv_stream_t *server, int status) {
|
||||
if (status == -1) {
|
||||
// error!
|
||||
return;
|
||||
}
|
||||
|
||||
uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
|
||||
uv_tcp_init(loop, client);
|
||||
if (uv_accept(server, (uv_stream_t*) client) == 0) {
|
||||
invoke_cgi_script(client);
|
||||
}
|
||||
else {
|
||||
uv_close((uv_handle_t*) client, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
loop = uv_default_loop();
|
||||
|
||||
uv_tcp_t server;
|
||||
uv_tcp_init(loop, &server);
|
||||
|
||||
struct sockaddr_in bind_addr;
|
||||
uv_ip4_addr("0.0.0.0", 7000, &bind_addr);
|
||||
uv_tcp_bind(&server, (const struct sockaddr *)&bind_addr, 0);
|
||||
int r = uv_listen((uv_stream_t*) &server, 128, on_new_connection);
|
||||
if (r) {
|
||||
fprintf(stderr, "Listen error %s\n", uv_err_name(r));
|
||||
return 1;
|
||||
}
|
||||
return uv_run(loop, UV_RUN_DEFAULT);
|
||||
}
|
13
deps/libuv/docs/code/cgi/tick.c
vendored
Normal file
13
deps/libuv/docs/code/cgi/tick.c
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main() {
|
||||
int i;
|
||||
for (i = 0; i < 10; i++) {
|
||||
printf("tick\n");
|
||||
fflush(stdout);
|
||||
sleep(1);
|
||||
}
|
||||
printf("BOOM!\n");
|
||||
return 0;
|
||||
}
|
31
deps/libuv/docs/code/detach/main.c
vendored
Normal file
31
deps/libuv/docs/code/detach/main.c
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
uv_loop_t *loop;
|
||||
uv_process_t child_req;
|
||||
uv_process_options_t options;
|
||||
|
||||
int main() {
|
||||
loop = uv_default_loop();
|
||||
|
||||
char* args[3];
|
||||
args[0] = "sleep";
|
||||
args[1] = "100";
|
||||
args[2] = NULL;
|
||||
|
||||
options.exit_cb = NULL;
|
||||
options.file = "sleep";
|
||||
options.args = args;
|
||||
options.flags = UV_PROCESS_DETACHED;
|
||||
|
||||
int r;
|
||||
if ((r = uv_spawn(loop, &child_req, &options))) {
|
||||
fprintf(stderr, "%s\n", uv_strerror(r));
|
||||
return 1;
|
||||
}
|
||||
fprintf(stderr, "Launched sleep with PID %d\n", child_req.pid);
|
||||
uv_unref((uv_handle_t*) &child_req);
|
||||
|
||||
return uv_run(loop, UV_RUN_DEFAULT);
|
||||
}
|
80
deps/libuv/docs/code/dns/main.c
vendored
Normal file
80
deps/libuv/docs/code/dns/main.c
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <uv.h>
|
||||
|
||||
uv_loop_t *loop;
|
||||
|
||||
void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
|
||||
buf->base = malloc(suggested_size);
|
||||
buf->len = suggested_size;
|
||||
}
|
||||
|
||||
void on_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) {
|
||||
if (nread < 0) {
|
||||
if (nread != UV_EOF)
|
||||
fprintf(stderr, "Read error %s\n", uv_err_name(nread));
|
||||
uv_close((uv_handle_t*) client, NULL);
|
||||
free(buf->base);
|
||||
free(client);
|
||||
return;
|
||||
}
|
||||
|
||||
char *data = (char*) malloc(sizeof(char) * (nread+1));
|
||||
data[nread] = '\0';
|
||||
strncpy(data, buf->base, nread);
|
||||
|
||||
fprintf(stderr, "%s", data);
|
||||
free(data);
|
||||
free(buf->base);
|
||||
}
|
||||
|
||||
void on_connect(uv_connect_t *req, int status) {
|
||||
if (status < 0) {
|
||||
fprintf(stderr, "connect failed error %s\n", uv_err_name(status));
|
||||
free(req);
|
||||
return;
|
||||
}
|
||||
|
||||
uv_read_start((uv_stream_t*) req->handle, alloc_buffer, on_read);
|
||||
free(req);
|
||||
}
|
||||
|
||||
void on_resolved(uv_getaddrinfo_t *resolver, int status, struct addrinfo *res) {
|
||||
if (status < 0) {
|
||||
fprintf(stderr, "getaddrinfo callback error %s\n", uv_err_name(status));
|
||||
return;
|
||||
}
|
||||
|
||||
char addr[17] = {'\0'};
|
||||
uv_ip4_name((struct sockaddr_in*) res->ai_addr, addr, 16);
|
||||
fprintf(stderr, "%s\n", addr);
|
||||
|
||||
uv_connect_t *connect_req = (uv_connect_t*) malloc(sizeof(uv_connect_t));
|
||||
uv_tcp_t *socket = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
|
||||
uv_tcp_init(loop, socket);
|
||||
|
||||
uv_tcp_connect(connect_req, socket, (const struct sockaddr*) res->ai_addr, on_connect);
|
||||
|
||||
uv_freeaddrinfo(res);
|
||||
}
|
||||
|
||||
int main() {
|
||||
loop = uv_default_loop();
|
||||
|
||||
struct addrinfo hints;
|
||||
hints.ai_family = PF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = IPPROTO_TCP;
|
||||
hints.ai_flags = 0;
|
||||
|
||||
uv_getaddrinfo_t resolver;
|
||||
fprintf(stderr, "irc.freenode.net is... ");
|
||||
int r = uv_getaddrinfo(loop, &resolver, on_resolved, "irc.freenode.net", "6667", &hints);
|
||||
|
||||
if (r) {
|
||||
fprintf(stderr, "getaddrinfo call error %s\n", uv_err_name(r));
|
||||
return 1;
|
||||
}
|
||||
return uv_run(loop, UV_RUN_DEFAULT);
|
||||
}
|
15
deps/libuv/docs/code/helloworld/main.c
vendored
Normal file
15
deps/libuv/docs/code/helloworld/main.c
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <uv.h>
|
||||
|
||||
int main() {
|
||||
uv_loop_t *loop = malloc(sizeof(uv_loop_t));
|
||||
uv_loop_init(loop);
|
||||
|
||||
printf("Now quitting.\n");
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
uv_loop_close(loop);
|
||||
free(loop);
|
||||
return 0;
|
||||
}
|
24
deps/libuv/docs/code/idle-basic/main.c
vendored
Normal file
24
deps/libuv/docs/code/idle-basic/main.c
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
#include <stdio.h>
|
||||
#include <uv.h>
|
||||
|
||||
int64_t counter = 0;
|
||||
|
||||
void wait_for_a_while(uv_idle_t* handle) {
|
||||
counter++;
|
||||
|
||||
if (counter >= 10e6)
|
||||
uv_idle_stop(handle);
|
||||
}
|
||||
|
||||
int main() {
|
||||
uv_idle_t idler;
|
||||
|
||||
uv_idle_init(uv_default_loop(), &idler);
|
||||
uv_idle_start(&idler, wait_for_a_while);
|
||||
|
||||
printf("Idling...\n");
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
uv_loop_close(uv_default_loop());
|
||||
return 0;
|
||||
}
|
43
deps/libuv/docs/code/idle-compute/main.c
vendored
Normal file
43
deps/libuv/docs/code/idle-compute/main.c
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
uv_loop_t *loop;
|
||||
uv_fs_t stdin_watcher;
|
||||
uv_idle_t idler;
|
||||
char buffer[1024];
|
||||
|
||||
void crunch_away(uv_idle_t* handle) {
|
||||
// Compute extra-terrestrial life
|
||||
// fold proteins
|
||||
// computer another digit of PI
|
||||
// or similar
|
||||
fprintf(stderr, "Computing PI...\n");
|
||||
// just to avoid overwhelming your terminal emulator
|
||||
uv_idle_stop(handle);
|
||||
}
|
||||
|
||||
void on_type(uv_fs_t *req) {
|
||||
if (stdin_watcher.result > 0) {
|
||||
buffer[stdin_watcher.result] = '\0';
|
||||
printf("Typed %s\n", buffer);
|
||||
|
||||
uv_buf_t buf = uv_buf_init(buffer, 1024);
|
||||
uv_fs_read(loop, &stdin_watcher, 0, &buf, 1, -1, on_type);
|
||||
uv_idle_start(&idler, crunch_away);
|
||||
}
|
||||
else if (stdin_watcher.result < 0) {
|
||||
fprintf(stderr, "error opening file: %s\n", uv_strerror(req->result));
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
loop = uv_default_loop();
|
||||
|
||||
uv_idle_init(loop, &idler);
|
||||
|
||||
uv_buf_t buf = uv_buf_init(buffer, 1024);
|
||||
uv_fs_read(loop, &stdin_watcher, 0, &buf, 1, -1, on_type);
|
||||
uv_idle_start(&idler, crunch_away);
|
||||
return uv_run(loop, UV_RUN_DEFAULT);
|
||||
}
|
33
deps/libuv/docs/code/interfaces/main.c
vendored
Normal file
33
deps/libuv/docs/code/interfaces/main.c
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
#include <stdio.h>
|
||||
#include <uv.h>
|
||||
|
||||
int main() {
|
||||
char buf[512];
|
||||
uv_interface_address_t *info;
|
||||
int count, i;
|
||||
|
||||
uv_interface_addresses(&info, &count);
|
||||
i = count;
|
||||
|
||||
printf("Number of interfaces: %d\n", count);
|
||||
while (i--) {
|
||||
uv_interface_address_t interface = info[i];
|
||||
|
||||
printf("Name: %s\n", interface.name);
|
||||
printf("Internal? %s\n", interface.is_internal ? "Yes" : "No");
|
||||
|
||||
if (interface.address.address4.sin_family == AF_INET) {
|
||||
uv_ip4_name(&interface.address.address4, buf, sizeof(buf));
|
||||
printf("IPv4 address: %s\n", buf);
|
||||
}
|
||||
else if (interface.address.address4.sin_family == AF_INET6) {
|
||||
uv_ip6_name(&interface.address.address6, buf, sizeof(buf));
|
||||
printf("IPv6 address: %s\n", buf);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
uv_free_interface_addresses(info, count);
|
||||
return 0;
|
||||
}
|
57
deps/libuv/docs/code/locks/main.c
vendored
Normal file
57
deps/libuv/docs/code/locks/main.c
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
#include <stdio.h>
|
||||
#include <uv.h>
|
||||
|
||||
uv_barrier_t blocker;
|
||||
uv_rwlock_t numlock;
|
||||
int shared_num;
|
||||
|
||||
void reader(void *n)
|
||||
{
|
||||
int num = *(int *)n;
|
||||
int i;
|
||||
for (i = 0; i < 20; i++) {
|
||||
uv_rwlock_rdlock(&numlock);
|
||||
printf("Reader %d: acquired lock\n", num);
|
||||
printf("Reader %d: shared num = %d\n", num, shared_num);
|
||||
uv_rwlock_rdunlock(&numlock);
|
||||
printf("Reader %d: released lock\n", num);
|
||||
}
|
||||
uv_barrier_wait(&blocker);
|
||||
}
|
||||
|
||||
void writer(void *n)
|
||||
{
|
||||
int num = *(int *)n;
|
||||
int i;
|
||||
for (i = 0; i < 20; i++) {
|
||||
uv_rwlock_wrlock(&numlock);
|
||||
printf("Writer %d: acquired lock\n", num);
|
||||
shared_num++;
|
||||
printf("Writer %d: incremented shared num = %d\n", num, shared_num);
|
||||
uv_rwlock_wrunlock(&numlock);
|
||||
printf("Writer %d: released lock\n", num);
|
||||
}
|
||||
uv_barrier_wait(&blocker);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
uv_barrier_init(&blocker, 4);
|
||||
|
||||
shared_num = 0;
|
||||
uv_rwlock_init(&numlock);
|
||||
|
||||
uv_thread_t threads[3];
|
||||
|
||||
int thread_nums[] = {1, 2, 1};
|
||||
uv_thread_create(&threads[0], reader, &thread_nums[0]);
|
||||
uv_thread_create(&threads[1], reader, &thread_nums[1]);
|
||||
|
||||
uv_thread_create(&threads[2], writer, &thread_nums[2]);
|
||||
|
||||
uv_barrier_wait(&blocker);
|
||||
uv_barrier_destroy(&blocker);
|
||||
|
||||
uv_rwlock_destroy(&numlock);
|
||||
return 0;
|
||||
}
|
20
deps/libuv/docs/code/multi-echo-server/hammer.js
vendored
Normal file
20
deps/libuv/docs/code/multi-echo-server/hammer.js
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
var net = require('net');
|
||||
|
||||
var PHRASE = "hello world";
|
||||
var write = function(socket) {
|
||||
socket.write(PHRASE, 'utf8');
|
||||
}
|
||||
|
||||
for (var i = 0; i < 1000; i++) {
|
||||
(function() {
|
||||
var socket = net.connect(7000, 'localhost', function() {
|
||||
socket.on('data', function(reply) {
|
||||
if (reply.toString().indexOf(PHRASE) != 0)
|
||||
console.error("Problem! '" + reply + "'" + " '" + PHRASE + "'");
|
||||
else
|
||||
write(socket);
|
||||
});
|
||||
write(socket);
|
||||
});
|
||||
})();
|
||||
}
|
114
deps/libuv/docs/code/multi-echo-server/main.c
vendored
Normal file
114
deps/libuv/docs/code/multi-echo-server/main.c
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <uv.h>
|
||||
|
||||
uv_loop_t *loop;
|
||||
|
||||
struct child_worker {
|
||||
uv_process_t req;
|
||||
uv_process_options_t options;
|
||||
uv_pipe_t pipe;
|
||||
} *workers;
|
||||
|
||||
int round_robin_counter;
|
||||
int child_worker_count;
|
||||
|
||||
uv_buf_t dummy_buf;
|
||||
char worker_path[500];
|
||||
|
||||
void close_process_handle(uv_process_t *req, int64_t exit_status, int term_signal) {
|
||||
fprintf(stderr, "Process exited with status %" PRId64 ", signal %d\n", exit_status, term_signal);
|
||||
uv_close((uv_handle_t*) req, NULL);
|
||||
}
|
||||
|
||||
void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
|
||||
buf->base = malloc(suggested_size);
|
||||
buf->len = suggested_size;
|
||||
}
|
||||
|
||||
void on_new_connection(uv_stream_t *server, int status) {
|
||||
if (status == -1) {
|
||||
// error!
|
||||
return;
|
||||
}
|
||||
|
||||
uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
|
||||
uv_tcp_init(loop, client);
|
||||
if (uv_accept(server, (uv_stream_t*) client) == 0) {
|
||||
uv_write_t *write_req = (uv_write_t*) malloc(sizeof(uv_write_t));
|
||||
dummy_buf = uv_buf_init("a", 1);
|
||||
struct child_worker *worker = &workers[round_robin_counter];
|
||||
uv_write2(write_req, (uv_stream_t*) &worker->pipe, &dummy_buf, 1, (uv_stream_t*) client, NULL);
|
||||
round_robin_counter = (round_robin_counter + 1) % child_worker_count;
|
||||
}
|
||||
else {
|
||||
uv_close((uv_handle_t*) client, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void setup_workers() {
|
||||
size_t path_size = 500;
|
||||
uv_exepath(worker_path, &path_size);
|
||||
strcpy(worker_path + (strlen(worker_path) - strlen("multi-echo-server")), "worker");
|
||||
fprintf(stderr, "Worker path: %s\n", worker_path);
|
||||
|
||||
char* args[2];
|
||||
args[0] = worker_path;
|
||||
args[1] = NULL;
|
||||
|
||||
round_robin_counter = 0;
|
||||
|
||||
// ...
|
||||
|
||||
// launch same number of workers as number of CPUs
|
||||
uv_cpu_info_t *info;
|
||||
int cpu_count;
|
||||
uv_cpu_info(&info, &cpu_count);
|
||||
uv_free_cpu_info(info, cpu_count);
|
||||
|
||||
child_worker_count = cpu_count;
|
||||
|
||||
workers = calloc(cpu_count, sizeof(struct child_worker));
|
||||
while (cpu_count--) {
|
||||
struct child_worker *worker = &workers[cpu_count];
|
||||
uv_pipe_init(loop, &worker->pipe, 1);
|
||||
|
||||
uv_stdio_container_t child_stdio[3];
|
||||
child_stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
|
||||
child_stdio[0].data.stream = (uv_stream_t*) &worker->pipe;
|
||||
child_stdio[1].flags = UV_IGNORE;
|
||||
child_stdio[2].flags = UV_INHERIT_FD;
|
||||
child_stdio[2].data.fd = 2;
|
||||
|
||||
worker->options.stdio = child_stdio;
|
||||
worker->options.stdio_count = 3;
|
||||
|
||||
worker->options.exit_cb = close_process_handle;
|
||||
worker->options.file = args[0];
|
||||
worker->options.args = args;
|
||||
|
||||
uv_spawn(loop, &worker->req, &worker->options);
|
||||
fprintf(stderr, "Started worker %d\n", worker->req.pid);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
loop = uv_default_loop();
|
||||
|
||||
setup_workers();
|
||||
|
||||
uv_tcp_t server;
|
||||
uv_tcp_init(loop, &server);
|
||||
|
||||
struct sockaddr_in bind_addr;
|
||||
uv_ip4_addr("0.0.0.0", 7000, &bind_addr);
|
||||
uv_tcp_bind(&server, (const struct sockaddr *)&bind_addr, 0);
|
||||
int r;
|
||||
if ((r = uv_listen((uv_stream_t*) &server, 128, on_new_connection))) {
|
||||
fprintf(stderr, "Listen error %s\n", uv_err_name(r));
|
||||
return 2;
|
||||
}
|
||||
return uv_run(loop, UV_RUN_DEFAULT);
|
||||
}
|
88
deps/libuv/docs/code/multi-echo-server/worker.c
vendored
Normal file
88
deps/libuv/docs/code/multi-echo-server/worker.c
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <uv.h>
|
||||
|
||||
uv_loop_t *loop;
|
||||
uv_pipe_t queue;
|
||||
|
||||
typedef struct {
|
||||
uv_write_t req;
|
||||
uv_buf_t buf;
|
||||
} write_req_t;
|
||||
|
||||
void free_write_req(uv_write_t *req) {
|
||||
write_req_t *wr = (write_req_t*) req;
|
||||
free(wr->buf.base);
|
||||
free(wr);
|
||||
}
|
||||
|
||||
void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
|
||||
buf->base = malloc(suggested_size);
|
||||
buf->len = suggested_size;
|
||||
}
|
||||
|
||||
void echo_write(uv_write_t *req, int status) {
|
||||
if (status) {
|
||||
fprintf(stderr, "Write error %s\n", uv_err_name(status));
|
||||
}
|
||||
free_write_req(req);
|
||||
}
|
||||
|
||||
void echo_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) {
|
||||
if (nread > 0) {
|
||||
write_req_t *req = (write_req_t*) malloc(sizeof(write_req_t));
|
||||
req->buf = uv_buf_init(buf->base, nread);
|
||||
uv_write((uv_write_t*) req, client, &req->buf, 1, echo_write);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nread < 0) {
|
||||
if (nread != UV_EOF)
|
||||
fprintf(stderr, "Read error %s\n", uv_err_name(nread));
|
||||
uv_close((uv_handle_t*) client, NULL);
|
||||
}
|
||||
|
||||
free(buf->base);
|
||||
}
|
||||
|
||||
void on_new_connection(uv_stream_t *q, ssize_t nread, const uv_buf_t *buf) {
|
||||
if (nread < 0) {
|
||||
if (nread != UV_EOF)
|
||||
fprintf(stderr, "Read error %s\n", uv_err_name(nread));
|
||||
uv_close((uv_handle_t*) q, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
uv_pipe_t *pipe = (uv_pipe_t*) q;
|
||||
if (!uv_pipe_pending_count(pipe)) {
|
||||
fprintf(stderr, "No pending count\n");
|
||||
return;
|
||||
}
|
||||
|
||||
uv_handle_type pending = uv_pipe_pending_type(pipe);
|
||||
assert(pending == UV_TCP);
|
||||
|
||||
uv_tcp_t *client = (uv_tcp_t*) malloc(sizeof(uv_tcp_t));
|
||||
uv_tcp_init(loop, client);
|
||||
if (uv_accept(q, (uv_stream_t*) client) == 0) {
|
||||
uv_os_fd_t fd;
|
||||
uv_fileno((const uv_handle_t*) client, &fd);
|
||||
fprintf(stderr, "Worker %d: Accepted fd %d\n", getpid(), fd);
|
||||
uv_read_start((uv_stream_t*) client, alloc_buffer, echo_read);
|
||||
}
|
||||
else {
|
||||
uv_close((uv_handle_t*) client, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
loop = uv_default_loop();
|
||||
|
||||
uv_pipe_init(loop, &queue, 1 /* ipc */);
|
||||
uv_pipe_open(&queue, 0);
|
||||
uv_read_start((uv_stream_t*)&queue, alloc_buffer, on_new_connection);
|
||||
return uv_run(loop, UV_RUN_DEFAULT);
|
||||
}
|
44
deps/libuv/docs/code/onchange/main.c
vendored
Normal file
44
deps/libuv/docs/code/onchange/main.c
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
uv_loop_t *loop;
|
||||
const char *command;
|
||||
|
||||
void run_command(uv_fs_event_t *handle, const char *filename, int events, int status) {
|
||||
char path[1024];
|
||||
size_t size = 1023;
|
||||
// Does not handle error if path is longer than 1023.
|
||||
uv_fs_event_getpath(handle, path, &size);
|
||||
path[size] = '\0';
|
||||
|
||||
fprintf(stderr, "Change detected in %s: ", path);
|
||||
if (events & UV_RENAME)
|
||||
fprintf(stderr, "renamed");
|
||||
if (events & UV_CHANGE)
|
||||
fprintf(stderr, "changed");
|
||||
|
||||
fprintf(stderr, " %s\n", filename ? filename : "");
|
||||
system(command);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc <= 2) {
|
||||
fprintf(stderr, "Usage: %s <command> <file1> [file2 ...]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
loop = uv_default_loop();
|
||||
command = argv[1];
|
||||
|
||||
while (argc-- > 2) {
|
||||
fprintf(stderr, "Adding watch on %s\n", argv[argc]);
|
||||
uv_fs_event_t *fs_event_req = malloc(sizeof(uv_fs_event_t));
|
||||
uv_fs_event_init(loop, fs_event_req);
|
||||
// The recursive flag watches subdirectories too.
|
||||
uv_fs_event_start(fs_event_req, run_command, argv[argc], UV_FS_EVENT_RECURSIVE);
|
||||
}
|
||||
|
||||
return uv_run(loop, UV_RUN_DEFAULT);
|
||||
}
|
94
deps/libuv/docs/code/pipe-echo-server/main.c
vendored
Normal file
94
deps/libuv/docs/code/pipe-echo-server/main.c
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <uv.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PIPENAME "\\\\?\\pipe\\echo.sock"
|
||||
#else
|
||||
#define PIPENAME "/tmp/echo.sock"
|
||||
#endif
|
||||
|
||||
uv_loop_t *loop;
|
||||
|
||||
typedef struct {
|
||||
uv_write_t req;
|
||||
uv_buf_t buf;
|
||||
} write_req_t;
|
||||
|
||||
void free_write_req(uv_write_t *req) {
|
||||
write_req_t *wr = (write_req_t*) req;
|
||||
free(wr->buf.base);
|
||||
free(wr);
|
||||
}
|
||||
|
||||
void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
|
||||
buf->base = malloc(suggested_size);
|
||||
buf->len = suggested_size;
|
||||
}
|
||||
|
||||
void echo_write(uv_write_t *req, int status) {
|
||||
if (status < 0) {
|
||||
fprintf(stderr, "Write error %s\n", uv_err_name(status));
|
||||
}
|
||||
free_write_req(req);
|
||||
}
|
||||
|
||||
void echo_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) {
|
||||
if (nread > 0) {
|
||||
write_req_t *req = (write_req_t*) malloc(sizeof(write_req_t));
|
||||
req->buf = uv_buf_init(buf->base, nread);
|
||||
uv_write((uv_write_t*) req, client, &req->buf, 1, echo_write);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nread < 0) {
|
||||
if (nread != UV_EOF)
|
||||
fprintf(stderr, "Read error %s\n", uv_err_name(nread));
|
||||
uv_close((uv_handle_t*) client, NULL);
|
||||
}
|
||||
|
||||
free(buf->base);
|
||||
}
|
||||
|
||||
void on_new_connection(uv_stream_t *server, int status) {
|
||||
if (status == -1) {
|
||||
// error!
|
||||
return;
|
||||
}
|
||||
|
||||
uv_pipe_t *client = (uv_pipe_t*) malloc(sizeof(uv_pipe_t));
|
||||
uv_pipe_init(loop, client, 0);
|
||||
if (uv_accept(server, (uv_stream_t*) client) == 0) {
|
||||
uv_read_start((uv_stream_t*) client, alloc_buffer, echo_read);
|
||||
}
|
||||
else {
|
||||
uv_close((uv_handle_t*) client, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void remove_sock(int sig) {
|
||||
uv_fs_t req;
|
||||
uv_fs_unlink(loop, &req, PIPENAME, NULL);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main() {
|
||||
loop = uv_default_loop();
|
||||
|
||||
uv_pipe_t server;
|
||||
uv_pipe_init(loop, &server, 0);
|
||||
|
||||
signal(SIGINT, remove_sock);
|
||||
|
||||
int r;
|
||||
if ((r = uv_pipe_bind(&server, PIPENAME))) {
|
||||
fprintf(stderr, "Bind error %s\n", uv_err_name(r));
|
||||
return 1;
|
||||
}
|
||||
if ((r = uv_listen((uv_stream_t*) &server, 128, on_new_connection))) {
|
||||
fprintf(stderr, "Listen error %s\n", uv_err_name(r));
|
||||
return 2;
|
||||
}
|
||||
return uv_run(loop, UV_RUN_DEFAULT);
|
||||
}
|
5
deps/libuv/docs/code/plugin/hello.c
vendored
Normal file
5
deps/libuv/docs/code/plugin/hello.c
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
#include "plugin.h"
|
||||
|
||||
void initialize() {
|
||||
mfp_register("Hello World!");
|
||||
}
|
39
deps/libuv/docs/code/plugin/main.c
vendored
Normal file
39
deps/libuv/docs/code/plugin/main.c
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
typedef void (*init_plugin_function)();
|
||||
|
||||
void mfp_register(const char *name) {
|
||||
fprintf(stderr, "Registered plugin \"%s\"\n", name);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc == 1) {
|
||||
fprintf(stderr, "Usage: %s [plugin1] [plugin2] ...\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uv_lib_t *lib = (uv_lib_t*) malloc(sizeof(uv_lib_t));
|
||||
while (--argc) {
|
||||
fprintf(stderr, "Loading %s\n", argv[argc]);
|
||||
if (uv_dlopen(argv[argc], lib)) {
|
||||
fprintf(stderr, "Error: %s\n", uv_dlerror(lib));
|
||||
continue;
|
||||
}
|
||||
|
||||
init_plugin_function init_plugin;
|
||||
if (uv_dlsym(lib, "initialize", (void **) &init_plugin)) {
|
||||
fprintf(stderr, "dlsym error: %s\n", uv_dlerror(lib));
|
||||
continue;
|
||||
}
|
||||
|
||||
init_plugin();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
7
deps/libuv/docs/code/plugin/plugin.h
vendored
Normal file
7
deps/libuv/docs/code/plugin/plugin.h
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef UVBOOK_PLUGIN_SYSTEM
|
||||
#define UVBOOK_PLUGIN_SYSTEM
|
||||
|
||||
// Plugin authors should use this to register their plugins with mfp.
|
||||
void mfp_register(const char *name);
|
||||
|
||||
#endif
|
49
deps/libuv/docs/code/proc-streams/main.c
vendored
Normal file
49
deps/libuv/docs/code/proc-streams/main.c
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
uv_loop_t *loop;
|
||||
uv_process_t child_req;
|
||||
uv_process_options_t options;
|
||||
|
||||
void on_exit(uv_process_t *req, int64_t exit_status, int term_signal) {
|
||||
fprintf(stderr, "Process exited with status %" PRId64 ", signal %d\n", exit_status, term_signal);
|
||||
uv_close((uv_handle_t*) req, NULL);
|
||||
}
|
||||
|
||||
int main() {
|
||||
loop = uv_default_loop();
|
||||
|
||||
size_t size = 500;
|
||||
char path[size];
|
||||
uv_exepath(path, &size);
|
||||
strcpy(path + (strlen(path) - strlen("proc-streams")), "test");
|
||||
|
||||
char* args[2];
|
||||
args[0] = path;
|
||||
args[1] = NULL;
|
||||
|
||||
/* ... */
|
||||
|
||||
options.stdio_count = 3;
|
||||
uv_stdio_container_t child_stdio[3];
|
||||
child_stdio[0].flags = UV_IGNORE;
|
||||
child_stdio[1].flags = UV_IGNORE;
|
||||
child_stdio[2].flags = UV_INHERIT_FD;
|
||||
child_stdio[2].data.fd = 2;
|
||||
options.stdio = child_stdio;
|
||||
|
||||
options.exit_cb = on_exit;
|
||||
options.file = args[0];
|
||||
options.args = args;
|
||||
|
||||
int r;
|
||||
if ((r = uv_spawn(loop, &child_req, &options))) {
|
||||
fprintf(stderr, "%s\n", uv_strerror(r));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return uv_run(loop, UV_RUN_DEFAULT);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user