login is possible

single-host
Marc Wäckerlin 9 years ago
parent 82bb795b85
commit 53a51b354c
  1. 8
      autogen.sh
  2. 100
      ax_cxx_compile_stdcxx_11.m4
  3. 233
      ax_init_standard_project.m4
  4. 298
      bootstrap.sh
  5. 95
      build-in-docker.sh
  6. 2
      doc/doxyfile.in
  7. 8
      doc/footer.html.in
  8. 33
      doc/header.html.in
  9. BIN
      doc/plantuml.jar
  10. 38
      doc/style.css
  11. 9
      makefile_test.inc.am
  12. 68
      nodejs/authentication/index.js
  13. 3
      nodejs/etc/servicedock.json
  14. 60
      nodejs/package.json.in
  15. 1004
      nodejs/public/javascripts/servicedock.js
  16. 23
      nodejs/public/stylesheets/servicedock.css
  17. 110
      nodejs/servicedock.js
  18. 535
      nodejs/sockets/index.js
  19. 21
      nodejs/views/index.ejs
  20. 2
      resolve-debbuilddeps.sh
  21. 17
      resolve-rpmbuilddeps.sh
  22. 16
      sql-to-dot.sed

@ -0,0 +1,8 @@
#!/bin/bash -e
if test -n "svn" -a -d .svn -a -e -x ; then
svn2cl
fi
aclocal
automake -a
autoconf

@ -4,12 +4,16 @@
#
# SYNOPSIS
#
# AX_REQUIRE_STDCXX_11
# AX_REQUIRE_STDCXX_14
# AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional])
# AX_CXX_COMPILE_STDCXX_14([ext|noext],[mandatory|optional])
#
# DESCRIPTION
#
# Check for baseline language coverage in the compiler for the C++11
# standard; if necessary, add switches to CXXFLAGS to enable support.
# or C++14 standard; if necessary, add switches to CXXFLAGS to
# enable support.
#
# The first argument, if specified, indicates whether you insist on an
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
@ -131,3 +135,97 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl
AC_SUBST(HAVE_CXX11)
fi
])
AC_DEFUN([AX_CXX_COMPILE_STDCXX_14], [dnl
m4_if([$1], [], [],
[$1], [ext], [],
[$1], [noext], [],
[m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_14])])dnl
m4_if([$2], [], [ax_cxx_compile_cxx14_required=true],
[$2], [mandatory], [ax_cxx_compile_cxx14_required=true],
[$2], [optional], [ax_cxx_compile_cxx14_required=false],
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_14])])dnl
AC_LANG_PUSH([C++])dnl
ac_success=no
AC_CACHE_CHECK(whether $CXX supports C++14 features by default,
ax_cv_cxx_compile_cxx14,
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
[ax_cv_cxx_compile_cxx14=yes],
[ax_cv_cxx_compile_cxx14=no])])
if test x$ax_cv_cxx_compile_cxx14 = xyes; then
ac_success=yes
fi
m4_if([$1], [noext], [], [dnl
if test x$ac_success = xno; then
for switch in -std=gnu++14 -std=gnu++0y; do
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx14_$switch])
AC_CACHE_CHECK(whether $CXX supports C++14 features with $switch,
$cachevar,
[ac_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS $switch"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXXFLAGS="$ac_save_CXXFLAGS"])
if eval test x\$$cachevar = xyes; then
CXXFLAGS="$CXXFLAGS $switch"
ac_success=yes
break
fi
done
fi])
m4_if([$1], [ext], [], [dnl
if test x$ac_success = xno; then
for switch in -std=c++14 -std=c++0y; do
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx14_$switch])
AC_CACHE_CHECK(whether $CXX supports C++14 features with $switch,
$cachevar,
[ac_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS $switch"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])],
[eval $cachevar=yes],
[eval $cachevar=no])
CXXFLAGS="$ac_save_CXXFLAGS"])
if eval test x\$$cachevar = xyes; then
CXXFLAGS="$CXXFLAGS $switch"
ac_success=yes
break
fi
done
fi])
AC_LANG_POP([C++])
if test x$ax_cxx_compile_cxx14_required = xtrue; then
if test x$ac_success = xno; then
AC_MSG_ERROR([*** A compiler with support for C++14 language features is required.])
fi
else
if test x$ac_success = xno; then
HAVE_CXX14=0
AC_MSG_NOTICE([No compiler with C++14 support was found])
AX_CXX_COMPILE_STDCXX_11([$1], [optional])
else
HAVE_CXX11=1
HAVE_CXX14=1
AC_DEFINE(HAVE_CXX14,1,
[define if the compiler supports basic C++14 syntax])
AC_DEFINE(HAVE_CXX11,1,
[define if the compiler supports basic C++14 syntax])
fi
AC_SUBST(HAVE_CXX11)
AC_SUBST(HAVE_CXX14)
fi
])
AC_DEFUN([AX_REQUIRE_STDCXX_11], [
if test x${HAVE_CXX11} != x1; then
AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.])
fi
])
AC_DEFUN([AX_REQUIRE_STDCXX_14], [
if test x${HAVE_CXX14} != x1; then
AC_MSG_ERROR([*** A compiler with support for C++14 language features is required.])
fi
])

@ -7,34 +7,32 @@
m4_define([mrw_esyscmd_s], [m4_normalize(m4_esyscmd([$1]))])
# define least version number from subversion's revision number:
# it is taken modulo 256 due to a bug on Apple's MacOSX
# it is taken modulo 256 due to a bug on Apple's SX
m4_define(x_least, m4_ifdef([x_least_fix], [x_least_fix],
m4_ifdef([x_least_diff],
mrw_esyscmd_s([
VCS_REVISION="ERROR-UNDEFINED-REVISION-to-be-built-in-subdirectory-of-checkout"
for path in . .. ../..; do
for path in . .. ../.. ../../..; do
if test -d .svn; then
svn upgrade 1>&2 > /dev/null || true
VCS_REVISION=$(LANG= svn info $path | sed -n 's/Last Changed Rev: //p')
if test -z "${VCS_REVISION}"; then VCS_REVISION=0; fi
break;
if test -n "${VCS_REVISION}"; then break; fi
elif test -d .git; then
VCS_REVISION=$(git rev-list --all --count)
if test -z "${VCS_REVISION}"; then VCS_REVISION=0; fi
break;
if test -n "${VCS_REVISION}"; then break; fi
fi
done
echo $ECHO_N $(($VCS_REVISION))
]), mrw_esyscmd_s([
VCS_REVISION="ERROR-UNDEFINED-REVISION-to-be-built-in-subdirectory-of-checkout"
for path in . .. ../..; do
for path in . .. ../.. ../../..; do
if test -d .svn; then
svn upgrade 1>&2 > /dev/null || true
VCS_REVISION=$(LANG= svn info $path | sed -n 's/Last Changed Rev: //p')
if test -z "${VCS_REVISION}"; then VCS_REVISION=0; fi
break;
if test -n "${VCS_REVISION}"; then break; fi
elif test -d .git; then
VCS_REVISION=$(git rev-list --all --count)
if test -z "${VCS_REVISION}"; then VCS_REVISION=0; fi
break;
if test -n "${VCS_REVISION}"; then break; fi
fi
done
# Mac does not support LEAST > 255
@ -48,15 +46,14 @@ m4_define(x_least, m4_ifdef([x_least_fix], [x_least_fix],
# add to x_minor if revision number is > 256
m4_define(x_minor_diff, m4_ifdef([x_least_fix], 0, mrw_esyscmd_s([
VCS_REVISION="ERROR-UNDEFINED-REVISION-to-be-built-in-subdirectory-of-checkout"
for path in . .. ../..; do
for path in . .. ../.. ../../..; do
if test -d .svn; then
svn upgrade 1>&2 > /dev/null || true
VCS_REVISION=$(LANG= svn info $path | sed -n 's/Last Changed Rev: //p')
if test -z "${VCS_REVISION}"; then VCS_REVISION=0; fi
break;
if test -n "${VCS_REVISION}"; then break; fi
elif test -d .git; then
VCS_REVISION=$(git rev-list --all --count)
if test -z "${VCS_REVISION}"; then VCS_REVISION=0; fi
break;
if test -n "${VCS_REVISION}"; then break; fi
fi;
done
# Mac does not support LEAST > 255
@ -132,7 +129,7 @@ AC_DEFUN([AX_SUBST], [
# m4_define(x_minor, MINOR_NUMBER) # project's minor version
# m4_include(ax_init_standard_project.m4)
# AC_INIT(x_package_name, x_version, x_bugreport, x_package_name)
# AM_INIT_AUTOMAKE([1.9 tar-pax])
# AM_INIT_AUTOMAKE([1.9 tar-pax parallel-tests color-tests])
# AX_INIT_STANDARD_PROJECT
#
# you change nothing but: YOUR_PACKAGE_NAME, MAJOR_NUMBER, MINOR_NUMBER
@ -173,17 +170,49 @@ AC_DEFUN([AX_INIT_STANDARD_PROJECT], [
AM_CPPFLAGS+=" '-DMAKE_STRING(X)=\#X' '-DNAMESPACE=${PACKAGE_TARNAME//[^a-zA-Z0-9]/_}'"
AX_SUBST(NUMBERS)
AX_SUBST(HOME)
README=$(tail -n +3 README)
if test -f README.md; then
README=$(tail -n +3 README.md)
DESCRIPTION=$(head -1 README.md)
else
README=$(tail -n +3 README)
DESCRIPTION=$(head -1 README)
fi
README_ESCAPED=$(echo "$README" | sed ':a;N;$!ba;s/\n/\\n/g;s,",\\",g')
if which pandoc 2>&1 > /dev/null; then
README_HTML=$(echo "$README" | pandoc -f markdown_github -t html | sed ':a;N;$!ba;s,\\\(.\),\\\\<span>\1</span>,g;s/\n/\\n/g;s,",\\",g;s, ,\&nbsp;\&nbsp;,g')
else
README_HTML="${README}"
fi
AX_SUBST(README)
_AM_SUBST_NOTMAKE([README])
DESCRIPTION=$(head -1 README)
AX_SUBST(README_ESCAPED)
_AM_SUBST_NOTMAKE([README_ESCAPED])
AX_SUBST(README_HTML)
_AM_SUBST_NOTMAKE([README_HTML])
AX_SUBST(DESCRIPTION)
_AM_SUBST_NOTMAKE([DESCRIPTION])
LICENSE=$(echo $(head -1 COPYING))
AX_SUBST(LICENSE)
COPYING=$(<COPYING)
AX_SUBST(COPYING)
_AM_SUBST_NOTMAKE([COPYING])
AUTHOR=$(head -1 AUTHORS)
AUTHOR_NAME=$(echo $AUTHOR | sed 's, *[[<(]].*$,,')
AUTHOR_URL=$(echo $AUTHOR | sed 's,.*(\(http[[^)]]*\)).*,\1,')
AUTHOR_MAIL=$(echo $AUTHOR | sed 's,.*<\(.*@.*\)>.*,\1,')
AX_SUBST(AUTHOR)
_AM_SUBST_NOTMAKE([AUTHOR])
AX_SUBST(AUTHOR_NAME)
AX_SUBST(AUTHOR_URL)
AX_SUBST(AUTHOR_MAIL)
PROJECT_URL="${PROJECT_URL:-${AUTHOR_URL}/projects/${PACKAGE_NAME}}"
SOURCE_DOWNLOAD="${SOURCE_DOWNLOAD:-${AUTHOR_URL}/downloads/${PACKAGE_NAME}}"
AX_SUBST(PROJECT_URL)
AX_SUBST(SOURCE_DOWNLOAD)
DISTRO=$(lsb_release -sc 2>/dev/null || uname -s 2>/dev/null)
AX_SUBST(DISTRO)
ARCH=$((@<:@@<:@ $(uname -sm) =~ 64 @:>@@:>@ && echo amd64) || (@<:@@<:@ $(uname -sm) =~ 'i?86' @:>@@:>@ && echo i386 || uname -sm))
AX_SUBST(ARCH)
DISTRIBUTOR=$(lsb_release -si 2>/dev/null || uname -s 2>/dev/null)
case "${DISTRIBUTOR// /-}" in
(Ubuntu) UBUNTU=1; AX_SUBST(UBUNTU);;
@ -243,6 +272,25 @@ AC_DEFUN([AX_INIT_STANDARD_PROJECT], [
else
AM_CPPFLAGS="${AM_CPPFLAGS} -DQT_NO_DEBUG_OUTPUT -DQT_NO_DEBUG"
fi
AC_ARG_WITH(gcov,
[AS_HELP_STRING([--with-gcov=FILE],
[enable gcov, set gcov file (defaults to gcov)])],
[GCOV="$enableval"], [GCOV="no"])
AM_CONDITIONAL(COVERAGE, test "$GCOV" != "no")
if test "$GCOV" != "no"; then
if test "$GCOV" == "yes"; then
GCOV=gcov
fi
AC_CHECK_PROG(has_gcov, [$GCOV], [yes], [no])
if test "$has_gcov" != "yes"; then
AC_MSG_ERROR([gcov: program $GCOV not found])
fi
AC_MSG_NOTICE([Coverage tests enabled, using ${GCOV}]);
AM_CXXFLAGS="${AM_CXXFLAGS:-} -O0 --coverage -fprofile-arcs -ftest-coverage"
AM_LDFLAGS="${AM_LDFLAGS} -O0 --coverage -fprofile-arcs"
AX_SUBST(GCOV)
fi
if test -f ${PACKAGE_NAME}.desktop.in; then
AC_CONFIG_FILES([${PACKAGE_NAME}.desktop])
@ -274,7 +322,7 @@ EOF
AC_DEFUN([AX_USE_CXX], [
m4_include(ax_cxx_compile_stdcxx_11.m4)
AC_LANG(C++)
AX_CXX_COMPILE_STDCXX_11(noext, optional)
AX_CXX_COMPILE_STDCXX_14(noext, optional)
AC_PROG_CXX
AC_PROG_CPP
@ -312,6 +360,43 @@ maintainer-clean-cxx-targets:
EOF
])
# use this in configure.ac to support old school C
AC_DEFUN([AX_USE_C], [
AC_LANG(C)
AC_PROG_CC
AC_PROG_CPP
AC_CONFIG_FILES([src/makefile])
AM_CPPFLAGS+=' -I ${top_srcdir}/src -I ${top_builddir}/src -I ${srcdir} -I ${builddir}'
AM_LDFLAGS+=' -L ${top_srcdir}/src -L ${top_builddir}/src'
# Get rid of those stupid -g -O2 options!
CXXFLAGS="${CXXFLAGS//-g -O2/}"
CFLAGS="${CFLAGS//-g -O2/}"
# pass compile flags to make distcheck
AM_DISTCHECK_CONFIGURE_FLAGS="CFLAGS='${CFLAGS}' CPPFLAGS='${CPPFLAGS}' CFLAGS='${CFLAGS}' LDFLAGS='${LDFLAGS}'"
AC_SUBST(AM_DISTCHECK_CONFIGURE_FLAGS)
AC_SUBST(AM_CFLAGS)
AC_SUBST(AM_CPPFLAGS)
AC_SUBST(AM_LDFLAGS)
AX_ADD_MAKEFILE_TARGET_DEP([maintainer-clean-am], [maintainer-clean-c-targets], [src/makefile.in])
test -f src/makefile.in && cat >> src/makefile.in <<EOF
#### Begin: Appended by $0
%.app: %
-rm -r [\$][@]
\$(MAKE) DESTDIR=[\$][\$](pwd)/[\$][@]/tmp install
\${top_builddir}/mac-create-app-bundle.sh \
[\$][@] [\$][<] [\$][\$](pwd)/[\$][@]/tmp\${prefix}
maintainer-clean-c-targets:
-rm makefile.in
#### End: $0
EOF
])
# use this in configure.ac to support tests without CppUnit
AC_DEFUN([AX_BUILD_TEST], [
AC_CONFIG_FILES([test/makefile])
@ -347,6 +432,33 @@ maintainer-clean-example-targets:
EOF
])
# use this in configure.ac to support C++ examples
AC_DEFUN([AX_USE_NODEJS], [
AC_PATH_PROG(ANDROID, [android], [0],
[${PATH}${PATH_SEPARATOR}${ANDROID_HOME}/tools])
AC_PATH_PROG(CORDOVA, [cordova], [0],
[${PATH}${PATH_SEPARATOR}$(pwd)/node_modules/cordova/bin])
if test ${CORDOVA} = 0; then
AC_MSG_WARN([cordova is missing, on ubuntu install cordova-cli from repository ppa:cordova-ubuntu/ppa])
fi
if test ${ANDROID} = 0; then
AC_MSG_WARN([android sdk is missing, set variable ANDROID_HOME after installation])
fi
AM_CONDITIONAL(HAVE_CORDOVA, [test ${CORDOVA} != 0 -a ${ANDROID} != 0])
AX_SUBST(CORDOVA)
AC_CONFIG_FILES([nodejs/package.json])
AC_CONFIG_FILES([nodejs/makefile])
AC_CONFIG_FILES([cordova/makefile])
AC_CONFIG_FILES([cordova/config.xml])
AX_ADD_MAKEFILE_TARGET_DEP([maintainer-clean-am], [maintainer-clean-example-targets], [examples/makefile.in])
test -f examples/makefile.in && cat >> examples/makefile.in <<EOF
#### Begin: Appended by $0
maintainer-clean-example-targets:
-rm makefile.in
#### End: $0
EOF
])
# use this in configure.ac to support HTML data for webservers
AC_DEFUN([AX_BUILD_HTML], [
AC_CONFIG_FILES([html/makefile])
@ -389,7 +501,11 @@ EOF
# use this in configure.ac to support debian packages
AC_DEFUN([AX_USE_DEBIAN_PACKAGING], [
README_DEB=$(tail -n +3 README | sed -e 's/^ *$/./g' -e 's/^/ /g')
if test -f README.md; then
README_DEB=$(tail -n +3 README.md | sed -e 's/^ *$/./g' -e 's/^/ /g')
else
README_DEB=$(tail -n +3 README | sed -e 's/^ *$/./g' -e 's/^/ /g')
fi
AC_SUBST(README_DEB)
_AM_SUBST_NOTMAKE([README_DEB])
AC_CONFIG_FILES([debian/changelog debian/control])
@ -412,12 +528,15 @@ EOF
AC_DEFUN([AX_USE_RPM_PACKAGING], [
AC_CONFIG_FILES([${PACKAGE_NAME}.spec])
#AX_ADD_MAKEFILE_TARGET_DEP([clean-am], [clean-rpm-targets], [makefile.in])
AX_ADD_MAKEFILE_TARGET_DEP([clean-am], [clean-rpm-targets], [makefile.in])
AX_ADD_MAKEFILE_TARGET_DEP([distclean-am], [distclean-rpm-targets], [makefile.in])
test -f makefile.in && cat >> makefile.in <<EOF
#### Begin: Appended by $0
EXTRA_DIST += \${PACKAGE_NAME}.spec.in
rpm: dist
rpmbuild -ba --define "_topdir \$\$(pwd)" --define "_sourcedir \$\$(pwd)" \${PACKAGE_NAME}.spec
clean-rpm-targets:
-rm -rf BUILD BUILDROOT RPMS SPECS SRPMS
distclean-rpm-targets:
-rm \${PACKAGE_NAME}.spec
#### End: $0
@ -434,6 +553,7 @@ AC_DEFUN([AX_USE_DOXYGEN], [
AC_CHECK_PROG(have_doxygen, doxygen, yes, no)
AC_CHECK_PROG(have_dot, dot, yes, no)
AC_CHECK_PROG(have_mscgen, mscgen, yes, no)
AM_CONDITIONAL(NEED_PLANTUML, test "$have_doxygen" = "yes" -a "1.8.11" != $((echo "1.8.11"; doxygen -v) | sort -V | head -1))
PDF_DOC=${PACKAGE_NAME}-${PACKAGE_VERSION}.pdf
AC_SUBST(PDF_DOC)
if test "$have_doxygen" = "no"; then
@ -448,22 +568,38 @@ AC_DEFUN([AX_USE_DOXYGEN], [
AC_MSG_WARN([Missing program mscgen!
- when you rebild documentation, there are no message state charts
- there are precompiled derived files in the distribution]); fi
AC_CONFIG_FILES([doc/makefile doc/doxyfile])
AC_CONFIG_FILES([doc/makefile doc/doxyfile doc/header.html doc/footer.html])
AX_ADD_MAKEFILE_TARGET_DEP([clean-am], [clean-documentation], [doc/makefile.in])
AX_ADD_MAKEFILE_TARGET_DEP([distclean-am], [distclean-documentation], [doc/makefile.in])
AX_ADD_MAKEFILE_TARGET_DEP([maintainer-clean-am], [maintainer-clean-documentation], [doc/makefile.in])
AX_ADD_MAKEFILE_TARGET_DEP([install-data-am], [install-data-documentation], [doc/makefile.in])
AX_ADD_MAKEFILE_TARGET_DEP([uninstall-am], [uninstall-documentation], [doc/makefile.in])
AX_ADD_MAKEFILE_TARGET_DEP([all], [doc], [doc/makefile.in])
AX_ADD_MAKEFILE_TARGET_DEP([.PHONY], [pdf], [doc/makefile.in])
AX_ADD_MAKEFILE_TARGET_DEP([.PHONY], [pdf gen-uml-images], [doc/makefile.in])
test -f doc/makefile.in && cat >> doc/makefile.in <<EOF
#### Begin: Appended by $0
doc: doxyfile
doc: doxyfile @NEED_PLANTUML_TRUE@ gen-uml-images
@NEED_PLANTUML_TRUE@ doxyadd() { grep -q "\$\$[1] += \$\$[2]" doxyfile || sed -i '/^'"\$\$[1]"' *=/a'"\$\$[1]"' += '"\$\$[2]" doxyfile; }; \\
@NEED_PLANTUML_TRUE@ doxyadd ALIASES '"startuml{1}=@image html \\\\1\\\\n@image latex \\\\1\\\\n\\\\if DontIgnorePlantUMLCode"'; \\
@NEED_PLANTUML_TRUE@ doxyadd ALIASES '"enduml=\\\\endif"'; \\
@NEED_PLANTUML_TRUE@ doxyadd IMAGE_PATH '"gen-uml-images"';
doxygen doxyfile
@PEDANTIC_TRUE@ test \! -s doxygen.errors
@NEED_PLANTUML_TRUE@EXTRA_DIST = ${EXTRA_DIST} plantuml.jar
@NEED_PLANTUML_TRUE@
@NEED_PLANTUML_TRUE@gen-uml-images:
@NEED_PLANTUML_TRUE@ test -d gen-uml-images || mkdir gen-uml-images
@NEED_PLANTUML_TRUE@ eval \$\$(sed -n 's, *INPUT *\\(+\\?\\)= *\\(.*\\),INPUT\\1=" \\2",gp' doxyfile); \\
@NEED_PLANTUML_TRUE@ eval \$\$(sed -n 's, *FILE_PATTERNS *\\(+\\?\\)= *\\(.*\\),FILE_PATTERNS\\1=" \\2",gp' doxyfile); \\
@NEED_PLANTUML_TRUE@ SOURCES="**.("\$\$(echo \$\${FILE_PATTERNS} | sed 's,*.,,g;s, ,|,g')")"; \\
@NEED_PLANTUML_TRUE@ for src in \$\$INPUT; do \\
@NEED_PLANTUML_TRUE@ java -Djava.awt.headless=true -jar \${top_srcdir}/doc/plantuml.jar -v -o \$\$(pwd)/gen-uml-images "\$\$src/\$\$SOURCES"; \\
@NEED_PLANTUML_TRUE@ done
clean-documentation:
-rm doxygen.errors @PDF_DOC@
@NEED_PLANTUML_TRUE@ -rm -rf gen-uml-images
distclean-documentation:
-rm -r html
-rm @PACKAGE_NAME@.doxytag
@ -480,6 +616,55 @@ uninstall-documentation:
EOF
])
# use this in configure.ac to support Doxygen documentation generation
AC_DEFUN([AX_USE_PERLDOC], [
PERL_SOURCES="m4_default([$1], [perl])"
AX_SUBST(PERL_SOURCES)
if test -z "$PERL_SOURCES"; then
AC_MSG_ERROR([You must specify the path to per files
- use [AX]_[USE]_PERLDOC([[pathes to perldoc]])]); fi
AC_CHECK_PROG(have_perldoc, pods2html, yes, no)
if test "$have_doxygen" = "no"; then
AC_MSG_WARN([Missing program pods2html!
- you cannot rebuild the documentation
- there are precompiled derived files in the distribution
- if you need to generate documentation, install libpod-tree-perl]); fi
AC_CONFIG_FILES([doc/makefile])
AX_ADD_MAKEFILE_TARGET_DEP([distclean-am], [distclean-perldoc], [doc/makefile.in])
AX_ADD_MAKEFILE_TARGET_DEP([maintainer-clean-am], [maintainer-clean-perldoc], [doc/makefile.in])
AX_ADD_MAKEFILE_TARGET_DEP([install-data-am], [install-data-perldoc], [doc/makefile.in])
AX_ADD_MAKEFILE_TARGET_DEP([uninstall-am], [uninstall-perldoc], [doc/makefile.in])
AX_ADD_MAKEFILE_TARGET_DEP([all], [doc], [doc/makefile.in])
AX_ADD_MAKEFILE_TARGET_DEP([.PHONY], [doc], [doc/makefile.in])
test -f doc/makefile.in && cat >> doc/makefile.in <<EOF
#### Begin: Appended by $0
doc: perldoc/index.html
perldoc/index.html: \${PERL_SOURCES:%=perldoc/%}
echo "<html><head><title>Perl Documentation</title></head><body><h1>Perl Documentation</h1><ul>" > perldoc/index.html
for p in \${PERL_SOURCES:%=perldoc/%}; do \
echo '<li><a href="'"\$\${p#perldoc/}"'/index.html">'"\$\${p#perldoc/}"'</a></li>' >> perldoc/index.html; \
done
echo "</ul></body></html>" >> perldoc/index.html
perldoc/%:
pods2html --notoc --empty --index index @top_srcdir@/\${@:perldoc/%=%} \$[@]
distclean-perldoc:
-rm -r perldoc
maintainer-clean-perldoc:
-rm makefile.in
install-data-perldoc:
test -d \$(DESTDIR)\${docdir} || mkdir -p \$(DESTDIR)\${docdir}
chmod -R u+w \$(DESTDIR)\${docdir}
cp -r perldoc \$(DESTDIR)\${docdir}/
uninstall-perldoc:
-chmod -R u+w \$(DESTDIR)\${docdir}
-rm -rf \$(DESTDIR)\${docdir}/perldoc
#### End: $0
EOF
])
# require a specific package, with fallback: test for a header
# - parameter:
# $1 = unique id (no special characters)

@ -23,17 +23,22 @@ docker=0
buildtarget=""
overwrite=0
rebuild=0
novcs=0
excludevcs=()
rebuildfiles=()
while test $# -gt 0; do
case "$1" in
(--configure|-c) configure=1;;
(--docker|-d) docker=1;;
(--build|-b) configure=1; build=1; buildtarget+=" distcheck";;
(--target|-t) shift; configure=1; build=1; buildtarget+=" $1";;
(--all|-a) shift; configure=1; build=1; buildtarget+=" all";;
(--clean) shift; configure=1; build=1; buildtarget+=" maintainer-clean";;
(--target|-t) shift; configure=1; build=1; buildtarget+=" $1";;
(--overwrite|-o) overwrite=1;;
(--rebuild|-r) rebuild=1;;
(--rebuild-file|-f) shift; rebuildfiles+=("$1");;
(--no-vcs|-n) novcs=1;;
(--exclude-vcs|-x) shift; excludevcs+=("$1");;
(--version|-v)
echo "$Id$";
exit;;
@ -47,10 +52,14 @@ OPTIONS
--configure, -c call ./configure after initialization
--docker, -d build and run tests in a docker instance
--build, -b build, also call ./configure && make distcheck
--all, -a same as -b, but make target all
--clean same as -b, but make target maintainer-clean
--target, -t <target> same as -b, but specify target instead of distcheck
--overwrite, -o overwrite all basic files (bootstrap.sh, m4-macros)
--rebuild, -r force rebuild of generated files, even if modified
--rebuild-file, -f <file> rebild specific file (can be added multiple times)
--no-vcs, -n do not automatically add files to version control
--exclude-vcs, -x <file> exclude specific file from version control
--help, -h show this help
--version, -v show version and date of this file
@ -109,18 +118,22 @@ RUNNING
If you run ${MY_NAME}, it first generates the necessary files (see
below), then first runs make distclean if a makefile exists. After
this it calles aclocal, libtoolize, automake, autoconf and
optionally ./configure.
optionally ./configure. If necessary, files are added to version
control.
GENERATED FILES
This script copies the following files into your project environment:
* ${MY_NAME}
* autogen.sh - just the basics to initialize auto tools and create configure
* ax_init_standard_project.m4 - auxiliary macro definition file
* ax_cxx_compile_stdcxx_11.m4 - auxiliary macro definition file
* ax_check_qt.m4 - auxiliary macro definition file
* makefile_test.inc.am - makefile to be included in tests
* resolve-debbuilddeps.sh - script to install debian package dependencies
* resolve-rpmbuilddeps.sh - script to install RPM package dependencies
* build-in-docker.sh - script to build the project encapsulated in a docker container
* build-in-docker.conf - additional configuration for build-in-docker.sh
* build-resource-file.sh - build resource.qrc file from a resource directory
* sql-to-dot.sed - script to convert SQL schema files to graphviz dot in doxygen
* mac-create-app-bundle.sh - script to create apple mac os-x app-bundle
@ -136,9 +149,14 @@ GENERATED FILES
* src/version.cxx - if you enabled AX_USE_CXX
* html/makefile.am - if you enabled AX_BUILD_HTML
* scripts/makefile.am - if you enabled AX_USE_SCRIPTS
* doc/makefile.am - if you enabled AX_USE_DOXYGEN
* doc/makefile.am - if you enabled AX_USE_DOXYGEN or AX_USE_PERLDOC
* doc/doxyfile.in - if you enabled AX_USE_DOXYGEN
* test/makefile.am - if you enabled AX_BUILD_TEST or AX_USE_CPPUNIT
* doc/header.html.in - if you enabled AX_USE_DOXYGEN
* doc/footer.html.in - if you enabled AX_USE_DOXYGEN
* doc/style.css - if you enabled AX_USE_DOXYGEN
* doc/plantuml.jar - if you enable AX_USE_DOXYGEN
* test/makefile.am - if you enabled AX_USE_CPPUNIT and AX_USE_CXX
* test/${DEFAULT_PROJECT_NAME#lib}.cxx - if you enabled AX_BUILD_TEST or AX_USE_CPPUNIT
* examples/makefile.am - if you enabled AX_BUILD_EXAMPLES
* debian/changelog.in - if you enabled AX_USE_DEBIAN_PACKAGING
* debian/control.in - if you enabled AX_USE_DEBIAN_PACKAGING
@ -179,6 +197,7 @@ FILES TO EDIT
* src/makefile.am
* html/makefile.am
* test/makefile.am
* test/${DEFAULT_PROJECT_NAME}.cxx
* examples/makefile.am
FILE DEPENDENCIES
@ -189,8 +208,8 @@ FILE DEPENDENCIES
* test/makefile.am depends on AX_USE_LIBTOOL
* html/makefile.am depends on AX_BUILD_HTML
* doc/doxyfile.in depends on AX_BUILD_EXAMPLES
* debian/control.in depends on AX_USE_DOXYGEN, AX_USE_CPPUNIT
AX_CXX_QT, AX_CHECK_QT, AX_REQUIRE_QT, AX_USE_LIBTOOL
* debian/control.in depends on AX_USE_DOXYGEN, AX_USE_PERLDOC,
AX_USE_CPPUNIT AX_CXX_QT, AX_CHECK_QT, AX_REQUIRE_QT, AX_USE_LIBTOOL
* debian/${DEFAULT_PROJECT_NAME}.install depends on AX_USE_LIBTOOL
* debian/${DEFAULT_PROJECT_NAME}.dirs depends on AX_USE_LIBTOOL
* debian/${DEFAULT_PROJECT_NAME}-dev.install depends on AX_USE_LIBTOOL
@ -224,6 +243,7 @@ FILES
* Enable LibTool library creation: AX_USE_LIBTOOL
* Enable Scripts: AX_USE_SCRIPTS
* Enable Doxygen documentation generation: AX_USE_DOXYGEN
* Enable Perldoc documentation generation: AX_USE_PERLDOC
* Enable Debian packaging by calling "make deb": AX_USE_DEBIAN_PACKAGING
* Enable RPM packaging by calling "make rpm": AX_USE_RPM_PACKAGING
* Enable C++ testing using CppUnit: AX_USE_CPPUNIT
@ -345,7 +365,7 @@ contains() {
checkdir() {
if ! test -d "$1"; then # create path
run mkdir -p "$1"
if test -n "${VCS}"; then
if test -n "${VCS}" -a $novcs -eq 0 && ! contains "$1" "${excludevcs[@]}"; then
run ${VCS} add "$1"
fi
fi
@ -360,13 +380,17 @@ checkfile() {
}
to() {
mode="u=rw,g=rw,o=r"
while test $# -gt 0; do
mode="u=rw,g=rw,o=r"
case "$1" in
(--condition) shift # test for a tag, abort if not set
if ! testtag "$1"; then
return 0
fi;;
(--unless) shift # test for a tag, abort if set
if testtag "$1"; then
return 0
fi;;
(--mode) shift # test for a tag, abort if not set
mode="$1";;
(*) break;;
@ -392,9 +416,9 @@ to() {
else
echo -e " \e[32msuccess\e[0m"
fi
chmod $mode $1
run chmod $mode $1
if test $exists -eq 0; then
if test -n "${VCS}"; then
if test -n "${VCS}" -a $novcs -eq 0 && ! contains "$1" "${excludevcs[@]}"; then
run ${VCS} add "$1"
if test "${VCS}" = "svn"; then
run svn propset svn:keywords "Id" "$1"
@ -417,9 +441,12 @@ copy() {
source="${0%/*}/$1"
fi
fi
if test "${1%/*}" != "$1"; then
test -d "${1%/*}" || svn mkdir "${1%/*}"
fi
run cp "${source}" "$1"
if test $exists -eq 0; then
if test -n "${VCS}"; then
if test -n "${VCS}" -a $novcs -eq 0 && ! contains "$1" "${excludevcs[@]}"; then
run ${VCS} add "$1"
if test "${VCS}" = "svn"; then
run svn propset svn:keywords "Id" "$1"
@ -452,23 +479,27 @@ doxyadd() {
vcs2cl() {
exists=0
if test -f "Changelog"; then
if test -f "ChangeLog"; then
exists=1
else
touch "ChangeLog"
fi
if test "${VCS}" = "git"; then
${VCS}2cl > ChangeLog
elif test -n "${VCS}"; then
${VCS}2cl
if test -x $(which ${VCS}2cl); then
if test "${VCS}" = "git"; then
${VCS}2cl > ChangeLog
elif test -n "${VCS}"; then
${VCS}2cl
fi
fi
if test $exists -eq 0; then
if test -n "${VCS}"; then
if test -n "${VCS}" -a $novcs -eq 0 && ! contains "ChangeLog" "${excludevcs[@]}"; then
run ${VCS} add ChangeLog
fi
fi
}
# Check if we are in subversion root, if so, create trunk, branches, tags:
if test "${VCS}" = "svn"; then
if test "${VCS}" = "svn" -a $novcs -eq 0; then
if test "$(LANG= svn info | sed -n 's,Relative URL: *,,p')" = "^/"; then
svn mkdir trunk branches tags
cd trunk
@ -480,6 +511,7 @@ copy ${MY_NAME}
copy ax_init_standard_project.m4
copy ax_cxx_compile_stdcxx_11.m4
copy ax_check_qt.m4
copy makefile_test.inc.am
copy resolve-debbuilddeps.sh
copy resolve-rpmbuilddeps.sh
copy build-in-docker.sh
@ -502,7 +534,11 @@ ${DEFAULT_PROJECT_NAME}
add description for ${DEFAULT_PROJECT_NAME}
EOF
to configure.ac <<EOF && notice "please edit configure.ac, then rerun $0" && exit 0
${HEADER}m4_define(x_package_name, ${DEFAULT_PROJECT_NAME}) # project's name
${HEADER}# default is generated from AUTHORS and project name
PROJECT_URL=
SOURCE_DOWNLOAD=
m4_define(x_package_name, ${DEFAULT_PROJECT_NAME}) # project's name
m4_define(x_major, 0) # project's major version
m4_define(x_minor, 0) # project's minor version
m4_include(ax_init_standard_project.m4)
@ -515,6 +551,7 @@ AX_INIT_STANDARD_PROJECT
#AX_USE_LIBTOOL
#AX_USE_SCRIPTS
#AX_USE_DOXYGEN
#AX_USE_PERLDOC
#AX_USE_DEBIAN_PACKAGING
#AX_USE_RPM_PACKAGING
#AX_USE_CPPUNIT
@ -542,6 +579,20 @@ if ! testtag AX_CHECK_QT && \
! testtag AX_REQUIRE_QT; then
echo "${HEADER}MAINTAINERCLEANFILES = makefile.in" | \
to --condition AX_USE_CXX src/makefile.am
if ! ls src/*.[ch]xx; then
to --condition AX_USE_CXX src/${PACKAGE_NAME#lib}.hxx <<EOF
${CHEADER}#ifndef ${PackageName^^}_HXX
#define ${PackageName^^}_HXX
/** @mainpage @description
@readme
*/
#endif
EOF
fi
elif ! test -e src/makefile.am; then
to --condition AX_USE_CXX src/makefile.am <<EOF
${HEADER}bin_PROGRAMS = ${PACKAGE_NAME}
@ -632,10 +683,17 @@ int main(int argc, char *argv[]) try {
return 1;
}
EOF
to --condition AX_USE_CXX src/${PACKAGE_NAME}.hxx <<EOF
if ! ls src/*.[ch]xx; then
to --condition AX_USE_CXX src/${PACKAGE_NAME#lib}.hxx <<EOF
${CHEADER}#ifndef ${PackageName^^}_HXX
#define ${PackageName^^}_HXX
/** @mainpage @description
@readme
*/
#include <QMainWindow>
#include <ui_${PACKAGE_NAME}.hxx>
@ -652,7 +710,8 @@ class ${PackageName}: public QMainWindow, protected Ui::${PackageName} {
#endif
EOF
to --condition AX_USE_CXX src/${PACKAGE_NAME}.ui <<EOF
fi
to --condition AX_USE_CXX src/${PACKAGE_NAME#lib}.ui <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>${PackageName}</class>
@ -734,7 +793,7 @@ EOF
to --condition AX_USE_CXX src/version.cxx <<EOF
/*! @file
@id $Id\$
@id \$Id\$
*/
// 1 2 3 4 5 6 7 8
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
@ -778,7 +837,7 @@ ${HEADER}dist_bin_SCRIPTS =
MAINTAINERCLEANFILES = makefile.in
EOF
echo "${HEADER}MAINTAINERCLEANFILES = makefile.in" | to --condition AX_USE_DOXYGEN doc/makefile.am
echo "${HEADER}MAINTAINERCLEANFILES = makefile.in" | to --condition 'AX_USE_DOXYGEN|AX_USE_PERLDOC' doc/makefile.am
if testtag AX_BUILD_TEST; then
to test/runtests.sh < ${0%/*}/test/runtests.sh
fi
@ -789,16 +848,51 @@ AM_CPPFLAGS = -I\${top_srcdir}/src -I\${top_builddir}/src
AM_LDFLAGS = -L\${abs_top_builddir}/src/.libs
$(if testtag AX_USE_LIBTOOL; then
cat <<EOF3
LDADD = -l${PACKAGE_NAME#lib}
LDADD = -lcppunit -l${PACKAGE_NAME#lib}
EOF3
fi)
EOF2
fi)
TESTS =
check_PROGRAMS = ${PACKAGE_NAME#lib}
TESTS = \${check_PROGRAMS}
${PACKAGE_NAME#lib}_SOURCES = ${PACKAGE_NAME#lib}.cxx
MAINTAINERCLEANFILES = makefile.in
EOF
to --condition AX_USE_CPPUNIT --condition AX_USE_CXX test/${PACKAGE_NAME#lib}.cxx <<EOF
${CHEADER}
#include <cppunit/TestFixture.h>
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/XmlOutputter.h>
#include <fstream>
/// @todo Rename DummyTest and DummyTest::dummy()
/// @todo Write test cases
class DummyTest: public CppUnit::TestFixture {
public:
void dummy() {
}
CPPUNIT_TEST_SUITE(DummyTest);
CPPUNIT_TEST(dummy);
CPPUNIT_TEST_SUITE_END();
};
CPPUNIT_TEST_SUITE_REGISTRATION(DummyTest);
int main(int argc, char** argv) try {
std::ofstream ofs((*argv+std::string(".xml")).c_str());
CppUnit::TextUi::TestRunner runner;
runner.setOutputter(new CppUnit::XmlOutputter(&runner.result(), ofs));
runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
return runner.run() ? 0 : 1;
} catch (std::exception& e) {
std::cerr<<"***Exception: "<<e.what()<<std::endl;
return 1;
}
EOF
to --condition AX_BUILD_EXAMPLES examples/makefile.am <<EOF
${HEADER}AM_CPPFLAGS = -I\${top_srcdir}/src -I\${top_builddir}/src
AM_LDFLAGS = -L\${abs_top_builddir}/src/.libs
@ -814,12 +908,100 @@ www_DATA =
MAINTAINERCLEANFILES = makefile.in
EOF
to --condition AX_USE_DOXYGEN doc/header.html.in <<EOF
<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen \$doxygenversion"/>
<!--BEGIN PROJECT_NAME--><title>\$projectname: \$title</title><!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME--><title>\$title</title><!--END !PROJECT_NAME-->
<link href="\$relpath^tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="\$relpath^jquery.js"></script>
<script type="text/javascript" src="\$relpath^dynsections.js"></script>
\$treeview
\$search
\$mathjax
<link href="\$relpath^\$stylesheet" rel="stylesheet" type="text/css" />
\$extrastylesheet
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<div id="projecthead">
<div id="projectlogo"><img alt="" src="\$relpath^\$projectlogo"/></div>
<div id="projectname">\$projectname</span>&#160;<span id="projectnumber">\$projectnumber</div>
<div id="projectbrief">\$projectbrief</div>
</div>
<nav>
<a href="@PROJECT_URL@" target="_blank">Project Management</a>
<a href="@SOURCE_DOWNLOAD@" target="_blank">Download</a>
<div>\$searchbox</div>
</nav>
</div>
EOF
to --condition AX_USE_DOXYGEN doc/footer.html.in <<EOF
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
\$navpath
<li class="footer"><a href="@AUTHOR_URL@" target="_blank">@AUTHOR_NAME@</a></li>
</ul>
</div>
</body>
</html>
EOF
to --condition AX_USE_DOXYGEN doc/style.css <<EOF
#titlearea {
display: flex;
justify-content: space-between;
align-items: flex-begin;
}
#titlearea nav {
padding: 0;
margin: 0;
}
#titlearea nav a {
background-color: lightgray;
border: 1px solid gray;
color: black;
padding: 1ex;
margin: 0;
}
img, object {
max-width: 100% !important;
}
@media (max-width: 50em) {
#navrow1, #navrow2 {
display: block
}
#side-nav, #splitbar, .ui-resizable-handle ui-resizable-e, .ui-resizable-handle ui-resizable-s {
display: none;
}
#doc-content {
margin-left: 0 !important;
}
}
@media (min-width: 50em) {
#navrow1, #navrow2 {
display: none;
}
#side-nav, #splitbar, .ui-resizable-handle ui-resizable-e, .ui-resizable-handle ui-resizable-s {
display: block
}
}
EOF
if testtag AX_USE_DOXYGEN; then
copy doc/plantuml.jar
fi
if testtag AX_USE_DOXYGEN; then
if ! checkfile doc/doxyfile.in || \
contains doc/doxyfile.in "${rebuildfiles[@]}"; then
run doxygen -g doc/doxyfile.in
if test $exists -eq 0; then
if test -n "${VCS}"; then
if test -n "${VCS}" -a $novcs -eq 0 && ! contains "doc/doxyfile" "${excludevcs[@]}"; then
run ${VCS} add doc/doxyfile.in
if test "${VCS}" = "svn"; then
run svn propset svn:keywords "Id" doc/doxyfile.in
@ -829,17 +1011,21 @@ if testtag AX_USE_DOXYGEN; then
doxyreplace PROJECT_NAME "@PACKAGE_NAME@"
doxyreplace PROJECT_NUMBER "@PACKAGE_VERSION@"
doxyreplace PROJECT_BRIEF "@DESCRIPTION@"
doxyreplace PROJECT_LOGO "@top_srcdir@/@PACKACE_LOGO@"
doxyreplace PROJECT_LOGO "@top_srcdir@/@PACKAGE_LOGO@"
doxyreplace INLINE_INHERITED_MEMB YES
doxyreplace MULTILINE_CPP_IS_BRIEF YES
doxyreplace TAB_SIZE 2
doxyreplace ALIASES '"id=\\par File-ID\\n"'
doxyadd ALIASES '"copy=\\par Copyright\\n"'
doxyadd ALIASES '"copy=\\par Copyright by <a href="@AUTHOR_URL@" target="_blank">@AUTHOR_NAME@</a>\\n"'
doxyadd ALIASES '"license=\\par License\\n"'
doxyadd ALIASES '"classmutex=\\par Reentrant:\\nAccess is locked with class static mutex @c "'
doxyadd ALIASES '"instancemutex=\\par Reentrant:\\nAccess is locked with per instance mutex @c "'
doxyadd ALIASES '"mutex=\\par Reentrant:\\nAccess is locked with mutex @c "'
doxyadd ALIASES '"api=\\xrefitem api \\"API Call\\" \\"\\""'
doxyadd ALIASES '"description=@DESCRIPTION@"'
doxyadd ALIASES '"readme=@README_HTML@"'
doxyadd ALIASES '"author=<a href="@AUTHOR_URL@" target="_blank">@AUTHOR_NAME@</a>"'
doxyreplace PLANTUML_JAR_PATH '"@top_srcdir@/doc/plantuml.jar"'
doxyreplace ENABLE_PREPROCESSING YES
doxyreplace MACRO_EXPANSION YES
doxyadd PREDEFINED '"NAMESPACE=@PACKAGE_NAME@"'
@ -866,9 +1052,20 @@ if testtag AX_USE_DOXYGEN; then
if testtag AX_BUILD_TEST AX_USE_CPPUNIT; then
doxyadd INPUT "@top_srcdir@/test"
fi
if testtag AX_USE_NODEJS; then
doxyadd INPUT "@top_srcdir@/nodejs"
doxyadd EXCLUDE "@top_srcdir@/nodejs/node_modules"
doxyadd EXCLUDE "@top_srcdir@/nodejs/public/javascripts/ext"
fi
doxyreplace FILE_PATTERNS '*.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.idl *.ddl *.odl *.h *.hh *.hxx *.hpp *.h++ *.cs *.d *.php *.php4 *.php5 *.phtml *.inc *.m *.markdown *.md *.mm *.dox *.py *.f90 *.f *.for *.tcl *.vhd *.vhdl *.ucf *.qsf *.as *.js *.wt *.sql'
doxyreplace RECURSIVE YES
doxyreplace EXCLUDE_PATTERNS "moc_* uic_* qrc_*"
doxyreplace EXCLUDE_PATTERNS "moc_* uic_* qrc_* version.[ch]xx"
doxyreplace HTML_HEADER header.html
doxyreplace HTML_FOOTER footer.html
doxyreplace HTML_EXTRA_STYLESHEET style.css
doxyreplace HTML_DYNAMIC_SECTIONS YES
doxyreplace DISABLE_INDEX NO
doxyreplace GENERATE_TREEVIEW YES
if testtag AX_BUILD_EXAMPLES; then
doxyreplace EXAMPLE_PATH @top_srcdir@/examples
fi
@ -877,7 +1074,6 @@ if testtag AX_USE_DOXYGEN; then
doxyreplace SOURCE_BROWSER YES
doxyreplace INLINE_SOURCES YES
doxyreplace GENERATE_TESTLIST YES
doxyreplace GENERATE_TREEVIEW NO
doxyreplace SEARCHENGINE NO
doxyreplace GENERATE_HTML YES
doxyreplace GENERATE_LATEX NO
@ -904,7 +1100,7 @@ if testtag AX_USE_DEBIAN_PACKAGING; then
-- @AUTHOR@ @BUILD_DATE@
EOF
BUILD_DEPENDS="debhelper, ${VCSDEPENDS} pkg-config, automake, libtool, autotools-dev, lsb-release $(if testtag AX_USE_DOXYGEN; then echo -n ", doxygen, graphviz, mscgen"; fi; if testtag AX_USE_CPPUNIT; then echo -n ", libcppunit-dev"; fi; if testtag AX_CXX_QT || testtag AX_CHECK_QT AX_REQUIRE_QT; then echo -n ", qt5-default | libqt4-core | libqtcore4, qt5-qmake | qt4-qmake, qtbase5-dev | libqt4-dev, qtbase5-dev-tools | qt4-dev-tools, qttools5-dev-tools | qt4-dev-tools, qttools5-dev-tools | qt4-dev-tools"; fi)"
BUILD_DEPENDS="debhelper, ${VCSDEPENDS} pkg-config, automake, libtool, autotools-dev, pandoc, lsb-release $(if testtag AX_USE_DOXYGEN; then echo -n ", doxygen, graphviz, mscgen"; fi; if testtag AX_USE_PERLDOC; then echo -n ", libpod-tree-perl"; fi; if testtag AX_USE_PLANTUML; then echo -n ", default-jre-headless|default-jre"; fi; if testtag AX_USE_CPPUNIT; then echo -n ", libcppunit-dev"; fi; if testtag AX_CXX_QT || testtag AX_CHECK_QT AX_REQUIRE_QT; then echo -n ", qt5-default | libqt4-core | libqtcore4, qt5-qmake | qt4-qmake, qtbase5-dev | libqt4-dev, qtbase5-dev-tools | qt4-dev-tools, qttools5-dev-tools | qt4-dev-tools, qttools5-dev-tools | qt4-dev-tools"; fi)"
to debian/control.in <<EOF
Source: @PACKAGE_NAME@
Priority: extra
@ -975,10 +1171,17 @@ else
fi)
Source0: %{name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
BuildRequires: gnupg, ${VCSDEPENDS} automake, autoconf$(
BuildRequires: gnupg, ${VCSDEPENDS} make, automake, autoconf, rpm-build$(
if testtag AX_USE_DOXYGEN; then
echo -n ", doxygen";
fi)
fi
if testtag AX_USE_PERLDOC; then
echo -n ", libpod-tree-perl";
fi
if testtag AX_USE_PLANTUML; then
echo -n ", default-jre-headless";
fi
)
%if 0%{?fedora} != 20
$(if testtag AX_USE_DOXYGEN; then echo -n "BuildRequires: graphviz"; fi)
%endif
@ -1089,7 +1292,7 @@ fi
if testtag AX_USE_SCRIPTS; then
SUBDIRS="${SUBDIRS} scripts"
fi
if testtag AX_USE_DOXYGEN; then
if testtag 'AX_USE_DOXYGEN|AX_USE_PERLDOC'; then
SUBDIRS="${SUBDIRS} doc"
fi
if testtag AX_BUILD_EXAMPLES; then
@ -1103,13 +1306,26 @@ for d in src test scripts doc examples html; do
SUBDIRS="${SUBDIRS} $d"
fi
done
to --mode "u=rwx,g=rwx,o=rx" autogen.sh <<EOF
#!/bin/bash -e
if test -n "$VCS" -a -d .$VCS -a -e -x $(which ${VCS}2cl); then
$(case "$VCS" in
(svn) echo " ${VCS}2cl";;
(git) echo " ${VCS}2cl > ChangeLog";;
esac)
fi
aclocal
$(if testtag AX_USE_LIBTOOL; then echo libtoolize --force; fi)
automake -a
autoconf
EOF
to makefile.am<<EOF
${HEADER}SUBDIRS =${SUBDIRS}
desktopdir = \${datadir}/applications
desktop_DATA = @PACKAGE_DESKTOP@
dist_pkgdata_DATA = @PACKAGE_ICON@ ax_check_qt.m4 bootstrap.sh \\
resolve-rpmbuilddeps.sh \\
resolve-rpmbuilddeps.sh autogen.sh \\
ax_cxx_compile_stdcxx_11.m4 build-in-docker.sh \\
build-resource-file.sh \\
ax_init_standard_project.m4 \\
@ -1133,6 +1349,12 @@ Libs: -L\${libdir} -l${PACKAGE_NAME#lib} @LDFLAGS@
Cflags: -I\${includedir} @CPPFLAGS@
Requires: @PKG_REQUIREMENTS@
EOF
to build-in-docker.conf <<EOF
repos+=("Debian|Ubuntu-precise::::::universe")
repos+=("Ubuntu-precise:::'deb http://archive.ubuntu.com/ubuntu precise universe'")
envs+=("-e 'HOME=\${HOME}'")
dirs+=("-v \${HOME}/.gnupg:\${HOME}/.gnupg:ro")
EOF
#### Cleanup If Makefile Exists ####
if test -f makefile; then
@ -1148,15 +1370,15 @@ run autoconf
#### Run Configure If User Requires ####
if test "$configure" -eq 1; then
./configure $*
./configure $* || exit 1
fi
#### Run Make If User Requires ####
if test "$build" -eq 1; then
make $buildtarget
make $buildtarget || exit 1
fi
#### Build In Docker If User Requires ####
if test "$docker" -eq 1; then
./build-in-docker.sh
./build-in-docker.sh || exit 1
fi

@ -2,6 +2,7 @@
set -o errtrace
# build and test everything in a fresh docker installation
mode="apt"
img="ubuntu:latest"
repos=()
keys=()
@ -24,6 +25,7 @@ while test $# -gt 0; do
echo "OPTIONS:"
echo
echo " -h, --help show this help"
echo " -m, --mode <type> mode: apt or yum, default: ${mode}"
echo " -i, --image <image> use given docker image instead of ${img}"
echo " -t, --targets targets specify build targets, default: ${targets}"
echo " -r, --repo <url> add given apt repository"
@ -34,6 +36,8 @@ while test $# -gt 0; do
echo " -c, --cmd <command> execute commands as root in docker"
echo " -w, --wait on error keep docker container and wait for enter"
echo
echo " The option -i must be after -m, because mode sets a new default image"
echo
echo " The options -r -k -e -d -p -c can be repeated several times."
echo
echo " The options -r -p -c allow an if-then-else contruct"
@ -60,6 +64,17 @@ while test $# -gt 0; do
echo
exit 0
;;
(-m|--mode) shift;
mode="$1"
case "$mode" in
(apt) img="ubuntu:latest";;
(yum) img="centos:latest";;
(*)
echo "**** ERROR: unknown mode '$1', try --help" 1>&2
exit 1
;;
esac
;;
(-i|--image) shift;
img="$1"
;;
@ -167,34 +182,56 @@ function ifthenelse() {
set -x
OPTIONS='-o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confnew -y --force-yes --no-install-suggests --no-install-recommends'
docker pull $img
DOCKER_ID=$(docker run -d ${dirs[@]} ${envs[@]} -w /workdir $img sleep infinity)
DOCKER_ID=$(docker run -d ${dirs[@]} ${envs[@]} -e HOME="${HOME}" -w /workdir $img sleep infinity)
trap 'traperror '"${DOCKER_ID}"' "$? ${PIPESTATUS[@]}" $LINENO $BASH_LINENO "$BASH_COMMAND" "${FUNCNAME[@]}" "${FUNCTION}"' SIGINT INT TERM EXIT
for f in 'libpam-systemd:amd64' 'policykit*' 'colord'; do
docker exec -it ${DOCKER_ID} bash -c "echo 'Package: $f' >> /etc/apt/preferences"
docker exec -it ${DOCKER_ID} bash -c "echo 'Pin-Priority: -100' >> /etc/apt/preferences"
docker exec -it ${DOCKER_ID} bash -c "echo >> /etc/apt/preferences"
done
docker exec ${DOCKER_ID} apt-get update ${OPTIONS}
docker exec ${DOCKER_ID} apt-get upgrade ${OPTIONS}
docker exec ${DOCKER_ID} apt-get install ${OPTIONS} python-software-properties software-properties-common apt-transport-https dpkg-dev lsb-release || \
docker exec ${DOCKER_ID} apt-get install ${OPTIONS} software-properties-common apt-transport-https dpkg-dev lsb-release || \
docker exec ${DOCKER_ID} apt-get install ${OPTIONS} python-software-properties apt-transport-https dpkg-dev lsb-release;
for repo in "${repos[@]}"; do
ifthenelse "${repo}" "apt-add-repository ARG"
done
for key in "${keys[@]}"; do
wget -O- "$key" \
| docker exec -i ${DOCKER_ID} apt-key add -
done
docker exec ${DOCKER_ID} apt-get update ${OPTIONS}
for package in "${packages[@]}"; do
ifthenelse "${package}" "apt-get install ${OPTIONS} ARG"
done
for command in "${commands[@]}"; do
ifthenelse "${command}" "ARG"
done
docker exec ${DOCKER_ID} ./resolve-debbuilddeps.sh
docker exec -u $(id -u) ${DOCKER_ID} test -d .svn && svn upgrade || true
docker exec -u $(id -u) ${DOCKER_ID} ./bootstrap.sh -t "${targets}"
case $mode in
(apt)
OPTIONS='-o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confnew -y --force-yes --no-install-suggests --no-install-recommends'
for f in 'libpam-systemd:amd64' 'policykit*' 'colord'; do
docker exec ${DOCKER_ID} bash -c "echo 'Package: $f' >> /etc/apt/preferences"
docker exec ${DOCKER_ID} bash -c "echo 'Pin-Priority: -100' >> /etc/apt/preferences"
docker exec ${DOCKER_ID} bash -c "echo >> /etc/apt/preferences"
done
docker exec ${DOCKER_ID} apt-get update ${OPTIONS}
docker exec ${DOCKER_ID} apt-get upgrade ${OPTIONS}
docker exec ${DOCKER_ID} apt-get install ${OPTIONS} python-software-properties software-properties-common apt-transport-https dpkg-dev lsb-release || \
docker exec ${DOCKER_ID} apt-get install ${OPTIONS} software-properties-common apt-transport-https dpkg-dev lsb-release || \
docker exec ${DOCKER_ID} apt-get install ${OPTIONS} python-software-properties apt-transport-https dpkg-dev lsb-release;
for repo in "${repos[@]}"; do
ifthenelse "${repo}" "apt-add-repository ARG"
done
for key in "${keys[@]}"; do
wget -O- "$key" \
| docker exec -i ${DOCKER_ID} apt-key add -
done
docker exec ${DOCKER_ID} apt-get update ${OPTIONS}
for package in "${packages[@]}"; do
ifthenelse "${package}" "apt-get install ${OPTIONS} ARG"
done
for command in "${commands[@]}"; do
ifthenelse "${command}" "ARG"
done
docker exec ${DOCKER_ID} ./resolve-debbuilddeps.sh
;;
(yum)
./bootstrap.sh -t dist
if [[ "$img" =~ "centos" ]]; then
docker exec ${DOCKER_ID} yum install -y redhat-lsb
docker exec -i ${DOCKER_ID} bash -c 'cat > /etc/yum.repos.d/wandisco-svn.repo' <<EOF
[WandiscoSVN]
name=Wandisco SVN Repo
EOF
docker exec -i ${DOCKER_ID} bash -c 'echo "baseurl=http://opensource.wandisco.com/centos/$(lsb_release -sr | sed '"'"'s,[^0-9].*,,'"'"')/svn-'$(svn --version | head -1 | sed 's,[^0-9]*\([0-9]\+\.[0-9]\+\).*,\1,')'/RPMS/$(uname -i)/" >> /etc/yum.repos.d/wandisco-svn.repo'
docker exec -i ${DOCKER_ID} bash -c 'cat >> /etc/yum.repos.d/wandisco-svn.repo' <<EOF
enabled=1
gpgcheck=0
EOF
fi
docker exec ${DOCKER_ID} yum install -y rpm-build
docker exec ${DOCKER_ID} groupadd -g $(id -g) build
docker exec ${DOCKER_ID} useradd -g $(id -g) -u $(id -u) build
docker exec ${DOCKER_ID} ./resolve-rpmbuilddeps.sh || true
;;
esac
docker exec -u $(id -u):$(id -g) ${DOCKER_ID} ./bootstrap.sh -t "${targets}"

@ -51,7 +51,7 @@ PROJECT_BRIEF = @DESCRIPTION@
# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
# to the output directory.
PROJECT_LOGO = @top_srcdir@/@PACKACE_LOGO@
PROJECT_LOGO = @top_srcdir@/@PACKAGE_LOGO@
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is

@ -0,0 +1,8 @@
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
$navpath
<li class="footer"><a href="@AUTHOR_URL@" target="_blank">@AUTHOR_NAME@</a></li>
</ul>
</div>
</body>
</html>

@ -0,0 +1,33 @@
<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen $doxygenversion"/>
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="$relpath^jquery.js"></script>
<script type="text/javascript" src="$relpath^dynsections.js"></script>
$treeview
$search
$mathjax
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
$extrastylesheet
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<div id="projecthead">
<div id="projectlogo"><img alt="" src="$relpath^$projectlogo"/></div>
<div id="projectname">$projectname</span>&#160;<span id="projectnumber">$projectnumber</div>
<div id="projectbrief">$projectbrief</div>
</div>
<nav>
<a href="@PROJECT_URL@" target="_blank">Project Management</a>
<a href="@SOURCE_DOWNLOAD@" target="_blank">Download</a>
<div>$searchbox</div>
</nav>
</div>

Binary file not shown.

@ -0,0 +1,38 @@
#titlearea {
display: flex;
justify-content: space-between;
align-items: flex-begin;
}
#titlearea nav {
padding: 0;
margin: 0;
}
#titlearea nav a {
background-color: lightgray;
border: 1px solid gray;
color: black;
padding: 1ex;
margin: 0;
}
img, object {
max-width: 100% !important;
}
@media (max-width: 50em) {
#navrow1, #navrow2 {
display: block
}
#side-nav, #splitbar, .ui-resizable-handle ui-resizable-e, .ui-resizable-handle ui-resizable-s {
display: none;
}
#doc-content {
margin-left: 0 !important;
}
}
@media (min-width: 50em) {
#navrow1, #navrow2 {
display: none;
}
#side-nav, #splitbar, .ui-resizable-handle ui-resizable-e, .ui-resizable-handle ui-resizable-s {
display: block
}
}

@ -0,0 +1,9 @@
## @id $Id$
## 1 2 3 4 5 6 7 8
## 45678901234567890123456789012345678901234567890123456789012345678901234567890
%.gcda: %
gcov $<
CLEANFILES += ${CLEANFILES} ${TEST:%=%.gcno} ${TEST:%=%.gcda} *.gcov

@ -1,69 +1,49 @@
module.exports = function(config) {
const crypto = require('crypto');
const password = crypto.randomBytes(256);
var cookie = require('cookie-encryption');
// const cipher = crypto.createCipher('aes256', password);
// const decipher = crypto.createDecipher('aes256', password);
// var encrypted = cipher.update(JSON.stringify(user), 'utf8', 'base64')
// + cipher.final('base64');
// console.log("encrypted", encrypted);
// var decrypted = decipher.update(encrypted, 'base64', 'utf8') + decipher.final('utf8');
// console.log("decrypted", decrypted);
var authentication = function (req, res, next) {
return next();
}
if (config) {
var cipher = config.cookies && config.cookies.cipher ? config.cookies.cipher : "aes256";
authentication = function (username, password, success, fail) {
authentication = function (req, res, next) {
function unauthorized(res) {
res.setHeader('WWW-Authenticate', 'Basic realm=Authorization Required');
res.status(401).send('Not logged in. <a href="/">Login</a>');
};
var user = require('basic-auth')(req);
var vault = cookie('credentials');
if (!user || !user.name || !user.pass) {
return unauthorized(res);
};
if (config.passwords && config.passwords[user.name]) {
if (crypto.getHashes().indexOf(config.passwords[user.name][0])>=0) {
if (crypto.createHash(config.passwords[user.name][0])
.update(user.pass, 'utf8').digest('hex') === config.passwords[user.name][1]) {
return next();
if (config) {
const crypto = require('crypto');
if (config.passwords && config.passwords[username]) {
if (crypto.getHashes().indexOf(config.passwords[username][0])>=0) {
if (crypto.createHash(config.passwords[username][0]).update(password, 'utf8').digest('hex') === config.passwords[username][1]) {
success();
return;
} else {
fail();
return;
}
} else {
console.log("**** HASH NOT FOUND ****");
console.log(config.passwords[user.name][0]);
console.log(config.passwords[username][0]);
console.log(crypto.getHashes());
fail();
return;
}
}
if (config.ldap) try {
var LdapAuth = require('ldapauth');
var auth = new LdapAuth(config.ldap);
auth.authenticate(user.name, user.pass, function(err, usr) {
auth.authenticate(username, password, function(err, usr) {
auth.close(function(err) {})
if (err) {
console.log("**** ERROR: LDAP Authentication failed:", err);
return unauthorized(res);
fail();
return;
}
console.log("**** SUCCESS: LDAP Authentication:");
return next();
success();
return;
});
return; // need to block here!
} catch (e) {
console.log("**** Error: LDAP failed: ", e, e.stack);
fail();
return;
}
return unauthorized(res);
};
}
fail();
return;
}
return authentication;

@ -1,9 +1,6 @@
{
"port": 8888,
"restrict": {
"cookies": {
"cipher": "aes256"
},
"passwords": {
"marc": ["sha256", "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"],
"foo": ["sha256", "fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9"]

@ -1,33 +1,31 @@
{
"name": "@PACKAGE_NAME@",
"version": "@PACKAGE_VERSION@",
"private": true,
"description": "Docker as a Service",
"main": "servicedock.js",
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Marc Wäckerlin",
"license": "LGPL3",
"path": {
"prefix": "@PREFIX@",
"sysconf": "@SYSCONFDIR@",
"pkgdata": "@PKGDATADIR@",
"localstate": "@LOCALSTATEDIR@",
"log": "@LOCALSTATEDIR@/log/@PACKAGE_NAME@.log",
"config": "@SYSCONFDIR@/@PACKAGE_NAME@.json",
"nodejs": "@PKGDATADIR@/nodejs"
},
"dependencies": {
"express": "~2.5.8",
"stylus": "~0.53.0",
"ejs": ">= 0.0.1",
"socket.io": "~1.4.4",
"pty.js": "~0.3.0",
"async": "~1.5.2",
"basic-auth": "~1.0.3",
"ldapauth": "~2.2.4",
"cookie-encryption": "~1.4.2"
}
"name": "@PACKAGE_NAME@",
"version": "@PACKAGE_VERSION@",
"private": true,
"dependencies": {
"express": "~2.5.8",
"stylus": "~0.53.0",
"ejs": ">= 0.0.1",
"socket.io": "~1.4.4",
"pty.js": "~0.3.0",
"async": "~1.5.2",
"socketio-auth": "0.0.5"
},
"description": "@DESCRIPTION@",
"main": "@PACKAGE_NAME@.js",
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "@AUTHOR@",
"license": "@LICENSE@",
"path": {
"prefix": "@PREFIX@",
"sysconf": "@SYSCONFDIR@",
"pkgdata": "@PKGDATADIR@",
"localstate": "@LOCALSTATEDIR@",
"log": "@LOCALSTATEDIR@/log/@PACKAGE_NAME@.log",
"config": "@SYSCONFDIR@/@PACKAGE_NAME@.json",
"nodejs": "@PKGDATADIR@/nodejs"
}
}

@ -1,10 +1,10 @@
/*! @file
@id $Id$
@id $Id$
This is the main application as it is fully run in the user's browser.
This is the main application as it is fully run in the user's browser.
*/
*/
// 1 2 3 4 5 6 7 8
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
@ -14,225 +14,247 @@ var focused = null;
var docker = new Docker();
function htmlenc(html) {
return $('<div/>').text(html).html();
return $('<div/>').text(html).html();
}
function htmldec(data) {
return $('<div/>').html(data).text();
return $('<div/>').html(data).text();
}
/// Show error messsage
/** Fades in an error message and logs to console.
@param data (optional) The error can be a string or any structure.
Strings are shown to the user, structures are logged only.
@param stay (optional) If not given as @c true, reloads page after 5s. */
@param data (optional) The error can be a string or any structure.
Strings are shown to the user, structures are logged only.
@param stay (optional) If not given as @c true, reloads page after 5s. */
function error(data) {
$("#status").fadeOut("slow", function() {
$("#status").addClass("error")
$("#status").removeClass("notice")
$("#status").removeClass("success")
if (data) {
if (typeof data == 'string') {
$("#status").html(data);
console.log("error: "+data);
} else {
$("#status").html('unknown error: '+JSON.stringify(data));
console.log("error: ", data);
console.log((new Error('stacktrace')));
}
} else {
$("#status").html('error');
console.log("error");
}
$("#status").fadeIn("slow");
});
$("#status").fadeOut("slow", function() {
$("#status").addClass("error")
$("#status").removeClass("notice")
$("#status").removeClass("success")
if (data) {
if (typeof data == 'string') {
$("#status").html(data);
console.log("error: "+data);
} else {
$("#status").html('unknown error: '+JSON.stringify(data));
console.log("error: ", data);
console.log((new Error('stacktrace')));
}
} else {
$("#status").html('error');
console.log("error");
}
$("#status").fadeIn("slow");
});
}
/// Show notice messsage
/** Fades in an notice message and logs to console.
@param text (optional) The data is a string. */
@param text (optional) The data is a string. */
function notice(text) {
$("#status").fadeOut("slow", function() {
$("#status").addClass("notice")
$("#status").removeClass("error")
$("#status").removeClass("success")
if (text) {
$("#status").html(text);
console.log("notice: "+text);
} else {
$("#status").html('');
console.log("notice");
}
$("#status").fadeIn("slow");
});
$("#status").fadeOut("slow", function() {
$("#status").addClass("notice")
$("#status").removeClass("error")
$("#status").removeClass("success")
if (text) {
$("#status").html(text);
console.log("notice: "+text);
} else {
$("#status").html('');
console.log("notice");
}
$("#status").fadeIn("slow");
});
}
/// Show notice messsage
/** Fades in an success message and logs to console.
@param text (optional) The data is a string. */
@param text (optional) The data is a string. */
function success(text) {
$("#status").fadeOut("slow", function() {
$("#status").addClass("success")
$("#status").removeClass("error")
$("#status").removeClass("notice")
if (text) {
$("#status").html(text);
console.log("success: "+text);
} else {
$("#status").html('');
console.log("success");
}
$("#status").fadeIn("slow");
});
$("#status").fadeOut("slow", function() {
$("#status").addClass("success")
$("#status").removeClass("error")
$("#status").removeClass("notice")
if (text) {
$("#status").html(text);
console.log("success: "+text);
} else {
$("#status").html('');
console.log("success");
}
$("#status").fadeIn("slow");
});
}
/// Show status message in the main screen area
/** @param text Text is a message or some complex HTML from the server.
@param msg The success message text */
@param msg The success message text */
function status(text, msg) {
$("#main").hide();
$("#main").html(text);
if (msg) success(msg);
else setTimeout("$('#status').fadeOut('slow')", 5000);
zoom(0);
stats();
$("#main").show();
$("form input:first-child").focus();
docker.containers.contextmenu("#main");
$("#main").hide();
$("#main").html(text);
if (msg) success(msg);
else setTimeout("$('#status').fadeOut('slow')", 5000);
zoom(0);
$("#main").show();
$("form input:first-child").focus();
docker.containers.contextmenu("#main");
}
function emit(signal, data) {
console.log("<-snd "+signal, data);
socket.emit(signal, data);
}
function connected() {
console.log("server connected");
$("#connectionstatus #bad").hide();
$("#connectionstatus #good").show();
success("server connected");
console.log("<-snd "+signal, data);
socket.emit(signal, data);
}
function connect() {
$("#server").html($("#username").val()+'@'+window.location.hostname)
console.log("server connect");
$("#connectionstatus #bad").hide();
$("#connectionstatus #authentication").show();
$("#connectionstatus #good").hide();
success("login to server");
socket.emit('authentication', {
username: $("#username").val(),
password: $("#password").val()
});
}
function authenticated() {
$("#server").html($("#username").val()+'@'+window.location.hostname)
console.log("server authenticated");
$("#connectionstatus #bad").hide();
$("#connectionstatus #authentication").hide();
$("#connectionstatus #good").show();
success("server connected");
start();
}
function unauthorized() {
$("#server").html($("#username").val()+'@'+window.location.hostname)
console.log("authentication failed");
$("#connectionstatus #good").hide();
$("#connectionstatus #authentication").hide();
$("#connectionstatus #bad").show();
error("authentication failed", true);
}
function disconnected() {
console.log("server disconnected");
$("#connectionstatus #good").hide();
$("#connectionstatus #bad").show();
error("server disconnected", true);
}
function connectionstatus() {
if (socket.connected) connected(); else disconnected();
$("#server").html($("#username").val()+'@'+window.location.hostname)
console.log("server disconnected");
$("#connectionstatus #good").hide();
$("#connectionstatus #authentication").hide();
$("#connectionstatus #bad").show();
error("server disconnected", true);
}
/// Toggle Menu Display
function togglemenu() {
$("#menu").toggle();
$("#menu").toggle();
}
/// Upload a configuration and send it to server
function upload(evt) {
if (!window.FileReader)
return error("your browser does not support file upload", true);
for (var i=0, f; f=evt.target.files[i]; ++i) {
var file = f;
var reader = new FileReader();
reader.onload = function(evt) {
if (evt.target.error) return error("error reading file", true);
if (evt.target.readyState==0) return notice("waiting for data …");
if (evt.target.readyState==1) return notice("loading data …");
tobecreated = JSON.parse(evt.target.result);
showCreate();
}
reader.readAsText(file);
if (!window.FileReader)
return error("your browser does not support file upload", true);
for (var i=0, f; f=evt.target.files[i]; ++i) {
var file = f;
var reader = new FileReader();
reader.onload = function(evt) {
if (evt.target.error) return error("error reading file", true);
if (evt.target.readyState==0) return notice("waiting for data …");
if (evt.target.readyState==1) return notice("loading data …");
tobecreated = JSON.parse(evt.target.result);
showCreate();
}
reader.readAsText(file);
}
}
var tobecreated = {};
function previewCreate() {
var name = $('#name').val();
var nodes = Object.create(tobecreated);
if (name != '') {
nodes[name] = {
status: docker.containers.Status.Preview,
id: null,
name: name,
image: {
name: $('#image').val(),
id: null
},
ports: $('#createports option').map(function() {return $(this).data();}).get(),
env: $('#createvars option').map(function() {return $(this).val();}).get(),
volumes: $('#createvolumes option').map(function() {return $(this).data();}).get(),
volumesfrom: $('#createvolumefroms option').map(function() {return $(this).val();}).get(),
links: $('#createlinks option').map(function() {return $(this).data();}).get(),
entrypoint: $('#createentrypoints option').map(function() {return $(this).val();}).get(),
cmd: $('#createcommands option').map(function() {return $(this).val();}).get(),
};
$('#doappend').unbind().click(function() {
tobecreated[name] = Object.create(nodes[name]);
tobecreated[name].status = docker.containers.Status.Prepared;
$('#createpreview').append('<option>'+name+'</option>');
$('#create form input[type=text]').val('');
$('#create form select.collect option').remove();
previewCreate();
});
$('#doremove').unbind().click(function() {
$(this).siblings('#createpreview').children('option:selected').each(function(a,b,c) {
delete tobecreated[b.innerHTML];
}).remove();
previewCreate();
});
$('#dosend').unbind().click(function() {
if (Object.keys(tobecreated).length>0) {
emit("create", docker.containers.configuration(tobecreated));
tobecreated = {};
showImage();
}
});
}
if ($('#image').val()!='') {
var img = docker.images.get($('#image').val());
if (img) {
$('#portintdata').empty().append(img.ports.map(function(i) {
var option = document.createElement('option');
option.value = i.replace(/\/.*/g, '');
return option;
}));
$('#varnamedata').empty().append(img.env.map(function(i) {
var option = document.createElement('option');
option.value = i.replace(/=.*/g, '');
return option;
}));
$('#varvaluedata').empty().append(img.env.map(function(i) {
var option = document.createElement('option');
option.value = i.replace(/^[^=]*=/g, '');
return option;
}));
$('#volumeextdata').empty();
$('#volumeintdata').empty();
for (i in img.volumes) {
var option = document.createElement('option');
option.value = i;
$('#volumeextdata').append(option);
$('#volumeintdata').append(option);
}
$('#volumesfromdata').empty().append(docker.containers.names(tobecreated).map(function(i) {
var option = document.createElement('option');
option.value = i;
return option;
}));
$('#linkcontainerdata').empty().append(docker.containers.names(tobecreated).map(function(i) {
var option = document.createElement('option');
option.value = i;
return option;
}));
}
var name = $('#name').val();
var nodes = Object.create(tobecreated);
if (name != '') {
nodes[name] = {
status: docker.containers.Status.Preview,
id: null,
name: name,
image: {
name: $('#image').val(),
id: null
},
ports: $('#createports option').map(function() {return $(this).data();}).get(),
env: $('#createvars option').map(function() {return $(this).val();}).get(),
volumes: $('#createvolumes option').map(function() {return $(this).data();}).get(),
volumesfrom: $('#createvolumefroms option').map(function() {return $(this).val();}).get(),
links: $('#createlinks option').map(function() {return $(this).data();}).get(),
entrypoint: $('#createentrypoints option').map(function() {return $(this).val();}).get(),
cmd: $('#createcommands option').map(function() {return $(this).val();}).get(),
};
$('#doappend').unbind().click(function() {
tobecreated[name] = Object.create(nodes[name]);
tobecreated[name].status = docker.containers.Status.Prepared;
$('#createpreview').append('<option>'+name+'</option>');
$('#create form input[type=text]').val('');
$('#create form select.collect option').remove();
previewCreate();
});
$('#doremove').unbind().click(function() {
$(this).siblings('#createpreview').children('option:selected').each(function(a,b,c) {
delete tobecreated[b.innerHTML];
}).remove();
previewCreate();
});
$('#dosend').unbind().click(function() {
if (Object.keys(tobecreated).length>0) {
emit("create", docker.containers.configuration(tobecreated));
tobecreated = {};
showImage();
}
});
}
if ($('#image').val()!='') {
var img = docker.images.get($('#image').val());
if (img) {
$('#portintdata').empty().append(img.ports.map(function(i) {
var option = document.createElement('option');
option.value = i.replace(/\/.*/g, '');
return option;
}));
$('#varnamedata').empty().append(img.env.map(function(i) {
var option = document.createElement('option');
option.value = i.replace(/=.*/g, '');
return option;
}));
$('#varvaluedata').empty().append(img.env.map(function(i) {
var option = document.createElement('option');
option.value = i.replace(/^[^=]*=/g, '');
return option;
}));
$('#volumeextdata').empty();
$('#volumeintdata').empty();
for (i in img.volumes) {
var option = document.createElement('option');
option.value = i;
$('#volumeextdata').append(option);
$('#volumeintdata').append(option);
}
$('#volumesfromdata').empty().append(docker.containers.names(tobecreated).map(function(i) {
var option = document.createElement('option');
option.value = i;
return option;
}));
$('#linkcontainerdata').empty().append(docker.containers.names(tobecreated).map(function(i) {
var option = document.createElement('option');
option.value = i;
return option;
}));
}
if (name=='' && nodes) for (name in nodes) break;
if (name && name!='') $('#preview').html(Viz("digraph {\n"+" rankdir="+rankdir+";\n"
+docker.containers.subgraph(name, nodes)
+"\n}"));
else $('#preview').html('');
}
if (name=='' && nodes) for (name in nodes) break;
if (name && name!='') $('#preview').html(Viz("digraph {\n"+" rankdir="+rankdir+";\n"
+docker.containers.subgraph(name, nodes)
+"\n}"));
else $('#preview').html('');
}
function create() {
@ -240,389 +262,401 @@ function create() {
var zoomlevel = 0;
function zoom(incr = 0) {
zoomlevel = (zoomlevel+incr)%2;
switch (zoomlevel) {
case 0: {
$("#main svg, #preview svg").css("width", "auto");
$("#main svg, #preview svg").css("height", "auto");
$("#main svg, #preview svg").css("max-width", "100%");
$("#main svg, #preview svg").css("max-height", "100%");
} break;
case 1: {
$("#main svg, #preview svg").css("width", "100%");
$("#main svg, #preview svg").css("height", "auto");
$("#main svg, #preview svg").css("max-width", "100%");
$("#main svg, #preview svg").css("max-height", "none");
} break;
case 2: {
$("#main.svg, #preview svg").css("width", "auto");
$("#main.svg, #preview svg").css("height", "100%");
$("#main.svg, #preview svg").css("max-width", "none");
$("#main.svg, #preview svg").css("max-height", "100%");
} break;
}
zoomlevel = (zoomlevel+incr)%2;
switch (zoomlevel) {
case 0: {
$("#main svg, #preview svg").css("width", "auto");
$("#main svg, #preview svg").css("height", "auto");
$("#main svg, #preview svg").css("max-width", "100%");
$("#main svg, #preview svg").css("max-height", "100%");
} break;
case 1: {
$("#main svg, #preview svg").css("width", "100%");
$("#main svg, #preview svg").css("height", "auto");
$("#main svg, #preview svg").css("max-width", "100%");
$("#main svg, #preview svg").css("max-height", "none");
} break;
case 2: {
$("#main.svg, #preview svg").css("width", "auto");
$("#main.svg, #preview svg").css("height", "100%");
$("#main.svg, #preview svg").css("max-width", "none");
$("#main.svg, #preview svg").css("max-height", "100%");
} break;
}
}
var viz = null;
var vizmore = null;
var rankdir = "LR";
function rotateviz() {
if (!viz) return;
if (rankdir == "LR")
rankdir = "TB";
else
rankdir = "LR";
showviz();
previewCreate();
if (!viz) return;
if (rankdir == "LR")
rankdir = "TB";
else
rankdir = "LR";
showviz();
previewCreate();
}
function showviz(vizpath, more) {
if (!vizpath) {
vizpath = viz;
more = vizmore;
} else {
viz = vizpath;
vizmore = more;
}
res = "digraph {\n"+" rankdir="+rankdir+";\n"+viz+"\n}";
try {
status(more?Viz(res)+more:Viz(res));
$('#main a > ellipse + text').attr('font-size', '12');
$('#main a > ellipse + text + text')
.attr('font-weight', 'bold')
.attr('font-size', '16')
.each(function() {$(this).attr('y', parseFloat($(this).attr('y'))+1.0)});
$('#main a > ellipse + text + text + text').attr('font-size', '12');
} catch(e) {
(res = res.split("\n")).forEach(function(v, i, a) {
a[i] = ("000"+(i+1)).slice(-3)+": "+v;
});
status("<h2>Exception Caught:</h2><p>"+e+"<p><pre>"+res.join("\n")+"</pre>");
}
if (!vizpath) {
vizpath = viz;
more = vizmore;
} else {
viz = vizpath;
vizmore = more;
}
res = "digraph {\n"+" rankdir="+rankdir+";\n"+viz+"\n}";
try {
status(more?Viz(res)+more:Viz(res));
$('#main a > ellipse + text').attr('font-size', '12');
$('#main a > ellipse + text + text')
.attr('font-weight', 'bold')
.attr('font-size', '16')
.each(function() {$(this).attr('y', parseFloat($(this).attr('y'))+1.0)});
$('#main a > ellipse + text + text + text').attr('font-size', '12');
} catch(e) {
(res = res.split("\n")).forEach(function(v, i, a) {
a[i] = ("000"+(i+1)).slice(-3)+": "+v;
});
status("<h2>Exception Caught:</h2><p>"+e+"<p><pre>"+res.join("\n")+"</pre>");
}
}
function details(name) {
if (name) focused = name;
else if (!focused) return overview();
showviz(docker.containers.subgraph(focused));
if (name) focused = name;
else if (!focused) return overview();
showviz(docker.containers.subgraph(focused));
}
/// Convert number of bytes to readable text
function size(num) {
if (num>0.6*1024) {
if (num>0.6*1024*1024) {
if (num>0.6*1024*1024*1024) {
if (num>0.6*1024*1024*1024*1024) {
return Math.round(num/1024/1024/1024/1024)+"TB";
} else {
return Math.round(num/1024/1024/1024)+"GB";
}
} else {
return Math.round(num/1024/1024)+"MB";
}
if (num>0.6*1024) {
if (num>0.6*1024*1024) {
if (num>0.6*1024*1024*1024) {
if (num>0.6*1024*1024*1024*1024) {
return Math.round(num/1024/1024/1024/1024)+"TB";
} else {
return Math.round(num/1024)+"kB";
return Math.round(num/1024/1024/1024)+"GB";
}
} else {
return Math.round(num/1024/1024)+"MB";
}
} else {
return num+"B";
return Math.round(num/1024)+"kB";
}
} else {
return num+"B";
}
}
var oldoldstats = null;
var oldstats = null;
function stats(data) {
console.log("->rcv stats");
if (!data && oldstats && oldoldstats) {
data = oldstats;
oldstats = oldoldstats;
}
if (oldstats) for (name in data) {
var s = data[name];
var o = oldstats[name];
if (!o|| !s) continue;
$('#main text + text:contains("'+name+'") + text')
.html('cpu: '
+(Math.round((s.cpuacct.usage.data-o.cpuacct.usage.data)
/(s.cpuacct.usage.date-o.cpuacct.usage.date)
/100)
/100)
+'% mem: '
+size(s.memory.usage_in_bytes.data));
}
oldoldstats = oldstats;
oldstats = data;
console.log("->rcv stats");
if (!data && oldstats && oldoldstats) {
data = oldstats;
oldstats = oldoldstats;
}
if (oldstats) for (name in data) {
var s = data[name];
var o = oldstats[name];
if (!o|| !s) continue;
$('#main text + text:contains("'+name+'") + text')
.html('cpu: '
+(Math.round((s.cpuacct.usage.data-o.cpuacct.usage.data)
/(s.cpuacct.usage.date-o.cpuacct.usage.date)
/100)
/100)
+'% mem: '
+size(s.memory.usage_in_bytes.data));
}
oldoldstats = oldstats;
oldstats = data;
}
function images(i) {
console.log("->rcv images");
docker.images.set(i);
$('#imagedata').empty().append(docker.images.tags().map(function(i) {
var option = document.createElement('option');
option.value = i;
return option;
}));
console.log("->rcv images");
docker.images.set(i);
$('#imagedata').empty().append(docker.images.tags().map(function(i) {
var option = document.createElement('option');
option.value = i;
return option;
}));
}
function containers(c) {
console.log("->rcv containers");
docker.containers.set(c);
if (focused && docker.containers.exists(focused))
details(focused);
else
overview();
console.log("->rcv containers");
docker.containers.set(c);
if (focused && docker.containers.exists(focused))
details(focused);
else
overview();
}
function showLogin() {
$("#close").hide();
$("#console").hide();
$("#create").hide();
$("#imagetools").hide();
$("#login").show();
$("#logs").hide();
$("#main").hide();
}
function showImage() {
$("#create").hide();
$("#logs").hide();
$("#console").hide();
$("#close").hide();
$("#imagetools").show();
$("#main").show();
$("#close").hide();
$("#console").hide();
$("#create").hide();
$("#imagetools").show();
$("#login").hide();
$("#logs").hide();
$("#main").show();
}
function showCreate() {
$("#main").hide();
$("#logs").hide();
$("#console").hide();
$("#imagetools").show();
$("#close").show();
$("#create").show();
previewCreate();
$("#close").show();
$("#console").hide();
$("#create").show();
$("#imagetools").show();
$("#login").hide();
$("#logs").hide();
$("#main").hide();
previewCreate();
}
function showConsole() {
$("#main").hide();
$("#create").hide();
$("#logs").hide();
$("#imagetools").hide();
$("#console").show();
$("#close").show();
// $("#command").focus();
// $("#command").val("");
// if ($("#screen").val()!="") $("#screen").append("\n");
$("#close").show();
$("#console").show();
$("#create").hide();
$("#imagetools").hide();
$("#login").hide();
$("#logs").hide();
$("#main").hide();
// $("#command").focus();
// $("#command").val("");
// if ($("#screen").val()!="") $("#screen").append("\n");
}
function showLogs() {
$("#main").hide();
$("#create").hide();
$("#console").hide();
$("#imagetools").hide();
$("#close").show();
$("#logs").show();
$("#close").show();
$("#console").hide();
$("#create").hide();
$("#imagetools").hide();
$("#login").hide();
$("#logs").show();
$("#main").hide();
}
function logs(data) {
console.log("->rcv logs("+data.name+")");
if (data.type=='done') {
$("#logs").append('<span class="'+data.type+'">\nDONE</span>');
} else {
$("#logs").append('<span class="'+data.type+'">'+htmlenc(data.text)+'</span>');
}
console.log("->rcv logs("+data.name+")");
if (data.type=='done') {
$("#logs").append('<span class="'+data.type+'">\nDONE</span>');
} else {
$("#logs").append('<span class="'+data.type+'">'+htmlenc(data.text)+'</span>');
}
}
function strInsert(str, pos, txt) {
return str.slice(0, pos)+txt+str.slice(pos);
return str.slice(0, pos)+txt+str.slice(pos);
}
function ansifilter(data) {
console.log("ansifilter");
var res = data;
var pos = -1;
var spans = 0;
while ((pos=res.indexOf("\x1B[")) >= 0) {
var end = res.indexOf("m", pos+2);
if (end>0) {
var control= res.slice(pos+2, end);
res = res.slice(0, pos)+res.slice(end+1);
control.split(';').forEach(function(c) {
switch (parseInt(c)) {
// set
case 1: res = strInsert(res, pos, '<span class="bold">'); ++spans; break;
case 2: res = strInsert(res, pos, '<span class="dim">'); ++spans; break;
case 4: res = strInsert(res, pos, '<span class="underlined">'); ++spans; break;
case 5: res = strInsert(res, pos, '<span class="blink">'); ++spans; break;
case 7: res = strInsert(res, pos, '<span class="reverse">'); ++spans; break;
case 8: res = strInsert(res, pos, '<span class="hidden">'); ++spans; break;
// reset
case 0: for (;spans;--spans) res = strInsert(res, pos, "</span>"); break;
case 21: if (spans) --spans; res = strInsert(res, pos, "</span>"); break;
case 22: if (spans) --spans; res = strInsert(res, pos, "</span>"); break;
case 23: if (spans) --spans; res = strInsert(res, pos, "</span>"); break;
case 25: if (spans) --spans; res = strInsert(res, pos, "</span>"); break;
case 27: if (spans) --spans; res = strInsert(res, pos, "</span>"); break;
case 28: if (spans) --spans; res = strInsert(res, pos, "</span>"); break;
// fg colors
case 39: res = strInsert(res, pos, '<span class="fgdefault">'); ++spans; break;
case 30: res = strInsert(res, pos, '<span class="fgblack">'); ++spans; break;
case 31: res = strInsert(res, pos, '<span class="fgred">'); ++spans; break;
case 32: res = strInsert(res, pos, '<span class="fggreen">'); ++spans; break;
case 33: res = strInsert(res, pos, '<span class="fgyellow">'); ++spans; break;
case 34: res = strInsert(res, pos, '<span class="fgblue">'); ++spans; break;
case 35: res = strInsert(res, pos, '<span class="fgmagenta">'); ++spans; break;
case 36: res = strInsert(res, pos, '<span class="fgcyan">'); ++spans; break;
case 37: res = strInsert(res, pos, '<span class="fglightgrey">'); ++spans; break;
case 90: res = strInsert(res, pos, '<span class="fgdarkgrey">'); ++spans; break;
case 91: res = strInsert(res, pos, '<span class="fglightred">'); ++spans; break;
case 92: res = strInsert(res, pos, '<span class="fglightgreen">'); ++spans; break;
case 93: res = strInsert(res, pos, '<span class="fglightyellow">'); ++spans; break;
case 94: res = strInsert(res, pos, '<span class="fglightblue">'); ++spans; break;
case 95: res = strInsert(res, pos, '<span class="fglightmagenta">'); ++spans; break;
case 96: res = strInsert(res, pos, '<span class="fglightcyan">'); ++spans; break;
case 97: res = strInsert(res, pos, '<span class="fgwhite">'); ++spans; break;
// bg colors
case 49: res = strInsert(res, pos, '<span class="bgdefault">'); ++spans; break;
case 40: res = strInsert(res, pos, '<span class="bgblack">'); ++spans; break;
case 41: res = strInsert(res, pos, '<span class="bgred">'); ++spans; break;
case 42: res = strInsert(res, pos, '<span class="bggreen">'); ++spans; break;
case 43: res = strInsert(res, pos, '<span class="bgyellow">'); ++spans; break;
case 44: res = strInsert(res, pos, '<span class="bgblue">'); ++spans; break;
case 45: res = strInsert(res, pos, '<span class="bgmagenta">'); ++spans; break;
case 46: res = strInsert(res, pos, '<span class="bgcyan">'); ++spans; break;
case 47: res = strInsert(res, pos, '<span class="bglightgrey">'); ++spans; break;
case 100: res = strInsert(res, pos, '<span class="bgdarkgrey">'); ++spans; break;
case 101: res = strInsert(res, pos, '<span class="bglightred">'); ++spans; break;
case 102: res = strInsert(res, pos, '<span class="bglightgreen">'); ++spans; break;
case 103: res = strInsert(res, pos, '<span class="bglightyellow">'); ++spans; break;
case 104: res = strInsert(res, pos, '<span class="bglightblue">'); ++spans; break;
case 105: res = strInsert(res, pos, '<span class="bglightmagenta">'); ++spans; break;
case 106: res = strInsert(res, pos, '<span class="bglightcyan">'); ++spans; break;
case 107: res = strInsert(res, pos, '<span class="bgwhite">'); ++spans; break;
}
});
} else {
break;
console.log("ansifilter");
var res = data;
var pos = -1;
var spans = 0;
while ((pos=res.indexOf("\x1B[")) >= 0) {
var end = res.indexOf("m", pos+2);
if (end>0) {
var control= res.slice(pos+2, end);
res = res.slice(0, pos)+res.slice(end+1);
control.split(';').forEach(function(c) {
switch (parseInt(c)) {
// set
case 1: res = strInsert(res, pos, '<span class="bold">'); ++spans; break;
case 2: res = strInsert(res, pos, '<span class="dim">'); ++spans; break;
case 4: res = strInsert(res, pos, '<span class="underlined">'); ++spans; break;
case 5: res = strInsert(res, pos, '<span class="blink">'); ++spans; break;
case 7: res = strInsert(res, pos, '<span class="reverse">'); ++spans; break;
case 8: res = strInsert(res, pos, '<span class="hidden">'); ++spans; break;
// reset
case 0: for (;spans;--spans) res = strInsert(res, pos, "</span>"); break;
case 21: if (spans) --spans; res = strInsert(res, pos, "</span>"); break;
case 22: if (spans) --spans; res = strInsert(res, pos, "</span>"); break;
case 23: if (spans) --spans; res = strInsert(res, pos, "</span>"); break;
case 25: if (spans) --spans; res = strInsert(res, pos, "</span>"); break;
case 27: if (spans) --spans; res = strInsert(res, pos, "</span>"); break;
case 28: if (spans) --spans; res = strInsert(res, pos, "</span>"); break;
// fg colors
case 39: res = strInsert(res, pos, '<span class="fgdefault">'); ++spans; break;
case 30: res = strInsert(res, pos, '<span class="fgblack">'); ++spans; break;
case 31: res = strInsert(res, pos, '<span class="fgred">'); ++spans; break;
case 32: res = strInsert(res, pos, '<span class="fggreen">'); ++spans; break;
case 33: res = strInsert(res, pos, '<span class="fgyellow">'); ++spans; break;
case 34: res = strInsert(res, pos, '<span class="fgblue">'); ++spans; break;
case 35: res = strInsert(res, pos, '<span class="fgmagenta">'); ++spans; break;
case 36: res = strInsert(res, pos, '<span class="fgcyan">'); ++spans; break;
case 37: res = strInsert(res, pos, '<span class="fglightgrey">'); ++spans; break;
case 90: res = strInsert(res, pos, '<span class="fgdarkgrey">'); ++spans; break;
case 91: res = strInsert(res, pos, '<span class="fglightred">'); ++spans; break;
case 92: res = strInsert(res, pos, '<span class="fglightgreen">'); ++spans; break;
case 93: res = strInsert(res, pos, '<span class="fglightyellow">'); ++spans; break;
case 94: res = strInsert(res, pos, '<span class="fglightblue">'); ++spans; break;
case 95: res = strInsert(res, pos, '<span class="fglightmagenta">'); ++spans; break;
case 96: res = strInsert(res, pos, '<span class="fglightcyan">'); ++spans; break;
case 97: res = strInsert(res, pos, '<span class="fgwhite">'); ++spans; break;
// bg colors
case 49: res = strInsert(res, pos, '<span class="bgdefault">'); ++spans; break;
case 40: res = strInsert(res, pos, '<span class="bgblack">'); ++spans; break;
case 41: res = strInsert(res, pos, '<span class="bgred">'); ++spans; break;
case 42: res = strInsert(res, pos, '<span class="bggreen">'); ++spans; break;
case 43: res = strInsert(res, pos, '<span class="bgyellow">'); ++spans; break;
case 44: res = strInsert(res, pos, '<span class="bgblue">'); ++spans; break;
case 45: res = strInsert(res, pos, '<span class="bgmagenta">'); ++spans; break;
case 46: res = strInsert(res, pos, '<span class="bgcyan">'); ++spans; break;
case 47: res = strInsert(res, pos, '<span class="bglightgrey">'); ++spans; break;
case 100: res = strInsert(res, pos, '<span class="bgdarkgrey">'); ++spans; break;
case 101: res = strInsert(res, pos, '<span class="bglightred">'); ++spans; break;
case 102: res = strInsert(res, pos, '<span class="bglightgreen">'); ++spans; break;
case 103: res = strInsert(res, pos, '<span class="bglightyellow">'); ++spans; break;
case 104: res = strInsert(res, pos, '<span class="bglightblue">'); ++spans; break;
case 105: res = strInsert(res, pos, '<span class="bglightmagenta">'); ++spans; break;
case 106: res = strInsert(res, pos, '<span class="bglightcyan">'); ++spans; break;
case 107: res = strInsert(res, pos, '<span class="bgwhite">'); ++spans; break;
}
});
} else {
break;
}
for (;spans;--spans) res += "</span>";
console.log(res);
return res.replace(/\r\r\n/g, '\n');
}
for (;spans;--spans) res += "</span>";
console.log(res);
return res.replace(/\r\r\n/g, '\n');
}
function ascii(txt) {
var res = "";
for (i=0; i<txt.length; ++i) {
if (res) res += ",";
res += txt.charCodeAt(i).toString();
}
return res;
var res = "";
for (i=0; i<txt.length; ++i) {
if (res) res += ",";
res += txt.charCodeAt(i).toString();
}
return res;
}
function bash_data(data) {
console.log("->rcv bash-data("+data.name+")", data);
if (data.type=='done') {
$("#screen").append('<span class="'+data.type+'">\nDONE</span>');
} else {
var buff = "";
console.log("ASCII: ", ascii(data.text));
for (var i=0; i<data.text.length; ++i) {
switch (data.text.charCodeAt(i)) {
case 7:
case 8:
if (buff.length) $("#screen").append(ansifilter(htmlenc(buff)));
buff = "";
$('#screen').html(function (_,txt) {
return txt.slice(0, -1);
});
break;
default: buff += data.text[i];
}
}
if (buff.length) $("#screen").append(ansifilter(htmlenc(buff)));
console.log("->rcv bash-data("+data.name+")", data);
if (data.type=='done') {
$("#screen").append('<span class="'+data.type+'">\nDONE</span>');
} else {
var buff = "";
console.log("ASCII: ", ascii(data.text));
for (var i=0; i<data.text.length; ++i) {
switch (data.text.charCodeAt(i)) {
case 7:
case 8:
if (buff.length) $("#screen").append(ansifilter(htmlenc(buff)));
buff = "";
$('#screen').html(function (_,txt) {
return txt.slice(0, -1);
});
break;
default: buff += data.text[i];
}
}
$("#screen").animate({
scrollTop: $("#screen").prop('scrollHeight')
}, 500);
$("#screen").focus();
if (buff.length) $("#screen").append(ansifilter(htmlenc(buff)));
}
$("#screen").animate({
scrollTop: $("#screen").prop('scrollHeight')
}, 500);
$("#screen").focus();
}
function overview() {
focused = null;
showviz(docker.containers.graph());
focused = null;
showviz(docker.containers.graph());
}
/// Initial Function: Startup
/** Decide whether to login or to create a new user */
/** To be called after login */
function start() {
$("#imagetools").hide();
$("#close").hide();
$("#popup").hide();
$("#menu").hide();
$("#username").html(window.location.hostname)
try {
status("Starting up ...");
emit("images");
emit("containers");
showImage();
} catch (m) {
error(m);
}
$("#imagetools").hide();
$("#close").hide();
$("#popup").hide();
$("#menu").hide();
try {
status("Starting up ...");
emit("images");
emit("containers");
showImage();
} catch (m) {
error(m);
}
}
function initForms() {
$('#create form *').change(previewCreate);
$("#create form fieldset .add").unbind().click(function() {
$(this).siblings("select.collect")
.append('<option '+$(this).siblings("input")
.map(function() {
if (this.hasAttribute('data-name')) {
var res = "";
var obj = this;
this.getAttribute('data-name').split(' ').forEach(function(n) {
res += 'data-'+n+'="'+
(obj.type!='checkbox'||obj.checked
$('#create form *').change(previewCreate);
$("#create form fieldset .add").unbind().click(function() {
$(this).siblings("select.collect")
.append('<option '+$(this).siblings("input")
.map(function() {
if (this.hasAttribute('data-name')) {
var res = "";
var obj = this;
this.getAttribute('data-name').split(' ').forEach(function(n) {
res += 'data-'+n+'="'+
(obj.type!='checkbox'||obj.checked
?obj.value:obj.getAttribute('data-false'))
.replace(/&/g, '&amp;')
.replace(/"/g, '&quot;')
+'"';
})
return res;
} else return '';
}).get().join(' ')+'>'+$(this).siblings("input")
.map(function() {
var val = this.value;
var sep = this.getAttribute('data-separator') || '';
if (this.type=='checkbox' && !this.checked) {
val=''; sep=''
}
return sep+val;
}).get().join('')+'</option>');
$(this).siblings("input[type=text]").val('');
previewCreate();
});
$("#create form fieldset .remove").unbind().click(function() {
$(this).siblings('select.collect').children('option:selected').remove();
previewCreate();
});
.replace(/&/g, '&amp;')
.replace(/"/g, '&quot;')
+'"';
})
return res;
} else return '';
}).get().join(' ')+'>'+$(this).siblings("input")
.map(function() {
var val = this.value;
var sep = this.getAttribute('data-separator') || '';
if (this.type=='checkbox' && !this.checked) {
val=''; sep=''
}
return sep+val;
}).get().join('')+'</option>');
$(this).siblings("input[type=text]").val('');
previewCreate();
});
$("#create form fieldset .remove").unbind().click(function() {
$(this).siblings('select.collect').children('option:selected').remove();
previewCreate();
});
}
function init() {
$("#logout").attr("href",
window.location.protocol+"//X:X@"
+window.location.hostname
+(window.location.port?":":"")+window.location.port
+window.location.pathname);
socket = io.connect();
socket.io
.on("connect", connected)
.on("reconnect", connected)
.on("disconnect", disconnected)
.on("error", disconnected);
socket
.on("fail", error)
.on("containers", containers)
.on("images", images)
.on("stats", stats)
.on("logs", logs)
.on("bash-data", bash_data);
initForms();
start();
socket = io.connect();
socket
.io
.on("connect", connect)
.on("reconnect", connect)
.on("disconnect", disconnected)
.on("error", disconnected);
socket
.on("authenticated", authenticated)
.on("unauthorized", unauthorized)
.on("fail", error)
.on("containers", containers)
.on("images", images)
.on("stats", stats)
.on("logs", logs)
.on("bash-data", bash_data);
$("#server").html($("#username").value+'@'+window.location.hostname)
initForms();
showLogin();
}
/// On Load, Call @ref start
/*
$(window.onbeforeunload = function() {
return "Are you sure you want to navigate away?";
});
$(window.onbeforeunload = function() {
return "Are you sure you want to navigate away?";
});
*/
$(init);

@ -156,6 +156,7 @@ table.docker li+li {
#statusbar {
position: fixed;
width: 100%;
left: 0;
right: 0;
bottom: 0;
@ -163,8 +164,22 @@ table.docker li+li {
padding: 0 1em 0 1em;
color: white;
}
#status: {
float: right;
#status {
position: fixed;
right: 0;
bottom: 0;
margin: 0 1em 0 1em;
padding: 0 1em 0 1em;
}
#good {
color: green;
}
#authentication {
color: yellow;
}
#bad {
color: red;
}
@media (max-width: 45em) {
#username {
@ -234,7 +249,7 @@ table.docker li+li {
background-color: #777;
}
#main, #logs, #console, #create {
#main, #logs, #console, #create, #login {
position: fixed;
top: 1.5em;
left: 0;
@ -246,7 +261,7 @@ table.docker li+li {
bottom: 1.5em;
}
#main, #create {
#main, #create, #login {
background-color: white;
}

@ -1,69 +1,69 @@
try {
process.on('uncaughtException', function(e) {
console.log("**** UNCAUGHT EXCEPTION ****");
console.log(e);
console.log(e.stack);
process.exit(1);
});
/**
* Module dependencies.
*/
process.on('uncaughtException', function(e) {
console.log("**** UNCAUGHT EXCEPTION ****");
console.log(e);
console.log(e.stack);
process.exit(1);
});
/**
* Module dependencies.
*/
var express = require('express')
var express = require('express')
, routes = require(__dirname+'/routes');
var app = module.exports = express.createServer();
var io = require('socket.io').listen(app);
var sockets = require(__dirname+'/sockets')(io);
var package = require(__dirname+'/package.json');
var config = require(package.path.config);
var docker = require(__dirname+'/docker')(app);
var authentication = require(__dirname+'/authentication')(config.restrict);
var app = module.exports = express.createServer();
var io = require('socket.io').listen(app);
var package = require(__dirname+'/package.json');
var config = require(package.path.config);
var docker = require(__dirname+'/docker')(app);
//var authentication = require(__dirname+'/authentication')(config.restrict);
var sockets = require(__dirname+'/sockets')(io);
// Configuration
process.argv.forEach(function(val, index) {
if (index<2) {return}
if (index!=2 || typeof val != 'number') {
console.log("**** ERROR: Unexpected Argument - allowed is only a port number");
process.exit(1);
}
config.port = val;
});
if (typeof config.port != 'number') {
console.log("**** WARNING: no valid port given, defaults to 8888");
config.port = 8888;
// Configuration
process.argv.forEach(function(val, index) {
if (index<2) {return}
if (index!=2 || isNaN(val)) {
console.log("**** ERROR: Unexpected Argument - allowed is only a port number");
process.exit(1);
}
config.port = parseInt(val);
});
if (typeof config.port != 'number') {
console.log("**** WARNING: no valid port given, defaults to 8888");
config.port = 8888;
}
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(require('stylus').middleware({ src: __dirname + '/public' }));
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(require('stylus').middleware({ src: __dirname + '/public' }));
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// Routes
app.get('/', authentication, routes.index);
// Routes
app.get('/', routes.index);
app.listen(config.port, function() {
console.log("Express server listening on port %d in %s mode",
app.address().port, app.settings.env);
});
app.listen(config.port, function() {
console.log("Express server listening on port %d in %s mode",
app.address().port, app.settings.env);
});
} catch (e) {
console.log("**** EXCEPTION ****");
console.log(e);
console.log(e.stack);
process.exit(1);
console.log("**** EXCEPTION ****");
console.log(e);
console.log(e.stack);
process.exit(1);
}

@ -1,298 +1,311 @@
module.exports = function(io) {
var pty = require('pty.js');
var proc = require('child_process');
var docker = require(__dirname+'/../docker')();
var pty = require('pty.js');
var proc = require('child_process');
var docker = require(__dirname+'/../docker')();
var module={};
var idtoname = {};
function broadcast(signal, data) {
console.log("<= signal: "+signal);
io.sockets.emit(signal, data);
var module={};
var idtoname = {};
function broadcast(signal, data) {
console.log("<= signal: "+signal);
io.sockets.emit(signal, data);
}
function exec(cmd, callback) {
if (cmd.length>40) {
console.log("== "+cmd.slice(0, 30+cmd.slice(30).indexOf(' '))+" ...");
} else {
console.log("== "+cmd);
}
proc.exec(cmd, {maxBuffer: 10*1024*1024}, callback);
}
function fail(txt, data) {
console.log("** "+txt, data);
}
var oldcontainer = null;
function containerinspect(error, stdout, stderr) {
if (error || stderr)
return fail("inspect docker containers failed", {
error: error, stderr: stderr, stdout: stdout
});
idtoname = {};
JSON.parse(stdout).forEach(function(n) {
if (n.State.Running) idtoname[n.Id] = n.Name.replace(/^\//, '');
});
if (oldcontainer && oldcontainer==stdout) return; // do not resend same containers
oldcontainer = stdout;
broadcast("containers", stdout);
}
function containerlist(error, stdout, stderr) {
if (error || stderr)
return fail("list docker containers failed", {
error: error, stderr: stderr, stdout: stdout
});
exec("docker inspect "+stdout.trim().replace(/\n/g, " "), containerinspect);
}
function updatecontainers(error, stdout, stderr) {
if (error || stderr)
return fail("update docker container failed", {
error: error, stderr: stderr, stdout: stdout
});
exec("docker ps -aq --no-trunc ", containerlist);
}
var oldimage = null;
function imageinspect(error, stdout, stderr) {
if (error || stderr)
return fail("inspect docker images failed", {
error: error, stderr: stderr, stdout: stdout
});
if (oldimage && oldimage==stdout) return; // do not resend same images
oldimage = stdout;
broadcast("images", stdout);
}
function imagelist(error, stdout, stderr) {
if (error || stderr)
return fail("list docker images failed", {
error: error, stderr: stderr, stdout: stdout
});
exec("docker inspect "+stdout.trim().replace(/\n/g, " "),
imageinspect);
}
function updateimages(error, stdout, stderr) {
if (error || stderr)
return fail("update docker images failed", {
error: error, stderr: stderr, stdout: stdout
});
exec("docker images -q --no-trunc", imagelist);
}
function connection(socket, userdata) {
function exec(cmd, callback) {
if (cmd.length>40) {
console.log("== "+cmd.slice(0, 30+cmd.slice(30).indexOf(' '))+" ...");
} else {
console.log("== "+cmd);
}
proc.exec(cmd, {maxBuffer: 10*1024*1024}, callback);
console.log("=> new connection from "+userdata.username);
function emit(signal, data, info) {
if (typeof data == 'string' && !data.match("\n")) {
console.log("<- signal: "+signal+"("+data+")");
} else {
console.log("<- signal: "+signal);
}
if (info) console.log(info);
socket.emit(signal, data);
}
function fail(txt, data) {
console.log("** "+txt, data);
console.log("** "+txt, data);
emit("fail", txt);
}
var oldcontainer = null;
function containerinspect(error, stdout, stderr) {
if (error || stderr)
return fail("inspect docker containers failed", {
error: error, stderr: stderr, stdout: stdout
});
idtoname = {};
JSON.parse(stdout).forEach(function(n) {
if (n.State.Running) idtoname[n.Id] = n.Name.replace(/^\//, '');
});
if (oldcontainer && oldcontainer==stdout) return; // do not resend same containers
oldcontainer = stdout;
broadcast("containers", stdout);
}
function containerlist(error, stdout, stderr) {
if (error || stderr)
return fail("list docker containers failed", {
error: error, stderr: stderr, stdout: stdout
});
exec("docker inspect "+stdout.trim().replace(/\n/g, " "), containerinspect);
function modify(cmd, name) {
if (!name.match(/^[a-z0-9][-_:.+a-z0-9]*$/i))
return this.fail("illegal instance name");
exec("docker "+cmd+" "+name, updatecontainers);
}
function updatecontainers(error, stdout, stderr) {
if (error || stderr)
return fail("update docker container failed", {
error: error, stderr: stderr, stdout: stdout
function createContainer(cmds) {
if (cmds.length>0)
exec(cmds.shift(), function(error, stdout, stderr) {
if (error || stderr)
return this.fail("create container failed", {
error: error, stderr: stderr, stdout: stdout
});
exec("docker ps -aq --no-trunc ", containerlist);
createContainer(cmds);
})
else
updatecontainers();
}
var oldimage = null;
function imageinspect(error, stdout, stderr) {
if (error || stderr)
return fail("inspect docker images failed", {
error: error, stderr: stderr, stdout: stdout
});
if (oldimage && oldimage==stdout) return; // do not resend same images
oldimage = stdout;
broadcast("images", stdout);
function containers() {
console.log("-> containers");
if (oldcontainer) emit("containers", oldcontainer);
else updatecontainers();
}
function imagelist(error, stdout, stderr) {
if (error || stderr)
return fail("list docker images failed", {
error: error, stderr: stderr, stdout: stdout
});
exec("docker inspect "+stdout.trim().replace(/\n/g, " "),
imageinspect);
function images() {
console.log("-> images");
if (oldimage) emit("images", oldimage);
else updateimages();
}
function updateimages(error, stdout, stderr) {
if (error || stderr)
return fail("update docker images failed", {
error: error, stderr: stderr, stdout: stdout
});
exec("docker images -q --no-trunc", imagelist);
}
function connection(socket) {
console.log("new connection");
function emit(signal, data, info) {
if (typeof data == 'string' && !data.match("\n")) {
console.log("<- signal: "+signal+"("+data+")");
} else {
console.log("<- signal: "+signal);
}
if (info) console.log(info);
socket.emit(signal, data);
}
function fail(txt, data) {
console.log("** "+txt, data);
emit("fail", txt);
}
function modify(cmd, name) {
if (!name.match(/^[a-z0-9][-_:.+a-z0-9]*$/i))
return this.fail("illegal instance name");
exec("docker "+cmd+" "+name, updatecontainers);
}
function createContainer(cmds) {
if (cmds.length>0)
exec(cmds.shift(), function(error, stdout, stderr) {
if (error || stderr)
return this.fail("create container failed", {
error: error, stderr: stderr, stdout: stdout
});
createContainer(cmds);
})
else
updatecontainers();
}
function containers() {
console.log("-> containers");
if (oldcontainer) emit("containers", oldcontainer);
else updatecontainers();
}
function images() {
console.log("-> images");
if (oldimage) emit("images", oldimage);
else updateimages();
}
function start(name) {
console.log("-> start("+name+")");
modify("start", name);
}
function start(name) {
console.log("-> start("+name+")");
modify("start", name);
}
function stop(name) {
console.log("-> stop("+name+")");
modify("stop", name);
}
function stop(name) {
console.log("-> stop("+name+")");
modify("stop", name);
}
function pause(name) {
console.log("-> pause("+name+")");
modify("pause", name);
}
function pause(name) {
console.log("-> pause("+name+")");
modify("pause", name);
}
function unpause(name) {
console.log("-> unpause("+name+")");
modify("unpause", name);
}
function unpause(name) {
console.log("-> unpause("+name+")");
modify("unpause", name);
}
function remove(name) {
console.log("-> remove("+name+")");
modify("rm", name);
}
function remove(name) {
console.log("-> remove("+name+")");
modify("rm", name);
}
function create(data) {
console.log("-> create");
var d = new docker.Docker();
var dc = new d.Containers();
createContainer(dc.creation(data));
}
function create(data) {
console.log("-> create");
var d = new docker.Docker();
var dc = new d.Containers();
createContainer(dc.creation(data));
}
function logs(name) {
console.log("-> logs("+name+")");
var l = proc.spawn("docker", ["logs", "-f", name])
.on('close', function(code) {
function logs(name) {
console.log("-> logs("+name+")");
var l = proc.spawn("docker", ["logs", "-f", name])
.on('close', function(code) {
emit('logs', {name: name, type: 'done'});
});
l.stdout.on('data', function(data) {
emit('logs', {name: name, type: 'stdout', text: data.toString()});
});
l.stderr.on('data', function(data) {
emit('logs', {name: name, type: 'stderr', text: data.toString()});
});
}
});
l.stdout.on('data', function(data) {
emit('logs', {name: name, type: 'stdout', text: data.toString()});
});
l.stderr.on('data', function(data) {
emit('logs', {name: name, type: 'stderr', text: data.toString()});
});
}
var bash_connections = {};
var bash_connections = {};
function new_bash(name) {
if (!name.match(/^[a-z0-9][-_:.+a-z0-9]*$/i))
return this.fail("illegal instance name");
if (bash_connections[name]) return;
bash_connections[name] =
pty.spawn("docker", ["exec", "-it", name, "bash", "-i"]);
bash_connections[name].stdout.on('data', function(data) {
emit('bash-data', {name: name, type: 'stdout', text: data.toString()});
});
}
function new_bash(name) {
if (!name.match(/^[a-z0-9][-_:.+a-z0-9]*$/i))
return this.fail("illegal instance name");
if (bash_connections[name]) return;
bash_connections[name] =
pty.spawn("docker", ["exec", "-it", name, "bash", "-i"]);
bash_connections[name].stdout.on('data', function(data) {
emit('bash-data', {name: name, type: 'stdout', text: data.toString()});
});
}
function bash_start(name) {
console.log("-> bash-start("+name+")");
new_bash(name);
}
function bash_input(data) {
console.log("-> bash-input("+data.name+", "+data.text+")");
new_bash(data.name);
bash_connections[data.name].stdin.resume();
bash_connections[data.name].stdin.write(data.text);
}
function bash_start(name) {
console.log("-> bash-start("+name+")");
new_bash(name);
}
function bash_input(data) {
console.log("-> bash-input("+data.name+", "+data.text+")");
new_bash(data.name);
bash_connections[data.name].stdin.resume();
bash_connections[data.name].stdin.write(data.text);
}
function bash_end(name, text) {
console.log("-> bash-end("+name+")");
if (!bash_connections[name]) return;
bash_connections[name].stdin.close();
delete bash_connections[name]; bash_connections[name] = null;
}
function bash_end(name, text) {
console.log("-> bash-end("+name+")");
if (!bash_connections[name]) return;
bash_connections[name].stdin.close();
delete bash_connections[name]; bash_connections[name] = null;
}
socket
.on("containers", containers)
.on("images", images)
.on("start", start)
.on("stop", stop)
.on("pause", pause)
.on("unpause", unpause)
.on("remove", remove)
.on("create", create)
.on('logs', logs)
.on('bash-start', bash_start)
.on('bash-input', bash_input)
.on('bash-end', bash_end);
socket
.on("containers", containers)
.on("images", images)
.on("start", start)
.on("stop", stop)
.on("pause", pause)
.on("unpause", unpause)
.on("remove", remove)
.on("create", create)
.on('logs', logs)
.on('bash-start', bash_start)
.on('bash-input', bash_input)
.on('bash-end', bash_end);
}
function stats() {
var res = {};
var fs = require('fs');
var async = require('async');
var base = "/sys/fs/cgroup/";
var dataPoints = {
"cpuacct": [
"usage"
],
"memory": [
"usage_in_bytes",
"limit_in_bytes",
"max_usage_in_bytes"
]
};
async.forEachOf(idtoname, function(name, id, cb1) {
res[name] = {};
async.forEachOf(dataPoints, function(val1, category, cb2) {
res[name][category] = {};
async.each(val1, function(element, cb3) {
var file = base + category + '/docker/' + id + '/' + category + '.' + element;
fs.readFile(file, 'utf8', function(err, data) {
res[name][category][element] = {
date: (new Date()).getTime(),
data: {}
};
if (err) {cb3(); console.log(err); return}
data.trim().split('\n').forEach(function(v, i) {
var vals = v.split(' ');
switch (vals.length) {
case 1:
res[name][category][element].data = parseInt(vals[0]);
break;
case 2:
res[name][category][element].data[vals[0]] = parseInt(vals[1]);
break;
}
});
cb3();
});
}, function(err) {
cb2();
});
}, function(err) {
cb1();
}
function stats() {
var res = {};
var fs = require('fs');
var async = require('async');
var base = "/sys/fs/cgroup/";
var dataPoints = {
"cpuacct": [
"usage"
],
"memory": [
"usage_in_bytes",
"limit_in_bytes",
"max_usage_in_bytes"
]
};
async.forEachOf(idtoname, function(name, id, cb1) {
res[name] = {};
async.forEachOf(dataPoints, function(val1, category, cb2) {
res[name][category] = {};
async.each(val1, function(element, cb3) {
var file = base + category + '/docker/' + id + '/' + category + '.' + element;
fs.readFile(file, 'utf8', function(err, data) {
res[name][category][element] = {
date: (new Date()).getTime(),
data: {}
};
if (err) {cb3(); console.log(err); return}
data.trim().split('\n').forEach(function(v, i) {
var vals = v.split(' ');
switch (vals.length) {
case 1:
res[name][category][element].data = parseInt(vals[0]);
break;
case 2:
res[name][category][element].data[vals[0]] = parseInt(vals[1]);
break;
}
});
cb3();
});
}, function(err) {
if (err) return;
broadcast("stats", res);
cb2();
});
}
// Handle Connection
io.sockets.on('connection', connection);
}, function(err) {
cb1();
});
}, function(err) {
if (err) return;
broadcast("stats", res);
});
}
// Handle Connection
require('socketio-auth')(io, {
authenticate: function (socket, data, callback) {
console.log("=> authenticate: ", data.username);
//get credentials sent by the client
var username = data.username;
var password = data.password;
if (username=="hello")
return callback(null, "world" == password);
else
return callback(new Error("wrong credentials"));
},
postAuthenticate: connection,
timeout: "none"
});
// Regular Update of Stats
setInterval(function() {
stats();
}, 1000);
// Regular Update of Images and Containers
setInterval(function() {
updateimages();
updatecontainers();
}, 10000);
return module;
// Regular Update of Stats
setInterval(function() {
stats();
}, 1000);
// Regular Update of Images and Containers
setInterval(function() {
updateimages();
updatecontainers();
}, 10000);
return module;
}

@ -31,7 +31,6 @@
<ul id="menu" style="display: none" onmouseleave="$('#menu').hide();">
<li onclick="$('#menu').hide(); showCreate()">Create</li>
<li><label for="upload">Upload</label><input autocomplete="off" type="file" accept="*.json" id="upload"/></li>
<li><a id="logout" href="">Logout</a></li>
</ul>
<script type="text/javascript">
$(function() {
@ -46,6 +45,17 @@
</div>
<div id="login">
<h1>Login</h1>
<form onsubmit="connect()">
<label for="username">User Name</label>
<input id="username" type="text" />
<label for="password">Password</label>
<input id="password" type="password" />
<button type="button" onclick="connect()">Login</button>
</form>
</div>
<div id="create" style="display: none">
<form>
<fieldset>
@ -119,14 +129,15 @@
</div>
<div id="statusbar">
<span id="status">
<noscript>JavaScript is required for the interface.</noscript>
</span>
<span id="username">[unknown]</span>
<span id="server">[unknown]</span>
<span id="connectionstatus">
<span id="good" title="connected" style="display: none">&#x2714;</span>
<span id="authentication" title="authentication" style="display:none">&#x1f511;</span>
<span id="bad" title="disconnected">&#x2718;</span>
</span>
<span id="status">
<noscript>JavaScript is required for the interface.</noscript>
</span>
</div>
</body>

@ -16,7 +16,7 @@ if test -n "${SCHROOTNAME}"; then
SUDO="schroot -c "${SCHROOTNAME}" -u root -d / --"
else
DO=""
if grep -q '/docker/' /proc/1/cgroup; then
if grep -q '/docker' /proc/1/cgroup; then
SUDO=""
else
SUDO="sudo"

@ -12,19 +12,30 @@
SCHROOTNAME="$1"
PACKAGE_NAME=$(sed -n 's/^ *m4_define(x_package_name, \(.*\)).*/\1/p' configure.ac)
PKGCONFIGS="${2:-epel-release}" # packages to configure yum
if test -n "${SCHROOTNAME}"; then
schroot -c ${SCHROOTNAME} -- ./bootstrap.sh -t dist
FILES=$(LANG= schroot -c ${SCHROOTNAME} -- rpmbuild -bb --clean --nobuild --define "_topdir ." --define "_sourcedir ." ${PACKAGE_NAME}.spec 2>&1 | sed -n 's, is needed by.*,,p')
if test -n "${FILES}"; then
FIRST=$(echo "${FILES}" | egrep -o "${PKGCONFIGS// /|}")
if test -n "${FIRST}"; then
schroot -c ${SCHROOTNAME} -u root -- yum install -y ${FIRST} || \
schroot -c ${SCHROOTNAME} -u root -- zypper install -y ${FIRST} || \
schroot -c ${SCHROOTNAME} -u root -- dnf install -y ${FIRST}
fi
schroot -c ${SCHROOTNAME} -u root -- yum install -y ${FILES} || \
schroot -c ${SCHROOTNAME} -u root -- zypper install -y ${FILES} || \
schroot -c ${SCHROOTNAME} -u root -- dnf install -y ${FILES}
schroot -c ${SCHROOTNAME} -u root -- dnf install -y ${FILES}
fi
else
./bootstrap.sh -t dist
FILES=$(LANG= rpmbuild -bb --clean --nobuild --define "_topdir ." --define "_sourcedir ." ${PACKAGE_NAME}.spec 2>&1 | sed -n 's, is needed by.*,,p')
if test -n "${FILES}"; then
FIRST=$(echo "${FILES}" | egrep -o "${PKGCONFIGS// /|}")
if test -n "${FIRST}"; then
yum install -y ${FIRST} || \
zypper install -y ${FIRST} || \
dnf install -y ${FIRST}
fi
yum install -y ${FILES} || \
zypper install -y ${FILES} || \
dnf install -y ${FILES}

@ -11,6 +11,11 @@ H;$!d;$x
# remove all single-line comment lines
s/\n--[^\n]*//g
# encode html entities
s/&/\&amp##SEMICOLON##/g
s/</\&lt##SEMICOLON##/g
s/>/\&gt##SEMICOLON##/g
# reduce spaces
s,\t\| \+, ,g
@ -21,7 +26,7 @@ s,\t\| \+, ,g
s,\n\+,\n,g
# remove unknown commands
s,\(;\|\n\) *\(DELIMITER\|USE\|DROP\|CREATE[ \n]\+DATABASE\)[ \n]\+[^;]*;\+,,ig
s,\(;\|\n\) *\(INSERT\|DELIMITER\|USE\|DROP\|CREATE[ \n]\+DATABASE\)[ \n]\+[^;]*;\+,,ig
# convert special characters within quotes
:a;s/^\(\([^"]*"[^",]*"\)*[^"]*"[^"]*\),\([^"]*".*\)/\1\##COMMA##\3/g;ta
@ -34,17 +39,18 @@ h
s,.*\(create[ \n]\+table[^;]*;\).*,\1,ig
# start html table node
s|CREATE[ \n]\+TABLE[ \n]\+\(if[ \n]\+not[ \n]\+exists[ \n]\+\)\?`\?\(\w\+\)`\?| \2\n [shape=none, margin=0, label=<\n <table bgcolor="#dddddd">\n <tr><td bgcolor="#ddddff" colspan="4"><b>\2</b></td></tr>|ig
s|CREATE[ \n]\+TABLE[ \n]\+\(IF[ \n]\+NOT[ \n]\+EXISTS[ \n]\+\)\?`\?\(\w\+\)`\?| \2\n [shape=none, margin=0, label=<\n <table bgcolor="#dddddd">\n <tr><td bgcolor="#ddddff" colspan="4"><b>\2</b></td></tr>|ig
# remove key definitions
s/[),][\n ]*\(PRIMARY[ \n]\+\)\?KEY[ \n]\+[^(]*([^)]*)//gi
s/[),][\n ]*\(\(UNIQUE\|PRIMARY\)[ \n]\+\)\?KEY[ \n]\+[^(]*([^)]*)//gi
# move foreign keys as relation to the end
:b;s/\(\w\+\)\([^;]*\)FOREIGN[\n ]\+KEY[ \n]*([ \n]*`\?\([a-z]\+\)`\?[ \n]*)[ \n]*REFERENCES[ \n]*`\?\([a-z]\+\)`\?[ \n]*([ \n]*`\?\([a-z]\+\)`\?[ \n]*)[ \n]*\([^,)]*\)\([,)].*\)/\1\2\7\n \1:\3 -> \4:\5 [label="\6"]##SEMICOLON##/ig;tb
# create table rows
s|[(,][ \n]*`\?\(\w\+\)`\?[ \n]\+\(\w\+\(([^)]\+)\)\?\)[ \n]*\([^,)]*\)[ \n]\+COMMENT[ \n]*["']\([^"']*\)["'][ \n]*|\n <tr><td align="left" port="\1"><b>\1</b></td><td align="left">\2</td><td align="left">\4</td><td align="left">\5</td></tr>|gi
s|[(,][ \n]*`\?\(\w\+\)`\?[ \n]\+\(\w\+\(([^)]\+)\)\?\)[ \n]*\([^,)]*\)|\n <tr><td align="left" port="\1"><b>\1</b></td><td align="left">\2</td><td align="left">\4</td></tr>|g
s|[(,][ \n]*`\?\(\w\+\)`\?[ \n]\+\(\w\+\(([^)]\+)\)\?\)[ \n]*\([^,)]*\)|\n <tr><td align="left" port="\1"><b>\1</b></td><td align="left">\2</td><td align="left">\4</td><td></td></tr>|g
# extract comment
s|\(<td\( *\w*="\w*"\)* *>[^<]*\)COMMENT[ \n]\+["']\([^"']*\)["']\([^<]*</td>\)<td></td>|\1\4<td align="left">\3</td>|g
# add line breaks for long lines
s|\(<td[^>]*>[^<]\{30,40\}\)[ \n]\+\([^<]\{20,\}</td>\)|\1<br/>\2|g

Loading…
Cancel
Save