Selaa lähdekoodia

Merge branch 'v1.10' into add_conan_packaging_file

Tom Deblauwe 7 vuotta sitten
vanhempi
commit
7e54e65247
100 muutettua tiedostoa jossa 4677 lisäystä ja 1970 poistoa
  1. 2 0
      .gitignore
  2. 322 868
      .travis.yml
  3. 61 20
      CMakeLists.txt
  4. 26 2
      CREDITS.md
  5. 1 3
      LICENSE.md
  6. 23 3
      Makefile
  7. 34 28
      Qt/CivetWeb.pro
  8. 33 27
      README.md
  9. 52 1
      RELEASE_NOTES.md
  10. 1 1
      VisualStudio/civetweb.sln
  11. 7 6
      VisualStudio/civetweb_lua/civetweb_lua.vcxproj
  12. 2 2
      VisualStudio/duktape_lib/duktape_lib.vcxproj
  13. 2 2
      VisualStudio/ex_embed_cpp/ex_embed_cpp.vcxproj
  14. 2 2
      VisualStudio/ex_embedded_c/ex_embedded_c.vcxproj
  15. 2 2
      VisualStudio/lua_lib/lua_lib.vcxproj
  16. 5 4
      VisualStudio/unit_test/unit_test.vcxproj
  17. 3 3
      VisualStudio/unit_test/unit_test.vcxproj.filters
  18. 171 37
      appveyor.yml
  19. 1 1
      ci/travis/install_rocks.sh
  20. 1 1
      ci/travis/lua_env.sh
  21. 1 1
      ci/travis/run_ci_tests.sh
  22. 1 1
      ci/travis/setup_lua.sh
  23. 1 1
      contrib/buildroot/civetweb.mk
  24. 79 23
      docs/APIReference.md
  25. 49 24
      docs/Building.md
  26. 17 4
      docs/Contribution.md
  27. 79 19
      docs/Embedding.md
  28. 4 2
      docs/Installing.md
  29. 86 0
      docs/Interface_Changes_1.10.md
  30. 3 1
      docs/README.md
  31. 114 8
      docs/UserManual.md
  32. 4 4
      docs/api/mg_callbacks.md
  33. 37 0
      docs/api/mg_check_digest_access_authentication.md
  34. 1 1
      docs/api/mg_client_cert.md
  35. 29 0
      docs/api/mg_exit_library.md
  36. 40 0
      docs/api/mg_get_connection_info.md
  37. 32 0
      docs/api/mg_get_context_info.md
  38. 5 0
      docs/api/mg_get_request_info.md
  39. 29 0
      docs/api/mg_get_request_link.md
  40. 29 0
      docs/api/mg_get_response_info.md
  41. 30 0
      docs/api/mg_get_system_info.md
  42. 44 0
      docs/api/mg_init_library.md
  43. 6 1
      docs/api/mg_modify_passwords_file.md
  44. 12 11
      docs/api/mg_request_info.md
  45. 38 0
      docs/api/mg_response_info.md
  46. 31 0
      docs/api/mg_send_chunk.md
  47. 35 0
      docs/api/mg_send_digest_access_authentication_request.md
  48. 32 0
      docs/api/mg_send_http_error.md
  49. 24 2
      docs/api/mg_set_user_connection_data.md
  50. 3 3
      docs/api/mg_websocket_write.md
  51. 7 2
      examples/README.md
  52. 175 8
      examples/embedded_c/embedded_c.c
  53. 121 5
      examples/embedded_cpp/embedded_cpp.cpp
  54. 15 0
      examples/https/README.md
  55. 86 0
      examples/https/civetweb.conf
  56. 0 0
      format.bat
  57. 16 2
      include/CivetServer.h
  58. 301 55
      include/civetweb.h
  59. 17 0
      resources/Makefile.in-duktape
  60. 1 0
      resources/Makefile.in-lua
  61. 1 0
      resources/Makefile.in-os
  62. 17 12
      resources/cert/client.crt
  63. 14 9
      resources/cert/client.csr
  64. 25 13
      resources/cert/client.key
  65. 26 14
      resources/cert/client.key.orig
  66. 42 25
      resources/cert/client.pem
  67. BIN
      resources/cert/client.pfx
  68. 0 22
      resources/cert/make_cert.bat
  69. 0 31
      resources/cert/make_certs
  70. 55 0
      resources/cert/make_certs.bat
  71. 64 0
      resources/cert/make_certs.sh
  72. 17 27
      resources/cert/server.crt
  73. 14 25
      resources/cert/server.csr
  74. 25 49
      resources/cert/server.key
  75. 26 50
      resources/cert/server.key.orig
  76. 42 76
      resources/cert/server.pem
  77. 1 0
      resources/cert/server.pin
  78. 19 0
      resources/cert/server_bkup.crt
  79. 16 0
      resources/cert/server_bkup.csr
  80. 27 0
      resources/cert/server_bkup.key
  81. 30 0
      resources/cert/server_bkup.key.orig
  82. 46 0
      resources/cert/server_bkup.pem
  83. 1 0
      resources/cert/server_bkup.pin
  84. 0 92
      resources/cleanup.lua
  85. 32 5
      resources/coverity_check.sh
  86. 20 14
      src/CMakeLists.txt
  87. 25 10
      src/CivetServer.cpp
  88. 544 60
      src/civetweb.c
  89. 178 39
      src/handle_form.inl
  90. 257 28
      src/main.c
  91. 3 0
      src/md5.inl
  92. 101 89
      src/mod_duktape.inl
  93. 449 78
      src/mod_lua.inl
  94. 10 11
      src/sha1.inl
  95. 72 0
      src/third_party/duktape-1.8.0/AUTHORS.rst
  96. 25 0
      src/third_party/duktape-1.8.0/LICENSE.txt
  97. 34 0
      src/third_party/duktape-1.8.0/Makefile.cmdline
  98. 4 0
      src/third_party/duktape-1.8.0/Makefile.codepage
  99. 4 0
      src/third_party/duktape-1.8.0/Makefile.coffee
  100. 26 0
      src/third_party/duktape-1.8.0/Makefile.dukdebug

+ 2 - 0
.gitignore

@@ -112,6 +112,8 @@ ipch/
 *.opensdf
 *.sdf
 *.cachefile
+*.VC.db
+*.VC.VC.opendb
 
 # Visual Studio profiler
 *.psess

+ 322 - 868
.travis.yml

@@ -1,13 +1,27 @@
-language: c
+##############################################################################
+# Travis version specific build environment specification
+##############################################################################
+
+# The "precise" build environment on Travis is in the process of being decommissioned
+# see https://blog.travis-ci.com/2017-08-31-trusty-as-default-status
+# The "precise=true"+"sudo=required" environment seems to lack IPv6 support.
+# According to some tests, all "sudo=required" environments do not support IPv6, see 
+# https://github.com/travis-ci/travis-ci/issues/8361#issuecomment-328263113
+# The container environments for "sudo=false" support IPv6 localhost [::1] 
+# connections for server/client test. Thus, all tests with ENABLE_IPV6=YES
+#
+
+
+##############################################################################
+# Project specific settings
+##############################################################################
 
-sudo: false
+language: c
 
 cache:
   directories:
   - $HOME/third-party
 
-
-
 osx_image: xcode8
 
 addons:
@@ -19,9 +33,18 @@ addons:
     sources:
       - kubuntu-backports
 
+
 before_install:
+  - if [ "${TRAVIS_OS_NAME}" == "linux" ]; then
+      mkdir $HOME/usr;
+      export PATH="$HOME/usr/bin:$PATH";
+      wget https://cmake.org/files/v3.7/cmake-3.7.2-Linux-x86_64.sh --no-check-certificate;
+      chmod +x cmake-3.7.2-Linux-x86_64.sh;
+      ./cmake-3.7.2-Linux-x86_64.sh --prefix=$HOME/usr --exclude-subdir --skip-license;
+    fi
   - cmake --version
 
+
 install:
   - if [ "${BUILD_TYPE}" == "Coverage" -a "${TRAVIS_OS_NAME}" == "linux" ]; then
       PATH=~/.local/bin:${PATH};
@@ -30,9 +53,16 @@ install:
     fi
 
 before_script:
-  # Check some settings of the build server
+  # Check some settings of the build server (operating system, IPv6 availability, directory)
   - uname -a
+  - ifconfig
   - pwd
+  - ls -la
+  - if [ "${TRAVIS_OS_NAME}" == "linux" ]; then
+      apt-cache search gcc | grep "GNU C compiler";
+      apt-cache search clang | grep compiler;
+    fi
+  - if [[ "${BUILD_TYPE}" == "OSX_OPENSSL_1_1" ]]; then brew install openssl@1.1 ;fi
   # Generate the build scripts with CMake
   - mkdir output
   - gcc test/cgi_test.c -o output/cgi_test.cgi
@@ -48,15 +78,19 @@ before_script:
     -DCIVETWEB_DISABLE_CGI=${NO_CGI}
     -DCIVETWEB_SERVE_NO_FILES=${NO_FILES}
     -DCIVETWEB_ENABLE_SSL_DYNAMIC_LOADING=${ENABLE_SSL_DYNAMIC_LOADING}
+    -DCIVETWEB_SSL_OPENSSL_API_1_1=${OPENSSL_1_1}
     -DCIVETWEB_ENABLE_WEBSOCKETS=${ENABLE_WEBSOCKETS}
     -DCIVETWEB_ENABLE_CXX=${ENABLE_CXX}
     -DCIVETWEB_ENABLE_IPV6=${ENABLE_IPV6}
+    -DCIVETWEB_ENABLE_SERVER_STATS=${ENABLE_SERVER_STATS}
     -DCIVETWEB_ENABLE_LUA=${ENABLE_LUA}
     -DCIVETWEB_ENABLE_LUA_SHARED=${ENABLE_LUA_SHARED}
     -DCIVETWEB_ENABLE_DUKTAPE=${ENABLE_DUKTAPE}
     -DCIVETWEB_DISABLE_CACHING=${NO_CACHING}
     -DCIVETWEB_C_STANDARD=${C_STANDARD}
     -DCIVETWEB_CXX_STANDARD=${CXX_STANDARD}
+    -DCIVETWEB_ALLOW_WARNINGS=${ALLOW_WARNINGS}
+    ${ADDITIONAL_CMAKE_ARGS}
     ..
   - ls -la
 
@@ -72,22 +106,37 @@ script:
 after_success:
   - if [ "${BUILD_TYPE}" == "Coverage" -a "${TRAVIS_OS_NAME}" == "linux" ]; then
       coveralls --include src --exclude src/main.c --exclude src/third_party --include include --gcov-options '\-lp' --root .. --build-root .;
+      bash <(curl -s https://codecov.io/bash);
     fi
 
 
-###################################
+##############################################################################
+# build matrix (auto generated)
+##############################################################################
+
 
 matrix:
   fast_finish: false
   include:
 
-  -
+  - dist: trusty
+    sudo: false
     os: linux
     compiler: clang
+    addons:
+      apt:
+        sources:
+          - ubuntu-toolchain-r-test
+          - llvm-toolchain-precise-3.8
+        packages:
+          - clang-3.8
     env:
-      N=ClangLinuxMinimal
+      idx=1
+      N=Clang3.8-Linux-Minimal-Debug
+      MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8"
       BUILD_TYPE=Debug
       ENABLE_SSL_DYNAMIC_LOADING=YES
+      OPENSSL_1_1=NO
       ENABLE_CXX=NO
       ENABLE_LUA_SHARED=NO
       C_STANDARD=auto
@@ -99,83 +148,136 @@ matrix:
       NO_CGI=YES
       ENABLE_IPV6=NO
       ENABLE_WEBSOCKETS=NO
+      ENABLE_SERVER_STATS=NO
       ENABLE_LUA=NO
       ENABLE_DUKTAPE=NO
       NO_CACHING=NO
+      ALLOW_WARNINGS=YES
 
-  -
+  - dist: trusty
+    sudo: false
     os: linux
-    compiler: gcc
+    compiler: clang
+    addons:
+      apt:
+        sources:
+          - ubuntu-toolchain-r-test
+          - llvm-toolchain-precise-3.8
+        packages:
+          - clang-3.8
     env:
-      N=GCCLinuxMinimal
+      idx=2
+      N=Clang3.8-Linux-Default-Release
+      MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8"
       BUILD_TYPE=Release
       ENABLE_SSL_DYNAMIC_LOADING=YES
+      OPENSSL_1_1=NO
       ENABLE_CXX=NO
       ENABLE_LUA_SHARED=NO
       C_STANDARD=auto
       CXX_STANDARD=auto
-      FEATURES=0
+      FEATURES=7
       BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=NO
-      NO_CGI=YES
+      NO_FILES=NO
+      ENABLE_SSL=YES
+      NO_CGI=NO
       ENABLE_IPV6=NO
       ENABLE_WEBSOCKETS=NO
+      ENABLE_SERVER_STATS=NO
       ENABLE_LUA=NO
       ENABLE_DUKTAPE=NO
       NO_CACHING=NO
+      NO_CACHING=NO
+      ALLOW_WARNINGS=YES
 
-  -
-    os: osx
+  - dist: trusty
+    sudo: false
+    os: linux
     compiler: clang
+    addons:
+      apt:
+        sources:
+          - ubuntu-toolchain-r-test
+          - llvm-toolchain-precise-3.8
+        packages:
+          - clang-3.8
     env:
-      N=ClangOSXMinimal
+      idx=3
+      N=Clang3.8-Linux-Default-Release
+      MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8"
       BUILD_TYPE=Release
       ENABLE_SSL_DYNAMIC_LOADING=YES
+      OPENSSL_1_1=NO
       ENABLE_CXX=NO
       ENABLE_LUA_SHARED=NO
       C_STANDARD=auto
       CXX_STANDARD=auto
-      FEATURES=0
+      FEATURES=7
       BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=NO
-      NO_CGI=YES
+      NO_FILES=NO
+      ENABLE_SSL=YES
+      NO_CGI=NO
       ENABLE_IPV6=NO
       ENABLE_WEBSOCKETS=NO
+      ENABLE_SERVER_STATS=NO
       ENABLE_LUA=NO
       ENABLE_DUKTAPE=NO
       NO_CACHING=NO
+      ALLOW_WARNINGS=YES
 
-  -
+  - dist: trusty
+    sudo: false
     os: linux
     compiler: clang
+    addons:
+      apt:
+        sources:
+          - ubuntu-toolchain-r-test
+          - llvm-toolchain-precise-3.8
+        packages:
+          - clang-3.8
     env:
-      N=ClangLinuxMinNoCache
-      BUILD_TYPE=Debug
+      idx=4
+      N=Clang3.8-Linux-Complete-NoLua-Release
+      MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8"
+      BUILD_TYPE=Release
       ENABLE_SSL_DYNAMIC_LOADING=YES
+      OPENSSL_1_1=NO
       ENABLE_CXX=NO
       ENABLE_LUA_SHARED=NO
       C_STANDARD=auto
       CXX_STANDARD=auto
-      FEATURES=0
+      FEATURES=31
       BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=NO
-      NO_CGI=YES
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=NO
+      NO_FILES=NO
+      ENABLE_SSL=YES
+      NO_CGI=NO
+      ENABLE_IPV6=YES
+      ENABLE_WEBSOCKETS=YES
+      ENABLE_SERVER_STATS=YES
       ENABLE_LUA=NO
       ENABLE_DUKTAPE=NO
       NO_CACHING=YES
+      ALLOW_WARNINGS=YES
 
-  -
+
+  - dist: trusty
+    sudo: false
     os: linux
-    compiler: clang
+    compiler: gcc
+    addons:
+      apt:
+        sources:
+          - ubuntu-toolchain-r-test
+        packages:
+          - g++-5
     env:
-      N=ClangLinuxMax
-      BUILD_TYPE=Coverage
+      idx=5
+      N=GCC5-Linux-Complete-NoLua-Release
+      MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
+      BUILD_TYPE=Release
       ENABLE_SSL_DYNAMIC_LOADING=YES
+      OPENSSL_1_1=NO
       ENABLE_CXX=NO
       ENABLE_LUA_SHARED=NO
       C_STANDARD=auto
@@ -187,17 +289,20 @@ matrix:
       NO_CGI=NO
       ENABLE_IPV6=YES
       ENABLE_WEBSOCKETS=YES
+      ENABLE_SERVER_STATS=YES
       ENABLE_LUA=NO
       ENABLE_DUKTAPE=NO
       NO_CACHING=YES
-
-  -
-    os: linux
+      ALLOW_WARNINGS=YES
+  
+  - os: linux
     compiler: gcc
     env:
-      N=GCCLinuxMax
-      BUILD_TYPE=Release
+      idx=6
+      N=GCCAnyVersion-Linux-Coverage
+      BUILD_TYPE=Coverage
       ENABLE_SSL_DYNAMIC_LOADING=YES
+      OPENSSL_1_1=NO
       ENABLE_CXX=NO
       ENABLE_LUA_SHARED=NO
       C_STANDARD=auto
@@ -209,17 +314,20 @@ matrix:
       NO_CGI=NO
       ENABLE_IPV6=YES
       ENABLE_WEBSOCKETS=YES
+      ENABLE_SERVER_STATS=YES
       ENABLE_LUA=NO
       ENABLE_DUKTAPE=NO
-      NO_CACHING=YES
+      NO_CACHING=NO
+      ALLOW_WARNINGS=YES
 
-  -
-    os: osx
+  - os: osx
     compiler: clang
     env:
-      N=ClangOSXMax
+      idx=7
+      N=Clang-OSX-Complete-NoLua-Release
       BUILD_TYPE=Release
       ENABLE_SSL_DYNAMIC_LOADING=YES
+      OPENSSL_1_1=NO
       ENABLE_CXX=NO
       ENABLE_LUA_SHARED=NO
       C_STANDARD=auto
@@ -231,39 +339,90 @@ matrix:
       NO_CGI=NO
       ENABLE_IPV6=YES
       ENABLE_WEBSOCKETS=YES
+      ENABLE_SERVER_STATS=YES
       ENABLE_LUA=NO
       ENABLE_DUKTAPE=NO
       NO_CACHING=YES
+      ALLOW_WARNINGS=YES
 
   -
-    os: linux
+    os: osx
     compiler: clang
     env:
-      N=ClangLinuxDefault
+      idx=8
+      N=Clang-OSX-Complete-NoLua-Release-OpenSSL_1_1_NoDynLoad
+      BUILD_TYPE=OSX_OPENSSL_1_1
+      ENABLE_SSL_DYNAMIC_LOADING=NO
+      OPENSSL_1_1=YES
+      ENABLE_CXX=NO
+      ENABLE_LUA_SHARED=NO
+      C_STANDARD=auto
+      CXX_STANDARD=auto
+      FEATURES=31
+      BUILD_SHARED=NO
+      NO_FILES=NO
+      ENABLE_SSL=YES
+      NO_CGI=NO
+      ENABLE_IPV6=YES
+      ENABLE_WEBSOCKETS=YES
+      ENABLE_SERVER_STATS=YES
+      ENABLE_LUA=NO
+      ENABLE_DUKTAPE=NO
+      NO_CACHING=YES
+      ALLOW_WARNINGS=YES
+      OPENSSL_ROOT_DIR="/usr/local/opt/openssl@1.1"
+      LDFLAGS="-L${OPENSSL_ROOT_DIR}/lib"
+      CFLAGS="-I${OPENSSL_ROOT_DIR}/include"
+      ADDITIONAL_CMAKE_ARGS="-DCMAKE_SHARED_LINKER_FLAGS=${LDFLAGS} -DCMAKE_C_FLAGS=${CFLAGS}"
+      PATH="${OPENSSL_ROOT_DIR}/bin:$PATH"
+      DYLD_LIBRARY_PATH="${OPENSSL_ROOT_DIR}/lib:${DYLD_LIBRARY_PATH}"
+
+  - dist: trusty
+    sudo: false
+    os: linux
+    compiler: clang
+    addons:
+      apt:
+        sources:
+          - ubuntu-toolchain-r-test
+          - llvm-toolchain-trusty-5.0
+        packages:
+          - clang-5.0
+    env:
+      idx=9
+      N=Clang50-Linux-Default-Shared
       BUILD_TYPE=Debug
       ENABLE_SSL_DYNAMIC_LOADING=YES
+      OPENSSL_1_1=NO
       ENABLE_CXX=NO
       ENABLE_LUA_SHARED=NO
       C_STANDARD=auto
       CXX_STANDARD=auto
       FEATURES=7
-      BUILD_SHARED=NO
+      BUILD_SHARED=YES
       NO_FILES=NO
       ENABLE_SSL=YES
       NO_CGI=NO
       ENABLE_IPV6=NO
       ENABLE_WEBSOCKETS=NO
+      ENABLE_SERVER_STATS=NO
       ENABLE_LUA=NO
       ENABLE_DUKTAPE=NO
       NO_CACHING=NO
+      ALLOW_WARNINGS=YES
+      MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8"
 
   -
     os: linux
-    compiler: gcc
+    dist: precise
+    sudo: required
+    compiler: clang
     env:
-      N=GCCLinuxDefault
-      BUILD_TYPE=Release
+      idx=10
+      N=Precise-Clang-Linux-Default
+      BUILD_TYPE=Debug
       ENABLE_SSL_DYNAMIC_LOADING=YES
+      OPENSSL_1_1=NO
       ENABLE_CXX=NO
       ENABLE_LUA_SHARED=NO
       C_STANDARD=auto
@@ -275,45 +434,121 @@ matrix:
       NO_CGI=NO
       ENABLE_IPV6=NO
       ENABLE_WEBSOCKETS=NO
+      ENABLE_SERVER_STATS=NO
       ENABLE_LUA=NO
       ENABLE_DUKTAPE=NO
       NO_CACHING=NO
+      ALLOW_WARNINGS=YES
 
   -
     os: osx
     compiler: clang
     env:
-      N=ClangOSXDefault
+      idx=11
+      N=OSX-Package
       BUILD_TYPE=Release
       ENABLE_SSL_DYNAMIC_LOADING=YES
+      OPENSSL_1_1=NO
       ENABLE_CXX=NO
       ENABLE_LUA_SHARED=NO
       C_STANDARD=auto
       CXX_STANDARD=auto
-      FEATURES=7
+      FEATURES=31
       BUILD_SHARED=NO
       NO_FILES=NO
       ENABLE_SSL=YES
       NO_CGI=NO
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=NO
+      ENABLE_IPV6=YES
+      ENABLE_WEBSOCKETS=YES
+      ENABLE_SERVER_STATS=NO
       ENABLE_LUA=NO
       ENABLE_DUKTAPE=NO
       NO_CACHING=NO
+      ALLOW_WARNINGS=YES
+      MACOSX_PACKAGE=1
+
+  - dist: trusty
+    sudo: false
+    os: linux
+    compiler: clang
+    addons:
+      apt:
+        sources:
+          - ubuntu-toolchain-r-test
+          - llvm-toolchain-trusty-3.8
+        packages:
+          - clang-3.8
+    env:
+      idx=12
+      N=Clang-Linux-32bit-Complete-NoLua-Release
+      ARCH=x86
+      BUILD_TYPE=Release
+      ENABLE_SSL_DYNAMIC_LOADING=YES
+      OPENSSL_1_1=NO
+      ENABLE_CXX=NO
+      ENABLE_LUA_SHARED=NO
+      C_STANDARD=auto
+      CXX_STANDARD=auto
+      FEATURES=31
+      BUILD_SHARED=NO
+      NO_FILES=NO
+      ENABLE_SSL=YES
+      NO_CGI=NO
+      ENABLE_IPV6=YES
+      ENABLE_WEBSOCKETS=YES
+      ENABLE_SERVER_STATS=YES
+      ENABLE_LUA=NO
+      ENABLE_DUKTAPE=NO
+      NO_CACHING=YES
+      ALLOW_WARNINGS=YES
+      MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8"
+
+
+### Test all build types:
+# According to CMakeLists, options are:
+# None Debug Release RelWithDebInfo MinSizeRel Coverage
 
   -
     os: linux
     compiler: clang
     env:
-      N=ClangLinuxDefaultShared
+      idx=13
+      N=NoSslDynamicLoading
+      BUILD_TYPE=Release
+      ENABLE_SSL_DYNAMIC_LOADING=NO
+      OPENSSL_1_1=NO
+      ENABLE_CXX=NO
+      C_STANDARD=auto
+      CXX_STANDARD=auto
+      ENABLE_LUA_SHARED=NO
+      FEATURES=31
+      BUILD_SHARED=NO
+      NO_FILES=NO
+      ENABLE_SSL=YES
+      NO_CGI=NO
+      ENABLE_IPV6=YES
+      ENABLE_WEBSOCKETS=YES
+      ENABLE_LUA=NO
+      ENABLE_DUKTAPE=NO
+      NO_CACHING=NO
+      ALLOW_WARNINGS=YES
+      MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8"
+
+  -
+    os: linux
+    compiler: gcc
+    env:
+      idx=14
+      N=GCCLinuxDefault_Debug
       BUILD_TYPE=Debug
       ENABLE_SSL_DYNAMIC_LOADING=YES
+      OPENSSL_1_1=NO
       ENABLE_CXX=NO
       ENABLE_LUA_SHARED=NO
       C_STANDARD=auto
       CXX_STANDARD=auto
       FEATURES=7
-      BUILD_SHARED=YES
+      BUILD_SHARED=NO
       NO_FILES=NO
       ENABLE_SSL=YES
       NO_CGI=NO
@@ -322,20 +557,23 @@ matrix:
       ENABLE_LUA=NO
       ENABLE_DUKTAPE=NO
       NO_CACHING=NO
+      ALLOW_WARNINGS=YES
 
   -
     os: linux
     compiler: gcc
     env:
-      N=GCCLinuxDefaultShared
-      BUILD_TYPE=Release
+      idx=15
+      N=GCCLinuxDefault_RelWithDebInfo
+      BUILD_TYPE=RelWithDebInfo
       ENABLE_SSL_DYNAMIC_LOADING=YES
+      OPENSSL_1_1=NO
       ENABLE_CXX=NO
       ENABLE_LUA_SHARED=NO
       C_STANDARD=auto
       CXX_STANDARD=auto
       FEATURES=7
-      BUILD_SHARED=YES
+      BUILD_SHARED=NO
       NO_FILES=NO
       ENABLE_SSL=YES
       NO_CGI=NO
@@ -344,20 +582,23 @@ matrix:
       ENABLE_LUA=NO
       ENABLE_DUKTAPE=NO
       NO_CACHING=NO
+      ALLOW_WARNINGS=YES
 
   -
-    os: osx
-    compiler: clang
+    os: linux
+    compiler: gcc
     env:
-      N=ClangOSXDefaultShared
-      BUILD_TYPE=Release
+      idx=16
+      N=GCCLinuxDefault_MinSizeRel
+      BUILD_TYPE=MinSizeRel
       ENABLE_SSL_DYNAMIC_LOADING=YES
+      OPENSSL_1_1=NO
       ENABLE_CXX=NO
       ENABLE_LUA_SHARED=NO
       C_STANDARD=auto
       CXX_STANDARD=auto
       FEATURES=7
-      BUILD_SHARED=YES
+      BUILD_SHARED=NO
       NO_FILES=NO
       ENABLE_SSL=YES
       NO_CGI=NO
@@ -366,29 +607,32 @@ matrix:
       ENABLE_LUA=NO
       ENABLE_DUKTAPE=NO
       NO_CACHING=NO
+      ALLOW_WARNINGS=YES
 
   -
-    os: osx
-    compiler: clang
+    os: linux
+    compiler: gcc
     env:
-      N=OSX_Package
-      BUILD_TYPE=Release
+      idx=17
+      N=GCCLinuxDefault_None
+      BUILD_TYPE=None
       ENABLE_SSL_DYNAMIC_LOADING=YES
+      OPENSSL_1_1=NO
       ENABLE_CXX=NO
       ENABLE_LUA_SHARED=NO
       C_STANDARD=auto
       CXX_STANDARD=auto
-      FEATURES=31
+      FEATURES=7
       BUILD_SHARED=NO
       NO_FILES=NO
       ENABLE_SSL=YES
       NO_CGI=NO
-      ENABLE_IPV6=YES
-      ENABLE_WEBSOCKETS=YES
+      ENABLE_IPV6=NO
+      ENABLE_WEBSOCKETS=NO
       ENABLE_LUA=NO
       ENABLE_DUKTAPE=NO
       NO_CACHING=NO
-      MACOSX_PACKAGE=1
+      ALLOW_WARNINGS=YES
 
 
 #### Now all define combinations, but only for Linux clang
@@ -415,8 +659,8 @@ matrix:
 #      assert("ERROR in INV!")
 #    end
 #  end
-#  for i=0,31 do
-#    if true then -- (i~=0) and (i~=7) and (i~=31) then
+#  for i=0,511 do
+#    if (YN(i, 6)=="NO") and (YN(i, 7)=="NO") then
 #      print("  -")
 #      print("    os: linux")
 #      print("    compiler: clang")
@@ -424,6 +668,7 @@ matrix:
 #      print("      N=C" .. tostring(i) .. "_")
 #      print("      BUILD_TYPE=Release")
 #      print("      ENABLE_SSL_DYNAMIC_LOADING=YES")
+#      print("      OPENSSL_1_1=NO")
 #      print("      ENABLE_CXX=NO")
 #      print("      C_STANDARD=auto")
 #      print("      CXX_STANDARD=auto")
@@ -437,804 +682,13 @@ matrix:
 #      print("      ENABLE_WEBSOCKETS=" .. YN(i, 5))
 #      print("      ENABLE_LUA=" .. YN(i, 6))
 #      print("      ENABLE_DUKTAPE=" .. YN(i, 7))
-#      print("      NO_CACHING=NO")
+#      print("      NO_CACHING=" .. INV(YN(i, 8)))
+#      print("      ENABLE_SERVER_STATS=" .. YN(i, 9))
 #      print("")
 #    end
 #  end
 #
 
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C0_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=0
-      BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=NO
-      NO_CGI=YES
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C1_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=1
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=NO
-      NO_CGI=YES
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C2_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=2
-      BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=YES
-      NO_CGI=YES
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
+# TODO: Regenerate this matrix, once a stable Travis build is re-established
 
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C3_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=3
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=YES
-      NO_CGI=YES
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
 
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C4_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=4
-      BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=NO
-      NO_CGI=NO
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C5_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=5
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=NO
-      NO_CGI=NO
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C6_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=6
-      BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=YES
-      NO_CGI=NO
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C7_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=7
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=YES
-      NO_CGI=NO
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C8_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=8
-      BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=NO
-      NO_CGI=YES
-      ENABLE_IPV6=YES
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C9_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=9
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=NO
-      NO_CGI=YES
-      ENABLE_IPV6=YES
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C10_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=10
-      BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=YES
-      NO_CGI=YES
-      ENABLE_IPV6=YES
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C11_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=11
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=YES
-      NO_CGI=YES
-      ENABLE_IPV6=YES
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C12_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=12
-      BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=NO
-      NO_CGI=NO
-      ENABLE_IPV6=YES
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C13_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=13
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=NO
-      NO_CGI=NO
-      ENABLE_IPV6=YES
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C14_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=14
-      BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=YES
-      NO_CGI=NO
-      ENABLE_IPV6=YES
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C15_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=15
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=YES
-      NO_CGI=NO
-      ENABLE_IPV6=YES
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C16_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=16
-      BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=NO
-      NO_CGI=YES
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=YES
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C17_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=17
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=NO
-      NO_CGI=YES
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=YES
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C18_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=18
-      BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=YES
-      NO_CGI=YES
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=YES
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C19_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=19
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=YES
-      NO_CGI=YES
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=YES
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C20_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=20
-      BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=NO
-      NO_CGI=NO
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=YES
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C21_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=21
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=NO
-      NO_CGI=NO
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=YES
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C22_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=22
-      BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=YES
-      NO_CGI=NO
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=YES
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C23_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=23
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=YES
-      NO_CGI=NO
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=YES
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C24_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=24
-      BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=NO
-      NO_CGI=YES
-      ENABLE_IPV6=YES
-      ENABLE_WEBSOCKETS=YES
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C25_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=25
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=NO
-      NO_CGI=YES
-      ENABLE_IPV6=YES
-      ENABLE_WEBSOCKETS=YES
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C26_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=26
-      BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=YES
-      NO_CGI=YES
-      ENABLE_IPV6=YES
-      ENABLE_WEBSOCKETS=YES
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C27_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=27
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=YES
-      NO_CGI=YES
-      ENABLE_IPV6=YES
-      ENABLE_WEBSOCKETS=YES
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C28_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=28
-      BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=NO
-      NO_CGI=NO
-      ENABLE_IPV6=YES
-      ENABLE_WEBSOCKETS=YES
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C29_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=29
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=NO
-      NO_CGI=NO
-      ENABLE_IPV6=YES
-      ENABLE_WEBSOCKETS=YES
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C30_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=30
-      BUILD_SHARED=NO
-      NO_FILES=YES
-      ENABLE_SSL=YES
-      NO_CGI=NO
-      ENABLE_IPV6=YES
-      ENABLE_WEBSOCKETS=YES
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: clang
-    env:
-      N=C31_
-      BUILD_TYPE=Release
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      ENABLE_LUA_SHARED=NO
-      FEATURES=31
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=YES
-      NO_CGI=NO
-      ENABLE_IPV6=YES
-      ENABLE_WEBSOCKETS=YES
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-### Test all build types:
-# According to CMakeLists, options are:
-# None Debug Release RelWithDebInfo MinSizeRel Coverage
-
-  -
-    os: linux
-    compiler: gcc
-    env:
-      N=GCCLinuxDefault_Debug
-      BUILD_TYPE=Debug
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      ENABLE_LUA_SHARED=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      FEATURES=7
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=YES
-      NO_CGI=NO
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: gcc
-    env:
-      N=GCCLinuxDefault_RelWithDebInfo
-      BUILD_TYPE=RelWithDebInfo
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      ENABLE_LUA_SHARED=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      FEATURES=7
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=YES
-      NO_CGI=NO
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: gcc
-    env:
-      N=GCCLinuxDefault_MinSizeRel
-      BUILD_TYPE=MinSizeRel
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      ENABLE_LUA_SHARED=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      FEATURES=7
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=YES
-      NO_CGI=NO
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO
-
-  -
-    os: linux
-    compiler: gcc
-    env:
-      N=GCCLinuxDefault_None
-      BUILD_TYPE=None
-      ENABLE_SSL_DYNAMIC_LOADING=YES
-      ENABLE_CXX=NO
-      ENABLE_LUA_SHARED=NO
-      C_STANDARD=auto
-      CXX_STANDARD=auto
-      FEATURES=7
-      BUILD_SHARED=NO
-      NO_FILES=NO
-      ENABLE_SSL=YES
-      NO_CGI=NO
-      ENABLE_IPV6=NO
-      ENABLE_WEBSOCKETS=NO
-      ENABLE_LUA=NO
-      ENABLE_DUKTAPE=NO
-      NO_CACHING=NO

+ 61 - 20
CMakeLists.txt

@@ -26,7 +26,7 @@ include(CMakeDependentOption)
 
 # Set up the project
 project (civetweb)
-set(CIVETWEB_VERSION "1.9.1" CACHE STRING "The version of the civetweb library")
+set(CIVETWEB_VERSION "1.10.0" CACHE STRING "The version of the civetweb library")
 string(REGEX MATCH "([0-9]+)\\.([0-9]+)\\.([0-9]+)" CIVETWEB_VERSION_MATCH "${CIVETWEB_VERSION}")
 if ("${CIVETWEB_VERSION_MATCH}" STREQUAL "")
   message(FATAL_ERROR "Must specify a semantic version: major.minor.patch")
@@ -48,12 +48,6 @@ endif()
 # C++ wrappers
 option(CIVETWEB_ENABLE_THIRD_PARTY_OUTPUT "Shows the output of third party dependency processing" OFF)
 
-# Max Request Size
-set(CIVETWEB_MAX_REQUEST_SIZE 16384 CACHE STRING
-  "The largest amount of content bytes allowed in a request")
-set_property(CACHE CIVETWEB_MAX_REQUEST_SIZE PROPERTY VALUE ${CIVETWEB_MAX_REQUEST_SIZE})
-message(STATUS "Max Request Size - ${CIVETWEB_MAX_REQUEST_SIZE}")
-
 # Thread Stack Size
 set(CIVETWEB_THREAD_STACK_SIZE 102400 CACHE STRING
   "The stack size in bytes for each thread created")
@@ -84,22 +78,39 @@ message(STATUS "IP Version 6 - ${CIVETWEB_ENABLE_IPV6}")
 option(CIVETWEB_ENABLE_WEBSOCKETS "Enable websockets connections" OFF)
 message(STATUS "Websockets support - ${CIVETWEB_ENABLE_WEBSOCKETS}")
 
+# Server statistics support
+option(CIVETWEB_ENABLE_SERVER_STATS "Enable server statistics" OFF)
+message(STATUS "Server statistics support - ${CIVETWEB_ENABLE_SERVER_STATS}")
+
 # Memory debugging
 option(CIVETWEB_ENABLE_MEMORY_DEBUGGING "Enable the memory debugging features" OFF)
 message(STATUS "Memory Debugging - ${CIVETWEB_ENABLE_MEMORY_DEBUGGING}")
 
+# ASAN in debug mode (-fsanitize=address, etc)
+option(CIVETWEB_ENABLE_ASAN "Enable ASAN in debug mode" ON)
+message(STATUS "ASAN in debug mode - ${CIVETWEB_ENABLE_ASAN}")
+
+# ARCH flag
+option(CIVETWEB_ARCH "Force 32/64 bit architecture" OFF)
+message(STATUS "Force x32 / x64 architecture - ${CIVETWEB_ARCH}")
+
 # LUA CGI support
 option(CIVETWEB_ENABLE_LUA "Enable Lua CGIs" OFF)
 message(STATUS "Lua CGI support - ${CIVETWEB_ENABLE_LUA}")
 
+# Enable installing CivetWeb executables
+option(CIVETWEB_INSTALL_EXECUTABLE "Enable installing CivetWeb executable" ON)
+mark_as_advanced(FORCE CIVETWEB_INSTALL_EXECUTABLE) # Advanced users can disable
+message(STATUS "Executable installation - ${CIVETWEB_INSTALL_EXECUTABLE}") 
+
 # Allow builds to complete with warnings (do not set -Werror)
-if (LINUX)
-# CivetWeb Linux support is stable: Builds must be free from warnings.
-  option(CIVETWEB_ALLOW_WARNINGS "Do not stop build if there are warnings" OFF)
-else()
-# CivetWeb Linux support for other systems is in a setup phase.
-  option(CIVETWEB_ALLOW_WARNINGS "Do not stop build if there are warnings" ON)
-endif()
+# CivetWeb Linux support is stable:
+# Builds for GCC 4.6 and clang 3.4 are free from warnings.
+# However, GCC introduced a couple of new, partially idiotic warnings,
+# that can not be disabled using a #pragma directive.
+# It seems unreasonable to have all GCC versions warning free, but only
+# some selected ones.
+option(CIVETWEB_ALLOW_WARNINGS "Do not stop build if there are warnings" ON)
 message(STATUS "Build if there are warnings - ${CIVETWEB_ALLOW_WARNINGS}")
 
 # Link to the shared LUA library
@@ -188,6 +199,10 @@ message(STATUS "Duktape CGI support - ${CIVETWEB_ENABLE_DUKTAPE}")
 option(CIVETWEB_ENABLE_SSL "Enables the secure socket layer" ON)
 message(STATUS "SSL support - ${CIVETWEB_ENABLE_SSL}")
 
+# OpenSSL 1.1 API
+option(CIVETWEB_SSL_OPENSSL_API_1_1 "Use the OpenSSL 1.1 API" OFF)
+message(STATUS "Compile for OpenSSL 1.1 API - ${CIVETWEB_SSL_OPENSSL_API_1_1}")
+
 # Dynamically load or link the SSL libraries
 cmake_dependent_option(
   CIVETWEB_ENABLE_SSL_DYNAMIC_LOADING "Dynamically loads the SSL library rather than linking it" ON
@@ -254,18 +269,26 @@ if ("${CIVETWEB_C_STANDARD}" STREQUAL "auto")
 else()
   add_c_compiler_flag(-std=${CIVETWEB_C_STANDARD})
 endif()
+
+#Warnings: enable everything
 add_c_compiler_flag(-Wall)
 add_c_compiler_flag(-Wextra)
 add_c_compiler_flag(-Wshadow)
 add_c_compiler_flag(-Wconversion)
 add_c_compiler_flag(-Wmissing-prototypes)
 add_c_compiler_flag(-Weverything)
-add_c_compiler_flag(/W4)
-add_c_compiler_flag(-Wno-padded)
-add_c_compiler_flag(/Wd4820) # padding
-add_c_compiler_flag(-Wno-unused-macros)
-add_c_compiler_flag(-Wno-format-nonliteral)
 add_c_compiler_flag(-Wparentheses)
+add_c_compiler_flag(/W4) # VisualStudio highest warning level
+
+#Warnings: Disable some warnings
+add_c_compiler_flag(-Wno-padded) # padding in structures by compiler
+add_c_compiler_flag(-Wno-unused-macros) # so what?
+add_c_compiler_flag(-Wno-reserved-id-macros) # for system headers
+add_c_compiler_flag(-Wno-format-nonliteral) # printf(myFormatStringVar, ...)
+add_c_compiler_flag(-Wno-date-time) # using __DATE__ once
+add_c_compiler_flag(-Wno-cast-qual) # const cast
+add_c_compiler_flag(/Wd4820) # padding
+
 if (MINGW)
   add_c_compiler_flag(-Wno-format)
 endif()
@@ -277,11 +300,13 @@ add_c_compiler_flag(-pedantic-errors)
 add_c_compiler_flag(-fvisibility=hidden)
 add_c_compiler_flag(-fstack-protector-strong RELEASE)
 add_c_compiler_flag(-flto RELEASE)
+if (${CIVETWEB_ENABLE_ASAN})
 add_c_compiler_flag(-fsanitize=undefined DEBUG)
 add_c_compiler_flag(-fsanitize=address DEBUG)
 if (HAVE_C_FLAG_FSANITIZE_ADDRESS)
   add_c_compiler_flag(-static-asan DEBUG)
 endif()
+endif()
 add_c_compiler_flag(-fstack-protector-all DEBUG)
 if (MINGW)
   add_c_compiler_flag(-mwindows)
@@ -344,11 +369,13 @@ if (CIVETWEB_ENABLE_CXX)
   add_cxx_compiler_flag(-fvisibility=hidden)
   add_cxx_compiler_flag(-fstack-protector-strong RELEASE)
   add_cxx_compiler_flag(-flto RELEASE)
+  if (${CIVETWEB_ENABLE_ASAN})
   add_cxx_compiler_flag(-fsanitize=undefined DEBUG)
   add_cxx_compiler_flag(-fsanitize=address DEBUG)
   if (HAVE_CXX_FLAG_FSANITIZE_ADDRESS)
     add_cxx_compiler_flag(-static-asan DEBUG)
   endif()
+  endif()
   add_cxx_compiler_flag(-fstack-protector-all DEBUG)
   if (MINGW)
     add_cxx_compiler_flag(-mwindows)
@@ -369,6 +396,9 @@ endif()
 if (CIVETWEB_ENABLE_WEBSOCKETS)
   add_definitions(-DUSE_WEBSOCKET)
 endif()
+if (CIVETWEB_ENABLE_SERVER_STATS)
+  add_definitions(-DUSE_SERVER_STATS)
+endif()
 if (CIVETWEB_SERVE_NO_FILES)
   add_definitions(-DNO_FILES)
 endif()
@@ -399,8 +429,19 @@ else()
     add_definitions(-DCRYPTO_LIB="${CIVETWEB_SSL_CRYPTO_LIB}")
   endif()
 endif()
+if(CIVETWEB_SSL_OPENSSL_API_1_1)
+  add_definitions(-DOPENSSL_API_1_1)
+endif()
 add_definitions(-DUSE_STACK_SIZE=${CIVETWEB_THREAD_STACK_SIZE})
-add_definitions(-DMAX_REQUEST_SIZE=${CIVETWEB_MAX_REQUEST_SIZE})
+
+# Set 32 or 64 bit environment
+if (${CMAKE_ARCH} MATCHES "[Xx]86")
+add_c_compiler_flag(-m32)
+endif()
+if (${CMAKE_ARCH} MATCHES "[Xx]64")
+add_c_compiler_flag(-m64)
+endif()
+# TODO: add support for -march
 
 # Build the targets
 add_subdirectory(src)

+ 26 - 2
CREDITS.md

@@ -1,10 +1,15 @@
 # Civetweb Contributors
 
+* Abhishek Lekshmanan
+* Adam Bailey
+* Alan Somers
 * Alex Kozlov
 * bel2125
 * Ben M. Ward
-* brett
+* BigJoe
 * Bjoern Petri
+* Braedy Kuzma
+* brett
 * Brian Lambert
 * Brian Spratke
 * cdbishop
@@ -23,13 +28,16 @@
 * ehlertjd
 * Eric Tsau
 * Erik Beran
+* extergnoto
 * F-Secure Corporation
 * feneuilflo
 * Fernando G. Aranda
 * Grahack
 * grenclave
+* grunk
 * hansipie
 * HariKamath Kamath
+* Henry Chang
 * Jack
 * Jacob Skillin
 * Jan Willem Janssen
@@ -44,8 +52,10 @@
 * Jordan Shelley
 * Joshua Boyd
 * Joshua D. Boyd
+* kakwa
 * kalphamon
 * Keith Kyzivat
+* Kevin Branigan
 * Kevin Wojniak
 * Kimmo Mustonen
 * Lammert Bies
@@ -60,38 +70,51 @@
 * Matt Clarkson
 * mingodad
 * Morgan McGuire
+* mrdvlpr.xnu
 * Neil Jensen
 * Nick Hildebrant
 * Nigel Stewart
 * nihildeb
 * No Face Press
+* palortoff
+* Patrick Drechsler
 * Patrick Trinkle
 * Paul Sokolovsky
+* Paulo Brizolara
+* pavel.pimenov
+* PavelVozenilek
 * Perttu Ahola
 * Peter Foerster
 * Philipp Friedenberger
 * Philipp Hasper
 * Red54
 * Richard Screene
+* pkvamme
 * Sage Weil
 * Sangwhan Moon
 * Saumitra Vikram
 * Scott Nations
+* sgmesservey
 * shantanugadgil
+* Simon Hailes
+* slidertom
 * SpaceLord
 * sunfch
 * thewaterymoon
+* THILMANT, Bernard
 * Thomas Davis
 * tnoho
 * Toni Wilk
 * Ulrich Hertlein
 * Walt Steverson
+* webxer
 * William Greathouse
+* xeoshow
 * xtne6f
 * Yehuda Sadeh
 
 # Mongoose Contributors
-Civetweb is based on the Mongoose code.  The following users contributed to the original Mongoose release between 2010 and 2013.  This list was generated from the Mongoose GIT logs.  It does not contain contributions from the Mongoose mailing list.  There is no record for contributors prior to 2010.
+CivetWeb is based on the Mongoose code.  The following users contributed to the original Mongoose release between 2010 and 2013.  This list was generated from the Mongoose GIT logs.  It does not contain contributions from the Mongoose mailing list.  There is no record for contributors prior to 2010.
 
 * Sergey Lyubka
 * Arnout Vandecappelle (Essensium/Mind)
@@ -141,3 +164,4 @@ Civetweb is based on the Mongoose code.  The following users contributed to the
 * tayS
 * test
 * valenok
+

+ 1 - 3
LICENSE.md

@@ -11,7 +11,7 @@ Civetweb License
 
 ### Included with all features.
 
-> Copyright (c) 2013-2015 The CivetWeb developers ([CREDITS.md](https://github.com/civetweb/civetweb/blob/master/CREDITS.md))
+> Copyright (c) 2013-2017 The CivetWeb developers ([CREDITS.md](https://github.com/civetweb/civetweb/blob/master/CREDITS.md))
 >
 > Copyright (c) 2004-2013 Sergey Lyubka
 >
@@ -206,5 +206,3 @@ https://github.com/svaarala/duktape/blob/master/LICENSE.txt
 > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 > THE SOFTWARE.
 
-
-

+ 23 - 3
Makefile

@@ -77,6 +77,15 @@ else
   LCC = $(CC)
 endif
 
+ifdef WITH_ALL
+  WITH_WEBSOCKET = 1
+  WITH_IPV6 = 1
+  WITH_LUA = 1
+  WITH_DUKTAPE = 1
+  WITH_SERVER_STATS = 1
+  #WITH_CPP is not defined, ALL means only real features, not wrappers
+endif
+
 ifdef WITH_LUA_SHARED
   WITH_LUA = 1
 endif
@@ -110,6 +119,16 @@ endif
 ifdef WITH_WEBSOCKET
   CFLAGS += -DUSE_WEBSOCKET
 endif
+ifdef WITH_WEBSOCKETS
+  CFLAGS += -DUSE_WEBSOCKET
+endif
+
+ifdef WITH_SERVER_STAT
+  CFLAGS += -DUSE_SERVER_STATS
+endif
+ifdef WITH_SERVER_STATS
+  CFLAGS += -DUSE_SERVER_STATS
+endif
 
 ifdef CONFIG_FILE
   CFLAGS += -DCONFIG_FILE=\"$(CONFIG_FILE)\"
@@ -180,6 +199,7 @@ help:
 	@echo "   WITH_DEBUG=1          build with GDB debug support"
 	@echo "   WITH_IPV6=1           with IPV6 support"
 	@echo "   WITH_WEBSOCKET=1      build with web socket support"
+	@echo "   WITH_SERVER_STATS=1   build includes support for server statistics"
 	@echo "   WITH_CPP=1            build library with c++ classes"
 	@echo "   CONFIG_FILE=file      use 'file' as the config file"
 	@echo "   CONFIG_FILE2=file     use 'file' as the backup config file"
@@ -198,7 +218,6 @@ help:
 	@echo "   NO_SSL_DL             link against system libssl library"
 	@echo "   NO_FILES              do not serve files from a directory"
 	@echo "   NO_CACHING            disable caching (usefull for systems without timegm())"
-	@echo "   MAX_REQUEST_SIZE      maximum header size, default 16384"
 	@echo ""
 	@echo " Variables"
 	@echo "   TARGET_OS='$(TARGET_OS)'"
@@ -247,7 +266,7 @@ slib: lib$(CPROG).$(SHARED_LIB)
 
 clean:
 	$(RMRF) $(BUILD_DIR)
-	$(eval version=$(shell grep "define CIVETWEB_VERSION" include/civetweb.h | sed 's|.*VERSION "\(.*\)"|\1|g'))
+	$(eval version=$(shell grep -w "define CIVETWEB_VERSION" include/civetweb.h | sed 's|.*VERSION "\(.*\)"|\1|g'))
 	$(eval major=$(shell echo $(version) | cut -d'.' -f1))
 	$(RMRF) lib$(CPROG).a
 	$(RMRF) lib$(CPROG).so
@@ -269,7 +288,7 @@ lib$(CPROG).a: $(LIB_OBJECTS)
 
 lib$(CPROG).so: CFLAGS += -fPIC
 lib$(CPROG).so: $(LIB_OBJECTS)
-	$(eval version=$(shell grep "define CIVETWEB_VERSION" include/civetweb.h | sed 's|.*VERSION "\(.*\)"|\1|g'))
+	$(eval version=$(shell grep -w "define CIVETWEB_VERSION" include/civetweb.h | sed 's|.*VERSION "\(.*\)"|\1|g'))
 	$(eval major=$(shell echo $(version) | cut -d'.' -f1))
 	$(LCC) -shared -Wl,-soname,$@.$(major) -o $@.$(version).0 $(CFLAGS) $(LDFLAGS) $(LIB_OBJECTS)
 	ln -s -f $@.$(major) $@
@@ -310,3 +329,4 @@ indent:
 	astyle --suffix=none --style=linux --indent=spaces=4 --lineend=linux  include/*.h src/*.c src/*.cpp src/*.inl examples/*/*.c  examples/*/*.cpp
 
 .PHONY: all help build install clean lib so
+

+ 34 - 28
Qt/CivetWeb.pro

@@ -1,28 +1,34 @@
-TEMPLATE = app
-CONFIG += console
-CONFIG -= app_bundle
-CONFIG -= qt
-
-SOURCES += \
-    ../src/md5.inl \
-    ../src/sha1.inl \
-    ../src/handle_form.inl \
-    ../src/mod_lua.inl \
-    ../src/timer.inl \
-    ../src/civetweb.c \
-    ../src/main.c
-
-#include(deployment.pri)
-#qtcAddDeployment()
-
-HEADERS += \
-    ../include/civetweb.h
-
-INCLUDEPATH +=  \
-    ../include/
-
-LIBS += -lws2_32 -lComdlg32 -lUser32 -lShell32 -lAdvapi32
-
-
-DEFINES += USE_IPV6
-DEFINES += USE_WEBSOCKET
+TEMPLATE = app
+CONFIG += console
+CONFIG -= app_bundle
+CONFIG -= qt
+
+SOURCES += \
+    ../src/md5.inl \
+    ../src/sha1.inl \
+    ../src/handle_form.inl \
+    ../src/mod_lua.inl \
+    ../src/mod_duktape.inl \
+    ../src/timer.inl \
+    ../src/civetweb.c \
+    ../src/main.c
+
+#include(deployment.pri)
+#qtcAddDeployment()
+
+HEADERS += \
+    ../include/civetweb.h
+
+INCLUDEPATH +=  \
+    ../include/
+
+win32 {
+LIBS += -lws2_32 -lComdlg32 -lUser32 -lShell32 -lAdvapi32
+} else {
+LIBS += -lpthread -ldl -lm
+}
+
+
+DEFINES += USE_IPV6
+DEFINES += USE_WEBSOCKET
+DEFINES += USE_SERVER_STATS

+ 33 - 27
README.md

@@ -1,8 +1,10 @@
-![CivetWeb](https://raw.github.com/civetweb/civetweb/master/resources/civetweb_64x64.png "CivetWeb") CivetWeb
+![CivetWeb](https://raw.githubusercontent.com/civetweb/civetweb/master/resources/civetweb_64x64.png "CivetWeb") CivetWeb
 =======
 
 **The official home of CivetWeb is [https://github.com/civetweb/civetweb](https://github.com/civetweb/civetweb)**
 
+[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
+[![GitHub contributors](https://img.shields.io/github/contributors/civetweb/civetweb.svg)](https://github.com/civetweb/civetweb/blob/master/CREDITS.md)
 
 Continuous integration for Linux and OSX ([Travis CI](https://travis-ci.org/civetweb/civetweb)):
 
@@ -12,17 +14,21 @@ Continuous integration for Windows ([AppVeyor](https://ci.appveyor.com/project/c
 
 [![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/github/civetweb/civetweb?svg=true)](https://ci.appveyor.com/project/civetweb/civetweb/branch/master)
 
-Test coverage check ([coveralls](https://coveralls.io/github/civetweb/civetweb)) (currently in a setup phase):
+Test coverage check ([coveralls](https://coveralls.io/github/civetweb/civetweb), [codecov](https://codecov.io/gh/civetweb/civetweb/branch/master)) (currently in a setup and evaluation phase):
 
+[![Coveralls](https://img.shields.io/coveralls/civetweb/civetweb.svg?maxAge=3600)]()
 [![Coverage Status](https://coveralls.io/repos/github/civetweb/civetweb/badge.svg?branch=master)](https://coveralls.io/github/civetweb/civetweb?branch=master)
 
+[![codecov](https://codecov.io/gh/civetweb/civetweb/branch/master/graph/badge.svg)](https://codecov.io/gh/civetweb/civetweb)
+
+
+
 Static source code analysis ([Coverity](https://scan.coverity.com/projects/5784)):
 
 [![Coverity Scan Build Status](https://scan.coverity.com/projects/5784/badge.svg)](https://scan.coverity.com/projects/5784)
 
 
 
-
 Project Mission
 -----------------
 
@@ -37,7 +43,7 @@ It can also be used by end users as a stand-alone web server. It is available as
 Where to find the official version?
 -----------------------------------
 
-End users can download CivetWeb at SourceForge
+End users can download CivetWeb releases at SourceForge
 [https://sourceforge.net/projects/civetweb/](https://sourceforge.net/projects/civetweb/)
 
 Developers can contribute to CivetWeb via GitHub
@@ -46,12 +52,15 @@ Developers can contribute to CivetWeb via GitHub
 Trouble tickets should be filed on GitHub
 [https://github.com/civetweb/civetweb/issues](https://github.com/civetweb/civetweb/issues)
 
-Discussion/support group and announcements are at Google Groups
-[https://groups.google.com/d/forum/civetweb](https://groups.google.com/d/forum/civetweb)
+Announcements are at Google Groups
+[https://groups.google.com/d/forum/civetweb](https://groups.google.com/d/forum/civetweb). Some older support and discussion threads are there as well. However, recently support questions and discussions are usually [GitHub issues](https://github.com/civetweb/civetweb/issues).
 
 Source releases can be found on GitHub
 [https://github.com/civetweb/civetweb/releases](https://github.com/civetweb/civetweb/releases)
 
+A very brief overview can be found on GitHub Pages
+[http://civetweb.github.io/civetweb/](http://civetweb.github.io/civetweb/)
+
 
 Quick start documentation
 --------------------------
@@ -100,33 +109,29 @@ simplicity by a carefully selected list of features:
 
 ### Optionally included software
 
-<a href="http://lua.org">
-![Lua](https://raw.github.com/civetweb/civetweb/master/resources/lua-logo.jpg "Lua Logo")
-</a>
-<a href="http://sqlite.org">
-![Sqlite3](https://raw.github.com/civetweb/civetweb/master/resources/sqlite3-logo.jpg "Sqlite3 Logo")
-</a>
-<a href="http://keplerproject.github.io/luafilesystem/">
-![LuaFileSystem](https://raw.github.com/civetweb/civetweb/master/resources/luafilesystem-logo.jpg "LuaFileSystem Logo")
-</a>
-<a href="http://lua.sqlite.org/index.cgi/index">
-![LuaSQLite3](https://raw.github.com/civetweb/civetweb/master/resources/luasqlite-logo.jpg "LuaSQLite3 Logo")
-</a>
-<a href="http://viremo.eludi.net/LuaXML/index.html">
-![LuaXML](https://raw.github.com/civetweb/civetweb/master/resources/luaxml-logo.jpg "LuaXML Logo")
-</a>
-<a href="http://duktape.org">
-![Duktape](https://raw.github.com/civetweb/civetweb/master/resources/duktape-logo.png "Duktape Logo")
-</a>
+[![Lua](https://raw.githubusercontent.com/civetweb/civetweb/master/resources/lua-logo.jpg "Lua Logo")](http://lua.org)
+
+[![Sqlite3](https://raw.githubusercontent.com/civetweb/civetweb/master/resources/sqlite3-logo.jpg "Sqlite3 Logo")](http://sqlite.org)
+
+[![LuaFileSystem](https://raw.githubusercontent.com/civetweb/civetweb/master/resources/luafilesystem-logo.jpg "LuaFileSystem Logo")](http://keplerproject.github.io/luafilesystem/)
+
+[![LuaSQLite3](https://raw.githubusercontent.com/civetweb/civetweb/master/resources/luasqlite-logo.jpg "LuaSQLite3 Logo")](http://lua.sqlite.org/index.cgi/index)
+
+[![LuaXML](https://raw.githubusercontent.com/civetweb/civetweb/master/resources/luaxml-logo.jpg "LuaXML Logo")](http://viremo.eludi.net/LuaXML/index.html)
+
+[![Duktape](https://raw.githubusercontent.com/civetweb/civetweb/master/resources/duktape-logo.png "Duktape Logo")](http://duktape.org)
 
 
 Support
 -------
 
-This project is very easy to install and use. Please read the [documentation](https://github.com/civetweb/civetweb/blob/master/docs/)
-and have a look at the [examples] (https://github.com/civetweb/civetweb/blob/master/examples/).
+This project is very easy to install and use. 
+Please read the [documentation](https://github.com/civetweb/civetweb/blob/master/docs/)
+and have a look at the [examples](https://github.com/civetweb/civetweb/blob/master/examples/).
 More information may be found on the [mailing list](https://groups.google.com/d/forum/civetweb).
 
+Note: I do not take any liability or warranty for any linked contents.  Visit these pages and try the community support suggestions at your own risk.
+
 
 Contributions
 ---------------
@@ -134,7 +139,7 @@ Contributions
 Contributions are welcome provided all contributions carry the MIT license.
 
 DO NOT APPLY fixes copied from Mongoose to this project to prevent GPL tainting.
-Since 2013 CivetWeb and Mongoose are developed independently.
+Since 2013, CivetWeb and Mongoose are developed independently.
 By now the code base differs, so patches cannot be safely transfered in either direction.
 
 Some guidelines can be found in [docs/Contribution.md](https://github.com/civetweb/civetweb/blob/master/docs/Contribution.md).
@@ -160,3 +165,4 @@ A list of authors can be found in [CREDITS.md](https://github.com/civetweb/civet
 Using the CivetWeb project ensures the MIT licenses terms are applied and
 GPL cannot be imposed on any of this code, as long as it is sourced from
 here. This code will remain free with the MIT license protection.
+

+ 52 - 1
RELEASE_NOTES.md

@@ -1,3 +1,54 @@
+Release Notes v1.10
+===
+### Objectives: *OpenSSL 1.1 support, add server statistics and diagnostic data*
+
+Changes
+-------
+
+- Add missing `mg_` or `MG_` to symbols in civetweb.h. Symbols without will be removed a future version.
+- Add HTTPS server configuration example
+- Lua Pages: mg.include should support absolute, relative and virtual path types
+- Add API function for HTTP digest authentication
+- Improved interface documentation
+- Support parameters for Lua background scripts
+- Use new connection queue implementation (previously ALTERNATIVE\_QUEUE) as default
+- Add USE\_SERVER\_STATS define, so the server collects statistics data
+- Convert system\_info text output and all other diagnostic strings to JSON format
+- Add experimental function to query the connection status (may be dropped again)
+- Add document on proposed future interface changes (for comments)
+- Officially drop Symbian support
+- Ignore leading blank lines in multipart messages (for Android upload service)
+- Rewrite some functions, in particular request parsing
+- CORS preflight directly in the server, with additional config options
+- Solve some warnings from different static source code analysis tools
+- Collect server status data
+- Allow hostname in listening\_ports
+- Make maximum request size configurable
+- Allow multiple Sec-Websocket-Protocol
+- Add configuration option to send additional headers
+- Add configuration option for Strict-Transport-Security
+- Mark "file in memory" feature is a candidate for deletion
+- Improve examples
+- Fix timeout error when sending larger files
+- Add mg\_send\_chunk interface function
+- Allow to separate server private key and certificate chain in two different files
+- Support for multipart requests without quotes (for some C# clients)
+- Initialize SSL in mg\_init\_library, so https client functions can be used when no server is running
+- Allow "REPORT" HTTP method for REST calls to scripts
+- Allow to compile civetweb.c wih a C++ compiler
+- Lua: Remove internal length limits of encode/decode functions
+- Allow sub-resources of index script files
+- Add config parameter allow\_index\_script\_resource the aforementioned feature
+- Remove deprecated "uri" member of the request from the interface
+- Improve documentation
+- Make auth domain check optional (configuration)
+- Update unit test framework to check 0.11.0 (C89/C90 compilers still need a patched version)
+- Limit depth of mg.include for Lua server pages
+- Additional unit tests
+- OpenSSL 1.1 support
+- Update version number
+
+
 Release Notes v1.9.1
 ===
 ### Objectives: *Bug fix*
@@ -339,6 +390,6 @@ Changes
 
 - Renamed Mongoose to Civetweb in the code and documentation.
 - Replaced copyrighted images with new images
-- Created a new code respository at https://github.com/bel2125/civetweb
+- Created a new code respository at https://github.com/civetweb/civetweb
 - Created a distribution site at https://sourceforge.net/projects/civetweb/
 - Basic build testing

+ 1 - 1
VisualStudio/civetweb.sln

@@ -1,7 +1,7 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 14
-VisualStudioVersion = 14.0.23107.0
+VisualStudioVersion = 14.0.25420.1
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "civetweb_lua", "civetweb_lua\civetweb_lua.vcxproj", "{9BE9C008-E851-42B1-A034-BD4630AE4CD6}"
 	ProjectSection(ProjectDependencies) = postProject

+ 7 - 6
VisualStudio/civetweb_lua/civetweb_lua.vcxproj

@@ -22,13 +22,14 @@
     <ProjectGuid>{9BE9C008-E851-42B1-A034-BD4630AE4CD6}</ProjectGuid>
     <Keyword>Win32Proj</Keyword>
     <RootNamespace>civetweb_lua</RootNamespace>
+    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
     <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v140_xp</PlatformToolset>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
@@ -47,7 +48,7 @@
     <UseDebugLibraries>false</UseDebugLibraries>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v140_xp</PlatformToolset>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
@@ -101,7 +102,7 @@
       </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>USE_DUKTAPE;USE_IPV6;LUA_COMPAT_ALL;USE_LUA;USE_LUA_SQLITE3;USE_LUA_FILE_SYSTEM;USE_WEBSOCKET;WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>USE_SERVER_STATS;USE_DUKTAPE;USE_IPV6;LUA_COMPAT_ALL;USE_LUA;USE_LUA_SQLITE3;USE_LUA_FILE_SYSTEM;USE_WEBSOCKET;WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>$(ProjectDir)..\..\include;$(ProjectDir)..\..\src\third_party;$(ProjectDir)..\..\src\third_party\lua-5.2.4\src;$(ProjectDir)..\..\src\third_party\duktape-1.5.2\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
@@ -115,7 +116,7 @@
       </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>USE_DUKTAPE;USE_IPV6;LUA_COMPAT_ALL;USE_LUA;USE_LUA_SQLITE3;USE_LUA_FILE_SYSTEM;USE_WEBSOCKET;WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>USE_SERVER_STATS;USE_DUKTAPE;USE_IPV6;LUA_COMPAT_ALL;USE_LUA;USE_LUA_SQLITE3;USE_LUA_FILE_SYSTEM;USE_WEBSOCKET;WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>$(ProjectDir)..\..\include;$(ProjectDir)..\..\src\third_party;$(ProjectDir)..\..\src\third_party\lua-5.2.4\src;$(ProjectDir)..\..\src\third_party\duktape-1.5.2\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
@@ -145,7 +146,7 @@
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>USE_DUKTAPE;USE_IPV6;LUA_COMPAT_ALL;USE_LUA;USE_LUA_SQLITE3;USE_LUA_FILE_SYSTEM;USE_WEBSOCKET;WIN32;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>USE_SERVER_STATS;USE_DUKTAPE;USE_IPV6;LUA_COMPAT_ALL;USE_LUA;USE_LUA_SQLITE3;USE_LUA_FILE_SYSTEM;USE_WEBSOCKET;WIN32;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>$(ProjectDir)..\..\include;$(ProjectDir)..\..\src\third_party;$(ProjectDir)..\..\src\third_party\lua-5.2.4\src;$(ProjectDir)..\..\src\third_party\duktape-1.5.2\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
@@ -163,7 +164,7 @@
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>USE_DUKTAPE;USE_IPV6;LUA_COMPAT_ALL;USE_LUA;USE_LUA_SQLITE3;USE_LUA_FILE_SYSTEM;USE_WEBSOCKET;WIN32;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>USE_SERVER_STATS;USE_DUKTAPE;USE_IPV6;LUA_COMPAT_ALL;USE_LUA;USE_LUA_SQLITE3;USE_LUA_FILE_SYSTEM;USE_WEBSOCKET;WIN32;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>$(ProjectDir)..\..\include;$(ProjectDir)..\..\src\third_party;$(ProjectDir)..\..\src\third_party\lua-5.2.4\src;$(ProjectDir)..\..\src\third_party\duktape-1.5.2\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>

+ 2 - 2
VisualStudio/duktape_lib/duktape_lib.vcxproj

@@ -29,7 +29,7 @@
     <ConfigurationType>StaticLibrary</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
     <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v140_xp</PlatformToolset>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
@@ -42,7 +42,7 @@
     <UseDebugLibraries>false</UseDebugLibraries>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v140_xp</PlatformToolset>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>

+ 2 - 2
VisualStudio/ex_embed_cpp/ex_embed_cpp.vcxproj

@@ -28,7 +28,7 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v140_xp</PlatformToolset>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@@ -40,7 +40,7 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v140_xp</PlatformToolset>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>

+ 2 - 2
VisualStudio/ex_embedded_c/ex_embedded_c.vcxproj

@@ -35,7 +35,7 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v140_xp</PlatformToolset>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
@@ -47,7 +47,7 @@
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v140_xp</PlatformToolset>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
   </PropertyGroup>

+ 2 - 2
VisualStudio/lua_lib/lua_lib.vcxproj

@@ -29,7 +29,7 @@
     <ConfigurationType>StaticLibrary</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
     <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v140_xp</PlatformToolset>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>
@@ -42,7 +42,7 @@
     <UseDebugLibraries>false</UseDebugLibraries>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v140_xp</PlatformToolset>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
     <ConfigurationType>StaticLibrary</ConfigurationType>

+ 5 - 4
VisualStudio/unit_test/unit_test.vcxproj

@@ -33,20 +33,21 @@
     <ProjectGuid>{1AC4A7A6-0100-4287-97F4-B95807BE5607}</ProjectGuid>
     <Keyword>Win32Proj</Keyword>
     <RootNamespace>unit_test</RootNamespace>
+    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>true</UseDebugLibraries>
     <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v140_xp</PlatformToolset>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
     <ConfigurationType>Application</ConfigurationType>
     <UseDebugLibraries>false</UseDebugLibraries>
     <WholeProgramOptimization>true</WholeProgramOptimization>
     <CharacterSet>MultiByte</CharacterSet>
-    <PlatformToolset>v140</PlatformToolset>
+    <PlatformToolset>v140_xp</PlatformToolset>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
@@ -72,7 +73,7 @@
       </PrecompiledHeader>
       <WarningLevel>Level3</WarningLevel>
       <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>LOCAL_TEST;REPLACE_CHECK_FOR_LOCAL_DEBUGGING;USE_IPV6;USE_WEBSOCKET;MEMORY_DEBUGGING;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>REPLACE_CHECK_FOR_LOCAL_DEBUGGING;LOCAL_TEST;USE_IPV6;USE_WEBSOCKET;MEMORY_DEBUGGING;WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>$(ProjectDir)..\..\src;$(ProjectDir)..\..\include;$(ProjectDir)..\..\src\third_party\lua-5.2.4\src;$(ProjectDir)..\..\..\check-0.10.0\;$(ProjectDir)..\..\..\check-0.10.0\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
@@ -88,7 +89,7 @@
       <Optimization>MaxSpeed</Optimization>
       <FunctionLevelLinking>true</FunctionLevelLinking>
       <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>REPLACE_CHECK_FOR_LOCAL_DEBUGGING;WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>$(ProjectDir)..\..\src;$(ProjectDir)..\..\include;$(ProjectDir)..\..\src\third_party\lua-5.2.4\src;$(ProjectDir)..\..\..\check-0.10.0\;$(ProjectDir)..\..\..\check-0.10.0\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>

+ 3 - 3
VisualStudio/unit_test/unit_test.vcxproj.filters

@@ -39,6 +39,9 @@
     <ClInclude Include="..\..\test\civetweb_check.h">
       <Filter>Headerdateien</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\test\timertest.c">
+      <Filter>Quelldateien</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\test\public_server.c">
@@ -53,9 +56,6 @@
     <ClCompile Include="..\..\test\private_exe.c">
       <Filter>Quelldateien</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\test\timertest.c">
-      <Filter>Quelldateien</Filter>
-    </ClCompile>    
     <ClCompile Include="..\..\test\shared.c">
       <Filter>Quelldateien</Filter>
     </ClCompile>

+ 171 - 37
appveyor.yml

@@ -5,9 +5,13 @@ build:
 # no automatic build in script mode
 
 
-platform:
-  - x86
-  - x64
+skip_commits:
+  # Builds just testing something on Travis CI don't need to be 
+  # done on AppVeyor
+  message: /\[Travis\]/
+  # Dont build, if only documentation was changed
+  files:
+  - '**/*.md'
 
 
 environment:
@@ -18,47 +22,123 @@ environment:
   c_standard: auto
   cxx_standard: auto
   matrix:
-    - id: 1
-      compiler: msvc-18-seh
+    # Use default values
+    - id: Default-x86
+      compiler: msvc-19-seh
       build_shared: NO
       no_files: NO
       enable_ipv6: NO
       enable_ssl: YES
-      enable_websockets: YES
+      enable_websockets: NO
       no_cgi: NO
       no_caching: NO
       configuration: Release
-    - id: 2
-      compiler: msvc-18-seh
-      build_shared: YES
+      platform: x86
+    - id: Default-x64
+      compiler: msvc-19-seh
+      build_shared: NO
       no_files: NO
       enable_ipv6: NO
       enable_ssl: YES
+      enable_websockets: NO
+      no_cgi: NO
+      no_caching: NO
+      configuration: Release
+      platform: x64
+    # Use default values
+    - id: Full-x86
+      compiler: msvc-19-seh
+      build_shared: NO
+      no_files: NO
+      enable_ipv6: YES
+      enable_ssl: YES
       enable_websockets: YES
       no_cgi: NO
       no_caching: NO
       configuration: Release
-    - id: 3
-      compiler: msvc-18-seh
-      build_shared: YES
-      no_files: YES
-      enable_ipv6: NO
+      platform: x86
+    - id: Full-x64
+      compiler: msvc-19-seh
+      build_shared: NO
+      no_files: NO
+      enable_ipv6: YES
       enable_ssl: YES
       enable_websockets: YES
       no_cgi: NO
       no_caching: NO
       configuration: Release
-    - id: 4
-      compiler: gcc-5.1.0-posix
+      platform: x64
+    # Debug builds
+    - id: Full-x86-Debug
+      compiler: msvc-19-seh
+      build_shared: NO
+      no_files: NO
+      enable_ipv6: YES
+      enable_ssl: YES
+      enable_websockets: YES
+      no_cgi: NO
+      no_caching: NO
+      configuration: Debug
+      platform: x86
+    - id: Full-x64-Debug
+      compiler: msvc-19-seh
+      build_shared: NO
+      no_files: NO
+      enable_ipv6: YES
+      enable_ssl: YES
+      enable_websockets: YES
+      no_cgi: NO
+      no_caching: NO
+      configuration: Debug
+      platform: x64
+    # Minimum settings
+    - id: Minimal-x86
+      compiler: msvc-19-seh
+      build_shared: NO
+      no_files: YES
+      enable_ipv6: NO
+      enable_ssl: NO
+      enable_websockets: NO
+      no_cgi: YES
+      no_caching: YeS
+      configuration: Release
+      platform: x86
+    - id: Minimal-x64
+      compiler: msvc-19-seh
       build_shared: NO
       no_files: YES
       enable_ipv6: NO
       enable_ssl: NO
       enable_websockets: NO
       no_cgi: YES
-      no_caching: YES
+      no_caching: YeS
+      configuration: Release
+      platform: x64
+    # Test shared and debug build
+    - id: Shared-default-x86
+      compiler: msvc-19-seh
+      build_shared: YES
+      no_files: NO
+      enable_ipv6: NO
+      enable_ssl: YES
+      enable_websockets: NO
+      no_cgi: NO
+      no_caching: NO
       configuration: Release
-    - id: 5
+      platform: x86
+    - id: Shared-default-x64
+      compiler: msvc-19-seh
+      build_shared: YES
+      no_files: NO
+      enable_ipv6: NO
+      enable_ssl: YES
+      enable_websockets: NO
+      no_cgi: NO
+      no_caching: NO
+      configuration: Release
+      platform: x64
+    # MinGW
+    - id: Full-GCC-x64
       compiler: gcc-5.1.0-posix
       build_shared: NO
       no_files: NO
@@ -66,39 +146,46 @@ environment:
       enable_ssl: YES
       enable_websockets: YES
       no_cgi: NO
-      no_caching: YES
+      no_caching: NO
       configuration: Release
-    - id: 6
-      compiler: gcc-5.1.0-posix
+      platform: x64
+    # Visual Studio 2010
+    - id: Full-VS2010-x86
+      compiler: msvc-16-seh
       build_shared: NO
       no_files: NO
-      enable_ipv6: NO
+      enable_ipv6: YES
       enable_ssl: YES
       enable_websockets: YES
       no_cgi: NO
-      no_caching: YES
+      no_caching: NO
       configuration: Release
-    - id: 7
-      compiler: gcc-5.1.0-posix
-      build_shared: YES
+      platform: x86
+    # Visual Studio 2012
+    - id: Full-VS2012-x86
+      compiler: msvc-17-seh
+      build_shared: NO
       no_files: NO
-      enable_ipv6: NO
+      enable_ipv6: YES
       enable_ssl: YES
       enable_websockets: YES
       no_cgi: NO
-      no_caching: YES
+      no_caching: NO
       configuration: Release
-    - id: 8
-      compiler: gcc-5.1.0-posix
-      build_shared: YES
-      no_files: YES
-      enable_ipv6: NO
+      platform: x86
+    # Visual Studio 2013
+    - id: Full-VS2013-x86
+      compiler: msvc-18-seh
+      build_shared: NO
+      no_files: NO
+      enable_ipv6: YES
       enable_ssl: YES
       enable_websockets: YES
       no_cgi: NO
-      no_caching: YES
+      no_caching: NO
       configuration: Release
-    - id: 9
+      platform: x86
+    - id: Full-VS2013-x64
       compiler: msvc-18-seh
       build_shared: NO
       no_files: NO
@@ -107,7 +194,35 @@ environment:
       enable_websockets: YES
       no_cgi: NO
       no_caching: NO
-      configuration: Debug
+      configuration: Release
+      platform: x64
+    # Visual Studio 2015 is default
+    # Visual Studio 2017 is not yet default
+    - id: Full-VS2017-x86
+      compiler: msvc-20-seh
+      build_shared: NO
+      no_files: NO
+      enable_ipv6: YES
+      enable_ssl: YES
+      enable_websockets: YES
+      no_cgi: NO
+      no_caching: NO
+      configuration: Release
+      platform: x86
+      APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+    - id: Full-VS2017-x64
+      compiler: msvc-20-seh
+      build_shared: NO
+      no_files: NO
+      enable_ipv6: YES
+      enable_ssl: YES
+      enable_websockets: YES
+      no_cgi: NO
+      no_caching: NO
+      configuration: Release
+      platform: x64
+      APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
+
 
 install:
   # Derive some extra information
@@ -166,6 +281,7 @@ before_build:
   - if "%compiler_version%"=="17" (set "vs_version=11" & set "vs_year=2012")
   - if "%compiler_version%"=="18" (set "vs_version=12" & set "vs_year=2013")
   - if "%compiler_version%"=="19" (set "vs_version=14" & set "vs_year=2015")
+  - if "%compiler_version%"=="20" (set "vs_version=15" & set "vs_year=2017")
   - if "%compiler_name%"=="msvc" (set "generator=Visual Studio %vs_version% %vs_year%")
   - if "%compiler_name%"=="msvc" (
       if "%platform%"=="x64" (
@@ -231,12 +347,30 @@ test_script:
   - cmd /c "%test%"
   - cd "%source_path%"
 
+  - set "output_path=%source_path%\output"
+  - set "build_path=%output_path%\build"
+  - set "install_path=%output_path%\install"
+  - set "third_party_dir=C:\third-party"
+
 after_test:
+  - echo "Current directory:"
   - cd
   - dir
   - md dist
   - if "%build_type%"=="Release" (cmake "-DCMAKE_INSTALL_PREFIX=%install_path%" -P "%build_path%/cmake_install.cmake")
-  - if "%build_type%"=="Release" (copy "%build_path%" dist\)
+  - dir dist\
+  - echo "Output directory:"
+  - dir %output_path%
+  - echo "Build directory:"
+  - dir %build_path%
+  - if "%build_type%"=="Release" (echo "Install directory:")
+  - if "%build_type%"=="Release" (dir %install_path%)
+  - if "%build_type%"=="Release" (dir %install_path%\bin)
+  - if "%build_type%"=="Release" (dir %install_path%\include)
+  - if "%build_type%"=="Release" (dir %install_path%\lib)
+  - if "%build_type%"=="Release" (copy "%install_path%"\include dist\)
+  - if "%build_type%"=="Release" (copy "%install_path%"\bin\*.exe dist\)
+  - echo "Dist directory:"
   - dir dist\
 
 matrix:

+ 1 - 1
ci/travis/install_rocks.sh

@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 set -ev
 
 source ci/travis/lua_env.sh

+ 1 - 1
ci/travis/lua_env.sh

@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 
 LUAROCKS=ci/lua/bin/luarocks
 eval $($LUAROCKS path --bin)

+ 1 - 1
ci/travis/run_ci_tests.sh

@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
 set -ev
 
 source ci/travis/lua_env.sh

+ 1 - 1
ci/travis/setup_lua.sh

@@ -1,4 +1,4 @@
-#! /bin/bash
+#!/usr/bin/env /bash
 set -ev
 
 # this script installs a lua / luarocks environment in .travis/lua

+ 1 - 1
contrib/buildroot/civetweb.mk

@@ -4,7 +4,7 @@
 #
 ################################################################################
 
-CIVETWEB_VERSION = 1.9
+CIVETWEB_VERSION = 1.10
 CIVETWEB_SITE = http://github.com/civetweb/civetweb/tarball/v$(CIVETWEB_VERSION)
 CIVETWEB_LICENSE = MIT
 CIVETWEB_LICENSE_FILES = LICENSE.md

+ 79 - 23
docs/APIReference.md

@@ -5,17 +5,33 @@ A C API is available to integrate the CivetWeb functionality in a larger
 codebase. A C++ wrapper is also available, although it is not guaranteed
 that all functionality available through the C API can also be accessed
 from C++. This document describes the public C API. Basic usage examples of
-the API can be found in [Embedding.md](Embedding.md).
+the API can be found in [Embedding.md](Embedding.md), as well as in the
+examples directory.
 
 ## Macros
 
 | Macro | Description |
 | :--- | :--- |
-| **`CIVETWEB_VERSION`** | The current version of the website as a string with the major and minor version number seperated with a dot. For version 1.9, this string will for example have the value "1.9" |
+| **`CIVETWEB_VERSION`** | The current version of the software as a string with the major and minor version number seperated with a dot. For version 1.9, this string will have the value "1.9", for thw first patch of this version "1.9.1". |
+| **`CIVETWEB_VERSION_MAJOR`** | The current major version as number, e.g., (1) for version 1.9. |
+| **`CIVETWEB_VERSION_MINOR`** | The current minor version as number, e.g., (9) for version 1.9. |
+| **`CIVETWEB_VERSION_PATCH`** | The current patch version as number, e.g., (0) for version 1.9 or (1) for version 1.9.1. |
+
+## Handles
+
+* `struct mg_context *`
+Handle for one instance of the HTTP(S) server.
+All functions using `const struct mg_context *` as an argument do not modify a running server instance, but just query information. Functions using a non-const `struct mg_context *` as an argument may modify a server instance (e.g., register a new URI, stop the server, ...).
+
+* `struct mg_connection *`
+Handle for one individual client-server connection.
+Functions working with `const struct mg_connection *` operate on data already known to the server without reading data from or sending data to the client. Callbacks using a `const struct mg_connection *` argument are supposed to not call functions from the `mg_read()` and `mg_write()` family. To support a correct application, reading and writing functions require a non-const `struct mg_connection *` connection handle.
+
+The content of both structures is not defined in the interface - they are only used as opaque pointers (handles).
 
 ## Structures
 
-* [`struct client_cert;`](api/client_cert.md)
+* [`struct mg_client_cert;`](api/mg_client_cert.md)
 * [`struct mg_client_options;`](api/mg_client_options.md)
 * [`struct mg_callbacks;`](api/mg_callbacks.md)
 * [`struct mg_form_data_handler;`](api/mg_form_data_handler.md)
@@ -24,55 +40,95 @@ the API can be found in [Embedding.md](Embedding.md).
 * [`struct mg_request_info;`](api/mg_request_info.md)
 * [`struct mg_server_ports;`](api/mg_server_ports.md)
 
-## Functions
+
+## Library API Functions
+
+* [`mg_init_library( feature );`](api/mg_init_library.md)
+* [`mg_exit_library( feature );`](api/mg_exit_library.md)
 
 * [`mg_check_feature( feature );`](api/mg_check_feature.md)
-* [`mg_close_connection( conn );`](api/mg_close_connection.md)
+* [`mg_version();`](api/mg_version.md)
+
+
+## Server API Functions
+
+* [`mg_start( callbacks, user_data, options );`](api/mg_start.md)
+* [`mg_stop( ctx );`](api/mg_stop.md)
+
+* [`mg_get_builtin_mime_type( file_name );`](api/mg_get_builtin_mime_type.md)
+* [`mg_get_option( ctx, name );`](api/mg_get_option.md)
+* [`mg_get_server_ports( ctx, size, ports );`](api/mg_get_server_ports.md)
+* [`mg_get_user_data( ctx );`](api/mg_get_user_data.md)
+* [`mg_set_auth_handler( ctx, uri, handler, cbdata );`](api/mg_set_auth_handler.md)
+* [`mg_set_request_handler( ctx, uri, handler, cbdata );`](api/mg_set_request_handler.md)
+* [`mg_set_websocket_handler( ctx, uri, connect_handler, ready_handler, data_handler, close_handler, cbdata );`](api/mg_set_websocket_handler.md)
+
+* [`mg_lock_context( ctx );`](api/mg_lock_context.md)
+* [`mg_unlock_context( ctx );`](api/mg_unlock_context.md)
+
+* [`mg_get_context( conn );`](api/mg_get_context.md)
+
+* [`mg_send_http_error( conn, status_code, fmt, ... );`](api/mg_send_http_error.md)
+
+* [`mg_send_digest_access_authentication_request( conn, realm );`](api/mg_send_digest_access_authentication_request.md)
+* [`mg_check_digest_access_authentication( conn, realm, filename );`](api/mg_check_digest_access_authentication.md)
+* [`mg_modify_passwords_file( passwords_file_name, realm, user, password );`](api/mg_modify_passwords_file.md)
+
+
+## Client API Functions
+
 * [`mg_connect_client( host, port, use_ssl, error_buffer, error_buffer_size );`](api/mg_connect_client.md)
 * [`mg_connect_websocket_client( host, port, use_ssl, error_buffer, error_buffer_size, path, origin, data_func, close_func, user_data);`](api/mg_connect_websocket_client.md)
-* [`mg_cry( conn, fmt, ... );`](api/mg_cry.md)
+* [`mg_websocket_client_write( conn, opcode, data, data_len );`](api/mg_websocket_client_write.md)
+
 * [`mg_download( host, port, use_ssl, error_buffer, error_buffer_size, fmt, ... );`](api/mg_download.md)
-* [`mg_get_builtin_mime_type( file_name );`](api/mg_get_builtin_mime_type.md)
-* [`mg_get_context( conn );`](api/mg_get_context.md)
+
+
+## Common API Functions
+
+* [`mg_close_connection( conn );`](api/mg_close_connection.md)
+* [`mg_cry( conn, fmt, ... );`](api/mg_cry.md)
+
 * [`mg_get_cookie( cookie, var_name, buf, buf_len );`](api/mg_get_cookie.md)
 * [`mg_get_header( conn, name );`](api/mg_get_header.md)
-* [`mg_get_option( ctx, name );`](api/mg_get_option.md)
 * [`mg_get_request_info( conn );`](api/mg_get_request_info.md)
 * [`mg_get_response( conn, ebuf, ebuf_len, timeout );`](api/mg_get_response.md)
 * [`mg_get_response_code_text( conn, response_code );`](api/mg_get_response_code_text.md)
-* [`mg_get_server_ports( ctx, size, ports );`](api/mg_get_server_ports.md)
 * [`mg_get_user_connection_data( conn );`](api/mg_get_user_connection_data.md)
-* [`mg_get_user_data( ctx );`](api/mg_get_user_data.md)
-* [~~`mg_get_valid_option_names();`~~](api/mg_get_valid_option_names.md)
 * [`mg_get_valid_options();`](api/mg_get_valid_options.md)
 * [`mg_get_var( data, data_len, var_name, dst, dst_len );`](api/mg_get_var.md)
 * [`mg_get_var2( data, data_len, var_name, dst, dst_len, occurrence );`](api/mg_get_var2.md)
 * [`mg_handle_form_request( conn, fdh );`](api/mg_handle_form_request.md)
 * [`mg_lock_connection( conn );`](api/mg_lock_connection.md)
-* [`mg_lock_context( ctx );`](api/mg_lock_context.md)
 * [`mg_md5( buf, ... );`](api/mg_md5.md)
-* [`mg_modify_passwords_file( passwords_file_name, domain, user, password );`](api/mg_modify_passwords_file.md)
 * [`mg_printf( conn, fmt, ... );`](api/mg_printf.md)
 * [`mg_read( conn, buf, len );`](api/mg_read.md)
+* [`mg_send_chunk( conn, buf, len );`](api/mg_send_chunk.md)
 * [`mg_send_file( conn, path );`](api/mg_send_file.md)
 * [`mg_send_mime_file( conn, path, mime_type );`](api/mg_send_mime_file.md)
 * [`mg_send_mime_file2( conn, path, mime_type, additional_headers );`](api/mg_send_mime_file2.md)
-* [`mg_set_auth_handler( ctx, uri, handler, cbdata );`](api/mg_set_auth_handler.md)
-* [`mg_set_request_handler( ctx, uri, handler, cbdata );`](api/mg_set_request_handler.md)
 * [`mg_set_user_connection_data( conn, data );`](api/mg_set_user_connection_data.md)
-* [`mg_set_websocket_handler( ctx, uri, connect_handler, ready_handler, data_handler, close_handler, cbdata );`](api/mg_set_websocket_handler.md)
-* [`mg_start( callbacks, user_data, options );`](api/mg_start.md)
 * [`mg_start_thread( f, p );`](api/mg_start_thread.md)
 * [`mg_store_body( conn, path );`](api/mg_store_body.md)
-* [`mg_stop( ctx );`](api/mg_stop.md)
 * [`mg_strcasecmp( s1, s2 );`](api/mg_strcasecmp.md)
 * [`mg_strncasecmp( s1, s2, len );`](api/mg_strncasecmp.md)
 * [`mg_unlock_connection( conn );`](api/mg_unlock_connection.md)
-* [`mg_unlock_context( ctx );`](api/mg_unlock_context.md)
-* [~~`mg_upload( conn, destination_dir );`~~](api/mg_upload.md)
 * [`mg_url_decode( src, src_len, dst, dst_len, is_form_url_encoded );`](api/mg_url_decode.md)
 * [`mg_url_encode( src, dst, dst_len );`](api/mg_url_encode.md)
-* [`mg_version();`](api/mg_version.md)
-* [`mg_websocket_client_write( conn, opcode, data, data_len );`](api/mg_websocket_client_write.md)
 * [`mg_websocket_write( conn, opcode, data, data_len );`](api/mg_websocket_write.md)
 * [`mg_write( conn, buf, len );`](api/mg_write.md)
+
+
+## Diagnosis Functions
+
+* [`mg_get_system_info( buffer, buf_len );`](api/mg_get_system_info.md)
+* [`mg_get_context_info( ctx, buffer, buf_len );`](api/mg_get_context_info.md)
+* [`mg_get_connection_info( ctx, idx, buffer, buf_len );`](api/mg_get_context_info.md)
+
+
+## Deprecated:
+
+* [~~`mg_get_valid_option_names();`~~](api/mg_get_valid_option_names.md)
+* [~~`mg_upload( conn, destination_dir );`~~](api/mg_upload.md)
+
+

+ 49 - 24
docs/Building.md

@@ -82,27 +82,56 @@ make build WITH_LUA=1
 ```
 
 
-| Make Options              | Description                              |
-| ------------------------- | ---------------------------------------- |
-| WITH_LUA=1                | build with Lua support                   |
-| WITH_DEBUG=1              | build with GDB debug support             |
-| WITH_IPV6=1               | with IPV6 support                        |
-| WITH_WEBSOCKET=1          | build with web socket support            |
-| WITH_CPP=1                | build libraries with c++ classes         |
-| CONFIG_FILE=file          | use 'file' as the config file            |
-| CONFIG_FILE2=file         | use 'file' as the backup config file     |
-| HTMLDIR=/path             | place to install initial web pages       |
-| DOCUMENT_ROOT=/path       | HTMLDIR override, config option, install |
-|                           | nothing is installed here.               |
-| PORTS=8080                | listening ports override when installing |
-| SSL_LIB=libssl.so.0       | use versioned SSL library                |
-| CRYPTO_LIB=libcrypto.so.0 | system versioned CRYPTO library          |
-| PREFIX=/usr/local         | sets the install directory               |
-| COPT='-DNO_SSL'           | method to insert compile flags           |
+| Make Options              | Description                               |
+| ------------------------- | ----------------------------------------- |
+| WITH_LUA=1                | build with Lua support                    |
+| WITH_DUKTAPE=1            | build with server-side JavaScript support |
+| WITH_DEBUG=1              | build with GDB debug support              |
+| WITH_IPV6=1               | with IPV6 support                         |
+| WITH_WEBSOCKET=1          | build with web socket support             |
+| WITH_SERVER_STATS=1       | build with support for server statistics  |
+| WITH_CPP=1                | build libraries with c++ classes          |
+| CONFIG_FILE=file          | use 'file' as the config file             |
+| CONFIG_FILE2=file         | use 'file' as the backup config file      |
+| HTMLDIR=/path             | place to install initial web pages        |
+| DOCUMENT_ROOT=/path       | HTMLDIR override, config option, install  |
+|                           | nothing is installed here.                |
+| PORTS=8080                | listening ports override when installing  |
+| SSL_LIB=libssl.so.0       | use versioned SSL library                 |
+| CRYPTO_LIB=libcrypto.so.0 | system versioned CRYPTO library           |
+| PREFIX=/usr/local         | sets the install directory                |
+| COPT='-DNO_SSL'           | method to insert compile flags            |
 
 Note that the WITH_* options used for *make* are not identical to the
 preprocessor defines in the source code - usually USE_* is used there.
 
+## Changing PREFIX
+
+To change the target destination pass the `PREFIX` option to the command `make install` (not `make build`). Example usage:
+
+```
+$ make build
+$ make -n install PREFIX=/opt/civetweb
+```
+Note: The `-n` corresponds to the `--dry-run` option (it does not make any changes): You can see where `make install` would install. Example output of the above command:
+
+```
+$ make -n install PREFIX=/opt/civetweb
+install -d -m 755  "/opt/civetweb/share/doc/civetweb"
+install -m 644 resources/itworks.html /opt/civetweb/share/doc/civetweb/index.html
+install -m 644 resources/civetweb_64x64.png /opt/civetweb/share/doc/civetweb/
+install -d -m 755  "/opt/civetweb/etc"
+install -m 644 resources/civetweb.conf  "/opt/civetweb/etc/"
+sed -i 's#^document_root.*$#document_root /opt/civetweb/share/doc/civetweb#' "/opt/civetweb/etc/civetweb.conf"
+sed -i 's#^listening_ports.*$#listening_ports 8080#' "/opt/civetweb/etc/civetweb.conf"
+install -d -m 755  "/opt/civetweb/share/doc/civetweb"
+install -m 644 *.md "/opt/civetweb/share/doc/civetweb"
+install -d -m 755 "/opt/civetweb/bin"
+install -m 755 civetweb "/opt/civetweb/bin/"
+```
+
+If the output looks good: Just remove the `-n` option to actually install the software on your system.
+
 ## Setting compile flags
 
 Compile flags can be set using the *COPT* make option like so.
@@ -162,9 +191,8 @@ Building with Buildroot
 Building on Android
 ---------
 
-This is a small guide to help you run civetweb on Android. Currently it is
-tested on the HTC Wildfire. If you have managed to run it on other devices
-as well, please comment or drop an email in the mailing list.
+This is a small guide to help you run civetweb on Android, originally
+tested on the HTC Wildfire.
 Note: You do not need root access to run civetweb on Android.
 
 - Download the source from the Downloads page.
@@ -177,15 +205,12 @@ Note: You do not need root access to run civetweb on Android.
 - To test if the server is running fine, visit your web-browser and
   navigate to `http://127.0.0.1:8080` You should see the `Index of /` page.
 
-![screenshot](https://a248.e.akamai.net/camo.github.com/b88428bf009a2b6141000937ab684e04cc8586af/687474703a2f2f692e696d6775722e636f6d2f62676f6b702e706e67)
-
 
 Notes:
 
 - `jni` stands for Java Native Interface. Read up on Android NDK if you want
   to know how to interact with the native C functions of civetweb in Android
   Java applications.
-- TODO: A Java application that interacts with the native binary or a
-  shared library.
+
 
 

+ 17 - 4
docs/Contribution.md

@@ -3,8 +3,21 @@ Contributing to CivetWeb
 
 Contributions to CivetWeb are welcome, provided all contributions carry the MIT license.
 
-- Please first create an issue on GitHub or create a thread on the CivetWeb discussion group.
-- If possible, create a pull request on GitHub. Please take care your modifications pass the continuous integration checks. These checks are performed automatically when you create a pull request, but it may take some hours until all tests are completed.
-- Alternatively, you can post a patch. However, pull requests are preferred.
-- Contributor names are listed in CREDITS.md, unless you explicitly state you don't want your name to be listed there.
+- Please report issues on GitHub. If the issue you want to report is already reported there, add a note with your specific details to that issue. In case of doubt, please create a new issue.
+- If you know how to fix the issue, please create a pull request on GitHub. Please take care your modifications pass the continuous integration checks. These checks are performed automatically when you create a pull request, but it may take some hours until all tests are completed. Please provide a description for every pull request.
+- Alternatively, you can post a patch or describe the required modifications in a GitHub issue.
+However, a pull request would be preferred.
+- Contributor names are listed in CREDITS.md, unless you explicitly state you don't want your name to be listed there. This file is occasionally updated, adding new contributors, using author names from git commits and GitHub comments.
+
+
+- In case your modifications either
+  1. modify or extend the API,
+  2. affect multi-threading,
+  3. imply structural changes,
+  or
+  4. have significant influence on maintenance,
+  
+  please first create an issue on GitHub or create a thread on the CivetWeb discussion group, to discuss the planned changed.
+
+- In case you think you found a security issue that should be evaluated and fixed before public disclosure, feel free to write an email.  Although CivetWeb is a fork from Mongoose from 2013, the code bases are different now, so security vulnerabilities of Mongoose usually do not affect CivetWeb.  Open an issue for Mongoose vulnerabilities you want to have checked if CivetWeb is affected.
 

+ 79 - 19
docs/Embedding.md

@@ -24,15 +24,19 @@ but all functions required to run a HTTP server.
   - C implementation
     - src/civetweb.c
     - src/md5.inl (MD5 calculation)
-    - src/handle_form.inl (HTML form handling functions)
+    - src/sha1.inl (SHA calculation)
+    - src/handle\_form.inl (HTML form handling functions)
+    - src/timer.inl (optional timer support)
   - Optional: C++ wrapper
     - include/CivetServer.h (C++ interface)
     - src/CivetServer.cpp (C++ wrapper implementation)
   - Optional: Third party components
-    - src/third_party/* (third party components, mainly used for the standalone server)
-    - src/mod_*.inl (modules to access third party components from civetweb)
+    - src/third\_party/* (third party components, mainly used for the standalone server)
+    - src/mod\_*.inl (modules to access third party components from civetweb)
+
+
+Note: The C++ wrapper uses the official C interface (civetweb.h) and does not add new features to the server. Several features available in the C interface are missing in the C++ interface. While all features should be accessible using the C interface, this is not a design goal of the C++ interface.
 
-Note: The C++ wrapper uses the official C interface (civetweb.h) and does not add new features to the server. Some features available in the C interface might be missing in the C++ interface.
 
 #### Additional Source Files for Executables
 
@@ -42,12 +46,13 @@ starting the HTTP server.
   - Stand-alone C Server
       - src/main.c
   - Reference embedded C Server
-      - examples/embedded_c/embedded_c.c
+      - examples/embedded\_c/embedded\_c.c
   - Reference embedded C++ Server
-      - examples/embedded_cpp/embedded_cpp.cpp
+      - examples/embedded\_cpp/embedded\_cpp.cpp
 
 Note: The "embedded" example is actively maintained, updated, extended and tested. Other examples in the examples/ folder might be outdated and remain there for reference.
 
+
 Quick Start
 ------
 
@@ -70,6 +75,9 @@ By default, the server will automatically serve up files like a normal HTTP serv
   - Use contructor *options* to select the port and document root among other things.
   - Use constructor *callbacks* to add your own hooks.
 
+Alternative quick start: Have a look at the examples embedded\_c and embedded\_cpp
+
+
 Lua Support
 ------
 
@@ -77,15 +85,15 @@ Lua is a server side include functionality.  Files ending in .lua will be proces
 
 ##### Add the following CFLAGS
 
-  - -DLUA_COMPAT_ALL
-  - -DUSE_LUA
-  - -DUSE_LUA_SQLITE3
-  - -DUSE_LUA_FILE_SYSTEM
+  - `-DLUA_COMPAT_ALL`
+  - `-DUSE_LUA`
+  - `-DUSE_LUA_SQLITE3`
+  - `-DUSE_LUA_FILE_SYSTEM`
 
 ##### Add the following sources
 
-  - src/mod_lua.inl
-  - src/third_party/lua-5.2.4/src
+  - src/mod\_lua.inl
+  - src/third\_party/lua-5.2.4/src
      + lapi.c
      + lauxlib.c
      + lbaselib.c
@@ -118,11 +126,11 @@ Lua is a server side include functionality.  Files ending in .lua will be proces
      + lundump.c
      + lvm.c
      + lzio.c
-  - src/third_party/sqlite3.c
-  - src/third_party/sqlite3.h
-  - src/third_party/lsqlite3.c
-  - src/third_party/lfs.c
-  - src/third_party/lfs.h
+  - src/third\_party/sqlite3.c
+  - src/third\_party/sqlite3.h
+  - src/third\_party/lsqlite3.c
+  - src/third\_party/lfs.c
+  - src/third\_party/lfs.h
 
 This build is valid for Lua version Lua 5.2. It is also possible to build with Lua 5.1 (including LuaJIT) or Lua 5.3.
 
@@ -156,8 +164,8 @@ is configurable via `num_threads` configuration option. That number puts a
 limit on number of simultaneous requests that can be handled by CivetWeb.
 If you embed CivetWeb into a program that uses SSL outside CivetWeb as well,
 you may need to initialize SSL before calling `mg_start()`, and set the pre-
-processor define SSL_ALREADY_INITIALIZED. This is not required if SSL is used
-only within CivetWeb.
+processor define `SSL_ALREADY_INITIALIZED`. This is not required if SSL is
+used only within CivetWeb.
 
 When master thread accepts new a connection, a new accepted socket (described
 by `struct socket`) it placed into the accepted sockets queue,
@@ -174,11 +182,13 @@ which is `SOMAXCONN` and depends on the platform.
 Worker threads are running in an infinite loop, which in a simplified form
 looks something like this:
 
+```C
     static void *worker_thread() {
       while (consume_socket()) {
         process_new_connection();
       }
     }
+```
 
 Function `consume_socket()` gets a new accepted socket from the CivetWeb socket
 queue, atomically removing it from the queue. If the queue is empty,
@@ -198,3 +208,53 @@ All accepted sockets have `SO_RCVTIMEO` and `SO_SNDTIMEO` socket options set
 (controlled by the `request_timeout_ms` CivetWeb option, 30 seconds default)
 which specifies a read/write timeout on client connections.
 
+
+A minimal example
+------
+
+Initializing a HTTP server
+```C
+{
+    /* Server context handle */
+    struct mg_context *ctx;
+
+    /* Initialize the library */
+    mg_init_library(0);
+
+    /* Start the server */
+    ctx = mg_start(NULL, 0, NULL);
+
+    /* Add some handler */
+    mg_set_request_handler(ctx, "/hello", handler, "Hello world");
+
+    ... Run the application ...
+    
+    /* Stop the server */
+    mg_stop(ctx);
+
+    /* Un-initialize the library */
+    mg_exit_library();
+}
+```
+
+A simple callback
+```C
+static int
+handler(struct mg_connection *conn, void *ignored)
+{
+	const char *msg = "Hello world";
+	unsigned long len = (unsigned long)strlen(msg);
+
+	mg_printf(conn,
+	          "HTTP/1.1 200 OK\r\n"
+	          "Content-Length: %lu\r\n"
+	          "Content-Type: text/plain\r\n"
+	          "Connection: close\r\n\r\n",
+	          len);
+
+	mg_write(conn, msg, len);
+
+	return 200;
+}
+```
+

+ 4 - 2
docs/Installing.md

@@ -10,8 +10,10 @@ This pre-built version comes pre-built wit Lua support. Libraries for SSL suppor
 however, users may add an SSL library themselves.
 Instructions for adding SSL support can be found in [https://github.com/civetweb/civetweb/tree/master/docs](https://github.com/civetweb/civetweb/tree/master/docs)
 
-1a. 32 Bit: Install the [Visual C++ Redistributable for Visual Studio 2010](http://www.microsoft.com/en-us/download/details.aspx?id=8328)
-1b. 64 Bit: Install the [Visual C++ Redistributable for Visual Studio 2013](http://www.microsoft.com/en-us/download/details.aspx?id=40784)
+1. In case the Visual C++ Redistributable are not already installed:
+  32 Bit Version: Install the [Redistributable for Visual Studio 2010](http://www.microsoft.com/en-us/download/details.aspx?id=8328)
+  64 Bit Version: Install the [Redistributable for Visual Studio 2015](http://www.microsoft.com/en-us/download/details.aspx?id=48145)
+  Note: The required version of the Redistributables may vary, depending on the CivetWeb version.
 2. Download latest *civetweb-win.zip* from [SourceForge](https://sourceforge.net/projects/civetweb/files/)
 3. When started, Civetweb puts itself into the tray.
 

+ 86 - 0
docs/Interface_Changes_1.10.md

@@ -0,0 +1,86 @@
+# Interface changes
+
+## Proposed interface changes for 1.10
+
+Status: To be discussed
+
+### Server interface
+
+#### mg\_start / mg\_init\_library
+
+Calling mg\_init\_library is recommended before calling mg\_start.
+
+Compatibility:
+Initially, mg\_init\_library will be called implicitly if it has 
+not been called before mg\_start.
+If mg\_init\_library was not called, mg\_stop may leave memory leaks.
+
+#### mg\_websocket\_write functions
+
+Calling mg\_lock\_connection is no longer called implicitly
+in mg\_websocket\_write functions. 
+If you use websocket write functions them from two threads,
+you must call mg\_lock\_connection explicitly, just like for any
+other connection.
+
+This is an API harmonization issue.
+
+Compatibility:
+If a websocket connection was used in only one thread, there is
+no incompatibility. If a websocket connection was used in multiple
+threads, the user has to add the mg\_lock\_connection before and
+the mg\_unlock\_connection after the websocket write call.
+
+#### open\_file member of mg\_callbacks
+
+This member is going to be removed.
+It is superseeded by mg\_add\_request\_handler.
+
+Compatibility:
+Current code using open\_file needs to be changed.
+Instructions how to do this will be provided.
+
+
+### Client interface
+
+
+#### mg\_init\_library
+
+Calling mg\_init\_library is required before calling any client
+function. In particular, the TLS initialization must be done
+before using mg\_connect\_client\_secure.
+
+Compatibility:
+Some parts of the client interface did not work, if mg\_start
+was not called before. Now server and client become independent.
+
+#### mg\_connect\_client (family)
+
+mg_connect_client needs several new parameters (options).
+
+Details are to be defined.
+
+mg_connect_client and mg_download should return a different kind of
+mg_connection than used in server callbacks. At least, there should
+be a function mg_get_response_info, instead of using 
+mg_get_request_info, and getting the HTTP response code from the
+server by looking into the uri member of struct mg_request_info.
+
+
+### `size_t` in all interface
+
+Having `size_t` in interfaces while building for 32 and 64 bit
+complicates maintenance in an unnecessary way 
+(see [498](https://github.com/civetweb/civetweb/issues/498)).
+
+Replace all data sizes by 64 bit integers.
+
+
+### Pattern definition
+
+The current definition of pattern matching is problematic
+(see [499](https://github.com/civetweb/civetweb/issues/499)).
+
+Find and implement a new definition.
+
+

+ 3 - 1
docs/README.md

@@ -20,9 +20,11 @@ Developers can contribute to CivetWeb via GitHub
 Trouble tickets should be filed on GitHub
 [https://github.com/civetweb/civetweb/issues](https://github.com/civetweb/civetweb/issues)
 
-Discussion/support group and announcements are at Google Groups
+Announcements are at Google Groups
 [https://groups.google.com/d/forum/civetweb](https://groups.google.com/d/forum/civetweb)
 
+While older support question and discussion threads have been at [Google groups](https://groups.google.com/d/forum/civetweb), most newer ones are [GitHub issues](https://github.com/civetweb/civetweb/issues).
+
 Source releases can be found on GitHub
 [https://github.com/civetweb/civetweb/releases](https://github.com/civetweb/civetweb/releases)
 

+ 114 - 8
docs/UserManual.md

@@ -145,6 +145,11 @@ Authorization realm used for HTTP digest authentication. This domain is
 used in the encoding of the `.htpasswd` authorization files as well.
 Changing the domain retroactively will render the existing passwords useless.
 
+### enable\_auth\_domain\_check `yes`
+When using absolute URLs, verify the host is identical to the authentication\_domain. If enabled, requests to absolute URLs will only be processed 
+if they are directed to the domain. If disabled, absolute URLs to any host
+will be accepted.
+
 ### ssi\_pattern `**.shtml$|**.shtm$`
 All files that match `ssi_pattern` are treated as Server Side Includes (SSI).
 
@@ -295,14 +300,27 @@ all interfaces, both IPv4 and IPv6, use either the configuration
 `80,[::]:80` (create one socket for IPv4 and one for IPv6 only),
 or `+80` (create one socket for both, IPv4 and IPv6). 
 The `+`-notation to use IPv4 and IPv6 will only work in no network
-interface is specified. Depending on your IPv6 network environment,
-some configurations might not work (properly), so you have to test
-to find the configuration most suitable for your needs.
+interface is specified. Depending on your operating system version
+and IPv6 network environment, some configurations might not work
+as expected, so you have to test to find the configuration most 
+suitable for your needs. In case `+80` does not work for your
+environment, you need to use `80,[::]:80`.
 
 It is possible to use network interface addresses (e.g., `192.0.2.3:80`,
 `[2001:0db8::1234]:80`). To get a list of available network interface
 addresses, use `ipconfig` (in a `cmd` window in Windows) or `ifconfig` 
 (in a Linux shell).
+Alternatively, you could use the hostname for an interface. Check the 
+hosts file of your operating system for a proper hostname 
+(for Windows, usually found in C:\Windows\System32\drivers\etc\, 
+for most Linux distributions: /etc/hosts). E.g., to bind the IPv6 
+local host, you could use `ip6-localhost:80`. This translates to 
+`[::1]:80`. Beside the hosts file, there are several other name
+resolution services. Using your hostname might bind you to the
+localhost or an external interface. You could also try `hostname.local`,
+if the proper network services are installed (Zeroconf, mDNS, Bonjour, 
+Avahi). When using a hostname, you need to test in your particular network
+environment - in some cases, you might need to resort to a fixed IP address.
 
 ### document\_root `.`
 A directory to serve. By default, the current working directory is served.
@@ -356,7 +374,11 @@ A pattern for the files to hide. Files that match the pattern will not
 show up in directory listing and return `404 Not Found` if requested. Pattern
 must be for a file name only, not including directory names. Example:
 
-    civetweb -hide_files_patterns secret.txt|*.hide
+    civetweb -hide_files_patterns secret.txt|**.hide
+
+Note: hide\_file\_patterns uses the pattern described above. If you want to
+hide all files with a certain extension, make sure to use **.extension
+(not just *.extension).
 
 ### request\_timeout\_ms `30000`
 Timeout for network read and network write operations, in milliseconds.
@@ -423,8 +445,15 @@ files, ...), check for external resources, remove old log files, etc.
 
 The Lua state remains open until the server is stopped.
 In the future, some callback functions will be available to notify the
-script on changes of the server state.
+script on changes of the server state. See example lua script :
+[background.lua](https://github.com/civetweb/civetweb/blob/master/test/background.lua).
 
+Additional functions available in background script :
+sleep, root path, script name, isterminated
+
+### lua\_background\_script\_params `param1=1,param2=2`
+Can add dynamic parameters to background script.
+Parameters mapped to global 'mg' table 'params' field.
 
 ### websocket\_root
 In case civetweb is built with Lua and websocket support, Lua scripts may
@@ -433,11 +462,38 @@ be used for websockets as well. Since websockets use a different URL scheme
 websockets may also be served from a different directory. By default,
 the document_root is used as websocket_root as well.
 
-### access\_control\_allow\_origin
+
+### access\_control\_allow\_origin `*`
 Access-Control-Allow-Origin header field, used for cross-origin resource
 sharing (CORS).
 See the [Wikipedia page on CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing).
 
+
+### access\_control\_allow\_methods `*`
+Access-Control-Allow-Methods header field, used for cross-origin resource
+sharing (CORS) pre-flight requests.
+See the [Wikipedia page on CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing).
+
+If set to an empty string, pre-flights will not be supported directly by the server,
+but scripts may still support pre-flights by handling the OPTIONS method properly.
+If set to "*", the pre-flight will allow whatever method has been requested.
+If set to a comma separated list of valid HTTP methods, the pre-flight will return
+exactly this list as allowed method.
+If set in any other way, the result is unspecified.
+
+
+### access\_control\_allow\_headers `*`
+Access-Control-Allow-Headers header field, used for cross-origin resource
+sharing (CORS) pre-flight requests.
+See the [Wikipedia page on CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing).
+
+If set to an empty string, pre-flights will not allow additional headers.
+If set to "*", the pre-flight will allow whatever headers have been requested.
+If set to a comma separated list of valid HTTP headers, the pre-flight will return
+exactly this list as allowed headers.
+If set in any other way, the result is unspecified.
+
+
 ### error\_pages
 This option may be used to specify a directory for user defined error pages.
 The error pages may be specified for an individual http status code (e.g.,
@@ -469,6 +525,18 @@ This value should not exceed one year (RFC 2616, Section 14.21).
 A value of 0 will send "do not cache" headers for all static files.
 For values <0 and values >31622400, the behavior is undefined.
 
+### strict\_transport\_security\_max\_age
+
+Set the `Strict-Transport-Security` header, and set the `max-age` value.
+This instructs web browsers to interact with the server only using HTTPS,
+never by HTTP. If set, it will be sent for every request handled directly
+by the server, except scripts (CGI, Lua, ..) and callbacks. They must 
+send HTTP headers on their own.
+
+The time is specified in seconds. If this configuration is not set, 
+or set to -1, no `Strict-Transport-Security` header will be sent.
+For values <-1 and values >31622400, the behavior is undefined.
+
 ### decode\_url `yes`
 URL encoded request strings are decoded in the server, unless it is disabled
 by setting this option to `no`.
@@ -534,6 +602,37 @@ This option can be used to enable or disable the use of the Linux `sendfile` sys
 ### case\_sensitive `no`
 This option can be uset to enable case URLs for Windows servers. It is only available for Windows systems. Windows file systems are not case sensitive, but they still store the file name including case. If this option is set to `yes`, the comparison for URIs and Windows file names will be case sensitive.
 
+### allow\_index\_script\_resource `no`
+Index scripts (like `index.cgi` or `index.lua`) may have script handled resources.
+
+It this feature is activated, that /some/path/file.ext might be handled by:
+  1. /some/path/file.ext (with PATH\_INFO='/', if ext = cgi)
+  2. /some/path/index.lua with mg.request\_info.path\_info='/file.ext'
+  3. /some/path/index.cgi with PATH\_INFO='/file.ext'
+  4. /some/path/index.php with PATH\_INFO='/file.ext'
+  5. /some/index.lua with mg.request\_info.path\_info=='/path/file.ext'
+  6. /some/index.cgi with PATH\_INFO='/path/file.ext'
+  7. /some/index.php with PATH\_INFO='/path/file.ext'
+  8. /index.lua with mg.request\_info.path\_info=='/some/path/file.ext'
+  9. /index.cgi with PATH\_INFO='/some/path/file.ext'
+  10. /index.php with PATH\_INFO='/some/path/file.ext'
+
+Note: This example is valid, if the default configuration values for `index_files`, `cgi_pattern` and `lua_script_pattern` are used, and the server is built with CGI and Lua support enabled.
+
+If this feature is not activated, only the first file (/some/path/file.cgi) will be accepted.
+
+Note: This parameter affects only index scripts. A path like /here/script.cgi/handle/this.ext will call /here/script.cgi with PATH\_INFO='/handle/this.ext', no matter if this option is set to `yes` or `no`. 
+
+This feature can be used to completely hide the script extension from the URL.
+
+### additional\_header
+Send additional HTTP response header line for every request.
+The full header line including key and value must be specified, excluding the carriage return line feed.
+
+Example (used as command line option): 
+`-additional_header "X-Frame-Options: SAMEORIGIN"`
+
+This option can be specified multiple times. All specified header lines will be sent.
 
 # Lua Scripts and Lua Server Pages
 Pre-built Windows and Mac civetweb binaries have built-in Lua scripting
@@ -600,7 +699,9 @@ mg (table):
 
     mg.read()                  -- reads a chunk from POST data, returns it as a string
     mg.write(str)              -- writes string to the client
-    mg.include(path)           -- sources another Lua file
+    mg.include(filename, [pathtype]) -- include another Lua Page file (Lua Pages only)
+                               -- pathtype can be "abs", "rel"/"file" or "virt[ual]"
+                               -- like defined for SSI #include
     mg.redirect(uri)           -- internal redirect to a given URI
     mg.onerror(msg)            -- error handler, can be overridden
     mg.version                 -- a string that holds Civetweb version
@@ -609,6 +710,7 @@ mg (table):
     mg.get_var(str, varname)   -- extract variable from (query) string
     mg.get_cookie(str, cookie) -- extract cookie from a string
     mg.get_mime_type(filename) -- get MIME type of a file
+    mg.get_info(infotype)      -- get server status information
     mg.send_file(filename)     -- send a file, including MIME type
     mg.url_encode(str)         -- URL encode a string
     mg.url_decode(str, [form]) -- URL decode a string. If form=true, replace + by space.
@@ -648,10 +750,13 @@ connect (function):
     end
 
 
+All filename arguments are either absolute or relative to the civetweb working
+directory (not the document root or the Lua script/page file).
+    
 **IMPORTANT: Civetweb does not send HTTP headers for Lua pages. Therefore,
 every Lua Page must begin with a HTTP reply line and headers**, like this:
 
-    <? print('HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n') ?>
+    <? mg.write('HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n') ?>
     <html><body>
       ... the rest of the web page ...
 
@@ -706,3 +811,4 @@ An example is shown in
 - Embedding with OpenSSL on Windows might fail because of calling convention.
   To force Civetweb to use `__stdcall` convention, add `/Gz` compilation
   flag in Visual Studio compiler.
+

+ 4 - 4
docs/api/mg_callbacks.md

@@ -5,12 +5,12 @@
 ### Fields
 
 | Field | Description |
-| :--- | :--- | 
-|**`begin_request`**|**`int (*begin_request)( struct mg_connection * conn );`**|
+| :--- | :--- |
+|**`begin_request`**|**`int (*begin_request)( struct mg_connection *conn );`**|
 | |The `begin_request()` callback function is called when CivetWeb has received a new HTTP request. If the callback function does not process the request, it should return 0. In that case CivetWeb will handle the request with the default callback routine. If the callback function returns a value between 1 and 999, CivetWeb does nothing and the callback function should do all the processing, including sending the proper HTTP headers etc. Starting at CivetWeb version 1.7, the function `begin_request()` is called before any authorization is done. If an authorization check is required, `request_handler()` should be used instead. The return value of the callback function is not only used to signal CivetWeb to not further process the request. The returned value is also stored as HTTP status code in the access log. |
 |**`connection_close`**|**`void (*connection_close)( const struct mg_connection *conn );`**|
 | |The callback function `connection_close()` is called when CivetWeb is closing a connection. The per-context mutex is locked when the callback function is invoked. The function is primarly useful for noting when a websocket is closing and removing it from any application-maintained list of clients. *Using this callback for websocket connections is deprecated. Use* `mg_set_websocket_handler()` *instead.*|
-|**`end_request`**|**`void (*end_request)( const struct mg_connection * conn );`**|
+|**`end_request`**|**`void (*end_request)(const struct mg_connection *conn, int reply_status_code);`**|
 | |The callback function `end_request()` is called by CivetWeb when a request has been completely processed. It sends the reply status code which was sent to the client to the application.|
 |**`exit_context`**|**`void (*exit_context)( const struct mg_context *ctx );`**|
 | |The callback function `exit_context()` is called by CivetWeb when the server is stopped. It allows the application to do some cleanup on the application side.|
@@ -32,7 +32,7 @@
 |**`log_message`**|**`int (*log_message)( const struct mg_connection *conn, const char *message );`**|
 | |The callback function `log_message()` is called when CivetWeb is about to log a message. If the callback function returns 0, CivetWeb will use the default internal log routines to log the message. If a non-zero value is returned CivetWeb assumes that logging has already been done and no further action is performed.|
 |**`open_file`**|**`const char *(*open_file)( const struct mg_connection *conn, const char *path, size_t *data_len );`**|
-| |The callback function `open_file()` is called when a file is to be opened by CivetWeb. The callback can return a pointer to a memory location and set the memory block size in the variable pointed to by `data_len` to signal CivetWeb that the file should not be loaded from disk, but that instead a stored version in memory should be used. If the callback function returns NULL, CivetWeb will open the file from disk. This callback allows caching to be implementedi at the application side, or to serve specific files from static memory instead of from disk.|
+| |The callback function `open_file()` is called when a file is to be opened by CivetWeb. The callback can return a pointer to a memory location and set the memory block size in the variable pointed to by `data_len` to signal CivetWeb that the file should not be loaded from disk, but that instead a stored version in memory should be used. If the callback function returns NULL, CivetWeb will open the file from disk. This callback allows caching to be implemented at the application side, or to serve specific files from static memory instead of from disk.|
 |~~`upload`~~|**`void (*upload)( struct mg_connection * conn, const char *file_name );`**|
 | |*Deprecated. Use* `mg_handle_form_request()` *instead.* The callback function `upload()` is called when CivetWeb has uploaded a file to a temporary directory as result of a call to `mg_upload()`. The parameter `file_name` contains the full file name including path to the uploaded file.|
 |~~`websocket_connect`~~|**`int (*websocket_connect)( const struct mg_connection *conn );`**|

+ 37 - 0
docs/api/mg_check_digest_access_authentication.md

@@ -0,0 +1,37 @@
+# Civetweb API Reference
+
+### `mg_check_digest_access_authentication( conn, realm, filename );`
+
+### Parameters
+
+| Parameter | Type | Description |
+| :--- | :--- | :--- |
+|**`conn`**|`struct mg_connection *`| A pointer to the connection to be used to send data |
+|**`realm`**|`const char *`| The requested authentication realm or NULL |
+|**`filename`**|`const char *`| The path to the passwords file |
+
+### Return Value
+
+| Type | Description |
+| :--- | :--- |
+|`int`| An integer indicating success or failure |
+
+### Description
+
+This function can be used to check if a request header contains HTTP digest authentication
+information, matching user and password encoded within the password file.
+If the authentication realm (also called authentication domain) is NULL, the parameter
+`authentication_domain` as specified in the server configuration (`mg_start()`) is used.
+
+A positive return value means, the user name, realm and a correct password hash have been
+found in the passwords file.
+A return of 0 means, reading the password file succeeded, but there was no matching user,
+realm and password.
+The function returns a negative number on errors.
+
+### See Also
+
+* [`mg_send_digest_access_authentication_request();`](mg_send_digest_access_authentication_request.md)
+* [`mg_modify_passwords_file();`](mg_modify_passwords_file.md)
+* [`mg_start();`](mg_start.md)
+

+ 1 - 1
docs/api/client_cert.md → docs/api/mg_client_cert.md

@@ -1,6 +1,6 @@
 # Civetweb API Reference
 
-### `struct client_cert;`
+### `struct mg_client_cert;`
 
 ### Fields
 

+ 29 - 0
docs/api/mg_exit_library.md

@@ -0,0 +1,29 @@
+# Civetweb API Reference
+
+### `mg_exit_library( );`
+
+### Parameters
+
+none
+
+### Return Value
+
+| Type | Description |
+| :--- | :--- |
+|`unsigned`| **0** is returned or error |
+
+### Description
+
+The function `mg_exit_library()` should be called from an application program, when the library should be unloaded.
+It must be called only from one thread (it is not guaranteed to be thread safe).
+
+Only use `mg_exit_library( );` when you used [`mg_init_library( feature );`](api/mg_init_library.md) before.
+
+The library init and exit functions are new in version 1.9 (as dummy implementation) and effective only from version 1.10.
+For compatibility reasons, other functions (such as [`mg_start();`](mg_start.md)) will initialize the required features as well,
+but they will no longer do a de-initialization, leaving a memory leak when the library is unloaded.
+
+### See Also
+
+* [`mg_init_library( feature );`](mg_init_library.md)
+* [`mg_check_feature( feature );`](mg_check_feature.md)

+ 40 - 0
docs/api/mg_get_connection_info.md

@@ -0,0 +1,40 @@
+# Civetweb API Reference
+
+### `mg_get_connection_info( ctx, idx, buffer, buflen );`
+
+### Parameters
+
+| Parameter | Type | Description |
+| :--- | :--- | :--- |
+|**`ctx`**|`struct mg_context *`|The server context handle|
+|**`idx`**|`int`|Connection index within the context|
+|**`buffer**|`char *`|A string buffer to store the information|
+|**`buflen**|`int`|Size of the string buffer (including space for a terminating 0)|
+
+### Return Value
+
+| Type | Description |
+| :--- | :--- |
+|`int`|Available context information in bytes (excluding the terminating 0)|
+
+### Description
+
+The function `mg_get_connection_info()` returns statistics information collected for 
+a server connection index.  This may be empty if the server has not been built with 
+statistics support (`#define USE_SERVER_STATS`). 
+If data is available, the returned string is in JSON format. The exact content may
+vary, depending on the connection state and server version.
+
+### Note
+
+This is an experimental interface and may be changed, replaced
+or even removed in the future. Currently the index `idx` must be
+between `0` and `num_threads-1`. The thread is not locked for
+performance reasons, so the information may be inconsistent 
+in rare cases.
+
+### See Also
+
+* [`mg_get_system_info();`](mg_get_system_info.md)
+* [`mg_get_context_info();`](mg_get_context_info.md)
+

+ 32 - 0
docs/api/mg_get_context_info.md

@@ -0,0 +1,32 @@
+# Civetweb API Reference
+
+### `mg_get_context_info( ctx, buffer, buflen );`
+
+### Parameters
+
+| Parameter | Type | Description |
+| :--- | :--- | :--- |
+|**`ctx`**|`struct mg_context *`|The server context handle|
+|**`buffer**|`char *`|A string buffer to store the information|
+|**`buflen**|`int`|Size of the string buffer (including space for a terminating 0)|
+
+### Return Value
+
+| Type | Description |
+| :--- | :--- |
+|`int`|Available context information in bytes (excluding the terminating 0)|
+
+### Description
+
+The function `mg_get_context_info()` returns statistics information collected for
+the server context.  This may be empty if the server has not been built with
+statistics support (`#define USE_SERVER_STATS`).
+If data is available, the returned string is in JSON format. The exact content may
+vary, depending on the server state and server version.
+
+### See Also
+
+* [`mg_get_system_info();`](mg_get_system_info.md)
+* [`mg_get_connection_info();`](mg_get_connection_info.md)
+
+

+ 5 - 0
docs/api/mg_get_request_info.md

@@ -18,6 +18,11 @@
 
 The function `mg_get_request_info()` returns information about the request on a given connection. This information is returned as a pointer to a [`mg_request_info`](mg_request_info.md) structure. If an error occurs, a NULL pointer is returned instead.
 
+Use this function when implementing a server.
+
 ### See Also
 
 * [`struct mg_request_info;`](mg_request_info.md)
+* [`mg_get_response_info();`](mg_get_response_info.md)
+* [`struct mg_response_info;`](mg_response_info.md)
+

+ 29 - 0
docs/api/mg_get_request_link.md

@@ -0,0 +1,29 @@
+# Civetweb API Reference
+
+### `mg_get_request_link( conn, buf, buflen );`
+
+### Parameters
+
+| Parameter | Type | Description |
+| :--- | :--- | :--- |
+|**`conn`**|`struct mg_connection *`| A pointer referencing the connection |
+|**`buf`**|`char *`| A buffer to store the link |
+|**`buflen`**|`size_t`| Size of the buffer |
+
+### Return Value
+
+| Type | Description |
+| :--- | :--- |
+|`int`| Return code: <0 for error, >=0 for success |
+
+### Description
+
+Store a formatted link corresponding to the current request.
+
+E.g., returns
+`http://mydomain.com:8080/path/to/callback.ext`
+or 
+`http://127.0.0.1:8080/path/to/callback.ext`
+depending on the auth check settings.
+
+### See Also

+ 29 - 0
docs/api/mg_get_response_info.md

@@ -0,0 +1,29 @@
+# Civetweb API Reference
+
+### `mg_get_response_info( conn );`
+
+### Parameters
+
+| Parameter | Type | Description |
+| :--- | :--- | :--- |
+|**`conn`**|`const struct mg_connection *`|The connection for which the response info is needed|
+
+### Return Value
+
+| Type | Description |
+| :--- | :--- |
+|`const struct mg_request_info *`|Pointer to the requested info, or NULL if an error occured|
+
+### Description
+
+The function `mg_response_info()` returns information about a response on a client connection opened by `mg_connect_client()`. If an error occurs, a NULL pointer is returned instead.
+
+Use this function when implementing a client.
+
+### See Also
+
+* [`struct mg_response_info;`](mg_response_info.md)
+* [`mg_connect_client();`](mg_connect_client.md)
+* [`mg_get_request_info();`](mg_get_request_info.md)
+* [`struct mg_request_info;`](mg_request_info.md)
+

+ 30 - 0
docs/api/mg_get_system_info.md

@@ -0,0 +1,30 @@
+# Civetweb API Reference
+
+### `mg_get_system_info( buffer, buflen );`
+
+### Parameters
+
+| Parameter | Type | Description |
+| :--- | :--- | :--- |
+|**`buffer**|`char *`|A string buffer to store the information|
+|**`buflen**|`int`|Size of the string buffer (including space for a terminating 0)|
+
+### Return Value
+
+| Type | Description |
+| :--- | :--- |
+|`int`|Available system information in bytes (excluding the terminating 0)|
+
+### Description
+
+The function `mg_get_system_info()` returns information collected for the system 
+(operating system, compiler, version, ...). 
+Currently this data is returned as string is in JSON format, but changes to the 
+format are possible in future versions.  The exact content of the JSON object may vary, 
+depending on the operating system and server version.
+This string should be included for support requests.
+
+### See Also
+
+* [`mg_get_context_info();`](mg_get_context_info.md)
+

+ 44 - 0
docs/api/mg_init_library.md

@@ -0,0 +1,44 @@
+# Civetweb API Reference
+
+### `mg_init_library( feature );`
+
+### Parameters
+
+| Parameter | Type | Description |
+| :--- | :--- | :--- |
+|**`feature`**|`unsigned`| A bitmask indicating the features to be ininialized |
+
+### Return Value
+
+| Type | Description |
+| :--- | :--- |
+|`unsigned`| A value indicating the initialized features is available. **0** is returned or error |
+
+### Description
+
+The function `mg_init_library()` should be called from an application program before using any other function.
+It must be called only from one thread (it is not guaranteed to be thread safe).
+
+This function is new in version 1.9 (as dummy implementation) and effective only from version 1.10.
+For compatibility reasons, other functions (such as [`mg_start();`](mg_start.md)) will initialize the required features as well,
+but they will no longer do a de-initialization, leaving a memory leak when the library is unloaded.
+
+The following parameter values can be used:
+
+| Value | Compilation option | Description |
+| :---: | :---: | :--- |
+| **1** | NO_FILES | *Able to serve files*.  If this feature is available, the webserver is able to serve files directly from a directory tree. |
+| **2** | NO_SSL | *Support for HTTPS*. If this feature is available, the webserver van use encryption in the client-server connection. SSLv2, SSLv3, TLSv1.0, TLSv1.1 and TLSv1.2 are supported depending on the SSL library CivetWeb has been compiled with, but which protocols are used effectively when the server is running is dependent on the options used when the server is started. |
+| **4** | NO_CGI | *Support for CGI*. If this feature is available, external CGI scripts can be called by the webserver. |
+| **8** | USE_IPV6 | *Support IPv6*. The CivetWeb library is capable of communicating over both IPv4 and IPv6, but IPv6 support is only available if it has been enabled at compile time. |
+| **16** | USE_WEBSOCKET | Support for web sockets. WebSockets support is available in the CivetWeb library if the proper options has been used during cimpile time. |
+| **32** | USE_LUA | *Support for Lua scripts and Lua server pages*. CivetWeb supports server side scripting through the Lua language, if that has been enabled at compile time. Lua is an efficient scripting language which is less resource heavy than for example PHP. |
+| **64** | USE_DUKTAPE | *Support for server side JavaScript*. Server side JavaScript can be used for dynamic page generation if the proper options have been set at compile time. Please note that client side JavaScript execution is always available if it has been enabled in the connecting browser. |
+| **128** | NO_CACHING | *Support for caching*. The webserver will support caching, if it has not been disabled while compiling the library. |
+
+The parameters can added using bitwise or. Values above 255 are reserved, the behavior of the function is undefined if any unknown bit is set.
+
+### See Also
+
+* [`mg_check_feature( feature );`](api/mg_check_feature.md)
+* [`mg_exit_library( feature );`](api/mg_exit_library.md)

+ 6 - 1
docs/api/mg_modify_passwords_file.md

@@ -7,7 +7,7 @@
 | Parameter | Type | Description |
 | :--- | :--- | :--- |
 |**`passwords_file_name`**|`const char *`|The path to the passwords file|
-|**`domain`**|`const char *`|The domain of the user record|
+|**`realm`**|`const char *`|The authentication realm (domain) of the user record|
 |**`user`**|`const char *`|Username of the record to be added, changed or deleted|
 |**`password`**|`const char *`|Password associated with the user or NULL if the record must be deleted|
 
@@ -26,3 +26,8 @@ If the password parameter is not `NULL` an entry is added to the password file.
 The function returns 1 when successful and 0 if an error occurs.
 
 ### See Also
+
+* [`mg_check_digest_access_authentication();`](mg_check_digest_access_authentication.md)
+* [`mg_send_digest_access_authentication_request();`](mg_send_digest_access_authentication_request.md)
+
+

+ 12 - 11
docs/api/mg_request_info.md

@@ -7,21 +7,22 @@
 | Field | Type | Description |
 | :--- | :--- | :--- |
 |**`request_method`**|`const char *`| The request method used by the client for the connection this can be **GET**, **POST** or one of the other common HTTP request methods |
-|**`request_uri`**|`const char *`| The absolute or URL-encoded URI as it was sent in the request |
-|**`local_uri`**|`const char *`| The relative URL-encoded URI as it references the local resource. If the request URI does not reference a resource on the local server, this field is NULL |
+|**`request_uri`**|`const char *`| The absolute, relative or URL-encoded URI as it was sent in the request.  Example: "http://mydomain.com:8080/path/to/file.ext" or "/path/to/file.ext", depending on the client. |
+|**`local_uri`**|`const char *`| The relative URL-encoded URI as it references the local resource. If the request URI does not reference a resource on the local server, this field is NULL.  Example: "/path/to/file.ext" (even if the client used "http://mydomain.com:8080/path/to/file.ext" in the request) |
 |~~`uri`~~|`const char *`| *Deprecated. Use* `local_uri` *instead* |
 |**`http_version`**|`const char *`| The HTTP version as mentioned in the client request. This can be "1.0", "1.1", etc. |
-|**`remote_user`**|`const char *`| The name of the authenticated remote user, or NULL if no authentication was used |
-|**`remote addr`**|`char[48]`| The IP address of the remote client as a string. This can either represent an IPv4 or an IPv6 address. |
+|**`query_string`**|`const char *`| The HTTP query string, defined as URL part after the first '?' character, not including '?'. NULL if there is no '?'. |
+|**`remote_user`**|`const char *`| The name of the authenticated remote user, or NULL if no authentication was used. Only used for HTTP (digest) authentication, not for cookie based authentication. |
+|**`remote addr`**|`char[48]`| The IP address of the remote client as a string. This can either represent an IPv4 or an IPv6 address.  Example: "127.0.0.1" |
 |~~`remote_ip`~~|`long`| *Deprecated. Use* `remote_addr` *instead* |
-|**`content_length`**|`long long`| The content length of the request body. This value can be -1 if no content length was provided. |
-|**`remote_port`**|`int`| The port number at the client's side |
-|**`is_ssl`**|`int`| 1 if the connection is over SSL, and 0 if it is a plain connection |
+|**`content_length`**|`long long`| The content length of the request body. This value can be -1 if no content length was provided. The request may still have body data, but the server cannot determine the length until all data has arrived (e.g. when the client closes the connection, or the final chunk of a chunked request has been received). |
+|**`remote_port`**|`int`| The port number at the client's side (an integer number between 1 and 65535). |
+|**`is_ssl`**|`int`| 1 if the connection is over SSL (https), and 0 if it is a plain connection (http) |
 |**`user_data`**|`void *`| A pointer to the `user_data` information which was provided as a parameter to `mg_start()`. |
 |**`conn_data`**|`void *`| A pointer to connection specific user data |
-|**`num_headers`**|`int`| The number of HTTP request headers sent by the client |
-|**`http_headers`**|`struct mg_header[64]`| Array of structures with the HTTP request headers sent by the client |
-|**`client_cert`**|`struct client_cert *`| Pointer to the client certificate information, when available |
+|**`num_headers`**|`int`| The number of HTTP request headers sent by the client (see http_headers) |
+|**`http_headers`**|`struct mg_header[64]`| Array of structures with the HTTP request headers sent by the client. For the number of filled header fields, ee num_headers. |
+|**`client_cert`**|`struct mg_client_cert *`| Pointer to the client certificate information, when available. This field is only filled for https connections using client certificates. |
 
 ### Description
 
@@ -29,6 +30,6 @@ The `mg_request_info` structure contains the client information of an existing c
 
 ### See Also
 
-* [`struct client_cert;`](client_cert.md)
+* [`struct mg_client_cert;`](mg_client_cert.md)
 * [`struct mg_header;`](mg_header.md)
 * [`mg_get_request_info();`](mg_get_request_info.md)

+ 38 - 0
docs/api/mg_response_info.md

@@ -0,0 +1,38 @@
+# Civetweb API Reference
+
+### `struct mg_response_info;`
+
+### Fields
+
+struct mg_response_info {
+        int status_code;          /* E.g. 200 */
+        const char *status_text;  /* E.g. "OK" */
+        const char *http_version; /* E.g. "1.0", "1.1" */
+
+        long long content_length; /* Length (in bytes) of the request body,
+                                     can be -1 if no length was given. */
+
+        int num_headers; /* Number of HTTP headers */
+        struct mg_header
+            http_headers[MG_MAX_HEADERS]; /* Allocate maximum headers */
+};
+
+| Field | Type | Description |
+| :--- | :--- | :--- |
+|**`status code`**|`int`| The HTTP response code received by the client. |
+|**`status_text`**|`const char *`| The textual representation of the HTTP status code. |
+|**`http_version`**|`const char *`| The HTTP version as mentioned in the client request. This can be "1.0", "1.1", etc. |
+|**`content_length`**|`long long`| The content length of the request body. This value can be -1 if no content length was provided. The request may still have body data, but the server cannot determine the length until all data has arrived (e.g. when the client closes the connection, or the final chunk of a chunked request has been received). |
+|**`num_headers`**|`int`| The number of HTTP request headers sent by the client (see http_headers) |
+|**`http_headers`**|`struct mg_header[64]`| Array of structures with the HTTP request headers sent by the client. For the number of filled header fields, ee num_headers. |
+
+Note: This structure is not yet feature complete and will be extended in future versions.
+
+### Description
+
+The `mg_response_info` structure contains information on a completed request from a client.
+
+### See Also
+
+* [`struct mg_header;`](mg_header.md)
+* [`mg_get_response_info();`](mg_get_response_info.md)

+ 31 - 0
docs/api/mg_send_chunk.md

@@ -0,0 +1,31 @@
+# Civetweb API Reference
+
+### `mg_send_chunk( conn, buf, len );`
+
+### Parameters
+
+| Parameter | Type | Description |
+| :--- | :--- | :--- |
+|**`conn`**|`struct mg_connection *`| A pointer to the connection to be used to send data |
+|**`chunk`**|`const void *`| A pointer to the blob of information to be sent |
+|**`chunk_len`**|`size_t`| The amount of bytes to be sent |
+
+### Return Value
+
+| Type | Description |
+| :--- | :--- |
+|`int`| An integer indicating the amount of bytes sent, or failure |
+
+### Description
+
+The function `mg_send_chunk()` can be used to send a blob of arbitrary data over a connection. 
+Only use this function after sending a complete HTTP request or response header with "Transfer-Encoding: chunked" set. Otherwise: use `mg_write()`.
+The function returns a number **>0** if data was sent, the value **0** when the connection has been closed, and **-1** in case of an error.
+
+### See Also
+
+* [`mg_write();`](mg_write.md)
+* [`mg_printf();`](mg_print.md)
+* [`mg_lock_connection();`](mg_lock_connection.md)
+* [`mg_unlock_connection();`](mg_unlock_connection.md)
+

+ 35 - 0
docs/api/mg_send_digest_access_authentication_request.md

@@ -0,0 +1,35 @@
+# Civetweb API Reference
+
+### `mg_send_digest_access_authentication_request( conn, realm );`
+
+### Parameters
+
+| Parameter | Type | Description |
+| :--- | :--- | :--- |
+|**`conn`**|`struct mg_connection *`| A pointer to the connection to be used to send data |
+|**`realm`**|`const char *`| The requested authentication realm or NULL |
+
+### Return Value
+
+| Type | Description |
+| :--- | :--- |
+|`int`| An integer indicating success or failure |
+
+### Description
+
+This function can be used to send a HTTP Digest Authentication request to the client.
+Browsers will react with repeating the request with user authentication data.
+If they do not yet know the user authentication for the requested realm, they will show
+a dialog to query username and password.
+In case the authentication realm (also called domain) is NULL, the parameter
+`authentication_domain` from the server configuration is used.
+The function returns a negative number on errors.
+
+### See Also
+
+* [`mg_check_digest_access_authentication();`](mg_check_digest_access_authentication.md)
+* [`mg_modify_passwords_file();`](mg_modify_passwords_file.md)
+* [`mg_send_http_error();`](mg_send_http_error.md)
+* [`mg_write();`](mg_write.md)
+* [`mg_printf();`](mg_print.md)
+

+ 32 - 0
docs/api/mg_send_http_error.md

@@ -0,0 +1,32 @@
+# Civetweb API Reference
+
+### `mg_send_http_error( conn, status_code, fmt, ... );`
+
+### Parameters
+
+| Parameter | Type | Description |
+| :--- | :--- | :--- |
+|**`conn`**|`struct mg_connection *`|The connection over which the data must be sent|
+|**`status_code`**|`int`|The HTTP status code (see HTTP standard)|
+|**`fmt`**|`const char *`|Format string for an error message|
+|**`...`**|*various*|Parameters as specified in the format string|
+
+### Return Value
+
+| Type | Description |
+| :--- | :--- |
+
+
+### Description
+
+The function `mg_send_http_error()` can be used to send HTTP error messages from a server to a client.
+The `status_code` must be one of the predefined HTTP standard error codes (e.g., "404" for "Not Found").
+The status text (e.g., "Not Found") for standard error codes is known by this function.
+A body of the error message, to explain the error in more detail, can be specified using the `fmt` format specifier and additional arguments. The `fmt` format specifier works like for the `printf()` function in the standard C library.
+
+
+### See Also
+
+* [`mg_printf();`](mg_printf.md)
+* [`mg_write();`](mg_write.md)
+

+ 24 - 2
docs/api/mg_set_user_connection_data.md

@@ -15,8 +15,30 @@
 
 ### Description
 
-The function `mg_set_user_connection_data()` can be used to add or change the user data pointer attached to a connection. Using the value NULL in the call will remove a previously assigned user data pointer.
+The function `mg_set_user_connection_data()` can be used to set a user defined
+data pointer attached to a connection.  This value can be read using 
+`mg_get_user_connection_data()`.
+Any call to `mg_set_user_connection_data()` will overwrite a previously
+assigned user data pointer.
+
+`mg_set_user_connection_data()` requires a non-const 
+`struct mg_connection *` to set the user data pointer.  It is save to use the
+`const struct mg_connection *` passed to a websocket connect handler (with a
+const cast), since `const` just means you must not use `mg_read()` or
+`mg_write()` in this context.
+
+Alternatively, you can use the `init_connection` callback in 
+`struct mg_callbacks` to set the user data pointer.
+In this case, typically `init_connection` is used to allocate memory for
+a user defined `struct`, while `connection_close` is used to free this
+memory again.
+
 
 ### See Also
 
-* [`mg_get_user_connection_data();`](mg_user_connection_data.md)
+* [`mg_get_user_connection_data();`](mg_get_user_connection_data.md)
+* [`struct mg_callbacks`](mg_callbacks.md)
+* [`mg_set_websocket_handler();`](mg_set_websocket_handler.md)
+* [`mg_read();`](mg_read.md)
+* [`mg_write();`](mg_write.md)
+

+ 3 - 3
docs/api/mg_websocket_write.md

@@ -19,11 +19,11 @@
 
 ### Description
 
-The function `mg_websocket_write()` sends data to a websocket client wrapped in a websocket frame. The function issues calls to [`mg_lock_connection()`](mg_lock_connection.md) and [`mg_unlock_connaction()`](mg_unlock_connection.md) to ensure that the transmission is not interrupted. Data corruption can otherwise happn if the application is proactively communicating and responding to a request simultaneously.
+The function `mg_websocket_write()` sends data to a websocket client wrapped in a websocket frame. The function issues calls to [`mg_lock_connection()`](mg_lock_connection.md) and [`mg_unlock_connection()`](mg_unlock_connection.md) to ensure that the transmission is not interrupted. Data corruption can otherwise happen if the application is proactively communicating and responding to a request simultaneously.
 
-The function is available only when Civetweb is compilet with the `-DUSE_WEBSOCKET` option.
+The function is available only when Civetweb is compiled with the `-DUSE_WEBSOCKET` option.
 
-The function returns the number of bytes written, **0** when the connection has been closed and **-1** if an error occured.
+The function returns the number of bytes written, **0** when the connection has been closed and **-1** if an error occurred.
 
 ### See Also
 

+ 7 - 2
examples/README.md

@@ -2,7 +2,12 @@
 Examples
 =====
 
-These examples show how to embed civetweb into a C ([embedded_c](https://github.com/civetweb/civetweb/tree/master/examples/embedded_c)) or a C++ ([embedded_cpp](https://github.com/civetweb/civetweb/tree/master/examples/embedded_cpp)) application.
-The C++ wrapper only offers a subset of the full C API, thus the C example is more complete than the C++ example.
+Two examples show how to embed civetweb into a C ([embedded_c](https://github.com/civetweb/civetweb/tree/master/examples/embedded_c)) or a C++ ([embedded_cpp](https://github.com/civetweb/civetweb/tree/master/examples/embedded_cpp)) application.
+The C++ wrapper only offers a subset of the full C API, thus the C example is more complete than the C++ example. These examples were not designed with security in mind, but to show how the API can be used in principle. For more information, see the [documentation](https://github.com/civetweb/civetweb/tree/master/docs). Some examples can also be found in the [test](https://github.com/civetweb/civetweb/tree/master/test) folder (but they are less documented and adapted to the needs of the test framework).
+
+In addition, there is one example how to configure a HTTPS server, to comply with modern security standards ([https](https://github.com/civetweb/civetweb/tree/master/examples/https)). It does not hold any source, but only a configuration file and some documentation how to use it.
 
 Some no longer maintained examples can be found in the ["obsolete"](https://github.com/civetweb/civetweb/tree/master/examples/_obsolete) folder. It is not guaranteed that they work in the current version - they are kept for reference, but might be removed in the future.
+
+All examples are subject to the MIT license (unless noted otherwise) - they come without warranty of any kind.
+

+ 175 - 8
examples/embedded_c/embedded_c.c

@@ -21,15 +21,15 @@
 #define DOCUMENT_ROOT "."
 #ifdef NO_SSL
 #ifdef USE_IPV6
-#define PORT "[::]:8888"
+#define PORT "[::]:8888,8884"
 #else
-#define PORT "8888"
+#define PORT "8888,8884"
 #endif
 #else
 #ifdef USE_IPV6
 #define PORT "[::]:8888r,[::]:8843s,8884"
 #else
-#define PORT "8888r,8843s"
+#define PORT "8888r,8843s,8884"
 #endif
 #endif
 #define EXAMPLE_URI "/example"
@@ -77,15 +77,23 @@ ExampleHandler(struct mg_connection *conn, void *cbdata)
 	          "<p>To see a page from the CookieHandler handler <a "
 	          "href=\"cookie\">click cookie</a></p>");
 	mg_printf(conn,
+	          "<p>To see a page from the PostResponser handler <a "
+	          "href=\"postresponse\">click post response</a></p>");
+	mg_printf(conn,
 	          "<p>To see an example for parsing files on the fly <a "
 	          "href=\"on_the_fly_form\">click form</a> (form for "
 	          "uploading files)</p>");
 
 #ifdef USE_WEBSOCKET
 	mg_printf(conn,
-	          "<p>To test websocket handler <a href=\"/websocket\">click "
+	          "<p>To test the websocket handler <a href=\"/websocket\">click "
 	          "websocket</a></p>");
 #endif
+
+	mg_printf(conn,
+	          "<p>To test the authentication handler <a href=\"/auth\">click "
+	          "auth</a></p>");
+
 	mg_printf(conn, "<p>To exit <a href=\"%s\">click exit</a></p>", EXIT_URI);
 	mg_printf(conn, "</body></html>\n");
 	return 1;
@@ -142,7 +150,7 @@ BXHandler(struct mg_connection *conn, void *cbdata)
 	          "close\r\n\r\n");
 	mg_printf(conn, "<html><body>");
 	mg_printf(conn, "<h2>This is the BX handler %p!!!</h2>", cbdata);
-	mg_printf(conn, "<p>The actual uri is %s</p>", req_info->uri);
+	mg_printf(conn, "<p>The actual uri is %s</p>", req_info->local_uri);
 	mg_printf(conn, "</body></html>\n");
 	return 1;
 }
@@ -162,7 +170,7 @@ FooHandler(struct mg_connection *conn, void *cbdata)
 	mg_printf(conn,
 	          "<p>The request was:<br><pre>%s %s HTTP/%s</pre></p>",
 	          req_info->request_method,
-	          req_info->uri,
+	          req_info->local_uri,
 	          req_info->http_version);
 	mg_printf(conn, "</body></html>\n");
 	return 1;
@@ -445,7 +453,7 @@ CookieHandler(struct mg_connection *conn, void *cbdata)
 
 	mg_printf(conn, "<html><body>");
 	mg_printf(conn, "<h2>This is the CookieHandler.</h2>");
-	mg_printf(conn, "<p>The actual uri is %s</p>", req_info->uri);
+	mg_printf(conn, "<p>The actual uri is %s</p>", req_info->local_uri);
 
 	if (first_str[0] == 0) {
 		mg_printf(conn, "<p>This is the first time, you opened this page</p>");
@@ -460,6 +468,132 @@ CookieHandler(struct mg_connection *conn, void *cbdata)
 
 
 int
+PostResponser(struct mg_connection *conn, void *cbdata)
+{
+	long long r_total = 0;
+	int r, s;
+
+	char buf[2048];
+
+	const struct mg_request_info *ri = mg_get_request_info(conn);
+
+	if (strcmp(ri->request_method, "POST")) {
+		char buf[1024];
+		int ret = mg_get_request_link(conn, buf, sizeof(buf));
+
+		mg_printf(conn,
+		          "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
+		mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
+		mg_printf(conn,
+		          "%s method not allowed in the POST handler\n",
+		          ri->request_method);
+		if (ret >= 0) {
+			mg_printf(conn,
+			          "use a web tool to send a POST request to %s\n",
+			          buf);
+		}
+		return 1;
+	}
+
+	if (ri->content_length >= 0) {
+		/* We know the content length in advance */
+	} else {
+		/* We must read until we find the end (chunked encoding
+		 * or connection close), indicated my mg_read returning 0 */
+	}
+
+	mg_printf(conn,
+	          "HTTP/1.1 200 OK\r\nConnection: "
+	          "close\r\nTransfer-Encoding: chunked\r\n");
+	mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
+
+	r = mg_read(conn, buf, sizeof(buf));
+	while (r > 0) {
+		r_total += r;
+		s = mg_send_chunk(conn, buf, r);
+		if (r != s) {
+			/* Send error */
+			break;
+		}
+		r = mg_read(conn, buf, sizeof(buf));
+	}
+	mg_printf(conn, "0\r\n");
+
+	return 1;
+}
+
+
+int
+AuthStartHandler(struct mg_connection *conn, void *cbdata)
+{
+	static unsigned long long firstload = 0;
+	const char *passfile = "password_example_file.txt";
+	const char *realm = "password_example";
+	const char *user = "user";
+	char passwd[64];
+
+	if (firstload == 0) {
+
+		/* Set a random password (4 digit number - bad idea from a security
+		 * point of view, but this is an API demo, not a security tutorial),
+		 * and store it in some directory within the document root (extremely
+		 * bad idea, but this is still not a security tutorial).
+		 * The reason we create a new password every time the server starts
+		 * is just for demonstration - we don't want the browser to store the
+		 * password, so when we repeat the test we start with a new password.
+		 */
+		firstload = (unsigned long long)time(NULL);
+		sprintf(passwd, "%04u", (unsigned int)(firstload % 10000));
+		mg_modify_passwords_file(passfile, realm, user, passwd);
+
+		/* Just tell the user the new password generated for this test. */
+		mg_printf(conn,
+		          "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
+		          "close\r\n\r\n");
+
+		mg_printf(conn, "<!DOCTYPE html>\n");
+		mg_printf(conn, "<html>\n<head>\n");
+		mg_printf(conn, "<meta charset=\"UTF-8\">\n");
+		mg_printf(conn, "<title>Auth handlerexample</title>\n");
+		mg_printf(conn, "</head>\n");
+
+		mg_printf(conn, "<body>\n");
+		mg_printf(conn,
+		          "<p>The first time you visit this page, it's free!</p>\n");
+		mg_printf(conn,
+		          "<p>Next time, use username \"%s\" and password \"%s\"</p>\n",
+		          user,
+		          passwd);
+		mg_printf(conn, "</body>\n</html>\n");
+
+		return 1;
+	}
+
+	if (mg_check_digest_access_authentication(conn, realm, passfile) <= 0) {
+		/* No valid authorization */
+		mg_send_digest_access_authentication_request(conn, realm);
+		return 1;
+	}
+
+	mg_printf(conn,
+	          "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
+	          "close\r\n\r\n");
+
+	mg_printf(conn, "<!DOCTYPE html>\n");
+	mg_printf(conn, "<html>\n<head>\n");
+	mg_printf(conn, "<meta charset=\"UTF-8\">\n");
+	mg_printf(conn, "<title>Auth handlerexample</title>\n");
+	mg_printf(conn, "</head>\n");
+
+	mg_printf(conn, "<body>\n");
+	mg_printf(conn, "<p>This is the password protected contents</p>\n");
+	mg_printf(conn, "</body>\n</html>\n");
+
+	return 1;
+}
+
+
+int
 WebSocketStartHandler(struct mg_connection *conn, void *cbdata)
 {
 	mg_printf(conn,
@@ -585,7 +719,31 @@ WebsocketDataHandler(struct mg_connection *conn,
 	ASSERT(client->conn == conn);
 	ASSERT(client->state >= 1);
 
-	fprintf(stdout, "Websocket got data:\r\n");
+	fprintf(stdout, "Websocket got %lu bytes of ", (unsigned long)len);
+	switch (((unsigned char)bits) & 0x0F) {
+	case WEBSOCKET_OPCODE_CONTINUATION:
+		fprintf(stdout, "continuation");
+		break;
+	case WEBSOCKET_OPCODE_TEXT:
+		fprintf(stdout, "text");
+		break;
+	case WEBSOCKET_OPCODE_BINARY:
+		fprintf(stdout, "binary");
+		break;
+	case WEBSOCKET_OPCODE_CONNECTION_CLOSE:
+		fprintf(stdout, "close");
+		break;
+	case WEBSOCKET_OPCODE_PING:
+		fprintf(stdout, "ping");
+		break;
+	case WEBSOCKET_OPCODE_PONG:
+		fprintf(stdout, "pong");
+		break;
+	default:
+		fprintf(stdout, "unknown(%1xh)", ((unsigned char)bits) & 0x0F);
+		break;
+	}
+	fprintf(stdout, " data:\r\n");
 	fwrite(data, len, 1, stdout);
 	fprintf(stdout, "\r\n\r\n");
 
@@ -754,6 +912,8 @@ main(int argc, char *argv[])
 	    "DES-CBC3-SHA:AES128-SHA:AES128-GCM-SHA256",
 #endif
 #endif
+	    "enable_auth_domain_check",
+	    "no",
 	    0};
 	struct mg_callbacks callbacks;
 	struct mg_context *ctx;
@@ -849,9 +1009,16 @@ main(int argc, char *argv[])
 	/* Add handler for /cookie example */
 	mg_set_request_handler(ctx, "/cookie", CookieHandler, 0);
 
+	/* Add handler for /postresponse example */
+	mg_set_request_handler(ctx, "/postresponse", PostResponser, 0);
+
 	/* Add HTTP site to open a websocket connection */
 	mg_set_request_handler(ctx, "/websocket", WebSocketStartHandler, 0);
 
+	/* Add HTTP site with auth */
+	mg_set_request_handler(ctx, "/auth", AuthStartHandler, 0);
+
+
 #ifdef USE_WEBSOCKET
 	/* WS site for the websocket connection */
 	mg_set_websocket_handler(ctx,

+ 121 - 5
examples/embedded_cpp/embedded_cpp.cpp

@@ -6,6 +6,7 @@
 // Simple example program on how to use Embedded C++ interface.
 
 #include "CivetServer.h"
+#include <cstring>
 
 #ifdef _WIN32
 #include <windows.h>
@@ -44,6 +45,9 @@ class ExampleHandler : public CivetHandler
 		          "<p>To see a page from the *.foo handler <a "
 		          "href=\"xy.foo\">click here</a></p>\r\n");
 		mg_printf(conn,
+		          "<p>To see a page from the WebSocket handler <a "
+		          "href=\"ws\">click here</a></p>\r\n");
+		mg_printf(conn,
 		          "<p>To exit <a href=\"%s\">click here</a></p>\r\n",
 		          EXIT_URI);
 		mg_printf(conn, "</body></html>\r\n");
@@ -136,7 +140,7 @@ class FooHandler : public CivetHandler
 		mg_printf(conn,
 		          "<p>The request was:<br><pre>%s %s HTTP/%s</pre></p>\n",
 		          req_info->request_method,
-		          req_info->uri,
+		          req_info->request_uri,
 		          req_info->http_version);
 		mg_printf(conn, "</body></html>\n");
 
@@ -161,7 +165,7 @@ class FooHandler : public CivetHandler
 		mg_printf(conn,
 		          "<p>The request was:<br><pre>%s %s HTTP/%s</pre></p>\n",
 		          req_info->request_method,
-		          req_info->uri,
+		          req_info->request_uri,
 		          req_info->http_version);
 		mg_printf(conn, "<p>Content Length: %li</p>\n", (long)tlen);
 		mg_printf(conn, "<pre>\n");
@@ -176,7 +180,7 @@ class FooHandler : public CivetHandler
 				break;
 			}
 			wlen = mg_write(conn, buf, (size_t)rlen);
-			if (rlen != rlen) {
+			if (wlen != rlen) {
 				break;
 			}
 			nlen += wlen;
@@ -243,7 +247,7 @@ class FooHandler : public CivetHandler
                     break;
                 }
                 wlen = fwrite(buf, 1, (size_t)rlen, f);
-                if (rlen != rlen) {
+                if (wlen != rlen) {
                     fail = 1;
                     break;
                 }
@@ -268,6 +272,99 @@ class FooHandler : public CivetHandler
     }
 };
 
+class WsStartHandler : public CivetHandler
+{
+  public:
+	bool
+	handleGet(CivetServer *server, struct mg_connection *conn)
+	{
+
+	mg_printf(conn,
+	          "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: "
+	          "close\r\n\r\n");
+
+	mg_printf(conn, "<!DOCTYPE html>\n");
+	mg_printf(conn, "<html>\n<head>\n");
+	mg_printf(conn, "<meta charset=\"UTF-8\">\n");
+	mg_printf(conn, "<title>Embedded websocket example</title>\n");
+
+#ifdef USE_WEBSOCKET
+	/* mg_printf(conn, "<script type=\"text/javascript\"><![CDATA[\n"); ...
+	 * xhtml style */
+	mg_printf(conn, "<script>\n");
+	mg_printf(
+	    conn,
+	    "var i=0\n"
+	    "function load() {\n"
+	    "  var wsproto = (location.protocol === 'https:') ? 'wss:' : 'ws:';\n"
+	    "  connection = new WebSocket(wsproto + '//' + window.location.host + "
+	    "'/websocket');\n"
+	    "  websock_text_field = "
+	    "document.getElementById('websock_text_field');\n"
+	    "  connection.onmessage = function (e) {\n"
+	    "    websock_text_field.innerHTML=e.data;\n"
+	    "    i=i+1;"
+	    "    connection.send(i);\n"
+	    "  }\n"
+	    "  connection.onerror = function (error) {\n"
+	    "    alert('WebSocket error');\n"
+	    "    connection.close();\n"
+	    "  }\n"
+	    "}\n");
+	/* mg_printf(conn, "]]></script>\n"); ... xhtml style */
+	mg_printf(conn, "</script>\n");
+	mg_printf(conn, "</head>\n<body onload=\"load()\">\n");
+	mg_printf(
+	    conn,
+	    "<div id='websock_text_field'>No websocket connection yet</div>\n");
+#else
+	mg_printf(conn, "</head>\n<body>\n");
+	mg_printf(conn, "Example not compiled with USE_WEBSOCKET\n");
+#endif
+	mg_printf(conn, "</body>\n</html>\n");
+
+	return 1;
+}
+};
+
+
+#ifdef USE_WEBSOCKET
+class WebSocketHandler : public CivetWebSocketHandler {
+
+	virtual bool handleConnection(CivetServer *server,
+	                              const struct mg_connection *conn) {
+		printf("WS connected\n");
+		return true;
+	}
+
+	virtual void handleReadyState(CivetServer *server,
+	                              struct mg_connection *conn) {
+		printf("WS ready\n");
+
+		const char *text = "Hello from the websocket ready handler";
+		mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, text, strlen(text));
+	}
+
+	virtual bool handleData(CivetServer *server,
+	                        struct mg_connection *conn,
+	                        int bits,
+	                        char *data,
+	                        size_t data_len) {
+		printf("WS got %lu bytes: ", (long unsigned)data_len);
+		fwrite(data, 1, data_len, stdout);
+		printf("\n");
+
+		mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, data, data_len);
+		return (data_len<4);
+	}
+
+	virtual void handleClose(CivetServer *server,
+	                         const struct mg_connection *conn) {
+		printf("WS closed\n");
+	}
+};
+#endif
+
 
 int
 main(int argc, char *argv[])
@@ -281,7 +378,7 @@ main(int argc, char *argv[])
     }
 
 	// CivetServer server(options); // <-- C style start
-    CivetServer server(cpp_options); // <-- C++ style start
+	CivetServer server(cpp_options); // <-- C++ style start
 
 	ExampleHandler h_ex;
 	server.addHandler(EXAMPLE_URI, h_ex);
@@ -295,10 +392,29 @@ main(int argc, char *argv[])
 	ABHandler h_ab;
 	server.addHandler("/a/b", h_ab);
 
+	WsStartHandler h_ws;
+	server.addHandler("/ws", h_ws);
+
+#ifdef NO_FILES
+	/* This handler will handle "everything else", including
+	 * requests to files. If this handler is installed,
+	 * NO_FILES should be set. */
 	FooHandler h_foo;
 	server.addHandler("", h_foo);
 
+	printf("See a page from the \"all\" handler at http://localhost:%s/\n", PORT);
+#else
+	FooHandler h_foo;
+	server.addHandler("**.foo", h_foo);
 	printf("Browse files at http://localhost:%s/\n", PORT);
+#endif
+
+#ifdef USE_WEBSOCKET
+	WebSocketHandler h_websocket;
+	server.addWebSocketHandler("/websocket", h_websocket);
+	printf("Run websocket example at http://localhost:%s/ws\n", PORT);
+#endif
+
 	printf("Run example at http://localhost:%s%s\n", PORT, EXAMPLE_URI);
 	printf("Exit at http://localhost:%s%s\n", PORT, EXIT_URI);
 

+ 15 - 0
examples/https/README.md

@@ -0,0 +1,15 @@
+HTTPS Server configuration example
+====
+
+This directory contains an example [`civetweb.conf`](civetweb.conf) configuration file for a secure HTTPS server.  You can run a HTTPS server without most of the options there - only `ssl_certificate` and one port (e.g., `443s`) in `listening_ports` is required.  The default settings will work, but not comply with up to date security standards.  It is somewhat debatable what "up to date security" means - you can use the following web sites to run tests:
+
+- https://securityheaders.io
+- https://www.htbridge.com/ssl
+- https://www.htbridge.com/websec
+- https://www.ssllabs.com/ssltest/analyze.html / https://www.qualys.com/forms/freescan/
+- probably there are some more ... let me know!
+
+Instructions to run the test and to adapt the configuration can be found [`civetweb.conf`](civetweb.conf).  You can test this configuration directly with the standalone server, or you can take the settings and add it into your embedding code.
+
+Note: I do not take any warranty or liability for this configuration, or for the content of any linked web site.
+

+ 86 - 0
examples/https/civetweb.conf

@@ -0,0 +1,86 @@
+# Instructions to run (on Linux) to reproduce test results:
+# 
+# 1) copy civetweb executable here (examples/https directory)
+# 2) sudo ./civetweb
+#
+# Instructions to adapt to your own server:
+#
+# 1) generate your own server cert
+# 2) generate at least one backup server cert
+#    in case you want a self signed cert, you can use the script
+#    in resources/cert for both steps
+# 3) copy the content of the *.pin files into the Public-Key-Pins
+#    header config (the base64 encoded certificate hash)
+# 4) set the document root, and all other required http server settings
+# 5) Run the tests from the three websites below. They will tell you
+#    also what clients are compatible with your settings. The settings
+#    here are very strict and lock out most older clients/browsers.
+#    You will find some hints for fine tuning there as well.
+# 6) If you know all your clients, and give them client certificates in
+#    advance, you can significantly improve security by setting
+#    "ssl_verify_peer" to "yes" and specifying a client cert (directory)
+#    using "ssl_ca_file/path". This will lock out all clients without a
+#    proper certificate. Don't use it for your public home page, but
+#    consider it for your private remote access server.
+# 7) run civetweb, like above - or better create your own start script
+# You are welcome to share your thoughts and experience on GitHub 
+# (or Google groups) - see README.md in CivetWeb main directory
+
+# Don't run as super user, switch back to a regular user
+run_as_user user
+
+# The standard HTTP port 80 should redirect to the standard HTTPS port 443
+listening_ports 80r,443s
+
+# Don't forget to set the document root and domain
+#document_root tdb
+#authentication_domain mydomain.com
+
+# Set the a certificate
+ssl_certificate ../../resources/cert/server.pem
+
+# Require a client cert for your private server (see above)
+#ssl_verify_peer yes
+#ssl_ca_file ../../resources/cert/client.pem
+
+# Enforce TLS1.2 and some strong cipher(s)
+ssl_protocol_version 4
+ssl_cipher_list ECDH+AESGCM+AES256:!aNULL:!MD5:!DSS
+
+# Tell all browsers to access this site only as HTTPS for the next 180 days
+strict_transport_security_max_age 15552000                                  
+
+# Set some HTTP security header, see https://securityheaders.io
+additional_header Content-Security-Policy: script-src 'self'
+additional_header X-Frame-Options: SAMEORIGIN
+additional_header X-Xss-Protection: 1; mode=block
+additional_header X-Content-Type-Options: nosniff
+additional_header Referrer-Policy: same-origin
+additional_header Public-Key-Pins: pin-sha256="uz1UTAPen+xb+UoQqkVlEx4H653LbMjfRJcZx5OrjbI="; pin-sha256="pf3px1MBPmlTGAPoiHWqaSJ9L9Z+DKfwgsU7LfLnmsk="; max-age=7776000
+#additional_header Expect-CT: max-age=86400,report-uri="https://mydomain.com/report"
+
+
+# Ratings from 2017-09-03 (tests performed later may require more
+# strict security settings)
+#
+# Headers rated A+ from https://securityheaders.io/
+#
+# SSL rated B from https://www.htbridge.com/ssl when using a self signed
+# certificate, but no other weaknesses for modern browsers.
+# Site remarks some older TLS versions and some weaker ciphers are not
+# supported (but that's accessibility, not security).
+#
+# HTTPS rated A+ from https://www.htbridge.com/websec/ when using a self
+# signed certificate, generated with make_certs.sh in resources/cert/
+# and adding the server.pin and server_bkup.pin content into the
+# Public-Key-Pins header above.
+#
+# A rating of "T / If trust issues are ignored: A" (ignoring self-signed cert)
+# from https://www.ssllabs.com/ssltest/, https://www.qualys.com/forms/freescan/
+# (Note: this test is runs with reverse DNS name, while all others use the
+# IP address).
+#
+# Note: This settings are very strict and prevent some older but still common
+# versions of major browsers to access this site. The test web sites will give
+# you an overview. Test, before you use this settings.
+

+ 0 - 0
format.bat


+ 16 - 2
include/CivetServer.h

@@ -227,9 +227,11 @@ class CIVETWEB_API CivetServer
 	 * @throws CivetException
 	 */
 	CivetServer(const char **options,
-	            const struct CivetCallbacks *callbacks = 0);
+	            const struct CivetCallbacks *callbacks = 0,
+	            const void *UserContext = 0);
 	CivetServer(std::vector<std::string> options,
-	            const struct CivetCallbacks *callbacks = 0);
+	            const struct CivetCallbacks *callbacks = 0,
+	            const void *UserContext = 0);
 
 	/**
 	 * Destructor
@@ -531,6 +533,14 @@ class CIVETWEB_API CivetServer
 	                      std::string &dst,
 	                      bool append = false);
 
+	// generic user context which can be set/read,
+	// the server does nothing with this apart from keep it.
+	const void *
+	getUserContext() const
+	{
+		return UserContext;
+	}
+
   protected:
 	class CivetConnection
 	{
@@ -545,6 +555,10 @@ class CIVETWEB_API CivetServer
 	struct mg_context *context;
 	std::map<struct mg_connection *, class CivetConnection> connections;
 
+	// generic user context which can be set/read,
+	// the server does nothing with this apart from keep it.
+	const void *UserContext;
+
   private:
 	/**
 	 * requestHandler(struct mg_connection *, void *cbdata)

+ 301 - 55
include/civetweb.h

@@ -23,10 +23,11 @@
 #ifndef CIVETWEB_HEADER_INCLUDED
 #define CIVETWEB_HEADER_INCLUDED
 
-#define CIVETWEB_VERSION "1.9.1"
+#define CIVETWEB_VERSION "1.10"
 #define CIVETWEB_VERSION_MAJOR (1)
-#define CIVETWEB_VERSION_MINOR (9)
-#define CIVETWEB_VERSION_PATCH (1)
+#define CIVETWEB_VERSION_MINOR (10)
+#define CIVETWEB_VERSION_PATCH (0)
+#define CIVETWEB_VERSION_RELEASED
 
 #ifndef CIVETWEB_API
 #if defined(_WIN32)
@@ -75,6 +76,15 @@ struct mg_context;    /* Handle for the HTTP service itself */
 struct mg_connection; /* Handle for the individual connection */
 
 
+/* Maximum number of headers */
+#define MG_MAX_HEADERS (64)
+
+struct mg_header {
+	const char *name;  /* HTTP header name */
+	const char *value; /* HTTP header value */
+};
+
+
 /* This structure contains information about the HTTP request. */
 struct mg_request_info {
 	const char *request_method; /* "GET", "POST", etc */
@@ -83,13 +93,15 @@ struct mg_request_info {
 	const char *local_uri;      /* URL-decoded URI (relative). Can be NULL
 	                             * if the request_uri does not address a
 	                             * resource at the server host. */
-	const char *uri;            /* Deprecated: use local_uri instead */
-	const char *http_version;   /* E.g. "1.0", "1.1" */
-	const char *query_string;   /* URL part after '?', not including '?', or
-	                               NULL */
-	const char *remote_user;    /* Authenticated user, or NULL if no auth
-	                               used */
-	char remote_addr[48];       /* Client's IP address as a string. */
+#if defined(MG_LEGACY_INTERFACE)
+	const char *uri; /* Deprecated: use local_uri instead */
+#endif
+	const char *http_version; /* E.g. "1.0", "1.1" */
+	const char *query_string; /* URL part after '?', not including '?', or
+	                             NULL */
+	const char *remote_user;  /* Authenticated user, or NULL if no auth
+	                             used */
+	char remote_addr[48];     /* Client's IP address as a string. */
 
 #if defined(MG_LEGACY_INTERFACE)
 	long remote_ip; /* Client's IP address. Deprecated: use remote_addr instead
@@ -104,19 +116,42 @@ struct mg_request_info {
 	void *conn_data;          /* Connection-specific user data */
 
 	int num_headers; /* Number of HTTP headers */
-	struct mg_header {
-		const char *name;  /* HTTP header name */
-		const char *value; /* HTTP header value */
-	} http_headers[64];    /* Maximum 64 headers */
+	struct mg_header
+	    http_headers[MG_MAX_HEADERS]; /* Allocate maximum headers */
 
-	struct client_cert *client_cert; /* Client certificate information */
+	struct mg_client_cert *client_cert; /* Client certificate information */
 
 	const char *acceptedWebSocketSubprotocol; /* websocket subprotocol,
 	                                           * accepted during handshake */
 };
 
 
+/* This structure contains information about the HTTP request. */
+/* This structure may be extended in future versions. */
+struct mg_response_info {
+	int status_code;          /* E.g. 200 */
+	const char *status_text;  /* E.g. "OK" */
+	const char *http_version; /* E.g. "1.0", "1.1" */
+
+	long long content_length; /* Length (in bytes) of the request body,
+	                             can be -1 if no length was given. */
+
+	int num_headers; /* Number of HTTP headers */
+	struct mg_header
+	    http_headers[MG_MAX_HEADERS]; /* Allocate maximum headers */
+};
+
+
 /* Client certificate information (part of mg_request_info) */
+/* New nomenclature. */
+struct mg_client_cert {
+	const char *subject;
+	const char *issuer;
+	const char *serial;
+	const char *finger;
+};
+
+/* Old nomenclature. */
 struct client_cert {
 	const char *subject;
 	const char *issuer;
@@ -194,13 +229,34 @@ struct mg_callbacks {
 #endif /* MG_LEGACY_INTERFACE */
 
 	/* Called when civetweb is closing a connection.  The per-context mutex is
-	   locked when this is invoked.  This is primarily useful for noting when
-	   a websocket is closing and removing it from any application-maintained
-	   list of clients.
+	   locked when this is invoked.
+
+	   Websockets:
+	   Before mg_set_websocket_handler has been added, it was primarily useful
+	   for noting when a websocket is closing, and used to remove it from any
+	   application-maintained list of clients.
 	   Using this callback for websocket connections is deprecated: Use
-	   mg_set_websocket_handler instead. */
+	   mg_set_websocket_handler instead.
+
+	   Connection specific data:
+	   If memory has been allocated for the connection specific user data
+	   (mg_request_info->conn_data, mg_get_user_connection_data),
+	   this is the last chance to free it.
+	*/
 	void (*connection_close)(const struct mg_connection *);
 
+#if defined(MG_USE_OPEN_FILE)
+	/* Note: The "file in memory" feature is a deletion candidate, since
+	 * it complicates the code, and does not add any value compared to
+	 * "mg_add_request_handler".
+	 * See this discussion thread:
+	 * https://groups.google.com/forum/#!topic/civetweb/h9HT4CmeYqI
+	 * If you disagree, if there is any situation this is indeed useful
+	 * and cannot trivially be replaced by another existing feature,
+	 * please contribute to this discussion during the next 3 month
+	 * (till end of April 2017), otherwise this feature might be dropped
+	 * in future releases. */
+
 	/* Called when civetweb tries to open a file. Used to intercept file open
 	   calls, and serve file data from memory instead.
 	   Parameters:
@@ -214,6 +270,7 @@ struct mg_callbacks {
 	const char *(*open_file)(const struct mg_connection *,
 	                         const char *path,
 	                         size_t *data_len);
+#endif
 
 	/* Called when civetweb is about to serve Lua server page, if
 	   Lua support is enabled.
@@ -259,6 +316,21 @@ struct mg_callbacks {
 	   Parameters:
 	     ctx: context handle */
 	void (*exit_context)(const struct mg_context *ctx);
+
+	/* Called when initializing a new connection object.
+	 * Can be used to initialize the connection specific user data
+	 * (mg_request_info->conn_data, mg_get_user_connection_data).
+	 * When the callback is called, it is not yet known if a
+	 * valid HTTP(S) request will be made.
+	 * Parameters:
+	 *   conn: not yet fully initialized connection object
+	 *   conn_data: output parameter, set to initialize the
+	 *              connection specific user data
+	 * Return value:
+	 *   must be 0
+	 *   Otherwise, the result is undefined
+	 */
+	int (*init_connection)(const struct mg_connection *conn, void **conn_data);
 };
 
 
@@ -330,11 +402,10 @@ typedef int (*mg_request_handler)(struct mg_connection *conn, void *cbdata);
       ctx: server context
       uri: the URI (exact or pattern) for the handler
       handler: the callback handler to use when the URI is requested.
-               If NULL, an already registered handler for this URI will be
-   removed.
-               The URI used to remove a handler must match exactly the one used
-   to
-               register it (not only a pattern match).
+               If NULL, an already registered handler for this URI will
+               be removed.
+               The URI used to remove a handler must match exactly the
+               one used to register it (not only a pattern match).
       cbdata: the callback data to give to the handler when it is called. */
 CIVETWEB_API void mg_set_request_handler(struct mg_context *ctx,
                                          const char *uri,
@@ -417,7 +488,7 @@ CIVETWEB_API void mg_set_websocket_handler_with_subprotocols(
 
 /* mg_authorization_handler
 
-   Some description here
+   Callback function definition for mg_set_auth_handler
 
    Parameters:
       conn: current connection information.
@@ -469,6 +540,19 @@ CIVETWEB_API void *
 mg_get_user_connection_data(const struct mg_connection *conn);
 
 
+/* Get a formatted link corresponding to the current request
+
+   Parameters:
+      conn: current connection information.
+      buf: string buffer (out)
+      buflen: length of the string buffer
+   Returns:
+      <0: error
+      >=0: ok */
+CIVETWEB_API int
+mg_get_request_link(const struct mg_connection *conn, char *buf, size_t buflen);
+
+
 #if defined(MG_LEGACY_INTERFACE)
 /* Return array of strings that represent valid configuration options.
    For each option, option name and default value is returned, i.e. the
@@ -485,7 +569,7 @@ struct mg_option {
 	const char *default_value;
 };
 
-
+/* Old nomenclature */
 enum {
 	CONFIG_TYPE_UNKNOWN = 0x0,
 	CONFIG_TYPE_NUMBER = 0x1,
@@ -493,9 +577,23 @@ enum {
 	CONFIG_TYPE_FILE = 0x3,
 	CONFIG_TYPE_DIRECTORY = 0x4,
 	CONFIG_TYPE_BOOLEAN = 0x5,
-	CONFIG_TYPE_EXT_PATTERN = 0x6
+	CONFIG_TYPE_EXT_PATTERN = 0x6,
+	CONFIG_TYPE_STRING_LIST = 0x7,
+	CONFIG_TYPE_STRING_MULTILINE = 0x8
 };
 
+/* New nomenclature */
+enum {
+	MG_CONFIG_TYPE_UNKNOWN = 0x0,
+	MG_CONFIG_TYPE_NUMBER = 0x1,
+	MG_CONFIG_TYPE_STRING = 0x2,
+	MG_CONFIG_TYPE_FILE = 0x3,
+	MG_CONFIG_TYPE_DIRECTORY = 0x4,
+	MG_CONFIG_TYPE_BOOLEAN = 0x5,
+	MG_CONFIG_TYPE_EXT_PATTERN = 0x6,
+	MG_CONFIG_TYPE_STRING_LIST = 0x7,
+	MG_CONFIG_TYPE_STRING_MULTILINE = 0x8
+};
 
 /* Return array of struct mg_option, representing all valid configuration
    options of civetweb.c.
@@ -525,34 +623,56 @@ CIVETWEB_API int mg_get_server_ports(const struct mg_context *ctx,
                                      struct mg_server_ports *ports);
 
 
+#if defined(MG_LEGACY_INTERFACE)
 /* Deprecated: Use mg_get_server_ports instead. */
 CIVETWEB_API size_t
 mg_get_ports(const struct mg_context *ctx, size_t size, int *ports, int *ssl);
+#endif
 
 
 /* Add, edit or delete the entry in the passwords file.
-
-   This function allows an application to manipulate .htpasswd files on the
-   fly by adding, deleting and changing user records. This is one of the
-   several ways of implementing authentication on the server side. For another,
-   cookie-based way please refer to the examples/chat in the source tree.
-
-   If password is not NULL, entry is added (or modified if already exists).
-   If password is NULL, entry is deleted.
-
-   Return:
-     1 on success, 0 on error. */
+ *
+ * This function allows an application to manipulate .htpasswd files on the
+ * fly by adding, deleting and changing user records. This is one of the
+ * several ways of implementing authentication on the server side. For another,
+ * cookie-based way please refer to the examples/chat in the source tree.
+ *
+ * Parameter:
+ *   passwords_file_name: Path and name of a file storing multiple passwords
+ *   realm: HTTP authentication realm (authentication domain) name
+ *   user: User name
+ *   password:
+ *     If password is not NULL, entry modified or added.
+ *     If password is NULL, entry is deleted.
+ *
+ *  Return:
+ *    1 on success, 0 on error.
+ */
 CIVETWEB_API int mg_modify_passwords_file(const char *passwords_file_name,
-                                          const char *domain,
+                                          const char *realm,
                                           const char *user,
                                           const char *password);
 
 
-/* Return information associated with the request. */
+/* Return information associated with the request.
+ * Use this function to implement a server and get data about a request
+ * from a HTTP/HTTPS client.
+ * Note: Before CivetWeb 1.10, this function could be used to read
+ * a response from a server, when implementing a client, although the
+ * values were never returned in appropriate mg_request_info elements.
+ * It is strongly advised to use mg_get_response_info for clients.
+ */
 CIVETWEB_API const struct mg_request_info *
 mg_get_request_info(const struct mg_connection *);
 
 
+/* Return information associated with a HTTP/HTTPS response.
+ * Use this function in a client, to check the response from
+ * the server. */
+CIVETWEB_API const struct mg_response_info *
+mg_get_response_info(const struct mg_connection *);
+
+
 /* Send data to the client.
    Return:
     0   when the connection has been closed
@@ -619,6 +739,7 @@ CIVETWEB_API void mg_unlock_context(struct mg_context *ctx);
 
 
 /* Opcodes, from http://tools.ietf.org/html/rfc6455 */
+/* Old nomenclature */
 enum {
 	WEBSOCKET_OPCODE_CONTINUATION = 0x0,
 	WEBSOCKET_OPCODE_TEXT = 0x1,
@@ -628,6 +749,15 @@ enum {
 	WEBSOCKET_OPCODE_PONG = 0xa
 };
 
+/* New nomenclature */
+enum {
+	MG_WEBSOCKET_OPCODE_CONTINUATION = 0x0,
+	MG_WEBSOCKET_OPCODE_TEXT = 0x1,
+	MG_WEBSOCKET_OPCODE_BINARY = 0x2,
+	MG_WEBSOCKET_OPCODE_CONNECTION_CLOSE = 0x8,
+	MG_WEBSOCKET_OPCODE_PING = 0x9,
+	MG_WEBSOCKET_OPCODE_PONG = 0xa
+};
 
 /* Macros for enabling compiler-specific checks for printf-like arguments. */
 #undef PRINTF_FORMAT_STRING
@@ -656,20 +786,76 @@ CIVETWEB_API int mg_printf(struct mg_connection *,
                            ...) PRINTF_ARGS(2, 3);
 
 
+/* Send a part of the message body, if chunked transfer encoding is set.
+ * Only use this function after sending a complete HTTP request or response
+ * header with "Transfer-Encoding: chunked" set. */
+CIVETWEB_API int mg_send_chunk(struct mg_connection *conn,
+                               const char *chunk,
+                               unsigned int chunk_len);
+
+
 /* Send contents of the entire file together with HTTP headers. */
 CIVETWEB_API void mg_send_file(struct mg_connection *conn, const char *path);
 
+
+/* Send HTTP error reply. */
+CIVETWEB_API void mg_send_http_error(struct mg_connection *conn,
+                                     int status_code,
+                                     PRINTF_FORMAT_STRING(const char *fmt),
+                                     ...) PRINTF_ARGS(3, 4);
+
+
+/* Send HTTP digest access authentication request.
+ * Browsers will send a user name and password in their next request, showing
+ * an authentication dialog if the password is not stored.
+ * Parameters:
+ *   conn: Current connection handle.
+ *   realm: Authentication realm. If NULL is supplied, the sever domain
+ *          set in the authentication_domain configuration is used.
+ * Return:
+ *   < 0   Error
+ */
+CIVETWEB_API int
+mg_send_digest_access_authentication_request(struct mg_connection *conn,
+                                             const char *realm);
+
+
+/* Check if the current request has a valid authentication token set.
+ * A file is used to provide a list of valid user names, realms and
+ * password hashes. The file can be created and modified using the
+ * mg_modify_passwords_file API function.
+ * Parameters:
+ *   conn: Current connection handle.
+ *   realm: Authentication realm. If NULL is supplied, the sever domain
+ *          set in the authentication_domain configuration is used.
+ *   filename: Path and name of a file storing multiple password hashes.
+ * Return:
+ *   > 0   Valid authentication
+ *   0     Invalid authentication
+ *   < 0   Error (all values < 0 should be considered as invalid
+ *         authentication, future error codes will have negative
+ *         numbers)
+ *   -1    Parameter error
+ *   -2    File not found
+ */
+CIVETWEB_API int
+mg_check_digest_access_authentication(struct mg_connection *conn,
+                                      const char *realm,
+                                      const char *filename);
+
+
 /* Send contents of the entire file together with HTTP headers.
-   Parameters:
-     conn: Current connection information.
-     path: Full path to the file to send.
-     mime_type: Content-Type for file.  NULL will cause the type to be
-                looked up by the file extension.
-*/
+ * Parameters:
+ *   conn: Current connection handle.
+ *   path: Full path to the file to send.
+ *   mime_type: Content-Type for file.  NULL will cause the type to be
+ *              looked up by the file extension.
+ */
 CIVETWEB_API void mg_send_mime_file(struct mg_connection *conn,
                                     const char *path,
                                     const char *mime_type);
 
+
 /* Send contents of the entire file together with HTTP headers.
    Parameters:
      conn: Current connection information.
@@ -677,8 +863,8 @@ CIVETWEB_API void mg_send_mime_file(struct mg_connection *conn,
      mime_type: Content-Type for file.  NULL will cause the type to be
                 looked up by the file extension.
      additional_headers: Additional custom header fields appended to the header.
-                         Each header must start with an X- to ensure it is not
-   included twice.
+                         Each header should start with an X-, to ensure it is
+                         not included twice.
                          NULL does not append anything.
 */
 CIVETWEB_API void mg_send_mime_file2(struct mg_connection *conn,
@@ -686,6 +872,7 @@ CIVETWEB_API void mg_send_mime_file2(struct mg_connection *conn,
                                      const char *mime_type,
                                      const char *additional_headers);
 
+
 /* Store body data into a file. */
 CIVETWEB_API long long mg_store_body(struct mg_connection *conn,
                                      const char *path);
@@ -897,6 +1084,7 @@ struct mg_form_data_handler {
 
 /* Return values definition for the "field_found" callback in
  * mg_form_data_handler. */
+/* Old nomenclature */
 enum {
 	/* Skip this field (neither get nor store it). Continue with the
      * next field. */
@@ -909,6 +1097,18 @@ enum {
 	FORM_FIELD_STORAGE_ABORT = 0x10
 };
 
+/* New nomenclature */
+enum {
+	/* Skip this field (neither get nor store it). Continue with the
+     * next field. */
+	MG_FORM_FIELD_STORAGE_SKIP = 0x0,
+	/* Get the field value. */
+	MG_FORM_FIELD_STORAGE_GET = 0x1,
+	/* Store the field value into a file. */
+	MG_FORM_FIELD_STORAGE_STORE = 0x2,
+	/* Stop parsing this request. Skip the remaining fields. */
+	MG_FORM_FIELD_STORAGE_ABORT = 0x10
+};
 
 /* Process form data.
  * Returns the number of fields handled, or < 0 in case of an error.
@@ -933,8 +1133,8 @@ CIVETWEB_API const char *mg_get_builtin_mime_type(const char *file_name);
 
 
 /* Get text representation of HTTP status code. */
-CIVETWEB_API const char *mg_get_response_code_text(struct mg_connection *conn,
-                                                   int response_code);
+CIVETWEB_API const char *
+mg_get_response_code_text(const struct mg_connection *conn, int response_code);
 
 
 /* Return CivetWeb version. */
@@ -971,7 +1171,7 @@ CIVETWEB_API char *mg_md5(char buf[33], ...);
 
 /* Print error message to the opened error log stream.
    This utilizes the provided logging configuration.
-     conn: connection
+     conn: connection (not used for sending data, but to get perameters)
      fmt: format string without the line return
      ...: variable argument list
    Example:
@@ -1052,7 +1252,7 @@ mg_connect_client_secure(const struct mg_client_options *client_options,
 
 
 enum { TIMEOUT_INFINITE = -1 };
-
+enum { MG_TIMEOUT_INFINITE = -1 };
 
 /* Wait for a response from the server
    Parameters:
@@ -1089,8 +1289,9 @@ CIVETWEB_API int mg_get_response(struct mg_connection *conn,
         32  support Lua scripts and Lua server pages (USE_LUA is set)
         64  support server side JavaScript (USE_DUKTAPE is set)
        128  support caching (NO_CACHING not set)
+       256  support server statistics (USE_SERVER_STATS is set)
        The result is undefined, if bits are set that do not represent a
-       defined feature (currently: feature >= 256).
+       defined feature (currently: feature >= 512).
        The result is undefined, if no bit is set (feature == 0).
 
    Return:
@@ -1100,20 +1301,65 @@ CIVETWEB_API int mg_get_response(struct mg_connection *conn,
 CIVETWEB_API unsigned mg_check_feature(unsigned feature);
 
 
-/* Get information on the system. Useful, if in support requests.
+/* Get information on the system. Useful for support requests.
    Parameters:
      buffer: Store system information as string here.
      buflen: Length of buffer (including a byte required for a terminating 0).
    Return:
      Available size of system information, exluding a terminating 0.
      The information is complete, if the return value is smaller than buflen.
+     The result is a JSON formatted string, the exact content may vary.
    Note:
      It is possible to determine the required buflen, by first calling this
-     function with  buffer = NULL and buflen = NULL. The required buflen is
+     function with buffer = NULL and buflen = NULL. The required buflen is
      one byte more than the returned value.
 */
 CIVETWEB_API int mg_get_system_info(char *buffer, int buflen);
 
+
+/* Get context information. Useful for server diagnosis.
+   Parameters:
+     ctx: Context handle
+     buffer: Store context information here.
+     buflen: Length of buffer (including a byte required for a terminating 0).
+   Return:
+     Available size of system information, exluding a terminating 0.
+     The information is complete, if the return value is smaller than buflen.
+     The result is a JSON formatted string, the exact content may vary.
+     Note:
+     It is possible to determine the required buflen, by first calling this
+     function with buffer = NULL and buflen = NULL. The required buflen is
+     one byte more than the returned value. However, since the available
+     context information changes, you should allocate a few bytes more.
+*/
+CIVETWEB_API int
+mg_get_context_info(const struct mg_context *ctx, char *buffer, int buflen);
+
+
+#ifdef MG_EXPERIMENTAL_INTERFACES
+/* Get connection information. Useful for server diagnosis.
+   Parameters:
+     ctx: Context handle
+     idx: Connection index
+     buffer: Store context information here.
+     buflen: Length of buffer (including a byte required for a terminating 0).
+   Return:
+     Available size of system information, exluding a terminating 0.
+     The information is complete, if the return value is smaller than buflen.
+     The result is a JSON formatted string, the exact content may vary.
+   Note:
+     It is possible to determine the required buflen, by first calling this
+     function with buffer = NULL and buflen = NULL. The required buflen is
+     one byte more than the returned value. However, since the available
+     context information changes, you should allocate a few bytes more.
+*/
+CIVETWEB_API int mg_get_connection_info(const struct mg_context *ctx,
+                                        int idx,
+                                        char *buffer,
+                                        int buflen);
+#endif
+
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

+ 17 - 0
resources/Makefile.in-duktape

@@ -21,6 +21,22 @@ ifeq ($(WITH_DUKTAPE_VERSION), 105)
   DUKTAPE_VERSION_KNOWN = 1
 endif
 
+ifeq ($(WITH_DUKTAPE_VERSION), 108)
+  $(info Duktape: Using version 1.8.0)
+  DUKTAPE_DIR = src/third_party/duktape-1.8.0/src
+  DUKTAPE_SHARED_LIB_FLAG = -lduktape1.8
+  DUKTAPE_CFLAGS = -DDUKTAPE_VERSION_MAKEFILE=108
+  DUKTAPE_VERSION_KNOWN = 1
+endif
+
+ifeq ($(WITH_DUKTAPE_VERSION), 201)
+  $(info Duktape: Using version 2.1.1)
+  DUKTAPE_DIR = src/third_party/duktape-2.1.1/src
+  DUKTAPE_SHARED_LIB_FLAG = -lduktape2.1
+  DUKTAPE_CFLAGS = -DDUKTAPE_VERSION_MAKEFILE=201
+  DUKTAPE_VERSION_KNOWN = 1
+endif
+
 ifneq ($(DUKTAPE_VERSION_KNOWN), 1)
   $(error Duktape: Unknwon version - $(WITH_DUKTAPE_VERSION))
 endif
@@ -57,4 +73,5 @@ DUKTAPE_OBJECTS = $(DUKTAPE_SOURCES:.c=.o)
 OBJECTS += $(DUKTAPE_OBJECTS)
 CFLAGS += $(DUKTAPE_CFLAGS)
 SOURCE_DIRS = $(DUKTAPE_DIR)
+BUILD_DIRS += $(BUILD_DIR)/$(DUKTAPE_DIR)
 

+ 1 - 0
resources/Makefile.in-lua

@@ -108,6 +108,7 @@ LUA_OBJECTS = $(LUA_SOURCES:.c=.o)
 OBJECTS += $(LUA_OBJECTS)
 CFLAGS += $(LUA_CFLAGS)
 SOURCE_DIRS = $(LUA_DIR)
+BUILD_DIRS += $(BUILD_DIR)/$(LUA_DIR)
 
 
 ifneq ($(WITH_LUA_VERSION), 501)

+ 1 - 0
resources/Makefile.in-os

@@ -20,3 +20,4 @@ ifeq ($(TARGET_OS),)
     endif
   endif
 endif
+

+ 17 - 12
resources/cert/client.crt

@@ -1,14 +1,19 @@
 -----BEGIN CERTIFICATE-----
-MIICOTCCAaICCQCXNPrLNIw8IDANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJ4
-eDELMAkGA1UECAwCeHgxCzAJBgNVBAcMAnh4MQswCQYDVQQKDAJ4eDELMAkGA1UE
-CwwCeHgxCzAJBgNVBAMMAnh4MREwDwYJKoZIhvcNAQkBFgJ4eDAeFw0xNTEwMjUy
-MzMxNDJaFw0yNTEwMjIyMzMxNDJaMGExCzAJBgNVBAYTAnh4MQswCQYDVQQIDAJ4
-eDELMAkGA1UEBwwCeHgxCzAJBgNVBAoMAnh4MQswCQYDVQQLDAJ4eDELMAkGA1UE
-AwwCeHgxETAPBgkqhkiG9w0BCQEWAnh4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
-iQKBgQDGwWIIU2KUEufa0Ga5lnm7I8cX4LPRIFX4zL3g1Kuw27eRaJWJLz3Y97oi
-m0fUmhhKJoEFDxj9U4UbXZWMxzH5F8RfupUu+9yDqTWjTRaUQiM/C7dSPEevfqNP
-zBoERPrMzm9W5d8Ke04vpUzk0duoE6vyNQVECroNlHY7R4zQjwIDAQABMA0GCSqG
-SIb3DQEBCwUAA4GBAKZiZ2+sYJWFnQcfqcDJBwrbTo98SSxfryPmeVQSuM8AXC4I
-baX+fqkatdFidDBl96Aq8pDfqeAz+gqRoJ+Dx7opn5/b0WcB0lD+v25x+nO8g4z7
-HBzpVtvRTkC7dGase72csnqvyWm1xTSiHNRIghl0kZy8wb6V9GmJsHxBoKWN
+MIIDBjCCAe4CCQCFpskbTEyGpTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB
+VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
+cyBQdHkgTHRkMB4XDTE3MDkwMzE5MjIwNVoXDTI3MDkwMTE5MjIwNVowRTELMAkG
+A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
+IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ANyFUuYxv/uexSr/K9aSmcnEcylNH4S3NdlvMwFvW3XFqAV05tV6HnPnSELEk6t3
+8aMDUGKDBrrjwsVK6+S7OyrkioXeB9dWldHbqD7o3MkIM3sUxUtaR6x0RMZ+sIX4
+XpE0xULcip1bG0etP4Z2frEP2IOOValQcm4SCnKYZJyTr/oR31NmlIPU/47s74U6
+rqwwUE92bzvf1jGeUHEn7IAgSJNIUBNsOIdRQAMBuTJIAmG2qawXaetjLi/NBwNS
+d0OX2v3o9SrA+ZhQYpPG5xp3B3ncHgVvmhmp7hUdlYbiemcUHn18hZjxPVZLbtY8
+gQldrWyMZkVabSZjuIH3IKcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAUZsxxYVK
+l0tH8E0FCnRJTvG6gjOeiqJRIk7Mmg+hfFZK/ewqBixxg1OBM/xmPXfnI/ULRz74
+UMXnyDIsGakzrFDqWqPt3xots35yHHo2ZkVao6gV4qx0Reu86qeN5iRvG0EjoGMD
+7XRaw56E0XhvMBJW1CiUg944HSw4ptJli0dJCYa+P9s1Fop3lA0d9+dwKMKUyCDr
+yBz4XjyO9jXSQC/t0fkxC4gHhdH/ZaAq0Lem6Xxc40ZwoVc1+dHWFxn8d6L/RYvb
+16gOuw6s2Xt9h2K8OFKzehOgNZAkI2oUELRFUx9Wc8/Bcl6uEkBmPHRqeX5l35jo
+ztBrpAEsCy0cGg==
 -----END CERTIFICATE-----

+ 14 - 9
resources/cert/client.csr

@@ -1,11 +1,16 @@
 -----BEGIN CERTIFICATE REQUEST-----
-MIIBoTCCAQoCAQAwYTELMAkGA1UEBhMCeHgxCzAJBgNVBAgMAnh4MQswCQYDVQQH
-DAJ4eDELMAkGA1UECgwCeHgxCzAJBgNVBAsMAnh4MQswCQYDVQQDDAJ4eDERMA8G
-CSqGSIb3DQEJARYCeHgwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMbBYghT
-YpQS59rQZrmWebsjxxfgs9EgVfjMveDUq7Dbt5FolYkvPdj3uiKbR9SaGEomgQUP
-GP1ThRtdlYzHMfkXxF+6lS773IOpNaNNFpRCIz8Lt1I8R69+o0/MGgRE+szOb1bl
-3wp7Ti+lTOTR26gTq/I1BUQKug2UdjtHjNCPAgMBAAGgADANBgkqhkiG9w0BAQsF
-AAOBgQCVJKEisDii5qFbV75rOGF+tTChv3c051pWerl8U42s/MQ3jhzNb8+i7f2n
-Kn4yZU3u91xtAruAoKFPSnFpgQKyBRv57g5eM03nrUUImZcRT5Kkf4YsqRMsZ2yH
-MYk6QbTrJwibUoqEUUFgv0n5ONUBoEvhzZr0K9KZ3DLyIg1rpQ==
+MIICijCCAXICAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx
+ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBANyFUuYxv/uexSr/K9aSmcnEcylNH4S3NdlvMwFv
+W3XFqAV05tV6HnPnSELEk6t38aMDUGKDBrrjwsVK6+S7OyrkioXeB9dWldHbqD7o
+3MkIM3sUxUtaR6x0RMZ+sIX4XpE0xULcip1bG0etP4Z2frEP2IOOValQcm4SCnKY
+ZJyTr/oR31NmlIPU/47s74U6rqwwUE92bzvf1jGeUHEn7IAgSJNIUBNsOIdRQAMB
+uTJIAmG2qawXaetjLi/NBwNSd0OX2v3o9SrA+ZhQYpPG5xp3B3ncHgVvmhmp7hUd
+lYbiemcUHn18hZjxPVZLbtY8gQldrWyMZkVabSZjuIH3IKcCAwEAAaAAMA0GCSqG
+SIb3DQEBCwUAA4IBAQB/bapQm4nxXA01msL6nkjiVaeh/mj8Cr8sPFtQXVu+hxl9
+mjbisxDXwPhiFOiTlokQkINf+RMxQsVNr2y/sGZrSMimabwODDXnPpyir4b2WOWp
+VQQWbgnMVnvgKsjBpLLDr8VnLBiQ3mED+2QV0bxxJSgvvEuiZx/BlCgiu77D/8kj
+XUY/CXIBi00fIYigpRRdv2WtMQjtQe2fCSZZKOWu2ZWu2o24kEk28x5LO/WaJ4Ft
+lUHFOIp/wkKz/US4mbdQaD0bsg7MirAyGrCmZIHqQDhdDWq+o/brI7N/8yOk3qwc
+qPGkr9PYIPnuzZwStLJlPxKGXjCA40HpdmWA0kyc
 -----END CERTIFICATE REQUEST-----

+ 25 - 13
resources/cert/client.key

@@ -1,15 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----

+ 26 - 14
resources/cert/client.key.orig

@@ -1,18 +1,30 @@
 -----BEGIN RSA PRIVATE KEY-----
 Proc-Type: 4,ENCRYPTED
-DEK-Info: DES-EDE3-CBC,74B669EA97409DB5
+DEK-Info: DES-EDE3-CBC,161D2DE9FC3C5EE4
 
-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
+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
 -----END RSA PRIVATE KEY-----

+ 42 - 25
resources/cert/client.pem

@@ -1,29 +1,46 @@
 -----BEGIN CERTIFICATE-----
-MIICOTCCAaICCQCXNPrLNIw8IDANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJ4
-eDELMAkGA1UECAwCeHgxCzAJBgNVBAcMAnh4MQswCQYDVQQKDAJ4eDELMAkGA1UE
-CwwCeHgxCzAJBgNVBAMMAnh4MREwDwYJKoZIhvcNAQkBFgJ4eDAeFw0xNTEwMjUy
-MzMxNDJaFw0yNTEwMjIyMzMxNDJaMGExCzAJBgNVBAYTAnh4MQswCQYDVQQIDAJ4
-eDELMAkGA1UEBwwCeHgxCzAJBgNVBAoMAnh4MQswCQYDVQQLDAJ4eDELMAkGA1UE
-AwwCeHgxETAPBgkqhkiG9w0BCQEWAnh4MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
-iQKBgQDGwWIIU2KUEufa0Ga5lnm7I8cX4LPRIFX4zL3g1Kuw27eRaJWJLz3Y97oi
-m0fUmhhKJoEFDxj9U4UbXZWMxzH5F8RfupUu+9yDqTWjTRaUQiM/C7dSPEevfqNP
-zBoERPrMzm9W5d8Ke04vpUzk0duoE6vyNQVECroNlHY7R4zQjwIDAQABMA0GCSqG
-SIb3DQEBCwUAA4GBAKZiZ2+sYJWFnQcfqcDJBwrbTo98SSxfryPmeVQSuM8AXC4I
-baX+fqkatdFidDBl96Aq8pDfqeAz+gqRoJ+Dx7opn5/b0WcB0lD+v25x+nO8g4z7
-HBzpVtvRTkC7dGase72csnqvyWm1xTSiHNRIghl0kZy8wb6V9GmJsHxBoKWN
+MIIDBjCCAe4CCQCFpskbTEyGpTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB
+VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
+cyBQdHkgTHRkMB4XDTE3MDkwMzE5MjIwNVoXDTI3MDkwMTE5MjIwNVowRTELMAkG
+A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
+IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ANyFUuYxv/uexSr/K9aSmcnEcylNH4S3NdlvMwFvW3XFqAV05tV6HnPnSELEk6t3
+8aMDUGKDBrrjwsVK6+S7OyrkioXeB9dWldHbqD7o3MkIM3sUxUtaR6x0RMZ+sIX4
+XpE0xULcip1bG0etP4Z2frEP2IOOValQcm4SCnKYZJyTr/oR31NmlIPU/47s74U6
+rqwwUE92bzvf1jGeUHEn7IAgSJNIUBNsOIdRQAMBuTJIAmG2qawXaetjLi/NBwNS
+d0OX2v3o9SrA+ZhQYpPG5xp3B3ncHgVvmhmp7hUdlYbiemcUHn18hZjxPVZLbtY8
+gQldrWyMZkVabSZjuIH3IKcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAUZsxxYVK
+l0tH8E0FCnRJTvG6gjOeiqJRIk7Mmg+hfFZK/ewqBixxg1OBM/xmPXfnI/ULRz74
+UMXnyDIsGakzrFDqWqPt3xots35yHHo2ZkVao6gV4qx0Reu86qeN5iRvG0EjoGMD
+7XRaw56E0XhvMBJW1CiUg944HSw4ptJli0dJCYa+P9s1Fop3lA0d9+dwKMKUyCDr
+yBz4XjyO9jXSQC/t0fkxC4gHhdH/ZaAq0Lem6Xxc40ZwoVc1+dHWFxn8d6L/RYvb
+16gOuw6s2Xt9h2K8OFKzehOgNZAkI2oUELRFUx9Wc8/Bcl6uEkBmPHRqeX5l35jo
+ztBrpAEsCy0cGg==
 -----END CERTIFICATE-----
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----

BIN
resources/cert/client.pfx


+ 0 - 22
resources/cert/make_cert.bat

@@ -1,22 +0,0 @@
-del server.*
-
-c:\OpenSSL-Win32\bin\openssl.exe genrsa -des3 -out server.key 4096
-
-c:\OpenSSL-Win32\bin\openssl.exe req -sha256 -new -key server.key -out server.csr -utf8
-
-copy server.key server.key.orig
-
-c:\OpenSSL-Win32\bin\openssl.exe rsa -in server.key.orig -out server.key
-
-echo [ v3_ca ] > server.ext.txt
-echo [ req ] >> server.ext.txt
-echo req_extensions = my_extensions >> server.ext.txt
-echo [ my_extensions ] >> server.ext.txt
-echo extendedKeyUsage=serverAuth >> server.ext.txt
-echo crlDistributionPoints=URI:http://localhost/crl.pem >> server.ext.txt
-
-c:\OpenSSL-Win32\bin\openssl.exe x509 -req -days 365 -extensions v3_ca -extfile server.ext.txt -in server.csr -signkey server.key -out server.crt
-
-copy server.crt server.pem
-
-type server.key >> server.pem

+ 0 - 31
resources/cert/make_certs

@@ -1,31 +0,0 @@
-#using "pass" for every password
-
-openssl genrsa -des3 -out client.key 1024
-openssl req -new -key client.key -out client.csr
-
-cp client.key client.key.orig
-
-openssl rsa -in client.key.orig -out client.key
-
-openssl x509 -req -days 3650 -in client.csr -signkey client.key -out client.crt
-
-cp client.crt client.pem
-cat client.key >> client.pem
-
-openssl pkcs12 -export -inkey client.key -in client.pem -name ClientName -out client.pfx
-
-
-
-openssl genrsa -des3 -out server.key 1024
-openssl req -new -key server.key -out server.csr
-
-cp server.key server.key.orig
-
-openssl rsa -in server.key.orig -out server.key
-
-openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt
-
-cp server.crt server.pem
-cat server.key >> server.pem
-
-openssl pkcs12 -export -inkey server.key -in server.pem -name ServerName -out server.pfx

+ 55 - 0
resources/cert/make_certs.bat

@@ -0,0 +1,55 @@
+@echo off
+REM We need admin rights, otherwise the random state cannot be written
+REM Thanks to http://stackoverflow.com/a/10052222/1531708
+
+:: BatchGotAdmin
+:-------------------------------------
+REM  --> Check for permissions
+    IF "%PROCESSOR_ARCHITECTURE%" EQU "amd64" (
+>nul 2>&1 "%SYSTEMROOT%\SysWOW64\cacls.exe" "%SYSTEMROOT%\SysWOW64\config\system"
+) ELSE (
+>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
+)
+
+REM --> If error flag set, we do not have admin.
+if '%errorlevel%' NEQ '0' (
+    echo Requesting administrative privileges...
+    goto UACPrompt
+) else ( goto gotAdmin )
+
+:UACPrompt
+    echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
+    set params = %*:"=""
+    echo UAC.ShellExecute "cmd.exe", "/c ""%~s0"" %params%", "", "runas", 1 >> "%temp%\getadmin.vbs"
+
+    "%temp%\getadmin.vbs"
+    del "%temp%\getadmin.vbs"
+    exit /B
+
+:gotAdmin
+    pushd "%CD%"
+    CD /D "%~dp0"
+:-------------------------------------- 
+
+del server.*
+
+c:\OpenSSL-Win32\bin\openssl.exe genrsa -des3 -out server.key 4096
+
+c:\OpenSSL-Win32\bin\openssl.exe req -sha256 -new -key server.key -out server.csr -utf8
+
+copy server.key server.key.orig
+
+c:\OpenSSL-Win32\bin\openssl.exe rsa -in server.key.orig -out server.key
+
+echo [ v3_ca ] > server.ext.txt
+echo [ req ] >> server.ext.txt
+echo req_extensions = my_extensions >> server.ext.txt
+echo [ my_extensions ] >> server.ext.txt
+echo extendedKeyUsage=serverAuth >> server.ext.txt
+echo crlDistributionPoints=URI:http://localhost/crl.pem >> server.ext.txt
+
+c:\OpenSSL-Win32\bin\openssl.exe x509 -req -days 365 -extensions v3_ca -extfile server.ext.txt -in server.csr -signkey server.key -out server.crt
+
+copy server.crt server.pem
+
+type server.key >> server.pem

+ 64 - 0
resources/cert/make_certs.sh

@@ -0,0 +1,64 @@
+#!/bin/sh
+#using "pass" for every password
+
+echo "Generating client certificate ..."
+
+openssl genrsa -des3 -out client.key 2048
+openssl req -new -key client.key -out client.csr
+
+cp client.key client.key.orig
+
+openssl rsa -in client.key.orig -out client.key
+
+openssl x509 -req -days 3650 -in client.csr -signkey client.key -out client.crt
+
+cp client.crt client.pem
+cat client.key >> client.pem
+
+openssl pkcs12 -export -inkey client.key -in client.pem -name ClientName -out client.pfx
+
+
+echo "Generating first server certificate ..."
+
+openssl genrsa -des3 -out server.key 2048
+openssl req -new -key server.key -out server.csr
+
+cp server.key server.key.orig
+
+openssl rsa -in server.key.orig -out server.key
+
+openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt
+
+cp server.crt server.pem
+cat server.key >> server.pem
+
+openssl pkcs12 -export -inkey server.key -in server.pem -name ServerName -out server.pfx
+
+echo "First server certificate hash for Public-Key-Pins header:"
+
+openssl x509 -pubkey < server.crt | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64 > server.pin
+
+cat server.pin
+
+echo "Generating backup server certificate ..."
+
+openssl genrsa -des3 -out server_bkup.key 2048
+openssl req -new -key server_bkup.key -out server_bkup.csr
+
+cp server_bkup.key server_bkup.key.orig
+
+openssl rsa -in server_bkup.key.orig -out server_bkup.key
+
+openssl x509 -req -days 3650 -in server_bkup.csr -signkey server_bkup.key -out server_bkup.crt
+
+cp server_bkup.crt server_bkup.pem
+cat server_bkup.key >> server_bkup.pem
+
+openssl pkcs12 -export -inkey server_bkup.key -in server_bkup.pem -name ServerName -out server_bkup.pfx
+
+echo "Backup server certificate hash for Public-Key-Pins header:"
+
+openssl x509 -pubkey < server_bkup.crt | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64 > server_bkup.pin
+
+cat server_bkup.pin
+

+ 17 - 27
resources/cert/server.crt

@@ -1,29 +1,19 @@
 -----BEGIN CERTIFICATE-----
-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
+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
+dFIuUv3YzfenfA==
 -----END CERTIFICATE-----

+ 14 - 25
resources/cert/server.csr

@@ -1,27 +1,16 @@
 -----BEGIN CERTIFICATE REQUEST-----
-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
+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
 -----END CERTIFICATE REQUEST-----

+ 25 - 49
resources/cert/server.key

@@ -1,51 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----

+ 26 - 50
resources/cert/server.key.orig

@@ -1,54 +1,30 @@
 -----BEGIN RSA PRIVATE KEY-----
 Proc-Type: 4,ENCRYPTED
-DEK-Info: DES-EDE3-CBC,268D072E47DD85BF
+DEK-Info: DES-EDE3-CBC,9D77FEDB1409D1BC
 
-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
+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
 -----END RSA PRIVATE KEY-----

+ 42 - 76
resources/cert/server.pem

@@ -1,80 +1,46 @@
 -----BEGIN CERTIFICATE-----
-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
+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
+dFIuUv3YzfenfA==
 -----END CERTIFICATE-----
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----

+ 1 - 0
resources/cert/server.pin

@@ -0,0 +1 @@
+uz1UTAPen+xb+UoQqkVlEx4H653LbMjfRJcZx5OrjbI=

+ 19 - 0
resources/cert/server_bkup.crt

@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAe4CCQCFKfFGF1i10TANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB
+VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
+cyBQdHkgTHRkMB4XDTE3MDkwMzE5MjI1MVoXDTI3MDkwMTE5MjI1MVowRTELMAkG
+A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
+IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AKTJr3PzWOR1Hrjfk9bBA7TptI1hNYVn/Xvi2GSferhJaWg69b2Li4t5/JxElESR
+8fy0lBMzQ/yaFiQb51y7Q1c+Z6xWLxk322rfy3WhU3DYiFL2sJndrDvAhmso122Z
+xVADA0cQwo520MgFYpHNBF8BcFV2IRukzVX+/nVkki05XcwfbI2y6gqCRpOSXdE9
+gCDVan3tSRbtrwKu7IHy88mL6057o82Uezpl0KesoCwb4f5oqs2vThUmXKuxu8GO
+WpZNK4JFWnTgDOJrubZvKxzzL9E85DS9aXLk6dNKBJVKPCETnYw+2ArMgXzs+JuA
+C4AhV0e6unLX9DcavZ6j7JcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAJJWqVuQs
+guFZG/LZPeeh1WtZr9S6R5BT4+b+PH2teVyGtClXV6KpwcLNEVWzY3qPtrFFPQI1
+uEg6cY8w1JOiCmj/IWKsiHd+IdsqsFVKL+Bmvthm3HSgA6p6ZiVCG4E67p8xwiJP
+p5EwtMM/7BdS/tHLUOe1OpNZ8XtHRVUNbzy/+JV0So7WLP9ksGb6COL/9MF0/qG4
+4XrrvpZ9FAgRC9/22QyYiQqoaegGEy4E+KHOBxRmipInsU2H8aQA2sZzQ49Zew9E
+QI2jSJTC7EeuZ0OcZawKkJY1ZtIGmOo/Q956keOLdG8cxyq6pXW3gmq1X5QBxy1M
+pZYi5eIENGE63g==
+-----END CERTIFICATE-----

+ 16 - 0
resources/cert/server_bkup.csr

@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICijCCAXICAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx
+ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAKTJr3PzWOR1Hrjfk9bBA7TptI1hNYVn/Xvi2GSf
+erhJaWg69b2Li4t5/JxElESR8fy0lBMzQ/yaFiQb51y7Q1c+Z6xWLxk322rfy3Wh
+U3DYiFL2sJndrDvAhmso122ZxVADA0cQwo520MgFYpHNBF8BcFV2IRukzVX+/nVk
+ki05XcwfbI2y6gqCRpOSXdE9gCDVan3tSRbtrwKu7IHy88mL6057o82Uezpl0Kes
+oCwb4f5oqs2vThUmXKuxu8GOWpZNK4JFWnTgDOJrubZvKxzzL9E85DS9aXLk6dNK
+BJVKPCETnYw+2ArMgXzs+JuAC4AhV0e6unLX9DcavZ6j7JcCAwEAAaAAMA0GCSqG
+SIb3DQEBCwUAA4IBAQBvbql7sAA8XOwsszRUzOCLkFxfDsWJ0l5re2mGgHTEd5hc
+eDfM+Vdy8SVZX9OySdioVD6ACTse3rc1ULYn8jj1wvOd3/z/J9aUBcBACJG5D1Dl
++j+xvfhvgAGCEQn7ZMaWLFWrLs++aQ+EKbl0SypEI2rTJkyZlYSDVpa+LhqX4UOa
++RNlq1CX+85HCjBn0sWBNzhjrf3gwERRn5NfTab4FqwqGp2+s4GvbOJHrm8saMWu
+BlhcTzGGLBRKCQUHo5i9393b3oBOqtcpWPcZGhyAF1NUbYL7USnsiH6lkGReeaFi
+xy7vYmUn9j//vT64SmASG0oF+ecUF0q2W42sSqnU
+-----END CERTIFICATE REQUEST-----

+ 27 - 0
resources/cert/server_bkup.key

@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEApMmvc/NY5HUeuN+T1sEDtOm0jWE1hWf9e+LYZJ96uElpaDr1
+vYuLi3n8nESURJHx/LSUEzND/JoWJBvnXLtDVz5nrFYvGTfbat/LdaFTcNiIUvaw
+md2sO8CGayjXbZnFUAMDRxDCjnbQyAVikc0EXwFwVXYhG6TNVf7+dWSSLTldzB9s
+jbLqCoJGk5Jd0T2AINVqfe1JFu2vAq7sgfLzyYvrTnujzZR7OmXQp6ygLBvh/miq
+za9OFSZcq7G7wY5alk0rgkVadOAM4mu5tm8rHPMv0TzkNL1pcuTp00oElUo8IROd
+jD7YCsyBfOz4m4ALgCFXR7q6ctf0Nxq9nqPslwIDAQABAoIBAE/B7lHIrnWk2kHQ
+tNV0hj7B/smPC0COnHmhyeqp5dPcdFAmeVpMeDYBzOo1py2pFd6h6CmC3p0cVysS
+9mBDosxPQA6BiDpEdsa7mtZMRv6PTywYilFuoTYqcOTc16gMjRu02ZlD22boyxSE
+xria6kqxf5Vdn5ipo1jEGpTnIHkSS+Y8CetCaYgcezLaXlXN3RyjF6tCHMeS3iLl
+/zY2O4avG2BM+vvDGDW2FWtZg+hN+5Yk90Qt8dFTwvWRCfYaSWfi7id91p5X0rnL
+x1G07qw18LziKJj4HZiueqbDcDOYhfcA6sd0OHcvtXfGIoeqkXxi54cIOReRhN2/
+7ib3iUECgYEA2DNH5aiwc5uqTAL9RHTnuuFwQe46onJwnBkho+xEvvdsp2Q2f7VR
+c5M17fL+Rb5gq0O4vzeegKiYpo8gKjFp3Duv9Gdc/TB9sLEEt4NQMD4shV7ihBwC
+Rjsflww45dt0mccFZp1ncDYKWHDFzdhO+WB828FPFh/5dl6S+v4Q9bUCgYEAwx+G
+XhheTMSqoKGVJ283+4bNZWUSE99wcAhx9J3FkJera030mh0OHoCn0myBjRjxOSY/
+eBH8/0YoLkGYvTdEU/tYiLIWJ/ehC0eweXiwDehb5meco6u9WCeYvyPMLErXbe3K
+BQVyfcFzva4eC3dZ7lzxmyVyKXVTYgY0Hf7biJsCgYBKHdJg/eJ3z36jDkdK55Tl
+cRFt2MCLHhZSvR7WNlIe8W1zORyhzUP+DhJn32yh9jDnpZC5JNUWoDWsq9ZIAKac
+1G1uqNytA6mjIBxQ2RhtYXMbybp3ta5l6zDaNFtxGTmw2hSU6BMk2bHUPdzhw2zX
+eudy4qM9H3sCxEs49k5UHQKBgDz7I0FRGFehtznQhg73AWYIsTSZK9cuI7O/z+2F
+SXNxE0/L40AvCHSb/NcUtkBkpS8ZNwjNhmY5hOE/+v5XwXEFwpumHKqNB7XAx/SO
+tWcDUYVmqFu2lsxwQ5qpE2xcT4u5n0OGeku3I/cJ7bXjrSWDwracM1uloVOnYK5n
+MjE1AoGAeM6Wrb0VXRq025+OEfoFis3P9S0REkkkabM9+VLRSWi63uxg2cyipxUg
+qJUThbUm1aSS1F+XWjG7vrDjWT/GQTYj9/CH3mZRflZgLUltVHEZesLwWqn15Gl/
+BDwaV6RN7F3BCSzgEfCutrfGJqxA0tx5TTcupOgwpZVakN+hm3c=
+-----END RSA PRIVATE KEY-----

+ 30 - 0
resources/cert/server_bkup.key.orig

@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,E700A7E4CCCF78FC
+
+1/jqqjzwHWxdTvayJ+y//FTMuxZbIOT8hl4h+4zzh+/o45RHUa8n6nTI3mLSIK/i
+6yZqSaPaCiBINcLWmijbeDN73OhVL3rrum1VotcTUTA2LU0M+kLWpmcJrY5lsku2
+2voulXmLoCniup+nhnGXDWOk3jaLsMBOn3kYyVBgphwzGzKinFQnqzo/w6/2pJ/C
+iKb/GWNEuXwHkoTz7A4o1ZVVOQyx8h0klWbwjBEPB+cPE3h/bRTkJWTTy2yfCeUC
+nyRQ1BkWC6I5LLesC7gG0jsw3rcGkJnu+zNkxG43N9CkU74S/jNwktjqzKiSbO14
+SYu/NiaVLCtQTeaTeh39X8OGW4RzFbO32PVBl0jL5d8h3DpvTufbtC9BS9dADM0o
+pwCUVWiKKgApmqhFDyUpQB8ptfLewmp5ksB93NzdlPLV8vojJ7nBOrppaueXKQ6Z
+f380J3xCrVN7pTt/yT3mlvCnmb0gNhL6jAE53C112Upjmu40OBhwjGDjDXsOZBmZ
+NH0KEsLecIPgbx0W27h0j4JDdXGtI4mjFHHEnFj75We73BZ8BIlyRt7nxS+iFYNH
+hpbwuNc4dX953jwPy7CIxyms5cy4BigTv/rsgFWCxWxFcTqYkp6L3z8IC6apJDSp
+htKLzhFKjlXqP3vcwZYrAF26eOl6Pxn74853dRskAZNY5F40/7IjVb8l71tedWof
+WE5wpuXrZJd+GBeIM+plbPCnBiNSHuRzJPhLU3tsT3X70WfDxgIgM38P5uOOBLma
+hU/0wcL8+Q3HESPx5ju+5lYZBmozs5ANwMggXv0a1vBptI/kA0HeMQx52G4m1F+9
+aYRrNc+Exl901Yjn120Y6NllIk5EolsqNifDsems9sTiC91Fvh7yiYI5Pd7qCwoR
+2ssLbWda/+bgqtDXjmv4x1btWhWmbInBpCrp1YEwILlyNN6FQ/sQ8pvHtyC9+FcB
+xQ7wI0JnsCpj8E+P5C08EEgpTiUfelwYyTZLarAFMRe5HWZjgQW7+JvbiQ4Q3ZXM
+/DaYh6zGXvR4OomTqKN63i6iAckS7Uh3/XzaWbjOAxvMIgKhU7OBqDAlPvgXJh1y
+sDig2zTR603AURkWZir2OOr7XKZcqNj8lxt+BG+E6bwxdeIeEQn7f8Ef5oUmFNXQ
+o5zQwI12RDQXaBRDG/wTONrUhvc8TEM04jNGKMRPU6FlZSEF2zlTSU8/QtO56FwR
+MwhPlNUSgWgvqzFWoA4W7XWjAfYqvoVRcLjcZF2WBUJwYq4ZODNqBH+j3+Ftge9l
+wKc/9KjcurpAWbg7gq9XtwgiT8bYHcM3NSOwgnrOJ4wtukuwbLq2JjMLgFQeDAev
+NFJfbYoZ0iTyIq1WRS0MlhAwDKujDOoQLqkF41LC5Ac6RpMeR689xN18YE6b6iXp
+f93tHI+6Ru1I+2ZoGbvCPmasv3jk69C8A/StmUEcFfxmOr5qhQEVR2pIXfXKeqbE
+KCUoR4Wax42q/bDhgIOOmq+E9YsTuy4Iq5J25WDIbgWN35s0qXDm91s+aY0KtDUu
+fxGdOIHQHx10ARHUKZ6AhXSF+q5QQFy4ejlgiTMorvT0XUHmIQ82hw==
+-----END RSA PRIVATE KEY-----

+ 46 - 0
resources/cert/server_bkup.pem

@@ -0,0 +1,46 @@
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAe4CCQCFKfFGF1i10TANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB
+VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
+cyBQdHkgTHRkMB4XDTE3MDkwMzE5MjI1MVoXDTI3MDkwMTE5MjI1MVowRTELMAkG
+A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
+IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AKTJr3PzWOR1Hrjfk9bBA7TptI1hNYVn/Xvi2GSferhJaWg69b2Li4t5/JxElESR
+8fy0lBMzQ/yaFiQb51y7Q1c+Z6xWLxk322rfy3WhU3DYiFL2sJndrDvAhmso122Z
+xVADA0cQwo520MgFYpHNBF8BcFV2IRukzVX+/nVkki05XcwfbI2y6gqCRpOSXdE9
+gCDVan3tSRbtrwKu7IHy88mL6057o82Uezpl0KesoCwb4f5oqs2vThUmXKuxu8GO
+WpZNK4JFWnTgDOJrubZvKxzzL9E85DS9aXLk6dNKBJVKPCETnYw+2ArMgXzs+JuA
+C4AhV0e6unLX9DcavZ6j7JcCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAJJWqVuQs
+guFZG/LZPeeh1WtZr9S6R5BT4+b+PH2teVyGtClXV6KpwcLNEVWzY3qPtrFFPQI1
+uEg6cY8w1JOiCmj/IWKsiHd+IdsqsFVKL+Bmvthm3HSgA6p6ZiVCG4E67p8xwiJP
+p5EwtMM/7BdS/tHLUOe1OpNZ8XtHRVUNbzy/+JV0So7WLP9ksGb6COL/9MF0/qG4
+4XrrvpZ9FAgRC9/22QyYiQqoaegGEy4E+KHOBxRmipInsU2H8aQA2sZzQ49Zew9E
+QI2jSJTC7EeuZ0OcZawKkJY1ZtIGmOo/Q956keOLdG8cxyq6pXW3gmq1X5QBxy1M
+pZYi5eIENGE63g==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEApMmvc/NY5HUeuN+T1sEDtOm0jWE1hWf9e+LYZJ96uElpaDr1
+vYuLi3n8nESURJHx/LSUEzND/JoWJBvnXLtDVz5nrFYvGTfbat/LdaFTcNiIUvaw
+md2sO8CGayjXbZnFUAMDRxDCjnbQyAVikc0EXwFwVXYhG6TNVf7+dWSSLTldzB9s
+jbLqCoJGk5Jd0T2AINVqfe1JFu2vAq7sgfLzyYvrTnujzZR7OmXQp6ygLBvh/miq
+za9OFSZcq7G7wY5alk0rgkVadOAM4mu5tm8rHPMv0TzkNL1pcuTp00oElUo8IROd
+jD7YCsyBfOz4m4ALgCFXR7q6ctf0Nxq9nqPslwIDAQABAoIBAE/B7lHIrnWk2kHQ
+tNV0hj7B/smPC0COnHmhyeqp5dPcdFAmeVpMeDYBzOo1py2pFd6h6CmC3p0cVysS
+9mBDosxPQA6BiDpEdsa7mtZMRv6PTywYilFuoTYqcOTc16gMjRu02ZlD22boyxSE
+xria6kqxf5Vdn5ipo1jEGpTnIHkSS+Y8CetCaYgcezLaXlXN3RyjF6tCHMeS3iLl
+/zY2O4avG2BM+vvDGDW2FWtZg+hN+5Yk90Qt8dFTwvWRCfYaSWfi7id91p5X0rnL
+x1G07qw18LziKJj4HZiueqbDcDOYhfcA6sd0OHcvtXfGIoeqkXxi54cIOReRhN2/
+7ib3iUECgYEA2DNH5aiwc5uqTAL9RHTnuuFwQe46onJwnBkho+xEvvdsp2Q2f7VR
+c5M17fL+Rb5gq0O4vzeegKiYpo8gKjFp3Duv9Gdc/TB9sLEEt4NQMD4shV7ihBwC
+Rjsflww45dt0mccFZp1ncDYKWHDFzdhO+WB828FPFh/5dl6S+v4Q9bUCgYEAwx+G
+XhheTMSqoKGVJ283+4bNZWUSE99wcAhx9J3FkJera030mh0OHoCn0myBjRjxOSY/
+eBH8/0YoLkGYvTdEU/tYiLIWJ/ehC0eweXiwDehb5meco6u9WCeYvyPMLErXbe3K
+BQVyfcFzva4eC3dZ7lzxmyVyKXVTYgY0Hf7biJsCgYBKHdJg/eJ3z36jDkdK55Tl
+cRFt2MCLHhZSvR7WNlIe8W1zORyhzUP+DhJn32yh9jDnpZC5JNUWoDWsq9ZIAKac
+1G1uqNytA6mjIBxQ2RhtYXMbybp3ta5l6zDaNFtxGTmw2hSU6BMk2bHUPdzhw2zX
+eudy4qM9H3sCxEs49k5UHQKBgDz7I0FRGFehtznQhg73AWYIsTSZK9cuI7O/z+2F
+SXNxE0/L40AvCHSb/NcUtkBkpS8ZNwjNhmY5hOE/+v5XwXEFwpumHKqNB7XAx/SO
+tWcDUYVmqFu2lsxwQ5qpE2xcT4u5n0OGeku3I/cJ7bXjrSWDwracM1uloVOnYK5n
+MjE1AoGAeM6Wrb0VXRq025+OEfoFis3P9S0REkkkabM9+VLRSWi63uxg2cyipxUg
+qJUThbUm1aSS1F+XWjG7vrDjWT/GQTYj9/CH3mZRflZgLUltVHEZesLwWqn15Gl/
+BDwaV6RN7F3BCSzgEfCutrfGJqxA0tx5TTcupOgwpZVakN+hm3c=
+-----END RSA PRIVATE KEY-----

+ 1 - 0
resources/cert/server_bkup.pin

@@ -0,0 +1 @@
+pf3px1MBPmlTGAPoiHWqaSJ9L9Z+DKfwgsU7LfLnmsk=

+ 0 - 92
resources/cleanup.lua

@@ -1,92 +0,0 @@
--- Lua script used to clean up tabs and spaces in C, CPP and H files.
--- Copyright (c) 2014, bel
--- MIT License (http://opensource.org/licenses/mit-license.php)
---
--- It can be used from the command line:
--- Call Lua5.1 or Lua5.2 + this script file + the C/CPP/H file to clean
---
--- It can be used in Visual Studio as an external tool:
--- command: Lua5.1.exe or Lua5.2.exe
--- argument: "X:\civetweb\resources\cleanup.lua" $(ItemPath)
---
-
-clean = arg[1]
-print("Cleaning " .. clean)
-
-lines = io.lines(clean)
-if not lines then
-    print("Can not open file " .. clean)
-    return
-end
-
-function trimright(s)
-  return s:match "^(.-)%s*$"
-end
-
-local lineend = false
-local tabspace = false
-local changed = false
-local invalid = false
-local newfile = {}
-
-lineno = 0
-incmt = false
-
-for l in lines do
-    lineno = lineno + 1
-    local lt = trimright(l)
-    if (lt ~= l) then
-        lineend = true
-        changed = true
-    end
-    local mcmt = l:find("%/%*");
-    if mcmt then
-        if incmt then
-            print("line " .. lineno .. " nested comment")
-        end
-        if not (l:sub(mcmt):find("%*%/")) then
-            -- multiline comment begins here
-            incmt = true
-        end
-    elseif incmt then
-        if not l:find("^%s*%*") then
-            print("line " .. lineno .. " multiline comment without leading *")
-        end
-        if l:find("%*%/") then
-            incmt = false
-        end
-    else
-        local cmt = l:find("//")
-        if (cmt) and (l:sub(cmt-5, cmt+1) ~= "http://") and (l:sub(cmt-6, cmt+1) ~= "https://") then
-            print("line " .. lineno .. " has C++ comment //")
-        end
-    end
-    local lts = lt:gsub('\t', '    ')
-    if (lts ~= lt) then
-        tabspace = true
-        changed = true
-    end
-    for i=1,#lts do
-        local b = string.byte(lts,i)
-        if b<32 or b>=127 then
-            print("Letter " .. string.byte(l,i) .. " (" .. b .. ") found in line " .. lts)
-            invalid = true
-        end
-    end
-
-    newfile[#newfile + 1] = lts
-end
-
-print("Line endings trimmed:     " .. tostring(lineend))
-print("Tabs converted to spaces: " .. tostring(tabspace))
-print("Invalid characters:       " .. tostring(invalid))
-
-if changed then
-    local f = io.open(clean, "wb")
-    for i=1,#newfile do
-        f:write(newfile[i])
-        f:write("\n")
-    end
-    f:close()
-    print("File cleaned")
-end

+ 32 - 5
resources/coverity_check.sh

@@ -1,5 +1,6 @@
 #! /bin/sh
 
+# check if we use the correct directory
 ls src/civetweb.c
 if [ "$?" = "0" ]; then
 	echo "Building files for coverity check ..."
@@ -9,19 +10,44 @@ else
 	exit 1
 fi
 
-rm -rf cov_int/
-make clean
+# remove last build
+rm -rf cov_build/
 
-../cov-analysis-linux64-7.6.0/bin/cov-build  --dir cov-int make WITH_IPV6=1 WITH_WEBSOCKET=1 WITH_LUA_SHARED=1
+# copy files to build folder
+mkdir cov_build
+mkdir cov_build/src
+mkdir cov_build/include
+mkdir cov_build/resources
 
-rm civetweb_coverity_check.tgz
+cp Makefile cov_build/
+cp src/*.c cov_build/src/
+cp src/*.inl cov_build/src/
+cp include/civetweb.h cov_build/include/
+cp resources/Makefile.in-os cov_build/resources/
+
+cd cov_build
+
+# new scan build
+../../cov-analysis-linux64-8.7.0/bin/cov-build  --dir cov-int make WITH_IPV6=1 WITH_WEBSOCKET=1 WITH_SERVER_STATS=1
+
+
+# pack build results for upload
 tar czvf civetweb_coverity_check.tgz cov-int
 
+cd ..
+
+# check if the build was successful
 echo
-ls -la civetweb_coverity_check.tgz
+ls -la cov_build/civetweb_coverity_check.tgz
 
 if [ "$?" = "0" ]; then
 	echo "... done"
+	echo
+        echo "submit to https://scan.coverity.com/projects/bel2125-civetweb"
+	echo
+	echo "last commit was"
+	git log -n 1
+        echo
         echo
 else
 	echo "No civetweb_coverity_check.tgz file" 1>&2
@@ -29,5 +55,6 @@ else
 	exit 1
 fi
 
+# return "ok"
 exit 0
 

+ 20 - 14
src/CMakeLists.txt

@@ -39,13 +39,17 @@ if (CIVETWEB_ENABLE_WEBSOCKETS AND CIVETWEB_ENABLE_LUA AND LIBRT_FOUND)
 endif()
 
 # We need to link OpenSSL if not dynamically loading
-if (CIVETWEB_ENABLE_SLL AND NOT CIVETWEB_ENABLE_OPENSLL_DYNAMIC_LOADING)
-  find_package(OpenSSL)
-  target_link_libraries(c-library ${OPENSSL_LIBRARIES})
-else()
-  find_package(LibDl)
-  if (LIBDL_FOUND)
-    target_link_libraries(c-library -ldl)
+if (CIVETWEB_ENABLE_SSL)
+  if (CIVETWEB_ENABLE_SSL_DYNAMIC_LOADING)
+    find_package(LibDl)
+    if (LIBDL_FOUND)
+      target_link_libraries(c-library -ldl)
+    endif()
+  else()
+    find_package(OpenSSL)
+    include_directories(${OPENSSL_INCLUDE_DIR})
+    message(STATUS "OpenSSL include directory: ${OPENSSL_INCLUDE_DIR}")
+    target_link_libraries(c-library ${OPENSSL_LIBRARIES})
   endif()
 endif()
 
@@ -229,12 +233,14 @@ add_executable(c-executable main.c)
 set_target_properties(c-executable PROPERTIES
   OUTPUT_NAME "civetweb"
 )
-install(
-  TARGETS c-executable
-  ARCHIVE DESTINATION lib
-  LIBRARY DESTINATION lib
-  RUNTIME DESTINATION bin
-  COMPONENT server)
+if (CIVETWEB_INSTALL_EXECUTABLE)
+  install(
+    TARGETS c-executable
+    ARCHIVE DESTINATION lib
+    LIBRARY DESTINATION lib
+    RUNTIME DESTINATION bin
+    COMPONENT server)
+endif()
 if (BUILD_SHARED_LIBS)
   target_compile_definitions(c-executable PRIVATE CIVETWEB_DLL_IMPORTS)
 endif()
@@ -261,7 +267,7 @@ if (CIVETWEB_ENABLE_LUA)
     ARCHIVE DESTINATION lib
     LIBRARY DESTINATION lib
     RUNTIME DESTINATION bin
-    COMPONENT lua-library)  
+    COMPONENT lua-library)
 endif()
 
 # The C++ API library

+ 25 - 10
src/CivetServer.cpp

@@ -269,11 +269,14 @@ CivetCallbacks::CivetCallbacks()
 }
 
 CivetServer::CivetServer(const char **options,
-                         const struct CivetCallbacks *_callbacks)
+                         const struct CivetCallbacks *_callbacks,
+                         const void *UserContextIn)
     : context(0)
 {
 	struct CivetCallbacks callbacks;
 
+	UserContext = UserContextIn;
+
 	if (_callbacks) {
 		callbacks = *_callbacks;
 		userCloseHandler = _callbacks->connection_close;
@@ -288,11 +291,14 @@ CivetServer::CivetServer(const char **options,
 }
 
 CivetServer::CivetServer(std::vector<std::string> options,
-                         const struct CivetCallbacks *_callbacks)
+                         const struct CivetCallbacks *_callbacks,
+                         const void *UserContextIn)
     : context(0)
 {
 	struct CivetCallbacks callbacks;
 
+	UserContext = UserContextIn;
+
 	if (_callbacks) {
 		callbacks = *_callbacks;
 		userCloseHandler = _callbacks->connection_close;
@@ -321,17 +327,16 @@ CivetServer::~CivetServer()
 void
 CivetServer::closeHandler(const struct mg_connection *conn)
 {
-	const struct mg_request_info *request_info = mg_get_request_info(conn);
-	assert(request_info != NULL);
-	CivetServer *me = (CivetServer *)(request_info->user_data);
+	CivetServer *me = (CivetServer *)mg_get_user_data(mg_get_context(conn));
 	assert(me != NULL);
 
 	// Happens when a request hits the server before the context is saved
 	if (me->context == NULL)
 		return;
 
-	if (me->userCloseHandler)
+	if (me->userCloseHandler) {
 		me->userCloseHandler(conn);
+	}
 	mg_lock_context(me->context);
 	me->connections.erase(const_cast<struct mg_connection *>(conn));
 	mg_unlock_context(me->context);
@@ -574,11 +579,21 @@ CivetServer::urlEncode(const char *src,
 std::vector<int>
 CivetServer::getListeningPorts()
 {
-	std::vector<int> ports(10);
-	std::vector<int> ssl(10);
-	size_t size = mg_get_ports(context, ports.size(), &ports[0], &ssl[0]);
+	std::vector<int> ports(50);
+	std::vector<struct mg_server_ports> server_ports(50);
+	int size = mg_get_server_ports(context,
+	                               (int)server_ports.size(),
+	                               &server_ports[0]);
+	if (size <= 0) {
+		ports.resize(0);
+		return ports;
+	}
 	ports.resize(size);
-	ssl.resize(size);
+	server_ports.resize(size);
+	for (int i = 0; i < size; i++) {
+		ports[i] = server_ports[i].port;
+	}
+
 	return ports;
 }
 

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 544 - 60
src/civetweb.c


+ 178 - 39
src/handle_form.inl

@@ -90,7 +90,7 @@ url_encoded_field_get(const struct mg_connection *conn,
 {
 	char key_dec[1024];
 
-	char *value_dec = mg_malloc(value_len + 1);
+	char *value_dec = (char *)mg_malloc_ctx(value_len + 1, conn->ctx);
 	int value_dec_len, ret;
 
 	if (!value_dec) {
@@ -177,7 +177,7 @@ mg_handle_form_request(struct mg_connection *conn,
 {
 	const char *content_type;
 	char path[512];
-	char buf[1024];
+	char buf[1024]; /* Must not be smaller than ~900 - see sanity check */
 	int field_storage;
 	int buf_fill = 0;
 	int r;
@@ -517,13 +517,14 @@ mg_handle_form_request(struct mg_connection *conn,
 		/* The form data is in the request body data, encoded as multipart
 		 * content (see https://www.ietf.org/rfc/rfc1867.txt,
 		 * https://www.ietf.org/rfc/rfc2388.txt). */
-		const char *boundary;
+		char *boundary;
 		size_t bl;
 		ptrdiff_t used;
 		struct mg_request_info part_header;
-		char *hbuf, *hend, *fbeg, *fend, *nbeg, *nend;
-		const char *content_disp;
+		char *hbuf;
+		const char *content_disp, *hend, *fbeg, *fend, *nbeg, *nend;
 		const char *next;
+		unsigned part_no;
 
 		memset(&part_header, 0, sizeof(part_header));
 
@@ -539,22 +540,69 @@ mg_handle_form_request(struct mg_connection *conn,
 			return -1;
 		}
 
-		boundary = content_type + bl + 9;
-		bl = strlen(boundary);
+		/* Copy boundary string to variable "boundary" */
+		fbeg = content_type + bl + 9;
+		bl = strlen(fbeg);
+		boundary = (char *)mg_malloc(bl + 1);
+		if (!boundary) {
+			/* Out of memory */
+			mg_cry(conn,
+			       "%s: Cannot allocate memory for boundary [%lu]",
+			       __func__,
+			       (unsigned long)bl);
+			return -1;
+		}
+		memcpy(boundary, fbeg, bl);
+		boundary[bl] = 0;
+
+		/* RFC 2046 permits the boundary string to be quoted. */
+		/* If the boundary is quoted, trim the quotes */
+		if (boundary[0] == '"') {
+			hbuf = strchr(boundary + 1, '"');
+			if ((!hbuf) || (*hbuf != '"')) {
+				/* Malformed request */
+				mg_free(boundary);
+				return -1;
+			}
+			*hbuf = 0;
+			memmove(boundary, boundary + 1, bl);
+			bl = strlen(boundary);
+		}
+
+		/* Do some sanity checks for boundary lengths */
+		if (bl > 70) {
+			/* From RFC 2046:
+			 * Boundary delimiters must not appear within the
+			 * encapsulated material, and must be no longer
+			 * than 70 characters, not counting the two
+			 * leading hyphens.
+			 */
 
-		if (bl + 800 > sizeof(buf)) {
+			/* The initial sanity check
+			 * (bl + 800 > sizeof(buf))
+			 * is no longer required, since sizeof(buf) == 1024
+			 *
+			 * Original comment:
+			 */
 			/* Sanity check:  The algorithm can not work if bl >= sizeof(buf),
 			 * and it will not work effectively, if the buf is only a few byte
-			 * larger than bl, or it buf can not hold the multipart header
+			 * larger than bl, or if buf can not hold the multipart header
 			 * plus the boundary.
 			 * Check some reasonable number here, that should be fulfilled by
 			 * any reasonable request from every browser. If it is not
 			 * fulfilled, it might be a hand-made request, intended to
 			 * interfere with the algorithm. */
+			mg_free(boundary);
+			return -1;
+		}
+		if (bl < 4) {
+			/* Sanity check:  A boundary string of less than 4 bytes makes
+			 * no sense either. */
+			mg_free(boundary);
 			return -1;
 		}
 
-		for (;;) {
+		for (part_no = 0;; part_no++) {
 			size_t towrite, n;
 			int get_block;
 
@@ -563,21 +611,37 @@ mg_handle_form_request(struct mg_connection *conn,
 			            sizeof(buf) - 1 - (size_t)buf_fill);
 			if (r < 0) {
 				/* read error */
+				mg_free(boundary);
 				return -1;
 			}
 			buf_fill += r;
 			buf[buf_fill] = 0;
 			if (buf_fill < 1) {
 				/* No data */
+				mg_free(boundary);
 				return -1;
 			}
 
+			if (part_no == 0) {
+				int d = 0;
+				while ((buf[d] != '-') && (d < buf_fill)) {
+					d++;
+				}
+				if ((d > 0) && (buf[d] == '-')) {
+					memmove(buf, buf + d, (unsigned)buf_fill - (unsigned)d);
+					buf_fill -= d;
+					buf[buf_fill] = 0;
+				}
+			}
+
 			if (buf[0] != '-' || buf[1] != '-') {
 				/* Malformed request */
+				mg_free(boundary);
 				return -1;
 			}
 			if (strncmp(buf + 2, boundary, bl)) {
 				/* Malformed request */
+				mg_free(boundary);
 				return -1;
 			}
 			if (buf[bl + 2] != '\r' || buf[bl + 3] != '\n') {
@@ -586,6 +650,7 @@ mg_handle_form_request(struct mg_connection *conn,
 				if (((size_t)buf_fill != (size_t)(bl + 6))
 				    || (strncmp(buf + bl + 2, "--\r\n", 4))) {
 					/* Malformed request */
+					mg_free(boundary);
 					return -1;
 				}
 				/* End of the request */
@@ -597,12 +662,15 @@ mg_handle_form_request(struct mg_connection *conn,
 			hend = strstr(hbuf, "\r\n\r\n");
 			if (!hend) {
 				/* Malformed request */
+				mg_free(boundary);
 				return -1;
 			}
 
-			parse_http_headers(&hbuf, &part_header);
+			part_header.num_headers =
+			    parse_http_headers(&hbuf, part_header.http_headers);
 			if ((hend + 2) != hbuf) {
 				/* Malformed request */
+				mg_free(boundary);
 				return -1;
 			}
 
@@ -611,45 +679,115 @@ mg_handle_form_request(struct mg_connection *conn,
 
 			/* According to the RFC, every part has to have a header field like:
 			 * Content-Disposition: form-data; name="..." */
-			content_disp = get_header(&part_header, "Content-Disposition");
+			content_disp = get_header(part_header.http_headers,
+			                          part_header.num_headers,
+			                          "Content-Disposition");
 			if (!content_disp) {
 				/* Malformed request */
+				mg_free(boundary);
 				return -1;
 			}
 
 			/* Get the mandatory name="..." part of the Content-Disposition
 			 * header. */
 			nbeg = strstr(content_disp, "name=\"");
-			if (!nbeg) {
-				/* Malformed request */
-				return -1;
+			while ((nbeg != NULL) && (strcspn(nbeg - 1, ":,; \t") != 0)) {
+				/* It could be somethingname= instead of name= */
+				nbeg = strstr(nbeg + 1, "name=\"");
 			}
-			nbeg += 6;
-			nend = strchr(nbeg, '\"');
-			if (!nend) {
-				/* Malformed request */
-				return -1;
+
+			/* This line is not required, but otherwise some compilers
+			 * generate spurious warnings. */
+			nend = nbeg;
+			/* And others complain, the result is unused. */
+			(void)nend;
+
+			/* If name=" is found, search for the closing " */
+			if (nbeg) {
+				nbeg += 6;
+				nend = strchr(nbeg, '\"');
+				if (!nend) {
+					/* Malformed request */
+					mg_free(boundary);
+					return -1;
+				}
+			} else {
+				/* name= without quotes is also allowed */
+				nbeg = strstr(content_disp, "name=");
+				while ((nbeg != NULL) && (strcspn(nbeg - 1, ":,; \t") != 0)) {
+					/* It could be somethingname= instead of name= */
+					nbeg = strstr(nbeg + 1, "name=");
+				}
+				if (!nbeg) {
+					/* Malformed request */
+					mg_free(boundary);
+					return -1;
+				}
+				nbeg += 5;
+
+				/* RFC 2616 Sec. 2.2 defines a list of allowed
+				 * separators, but many of them make no sense
+				 * here, e.g. various brackets or slashes.
+				 * If they are used, probably someone is
+				 * trying to attack with curious hand made
+				 * requests. Only ; , space and tab seem to be
+				 * reasonable here. Ignore everything else. */
+				nend = nbeg + strcspn(nbeg, ",; \t");
 			}
 
 			/* Get the optional filename="..." part of the Content-Disposition
 			 * header. */
 			fbeg = strstr(content_disp, "filename=\"");
+			while ((fbeg != NULL) && (strcspn(fbeg - 1, ":,; \t") != 0)) {
+				/* It could be somethingfilename= instead of filename= */
+				fbeg = strstr(fbeg + 1, "filename=\"");
+			}
+
+			/* This line is not required, but otherwise some compilers
+			 * generate spurious warnings. */
+			fend = fbeg;
+
+			/* If filename=" is found, search for the closing " */
 			if (fbeg) {
 				fbeg += 10;
 				fend = strchr(fbeg, '\"');
+
 				if (!fend) {
 					/* Malformed request (the filename field is optional, but if
 					 * it exists, it needs to be terminated correctly). */
+					mg_free(boundary);
 					return -1;
 				}
 
 				/* TODO: check Content-Type */
 				/* Content-Type: application/octet-stream */
+			}
+			if (!fbeg) {
+				/* Try the same without quotes */
+				fbeg = strstr(content_disp, "filename=");
+				while ((fbeg != NULL) && (strcspn(fbeg - 1, ":,; \t") != 0)) {
+					/* It could be somethingfilename= instead of filename= */
+					fbeg = strstr(fbeg + 1, "filename=");
+				}
+				if (fbeg) {
+					fbeg += 9;
+					fend = fbeg + strcspn(fbeg, ",; \t");
+				}
+			}
+			if (!fbeg) {
+				fend = NULL;
+			}
 
-			} else {
-				fend = fbeg;
+			/* In theory, it could be possible that someone crafts
+			 * a request like name=filename=xyz. Check if name and
+			 * filename do not overlap. */
+			if (!(((ptrdiff_t)fbeg > (ptrdiff_t)nend)
+			      || ((ptrdiff_t)nbeg > (ptrdiff_t)fend))) {
+				mg_free(boundary);
+				return -1;
 			}
 
+			/* Call callback for new field */
 			memset(path, 0, sizeof(path));
 			field_count++;
 			field_storage = url_encoded_field_found(conn,
@@ -729,12 +867,14 @@ mg_handle_form_request(struct mg_connection *conn,
 				            sizeof(buf) - 1 - (size_t)buf_fill);
 				if (r < 0) {
 					/* read error */
+					mg_free(boundary);
 					return -1;
 				}
 				buf_fill += r;
 				buf[buf_fill] = 0;
 				if (buf_fill < 1) {
 					/* No data */
+					mg_free(boundary);
 					return -1;
 				}
 
@@ -766,24 +906,19 @@ mg_handle_form_request(struct mg_connection *conn,
 						       path);
 						mg_fclose(&fstore.access);
 						remove_bad_file(conn, path);
-					}
-					file_size += (int64_t)n;
-				}
-			}
-
-			if (field_storage == FORM_FIELD_STORAGE_STORE) {
-
-				if (fstore.access.fp) {
-					r = mg_fclose(&fstore.access);
-					if (r == 0) {
-						/* stored successfully */
-						field_stored(conn, path, file_size, fdh);
 					} else {
-						mg_cry(conn,
-						       "%s: Error saving file %s",
-						       __func__,
-						       path);
-						remove_bad_file(conn, path);
+						file_size += (int64_t)n;
+						r = mg_fclose(&fstore.access);
+						if (r == 0) {
+							/* stored successfully */
+							field_stored(conn, path, file_size, fdh);
+						} else {
+							mg_cry(conn,
+							       "%s: Error saving file %s",
+							       __func__,
+							       path);
+							remove_bad_file(conn, path);
+						}
 					}
 					fstore.access.fp = NULL;
 				}
@@ -802,9 +937,13 @@ mg_handle_form_request(struct mg_connection *conn,
 		}
 
 		/* All parts handled */
+		mg_free(boundary);
 		return field_count;
 	}
 
 	/* Unknown Content-Type */
 	return -1;
 }
+
+
+/* End of handle_form.inl */

+ 257 - 28
src/main.c

@@ -52,6 +52,8 @@
 #define NO_RETURN [[noreturn]]
 #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
 #define NO_RETURN _Noreturn
+#elif defined(__GNUC__)
+#define NO_RETURN __attribute((noreturn))
 #else
 #define NO_RETURN
 #endif
@@ -190,7 +192,7 @@ static NO_RETURN void
 die(const char *fmt, ...)
 {
 	va_list ap;
-	char msg[200] = "";
+	char msg[512] = "";
 
 	va_start(ap, fmt);
 	(void)vsnprintf(msg, sizeof(msg) - 1, fmt, ap);
@@ -357,6 +359,135 @@ sdup(const char *str)
 }
 
 
+#if 0 /* Unused code from "string duplicate with escape" */
+static unsigned
+hex2dec(char x)
+{
+    if ((x >= '0') && (x <= '9')) {
+        return (unsigned)x - (unsigned)'0';
+    }
+    if ((x >= 'A') && (x <= 'F')) {
+        return (unsigned)x - (unsigned)'A' + 10u;
+    }
+    if ((x >= 'a') && (x <= 'f')) {
+        return (unsigned)x - (unsigned)'a' + 10u;
+    }
+    return 0;
+}
+
+
+static char *
+sdupesc(const char *str)
+{
+	char *p = sdup(str);
+
+	if (p) {
+		char *d = p;
+		while ((d = strchr(d, '\\')) != NULL) {
+			switch (d[1]) {
+			case 'a':
+				d[0] = '\a';
+				memmove(d + 1, d + 2, strlen(d + 1));
+				break;
+			case 'b':
+				d[0] = '\b';
+				memmove(d + 1, d + 2, strlen(d + 1));
+				break;
+			case 'e':
+				d[0] = 27;
+				memmove(d + 1, d + 2, strlen(d + 1));
+				break;
+			case 'f':
+				d[0] = '\f';
+				memmove(d + 1, d + 2, strlen(d + 1));
+				break;
+			case 'n':
+				d[0] = '\n';
+				memmove(d + 1, d + 2, strlen(d + 1));
+				break;
+			case 'r':
+				d[0] = '\r';
+				memmove(d + 1, d + 2, strlen(d + 1));
+				break;
+			case 't':
+				d[0] = '\t';
+				memmove(d + 1, d + 2, strlen(d + 1));
+				break;
+			case 'u':
+				if (isxdigit(d[2]) && isxdigit(d[3]) && isxdigit(d[4])
+				    && isxdigit(d[5])) {
+					unsigned short u = (unsigned short)(hex2dec(d[2]) * 4096
+					                                    + hex2dec(d[3]) * 256
+					                                    + hex2dec(d[4]) * 16
+					                                    + hex2dec(d[5]));
+					char mbc[16];
+					int mbl = wctomb(mbc, (wchar_t)u);
+					if ((mbl > 0) && (mbl < 6)) {
+						memcpy(d, mbc, (unsigned)mbl);
+						memmove(d + mbl, d + 6, strlen(d + 5));
+						/* Advance mbl characters (+1 is below) */
+						d += (mbl - 1);
+					} else {
+						/* Invalid multi byte character */
+						/* TODO: define what to do */
+					}
+				} else {
+					/* Invalid esc sequence */
+					/* TODO: define what to do */
+				}
+				break;
+			case 'v':
+				d[0] = '\v';
+				memmove(d + 1, d + 2, strlen(d + 1));
+				break;
+			case 'x':
+				if (isxdigit(d[2]) && isxdigit(d[3])) {
+					d[0] = (char)((unsigned char)(hex2dec(d[2]) * 16
+					                              + hex2dec(d[3])));
+					memmove(d + 1, d + 4, strlen(d + 3));
+				} else {
+					/* Invalid esc sequence */
+					/* TODO: define what to do */
+				}
+				break;
+			case 'z':
+				d[0] = 0;
+				memmove(d + 1, d + 2, strlen(d + 1));
+				break;
+			case '\\':
+				d[0] = '\\';
+				memmove(d + 1, d + 2, strlen(d + 1));
+				break;
+			case '\'':
+				d[0] = '\'';
+				memmove(d + 1, d + 2, strlen(d + 1));
+				break;
+			case '\"':
+				d[0] = '\"';
+				memmove(d + 1, d + 2, strlen(d + 1));
+				break;
+			case 0:
+				if (d == p) {
+					/* Line is only \ */
+					free(p);
+					return NULL;
+				}
+			/* no break */
+			default:
+				/* invalid ESC sequence */
+				/* TODO: define what to do */
+				break;
+			}
+
+			/* Advance to next character */
+			d++;
+		}
+	}
+	return p;
+}
+#endif
+
+
 static const char *
 get_option(char **options, const char *option_name)
 {
@@ -386,6 +517,7 @@ set_option(char **options, const char *name, const char *value)
 {
 	int i, type;
 	const struct mg_option *default_options = mg_get_valid_options();
+	const char *multi_sep = NULL;
 
 	for (i = 0; main_config_options[i].name != NULL; i++) {
 		if (0 == strcmp(name, main_config_options[i].name)) {
@@ -406,7 +538,7 @@ set_option(char **options, const char *name, const char *value)
 		/* unknown option */
 		return 0;
 	case CONFIG_TYPE_NUMBER:
-		/* integer number > 0, e.g. number of threads */
+		/* integer number >= 0, e.g. number of threads */
 		if (atol(value) < 0) {
 			/* invalid number */
 			return 0;
@@ -415,6 +547,14 @@ set_option(char **options, const char *name, const char *value)
 	case CONFIG_TYPE_STRING:
 		/* any text */
 		break;
+	case CONFIG_TYPE_STRING_LIST:
+		/* list of text items, separated by , */
+		multi_sep = ",";
+		break;
+	case CONFIG_TYPE_STRING_MULTILINE:
+		/* lines of text, separated by carriage return line feed */
+		multi_sep = "\r\n";
+		break;
 	case CONFIG_TYPE_BOOLEAN:
 		/* boolean value, yes or no */
 		if ((0 != strcmp(value, "yes")) && (0 != strcmp(value, "no"))) {
@@ -428,7 +568,8 @@ set_option(char **options, const char *name, const char *value)
 		 * verify_existence later */
 		break;
 	case CONFIG_TYPE_EXT_PATTERN:
-		/* list of file extentions */
+		/* list of patterns, separated by | */
+		multi_sep = "|";
 		break;
 	default:
 		die("Unknown option type - option %s", name);
@@ -436,13 +577,27 @@ set_option(char **options, const char *name, const char *value)
 
 	for (i = 0; i < MAX_OPTIONS; i++) {
 		if (options[2 * i] == NULL) {
+			/* Option not set yet. Add new option */
 			options[2 * i] = sdup(name);
 			options[2 * i + 1] = sdup(value);
 			options[2 * i + 2] = NULL;
 			break;
 		} else if (!strcmp(options[2 * i], name)) {
-			free(options[2 * i + 1]);
-			options[2 * i + 1] = sdup(value);
+			if (multi_sep) {
+				/* Option already set. Overwrite */
+				char *s = malloc(strlen(options[2 * i + 1]) + strlen(multi_sep)
+				                 + strlen(value) + 1);
+				if (!s) {
+					die("Out of memory");
+				}
+				sprintf(s, "%s%s%s", options[2 * i + 1], multi_sep, value);
+				free(options[2 * i + 1]);
+				options[2 * i + 1] = s;
+			} else {
+				/* Option already set. Overwrite */
+				free(options[2 * i + 1]);
+				options[2 * i + 1] = sdup(value);
+			}
 			break;
 		}
 	}
@@ -451,9 +606,12 @@ set_option(char **options, const char *name, const char *value)
 		die("Too many options specified");
 	}
 
-	if (options[2 * i] == NULL || options[2 * i + 1] == NULL) {
+	if (options[2 * i] == NULL) {
 		die("Out of memory");
 	}
+	if (options[2 * i + 1] == NULL) {
+		die("Illegal escape sequence, or out of memory");
+	}
 
 	/* option set correctly */
 	return 1;
@@ -513,8 +671,9 @@ read_config_file(const char *config_file, char **options)
 
 			/* Trim additional spaces between option name and value - then
 			 * (line+j) contains the option value */
-			while (isspace(line[j]))
+			while (isspace(line[j])) {
 				j++;
+			}
 
 			/* Set option */
 			if (!set_option(options, line + i, line + j)) {
@@ -1121,6 +1280,8 @@ struct dlg_proc_param {
 	const char *name;
 	char *buffer;
 	unsigned buflen;
+	int idRetry;
+	BOOL (*fRetry)(struct dlg_proc_param *data);
 };
 
 
@@ -1264,7 +1425,7 @@ SettingsDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 		/* Initialize the dialog elements */
 		SendMessage(hDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hIcon);
 		SendMessage(hDlg, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)hIcon);
-		title = malloc(strlen(g_server_name) + 16);
+		title = (char *)malloc(strlen(g_server_name) + 16);
 		if (title) {
 			strcpy(title, g_server_name);
 			strcat(title, " settings");
@@ -1317,6 +1478,22 @@ InputDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 				/* There is no input line in this dialog. */
 				EndDialog(hDlg, IDOK);
 			}
+
+		} else if (ctrlId == IDRETRY) {
+
+			/* Get handle of input line */
+			hIn = GetDlgItem(hDlg, inBuf->idRetry);
+
+			if (hIn) {
+				/* Load current string */
+				GetWindowText(hIn, inBuf->buffer, (int)inBuf->buflen);
+				if (inBuf->fRetry) {
+					if (inBuf->fRetry(inBuf)) {
+						SetWindowText(hIn, inBuf->buffer);
+					}
+				}
+			}
+
 		} else if (ctrlId == IDCANCEL) {
 			EndDialog(hDlg, IDCANCEL);
 		}
@@ -1410,8 +1587,8 @@ get_password(const char *user,
 	static struct dlg_proc_param s_dlg_proc_param;
 
 	static struct {
-		DLGTEMPLATE template; /* 18 bytes */
-		WORD menu, class;
+		DLGTEMPLATE dlg_template; /* 18 bytes */
+		WORD menu, dlg_class;
 		wchar_t caption[1];
 		WORD fontsiz;
 		wchar_t fontface[7];
@@ -1554,6 +1731,7 @@ get_password(const char *user,
 	dia->cy = y + (WORD)(HEIGHT * 1.5);
 
 	s_dlg_proc_param.name = "Modify password";
+	s_dlg_proc_param.fRetry = NULL;
 
 	ok =
 	    (IDOK == DialogBoxIndirectParam(
@@ -1661,7 +1839,7 @@ add_control(unsigned char **mem,
 
 	dia->cdit++;
 
-	*mem = align(*mem, 3);
+	*mem = (unsigned char *)align(*mem, 3);
 	tp = (DLGITEMTEMPLATE *)*mem;
 
 	tp->id = id;
@@ -1672,7 +1850,7 @@ add_control(unsigned char **mem,
 	tp->cx = cx;
 	tp->cy = cy;
 
-	p = align(*mem + sizeof(*tp), 1);
+	p = (LPWORD)align(*mem + sizeof(*tp), 1);
 	*p++ = 0xffff;
 	*p++ = type;
 
@@ -1680,7 +1858,7 @@ add_control(unsigned char **mem,
 		*p++ = (WCHAR)*caption++;
 	}
 	*p++ = 0;
-	p = align(p, 1);
+	p = (LPWORD)align(p, 1);
 
 	*p++ = 0;
 	*mem = (unsigned char *)p;
@@ -1703,8 +1881,8 @@ show_settings_dialog()
 	static struct dlg_proc_param s_dlg_proc_param;
 
 	static struct {
-		DLGTEMPLATE template; /* 18 bytes */
-		WORD menu, class;
+		DLGTEMPLATE dlg_template; /* 18 bytes */
+		WORD menu, dlg_class;
 		wchar_t caption[1];
 		WORD fontsiz;
 		wchar_t fontface[7];
@@ -1762,6 +1940,11 @@ show_settings_dialog()
 			            15,
 			            12,
 			            "...");
+		} else if (options[i].type == CONFIG_TYPE_STRING_MULTILINE) {
+			/* TODO: This is not really uer friendly */
+			cl = 0x81;
+			style |= WS_BORDER | ES_AUTOHSCROLL | ES_MULTILINE | ES_WANTRETURN
+			         | ES_AUTOVSCROLL;
 		} else {
 			cl = 0x81;
 			style |= WS_BORDER | ES_AUTOHSCROLL;
@@ -1858,6 +2041,8 @@ show_settings_dialog()
 
 	dia->cy = ((nelems + 1) / 2 + 1) * HEIGHT + 30;
 
+	s_dlg_proc_param.fRetry = NULL;
+
 	DialogBoxIndirectParam(
 	    NULL, dia, NULL, SettingsDlgProc, (LPARAM)&s_dlg_proc_param);
 
@@ -1889,8 +2074,8 @@ change_password_file()
 	static struct dlg_proc_param s_dlg_proc_param;
 
 	static struct {
-		DLGTEMPLATE template; /* 18 bytes */
-		WORD menu, class;
+		DLGTEMPLATE dlg_template; /* 18 bytes */
+		WORD menu, dlg_class;
 		wchar_t caption[1];
 		WORD fontsiz;
 		wchar_t fontface[7];
@@ -2070,6 +2255,7 @@ change_password_file()
 		dia->cy = y + 20;
 
 		s_dlg_proc_param.name = path;
+		s_dlg_proc_param.fRetry = NULL;
 
 	} while ((IDOK == DialogBoxIndirectParam(NULL,
 	                                         dia,
@@ -2087,6 +2273,33 @@ change_password_file()
 }
 
 
+static BOOL
+sysinfo_reload(struct dlg_proc_param *prm)
+{
+	static char *buf = 0;
+	int cl, rl;
+
+	cl = mg_get_context_info(g_ctx, NULL, 0);
+	free(buf);
+	cl += 510;
+	buf = (char *)malloc(cl + 1);
+	rl = mg_get_context_info(g_ctx, buf, cl);
+	if ((rl > cl) || (rl <= 0)) {
+		if (g_ctx == NULL) {
+			prm->buffer = "Server not running";
+		} else if (rl <= 0) {
+			prm->buffer = "No server statistics available";
+		} else {
+			prm->buffer = "Please retry";
+		}
+	} else {
+		prm->buffer = buf;
+	}
+
+	return TRUE;
+}
+
+
 int
 show_system_info()
 {
@@ -2101,8 +2314,8 @@ show_system_info()
 	static struct dlg_proc_param s_dlg_proc_param;
 
 	static struct {
-		DLGTEMPLATE template; /* 18 bytes */
-		WORD menu, class;
+		DLGTEMPLATE dlg_template; /* 18 bytes */
+		WORD menu, dlg_class;
 		wchar_t caption[1];
 		WORD fontsiz;
 		wchar_t fontface[7];
@@ -2158,22 +2371,36 @@ show_system_info()
 	            g_system_info);
 
 	y += (WORD)(HEIGHT * 8);
+
+	add_control(&p,
+	            dia,
+	            0x80,
+	            IDRETRY,
+	            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
+	            WIDTH - 10 - 55 - 10 - 55,
+	            y,
+	            55,
+	            12,
+	            "Reload");
+
 	add_control(&p,
 	            dia,
 	            0x80,
 	            IDOK,
 	            WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP,
-	            (WIDTH - 55) / 2,
+	            WIDTH - 10 - 55,
 	            y,
 	            55,
 	            12,
-	            "Ok");
+	            "Close");
 
 	assert((intptr_t)p - (intptr_t)mem < (intptr_t)sizeof(mem));
 
 	dia->cy = y + (WORD)(HEIGHT * 1.5);
 
 	s_dlg_proc_param.name = "System information";
+	s_dlg_proc_param.fRetry = sysinfo_reload;
+	s_dlg_proc_param.idRetry = ID_CONTROLS + 1; /* Reload field with this ID */
 
 	ok =
 	    (IDOK == DialogBoxIndirectParam(
@@ -2452,15 +2679,15 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR cmdline, int show)
 	ShowWindow(hWnd, SW_HIDE);
 
 	if (g_icon_name) {
-		hIcon =
+		hIcon = (HICON)
 		    LoadImage(NULL, g_icon_name, IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
 	} else {
-		hIcon = LoadImage(GetModuleHandle(NULL),
-		                  MAKEINTRESOURCE(ID_ICON),
-		                  IMAGE_ICON,
-		                  16,
-		                  16,
-		                  0);
+		hIcon = (HICON)LoadImage(GetModuleHandle(NULL),
+		                         MAKEINTRESOURCE(ID_ICON),
+		                         IMAGE_ICON,
+		                         16,
+		                         16,
+		                         0);
 	}
 
 	TrayIcon.cbSize = sizeof(TrayIcon);
@@ -2610,9 +2837,11 @@ main(int argc, char *argv[])
 	        g_server_name,
 	        mg_get_option(g_ctx, "listening_ports"),
 	        mg_get_option(g_ctx, "document_root"));
+
 	while (g_exit_flag == 0) {
 		sleep(1);
 	}
+
 	fprintf(stdout,
 	        "Exiting on signal %d, waiting for all threads to finish...",
 	        g_exit_flag);

+ 3 - 0
src/md5.inl

@@ -466,3 +466,6 @@ md5_finish(md5_state_t *pms, md5_byte_t digest[16])
 	for (i = 0; i < 16; ++i)
 		digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
 }
+
+
+/* End of md5.inl */

+ 101 - 89
src/mod_duktape.inl

@@ -22,59 +22,60 @@ static const char *civetweb_ctx_id = "\xFF"
 static void *
 mg_duk_mem_alloc(void *udata, duk_size_t size)
 {
-	return mg_malloc(size);
+	return mg_malloc_ctx(size, (struct mg_context *)udata);
 }
 
 
 static void *
 mg_duk_mem_realloc(void *udata, void *ptr, duk_size_t newsize)
 {
-	return mg_realloc(ptr, newsize);
+	return mg_realloc_ctx(ptr, newsize, (struct mg_context *)udata);
 }
 
 
 static void
 mg_duk_mem_free(void *udata, void *ptr)
 {
+	(void)udata;
 	mg_free(ptr);
 }
 
 
 static void
-mg_duk_fatal_handler(duk_context *ctx, duk_errcode_t code, const char *msg)
+mg_duk_fatal_handler(duk_context *duk_ctx, duk_errcode_t code, const char *msg)
 {
 	/* Script is called "protected" (duk_peval_file), so script errors should
 	 * never yield in a call to this function. Maybe calls prior to executing
 	 * the script could raise a fatal error. */
 	struct mg_connection *conn;
 
-	duk_push_global_stash(ctx);
-	duk_get_prop_string(ctx, -1, civetweb_conn_id);
-	conn = (struct mg_connection *)duk_to_pointer(ctx, -1);
+	duk_push_global_stash(duk_ctx);
+	duk_get_prop_string(duk_ctx, -1, civetweb_conn_id);
+	conn = (struct mg_connection *)duk_to_pointer(duk_ctx, -1);
 
-	mg_cry(conn, "%s", msg);
+	mg_cry(conn, "JavaScript fatal (%u): %s", (unsigned)code, msg);
 }
 
 
 static duk_ret_t
-duk_itf_write(duk_context *ctx)
+duk_itf_write(duk_context *duk_ctx)
 {
 	struct mg_connection *conn;
 	duk_double_t ret;
 	duk_size_t len = 0;
-	const char *val = duk_require_lstring(ctx, -1, &len);
+	const char *val = duk_require_lstring(duk_ctx, -1, &len);
 
 	/*
-	    duk_push_global_stash(ctx);
-	    duk_get_prop_string(ctx, -1, civetweb_conn_id);
-	    conn = (struct mg_connection *)duk_to_pointer(ctx, -1);
+	    duk_push_global_stash(duk_ctx);
+	    duk_get_prop_string(duk_ctx, -1, civetweb_conn_id);
+	    conn = (struct mg_connection *)duk_to_pointer(duk_ctx, -1);
 	*/
-	duk_push_current_function(ctx);
-	duk_get_prop_string(ctx, -1, civetweb_conn_id);
-	conn = (struct mg_connection *)duk_to_pointer(ctx, -1);
+	duk_push_current_function(duk_ctx);
+	duk_get_prop_string(duk_ctx, -1, civetweb_conn_id);
+	conn = (struct mg_connection *)duk_to_pointer(duk_ctx, -1);
 
 	if (!conn) {
-		duk_error(ctx,
+		duk_error(duk_ctx,
 		          DUK_ERR_INTERNAL_ERROR,
 		          "function not available without connection object");
 		/* probably never reached, but satisfies static code analysis */
@@ -83,24 +84,24 @@ duk_itf_write(duk_context *ctx)
 
 	ret = mg_write(conn, val, len);
 
-	duk_push_number(ctx, ret);
+	duk_push_number(duk_ctx, ret);
 	return 1;
 }
 
 
 static duk_ret_t
-duk_itf_read(duk_context *ctx)
+duk_itf_read(duk_context *duk_ctx)
 {
 	struct mg_connection *conn;
 	char buf[1024];
 	int len;
 
-	duk_push_global_stash(ctx);
-	duk_get_prop_string(ctx, -1, civetweb_conn_id);
-	conn = (struct mg_connection *)duk_to_pointer(ctx, -1);
+	duk_push_global_stash(duk_ctx);
+	duk_get_prop_string(duk_ctx, -1, civetweb_conn_id);
+	conn = (struct mg_connection *)duk_to_pointer(duk_ctx, -1);
 
 	if (!conn) {
-		duk_error(ctx,
+		duk_error(duk_ctx,
 		          DUK_ERR_INTERNAL_ERROR,
 		          "function not available without connection object");
 		/* probably never reached, but satisfies static code analysis */
@@ -109,25 +110,25 @@ duk_itf_read(duk_context *ctx)
 
 	len = mg_read(conn, buf, sizeof(buf));
 
-	duk_push_lstring(ctx, buf, len);
+	duk_push_lstring(duk_ctx, buf, len);
 	return 1;
 }
 
 
 static duk_ret_t
-duk_itf_getoption(duk_context *ctx)
+duk_itf_getoption(duk_context *duk_ctx)
 {
 	struct mg_context *cv_ctx;
 	const char *ret;
 	duk_size_t len = 0;
-	const char *val = duk_require_lstring(ctx, -1, &len);
+	const char *val = duk_require_lstring(duk_ctx, -1, &len);
 
-	duk_push_current_function(ctx);
-	duk_get_prop_string(ctx, -1, civetweb_ctx_id);
-	cv_ctx = (struct mg_context *)duk_to_pointer(ctx, -1);
+	duk_push_current_function(duk_ctx);
+	duk_get_prop_string(duk_ctx, -1, civetweb_ctx_id);
+	cv_ctx = (struct mg_context *)duk_to_pointer(duk_ctx, -1);
 
 	if (!cv_ctx) {
-		duk_error(ctx,
+		duk_error(duk_ctx,
 		          DUK_ERR_INTERNAL_ERROR,
 		          "function not available without connection object");
 		/* probably never reached, but satisfies static code analysis */
@@ -136,9 +137,9 @@ duk_itf_getoption(duk_context *ctx)
 
 	ret = mg_get_option(cv_ctx, val);
 	if (ret) {
-		duk_push_string(ctx, ret);
+		duk_push_string(duk_ctx, ret);
 	} else {
-		duk_push_null(ctx);
+		duk_push_null(duk_ctx);
 	}
 
 	return 1;
@@ -149,102 +150,113 @@ static void
 mg_exec_duktape_script(struct mg_connection *conn, const char *script_name)
 {
 	int i;
-	duk_context *ctx = NULL;
+	duk_context *duk_ctx = NULL;
 
 	conn->must_close = 1;
 
 	/* Create Duktape interpreter state */
-	ctx = duk_create_heap(mg_duk_mem_alloc,
-	                      mg_duk_mem_realloc,
-	                      mg_duk_mem_free,
-	                      NULL,
-	                      mg_duk_fatal_handler);
-	if (!ctx) {
+	duk_ctx = duk_create_heap(mg_duk_mem_alloc,
+	                          mg_duk_mem_realloc,
+	                          mg_duk_mem_free,
+	                          (void *)conn->ctx,
+	                          mg_duk_fatal_handler);
+	if (!duk_ctx) {
 		mg_cry(conn, "Failed to create a Duktape heap.");
 		goto exec_duktape_finished;
 	}
 
 	/* Add "conn" object */
-	duk_push_global_object(ctx);
-	duk_push_object(ctx); /* create a new table/object ("conn") */
+	duk_push_global_object(duk_ctx);
+	duk_push_object(duk_ctx); /* create a new table/object ("conn") */
 
-	duk_push_c_function(ctx, duk_itf_write, 1 /* 1 = nargs */);
-	duk_push_pointer(ctx, (void *)conn);
-	duk_put_prop_string(ctx, -2, civetweb_conn_id);
-	duk_put_prop_string(ctx, -2, "write"); /* add function conn.write */
+	duk_push_c_function(duk_ctx, duk_itf_write, 1 /* 1 = nargs */);
+	duk_push_pointer(duk_ctx, (void *)conn);
+	duk_put_prop_string(duk_ctx, -2, civetweb_conn_id);
+	duk_put_prop_string(duk_ctx, -2, "write"); /* add function conn.write */
 
-	duk_push_c_function(ctx, duk_itf_read, 0 /* 0 = nargs */);
-	duk_push_pointer(ctx, (void *)conn);
-	duk_put_prop_string(ctx, -2, civetweb_conn_id);
-	duk_put_prop_string(ctx, -2, "read"); /* add function conn.read */
+	duk_push_c_function(duk_ctx, duk_itf_read, 0 /* 0 = nargs */);
+	duk_push_pointer(duk_ctx, (void *)conn);
+	duk_put_prop_string(duk_ctx, -2, civetweb_conn_id);
+	duk_put_prop_string(duk_ctx, -2, "read"); /* add function conn.read */
 
-	duk_push_string(ctx, conn->request_info.request_method);
-	duk_put_prop_string(ctx, -2, "request_method"); /* add string conn.r... */
+	duk_push_string(duk_ctx, conn->request_info.request_method);
+	duk_put_prop_string(duk_ctx,
+	                    -2,
+	                    "request_method"); /* add string conn.r... */
 
-	duk_push_string(ctx, conn->request_info.request_uri);
-	duk_put_prop_string(ctx, -2, "request_uri");
+	duk_push_string(duk_ctx, conn->request_info.request_uri);
+	duk_put_prop_string(duk_ctx, -2, "request_uri");
 
-	duk_push_string(ctx, conn->request_info.local_uri);
-	duk_put_prop_string(ctx, -2, "uri");
+	duk_push_string(duk_ctx, conn->request_info.local_uri);
+	duk_put_prop_string(duk_ctx, -2, "uri");
 
-	duk_push_string(ctx, conn->request_info.http_version);
-	duk_put_prop_string(ctx, -2, "http_version");
+	duk_push_string(duk_ctx, conn->request_info.http_version);
+	duk_put_prop_string(duk_ctx, -2, "http_version");
 
-	duk_push_string(ctx, conn->request_info.query_string);
-	duk_put_prop_string(ctx, -2, "query_string");
+	duk_push_string(duk_ctx, conn->request_info.query_string);
+	duk_put_prop_string(duk_ctx, -2, "query_string");
 
-	duk_push_string(ctx, conn->request_info.remote_addr);
-	duk_put_prop_string(ctx, -2, "remote_addr");
+	duk_push_string(duk_ctx, conn->request_info.remote_addr);
+	duk_put_prop_string(duk_ctx, -2, "remote_addr");
 
-	duk_push_int(ctx, conn->request_info.remote_port);
-	duk_put_prop_string(ctx, -2, "remote_port");
+	duk_push_int(duk_ctx, conn->request_info.remote_port);
+	duk_put_prop_string(duk_ctx, -2, "remote_port");
 
-	duk_push_int(ctx, ntohs(conn->client.lsa.sin.sin_port));
-	duk_put_prop_string(ctx, -2, "server_port");
+	duk_push_int(duk_ctx, ntohs(conn->client.lsa.sin.sin_port));
+	duk_put_prop_string(duk_ctx, -2, "server_port");
 
-	duk_push_object(ctx); /* subfolder "conn.http_headers" */
+	duk_push_object(duk_ctx); /* subfolder "conn.http_headers" */
 	for (i = 0; i < conn->request_info.num_headers; i++) {
-		duk_push_string(ctx, conn->request_info.http_headers[i].value);
-		duk_put_prop_string(ctx, -2, conn->request_info.http_headers[i].name);
+		duk_push_string(duk_ctx, conn->request_info.http_headers[i].value);
+		duk_put_prop_string(duk_ctx,
+		                    -2,
+		                    conn->request_info.http_headers[i].name);
 	}
-	duk_put_prop_string(ctx, -2, "http_headers");
+	duk_put_prop_string(duk_ctx, -2, "http_headers");
 
-	duk_put_prop_string(ctx, -2, "conn"); /* call the table "conn" */
+	duk_put_prop_string(duk_ctx, -2, "conn"); /* call the table "conn" */
 
 	/* Add "civetweb" object */
-	duk_push_global_object(ctx);
-	duk_push_object(ctx); /* create a new table/object ("conn") */
+	duk_push_global_object(duk_ctx);
+	duk_push_object(duk_ctx); /* create a new table/object ("conn") */
 
-	duk_push_string(ctx, CIVETWEB_VERSION);
-	duk_put_prop_string(ctx, -2, "version");
+	duk_push_string(duk_ctx, CIVETWEB_VERSION);
+	duk_put_prop_string(duk_ctx, -2, "version");
 
-	duk_push_string(ctx, script_name);
-	duk_put_prop_string(ctx, -2, "script_name");
+	duk_push_string(duk_ctx, script_name);
+	duk_put_prop_string(duk_ctx, -2, "script_name");
 
 	if (conn->ctx != NULL) {
-		duk_push_c_function(ctx, duk_itf_getoption, 1 /* 1 = nargs */);
-		duk_push_pointer(ctx, (void *)(conn->ctx));
-		duk_put_prop_string(ctx, -2, civetweb_ctx_id);
-		duk_put_prop_string(ctx, -2, "getoption"); /* add function conn.write */
+		duk_push_c_function(duk_ctx, duk_itf_getoption, 1 /* 1 = nargs */);
+		duk_push_pointer(duk_ctx, (void *)(conn->ctx));
+		duk_put_prop_string(duk_ctx, -2, civetweb_ctx_id);
+		duk_put_prop_string(duk_ctx,
+		                    -2,
+		                    "getoption"); /* add function conn.write */
 
 		if (conn->ctx->systemName != NULL) {
-			duk_push_string(ctx, conn->ctx->systemName);
-			duk_put_prop_string(ctx, -2, "system");
+			duk_push_string(duk_ctx, conn->ctx->systemName);
+			duk_put_prop_string(duk_ctx, -2, "system");
 		}
 	}
 
-	duk_put_prop_string(ctx, -2, "civetweb"); /* call the table "civetweb" */
+	duk_put_prop_string(duk_ctx,
+	                    -2,
+	                    "civetweb"); /* call the table "civetweb" */
 
-	duk_push_global_stash(ctx);
-	duk_push_pointer(ctx, (void *)conn);
-	duk_put_prop_string(ctx, -2, civetweb_conn_id);
+	duk_push_global_stash(duk_ctx);
+	duk_push_pointer(duk_ctx, (void *)conn);
+	duk_put_prop_string(duk_ctx, -2, civetweb_conn_id);
 
-	if (duk_peval_file(ctx, script_name) != 0) {
-		mg_cry(conn, "%s", duk_safe_to_string(ctx, -1));
+	if (duk_peval_file(duk_ctx, script_name) != 0) {
+		mg_cry(conn, "%s", duk_safe_to_string(duk_ctx, -1));
 		goto exec_duktape_finished;
 	}
-	duk_pop(ctx); /* ignore result */
+	duk_pop(duk_ctx); /* ignore result */
 
 exec_duktape_finished:
-	duk_destroy_heap(ctx);
+	duk_destroy_heap(duk_ctx);
 }
+
+
+/* End of mod_duktape.inl */

+ 449 - 78
src/mod_lua.inl

@@ -48,6 +48,13 @@ munmap(void *addr, int64_t length)
 static const char *LUASOCKET = "luasocket";
 static const char lua_regkey_ctx = 1;
 static const char lua_regkey_connlist = 2;
+static const char lua_regkey_lsp_include_history = 3;
+static const char *LUABACKGROUNDPARAMS = "mg";
+
+#ifndef LSP_INCLUDE_MAX_DEPTH
+#define LSP_INCLUDE_MAX_DEPTH (32)
+#endif
+
 
 /* Forward declarations */
 static void handle_request(struct mg_connection *);
@@ -69,6 +76,20 @@ reg_lstring(struct lua_State *L,
 	}
 }
 
+static void
+reg_llstring(struct lua_State *L,
+             const void *buffer1,
+             size_t buflen1,
+             const void *buffer2,
+             size_t buflen2)
+{
+	if (buffer1 != NULL && buffer2 != NULL) {
+		lua_pushlstring(L, (const char *)buffer1, buflen1);
+		lua_pushlstring(L, (const char *)buffer2, buflen2);
+		lua_rawset(L, -3);
+	}
+}
+
 #define reg_string(L, name, val)                                               \
 	reg_lstring(L, name, val, val ? strlen(val) : 0)
 
@@ -368,11 +389,11 @@ lsp_var_reader(lua_State *L, void *ud, size_t *sz)
 
 
 static int
-lsp(struct mg_connection *conn,
-    const char *path,
-    const char *p,
-    int64_t len,
-    lua_State *L)
+run_lsp(struct mg_connection *conn,
+        const char *path,
+        const char *p,
+        int64_t len,
+        lua_State *L)
 {
 	int i, j, pos = 0, lines = 1, lualines = 0, is_var, lua_ok;
 	char chunkname[MG_BUF_LEN];
@@ -520,6 +541,13 @@ lsp_keep_alive(lua_State *L)
 }
 
 
+/* Stack of includes */
+struct lsp_include_history {
+	int depth;
+	const char *script[LSP_INCLUDE_MAX_DEPTH + 1];
+};
+
+
 /* mg.include: Include another .lp file */
 static int
 lsp_include(lua_State *L)
@@ -528,16 +556,92 @@ lsp_include(lua_State *L)
 	    (struct mg_connection *)lua_touserdata(L, lua_upvalueindex(1));
 	int num_args = lua_gettop(L);
 	struct mg_file file = STRUCT_FILE_INITIALIZER;
-	const char *filename = (num_args == 1) ? lua_tostring(L, 1) : NULL;
+	const char *file_name = (num_args >= 1) ? lua_tostring(L, 1) : NULL;
+	const char *path_type = (num_args >= 2) ? lua_tostring(L, 2) : NULL;
+	struct lsp_include_history *include_history;
 
-	if (filename) {
-		if (handle_lsp_request(conn, filename, &file, L)) {
-			/* handle_lsp_request returned an error code, meaning an error
-			occured in
-			the included page and mg.onerror returned non-zero. Stop processing.
-			*/
-			lsp_abort(L);
+	if ((file_name) && (num_args <= 2)) {
+
+		lua_pushlightuserdata(L, (void *)&lua_regkey_lsp_include_history);
+		lua_gettable(L, LUA_REGISTRYINDEX);
+		include_history = (struct lsp_include_history *)lua_touserdata(L, -1);
+
+		if (include_history->depth >= ((int)(LSP_INCLUDE_MAX_DEPTH))) {
+			mg_cry(conn,
+			       "lsp max include depth of %i reached while including %s",
+			       (int)(LSP_INCLUDE_MAX_DEPTH),
+			       file_name);
+		} else {
+			char file_name_path[512];
+			char *p;
+			size_t len;
+			int truncated = 0;
+
+			file_name_path[511] = 0;
+
+			if (path_type && (*path_type == 'v')) {
+				/* "virtual" = relative to document root. */
+				(void)mg_snprintf(conn,
+				                  &truncated,
+				                  file_name_path,
+				                  sizeof(file_name_path),
+				                  "%s/%s",
+				                  conn->ctx->config[DOCUMENT_ROOT],
+				                  file_name);
+
+			} else if ((path_type && (*path_type == 'a'))
+			           || (path_type == NULL)) {
+				/* "absolute" = file name is relative to the
+				 * webserver working directory
+				 * or it is absolute system path. */
+				/* path_type==NULL is the legacy use case with 1 argument */
+				(void)mg_snprintf(conn,
+				                  &truncated,
+				                  file_name_path,
+				                  sizeof(file_name_path),
+				                  "%s",
+				                  file_name);
+
+			} else if (path_type && (*path_type == 'r' || *path_type == 'f')) {
+				/* "relative" = file name is relative to the
+				 * currect document */
+				(void)mg_snprintf(
+				    conn,
+				    &truncated,
+				    file_name_path,
+				    sizeof(file_name_path),
+				    "%s",
+				    include_history->script[include_history->depth]);
+
+				if (!truncated) {
+					if ((p = strrchr(file_name_path, '/')) != NULL) {
+						p[1] = '\0';
+					}
+					len = strlen(file_name_path);
+					(void)mg_snprintf(conn,
+					                  &truncated,
+					                  file_name_path + len,
+					                  sizeof(file_name_path) - len,
+					                  "%s",
+					                  file_name);
+				}
+
+			} else {
+				return luaL_error(
+				    L,
+				    "invalid path_type in include(file_name, path_type) call");
+			}
+
+			if (handle_lsp_request(conn, file_name_path, &file, L)) {
+				/* handle_lsp_request returned an error code, meaning an error
+				* occured in the included page and mg.onerror returned non-zero.
+				* Stop processing.
+				*/
+
+				lsp_abort(L);
+			}
 		}
+
 	} else {
 		/* Syntax error */
 		return luaL_error(L, "invalid include() call");
@@ -629,15 +733,25 @@ lsp_get_var(lua_State *L)
 	const char *data, *var_name;
 	size_t data_len, occurrence;
 	int ret;
-	char dst[512];
+	struct mg_context *ctx;
+
+	lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
+	lua_gettable(L, LUA_REGISTRYINDEX);
+	ctx = (struct mg_context *)lua_touserdata(L, -1);
 
 	if (num_args >= 2 && num_args <= 3) {
+		char *dst;
 		data = lua_tolstring(L, 1, &data_len);
 		var_name = lua_tostring(L, 2);
 		occurrence = (num_args > 2) ? (long)lua_tonumber(L, 3) : 0;
 
-		ret =
-		    mg_get_var2(data, data_len, var_name, dst, sizeof(dst), occurrence);
+		/* Allocate dynamically, so there is no internal limit for get_var */
+		dst = (char *)mg_malloc_ctx(data_len + 1, ctx);
+		if (!dst) {
+			return luaL_error(L, "out of memory in get_var() call");
+		}
+
+		ret = mg_get_var2(data, data_len, var_name, dst, data_len, occurrence);
 		if (ret >= 0) {
 			/* Variable found: return value to Lua */
 			lua_pushstring(L, dst);
@@ -645,6 +759,7 @@ lsp_get_var(lua_State *L)
 			/* Variable not found (TODO (mid): may be string too long) */
 			lua_pushnil(L);
 		}
+		mg_free(dst);
 	} else {
 		/* Syntax error */
 		return luaL_error(L, "invalid get_var() call");
@@ -696,22 +811,39 @@ lsp_get_cookie(lua_State *L)
 	const char *cookie;
 	const char *var_name;
 	int ret;
-	char dst[512];
+	struct mg_context *ctx;
+
+	lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
+	lua_gettable(L, LUA_REGISTRYINDEX);
+	ctx = (struct mg_context *)lua_touserdata(L, -1);
 
 	if (num_args == 2) {
-		cookie = lua_tostring(L, 1);
+		/* Correct number of arguments */
+		size_t data_len;
+		char *dst;
+
+		cookie = lua_tolstring(L, 1, &data_len);
 		var_name = lua_tostring(L, 2);
-		if (cookie != NULL && var_name != NULL) {
-			ret = mg_get_cookie(cookie, var_name, dst, sizeof(dst));
-		} else {
-			ret = -1;
+
+		if (cookie == NULL || var_name == NULL) {
+			/* Syntax error */
+			return luaL_error(L, "invalid get_cookie() call");
 		}
 
+		dst = (char *)mg_malloc_ctx(data_len + 1, ctx);
+		if (!dst) {
+			return luaL_error(L, "out of memory in get_cookie() call");
+		}
+
+		ret = mg_get_cookie(cookie, var_name, dst, data_len);
+
 		if (ret >= 0) {
 			lua_pushlstring(L, dst, ret);
 		} else {
 			lua_pushnil(L);
 		}
+		mg_free(dst);
+
 	} else {
 		/* Syntax error */
 		return luaL_error(L, "invalid get_cookie() call");
@@ -757,13 +889,27 @@ lsp_url_encode(lua_State *L)
 	int num_args = lua_gettop(L);
 	const char *text;
 	size_t text_len;
-	char dst[512 * 3];
+	char *dst;
+	int dst_len;
+	struct mg_context *ctx;
+
+	lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
+	lua_gettable(L, LUA_REGISTRYINDEX);
+	ctx = (struct mg_context *)lua_touserdata(L, -1);
 
 	if (num_args == 1) {
 		text = lua_tolstring(L, 1, &text_len);
 		if (text) {
-			mg_url_encode(text, dst, sizeof(dst));
-			lua_pushstring(L, dst);
+			dst_len = 3 * (int)text_len + 1;
+			dst = ((text_len < 0x2AAAAAAA) ? (char *)mg_malloc_ctx(dst_len, ctx)
+			                               : (char *)NULL);
+			if (dst) {
+				mg_url_encode(text, dst, dst_len);
+				lua_pushstring(L, dst);
+				mg_free(dst);
+			} else {
+				return luaL_error(L, "out of memory in url_decode() call");
+			}
 		} else {
 			lua_pushnil(L);
 		}
@@ -783,14 +929,28 @@ lsp_url_decode(lua_State *L)
 	const char *text;
 	size_t text_len;
 	int is_form;
-	char dst[512];
+	char *dst;
+	int dst_len;
+	struct mg_context *ctx;
+
+	lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
+	lua_gettable(L, LUA_REGISTRYINDEX);
+	ctx = (struct mg_context *)lua_touserdata(L, -1);
 
 	if (num_args == 1 || (num_args == 2 && lua_isboolean(L, 2))) {
 		text = lua_tolstring(L, 1, &text_len);
 		is_form = (num_args == 2) ? lua_isboolean(L, 2) : 0;
 		if (text) {
-			mg_url_decode(text, (int)text_len, dst, (int)sizeof(dst), is_form);
-			lua_pushstring(L, dst);
+			dst_len = (int)text_len + 1;
+			dst = ((text_len < 0x7FFFFFFF) ? (char *)mg_malloc_ctx(dst_len, ctx)
+			                               : (char *)NULL);
+			if (dst) {
+				mg_url_decode(text, (int)text_len, dst, dst_len, is_form);
+				lua_pushstring(L, dst);
+				mg_free(dst);
+			} else {
+				return luaL_error(L, "out of memory in url_decode() call");
+			}
 		} else {
 			lua_pushnil(L);
 		}
@@ -810,11 +970,16 @@ lsp_base64_encode(lua_State *L)
 	const char *text;
 	size_t text_len;
 	char *dst;
+	struct mg_context *ctx;
+
+	lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
+	lua_gettable(L, LUA_REGISTRYINDEX);
+	ctx = (struct mg_context *)lua_touserdata(L, -1);
 
 	if (num_args == 1) {
 		text = lua_tolstring(L, 1, &text_len);
 		if (text) {
-			dst = (char *)mg_malloc(text_len * 8 / 6 + 4);
+			dst = (char *)mg_malloc_ctx(text_len * 8 / 6 + 4, ctx);
 			if (dst) {
 				base64_encode((const unsigned char *)text, (int)text_len, dst);
 				lua_pushstring(L, dst);
@@ -842,11 +1007,16 @@ lsp_base64_decode(lua_State *L)
 	size_t text_len, dst_len;
 	int ret;
 	char *dst;
+	struct mg_context *ctx;
+
+	lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
+	lua_gettable(L, LUA_REGISTRYINDEX);
+	ctx = (struct mg_context *)lua_touserdata(L, -1);
 
 	if (num_args == 1) {
 		text = lua_tolstring(L, 1, &text_len);
 		if (text) {
-			dst = (char *)mg_malloc(text_len);
+			dst = (char *)mg_malloc_ctx(text_len, ctx);
 			if (dst) {
 				ret = base64_decode((const unsigned char *)text,
 				                    (int)text_len,
@@ -925,6 +1095,186 @@ lsp_random(lua_State *L)
 }
 
 
+/* mg.get_info */
+static int
+lsp_get_info(lua_State *L)
+{
+	int num_args = lua_gettop(L);
+	int type1, type2;
+	const char *arg1;
+	double arg2;
+	int len;
+	char *buf;
+
+	if (num_args == 1) {
+		type1 = lua_type(L, 1);
+		if (type1 == LUA_TSTRING) {
+			arg1 = lua_tostring(L, 1);
+			/* Get info according to argument */
+			if (!mg_strcasecmp(arg1, "system")) {
+				/* Get system info */
+				len = mg_get_system_info(NULL, 0);
+				if (len > 0) {
+					buf = mg_malloc(len + 64);
+					if (!buf) {
+						return luaL_error(L, "OOM in get_info() call");
+					}
+					len = mg_get_system_info(buf, len + 63);
+					lua_pushlstring(L, buf, len);
+					mg_free(buf);
+				} else {
+					lua_pushstring(L, "");
+				}
+				return 1;
+			}
+			if (!mg_strcasecmp(arg1, "context")) {
+				/* Get context */
+				struct mg_context *ctx;
+				lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
+				lua_gettable(L, LUA_REGISTRYINDEX);
+				ctx = (struct mg_context *)lua_touserdata(L, -1);
+
+				/* Get context info for server context */
+				len = mg_get_context_info(ctx, NULL, 0);
+				if (len > 0) {
+					buf = mg_malloc(len + 64);
+					if (!buf) {
+						return luaL_error(L, "OOM in get_info() call");
+					}
+					len = mg_get_context_info(ctx, buf, len + 63);
+					lua_pushlstring(L, buf, len);
+					mg_free(buf);
+				} else {
+					lua_pushstring(L, "");
+				}
+				return 1;
+			}
+			if (!mg_strcasecmp(arg1, "common")) {
+				/* Get context info for NULL context */
+				len = mg_get_context_info(NULL, NULL, 0);
+				if (len > 0) {
+					buf = mg_malloc(len + 64);
+					if (!buf) {
+						return luaL_error(L, "OOM in get_info() call");
+					}
+					len = mg_get_context_info(NULL, buf, len + 63);
+					lua_pushlstring(L, buf, len);
+					mg_free(buf);
+				} else {
+					lua_pushstring(L, "");
+				}
+				return 1;
+			}
+			return 0;
+		}
+	}
+
+	if (num_args == 2) {
+		type1 = lua_type(L, 1);
+		type2 = lua_type(L, 2);
+		if ((type1 == LUA_TSTRING) && (type2 == LUA_TNUMBER)) {
+			arg1 = lua_tostring(L, 1);
+			arg2 = lua_tonumber(L, 2);
+
+			/* Get info according to argument */
+			if (!mg_strcasecmp(arg1, "connection")) {
+
+				/* Get context */
+				struct mg_context *ctx;
+				lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
+				lua_gettable(L, LUA_REGISTRYINDEX);
+				ctx = (struct mg_context *)lua_touserdata(L, -1);
+
+				/* Get connection info for connection idx */
+				int idx = (int)(arg2 + 0.5);
+
+				/* Lua uses 1 based index, C uses 0 based index */
+				idx--;
+
+#ifdef MG_EXPERIMENTAL_INTERFACES
+				len = mg_get_connection_info(ctx, idx, NULL, 0);
+				if (len > 0) {
+					buf = mg_malloc(len + 64);
+					if (!buf) {
+						return luaL_error(L, "OOM in get_info() call");
+					}
+					len = mg_get_connection_info(ctx, idx, buf, len + 63);
+					lua_pushlstring(L, buf, len);
+					mg_free(buf);
+				} else {
+					lua_pushstring(L, "");
+				}
+#else
+				(void)ctx;
+				(void)idx;
+				lua_pushstring(L, "");
+#endif
+
+				return 1;
+			}
+			return 0;
+		}
+	}
+
+	/* Syntax error */
+	return luaL_error(L, "invalid get_info() call");
+}
+
+
+/* mg.get_option */
+static int
+lsp_get_option(lua_State *L)
+{
+	int num_args = lua_gettop(L);
+	int type1;
+	const char *arg1;
+	const char *data;
+
+	/* Get context */
+	struct mg_context *ctx;
+	lua_pushlightuserdata(L, (void *)&lua_regkey_ctx);
+	lua_gettable(L, LUA_REGISTRYINDEX);
+	ctx = (struct mg_context *)lua_touserdata(L, -1);
+
+	if (num_args == 0) {
+		const struct mg_option *opts = mg_get_valid_options();
+
+		if (!opts) {
+			return 0;
+		}
+
+		lua_newtable(L);
+		while (opts->name) {
+			data = mg_get_option(ctx, opts->name);
+			if (data) {
+				reg_string(L, opts->name, data);
+			}
+			opts++;
+		}
+
+		return 1;
+	}
+
+	if (num_args == 1) {
+		type1 = lua_type(L, 1);
+		if (type1 == LUA_TSTRING) {
+			arg1 = lua_tostring(L, 1);
+			/* Get option according to argument */
+			data = mg_get_option(ctx, arg1);
+			if (data) {
+				lua_pushstring(L, data);
+				return 1;
+			}
+			return 0;
+		}
+	}
+
+	/* Syntax error */
+	return luaL_error(L, "invalid get_option() call");
+}
+
+
+/* UUID library and function pointer */
 union {
 	void *p;
 	void (*f)(unsigned char uuid[16]);
@@ -1068,12 +1418,16 @@ lwebsock_write(lua_State *L)
 		if (client) {
 			for (i = 0; i < ws->references; i++) {
 				if (client == ws->conn[i]) {
+					mg_lock_connection(ws->conn[i]);
 					mg_websocket_write(ws->conn[i], opcode, str, size);
+					mg_unlock_connection(ws->conn[i]);
 				}
 			}
 		} else {
 			for (i = 0; i < ws->references; i++) {
+				mg_lock_connection(ws->conn[i]);
 				mg_websocket_write(ws->conn[i], opcode, str, size);
+				mg_unlock_connection(ws->conn[i]);
 			}
 		}
 	} else {
@@ -1185,8 +1539,9 @@ lwebsocket_set_timer(lua_State *L, int is_periodic)
 		timediff = (double)lua_tonumber(L, 2);
 		txt = lua_tostring(L, 1);
 		txt_len = strlen(txt);
-		arg = (struct laction_arg *)mg_malloc(sizeof(struct laction_arg)
-		                                      + txt_len + 10);
+		arg = (struct laction_arg *)mg_malloc_ctx(sizeof(struct laction_arg)
+		                                              + txt_len + 10,
+		                                          ctx);
 		arg->state = L;
 		arg->script = ws->script;
 		arg->pmutex = &(ws->ws_mutex);
@@ -1310,7 +1665,7 @@ prepare_lua_request_info(struct mg_connection *conn, lua_State *L)
 }
 
 
-void
+static void
 civetweb_open_lua_libs(lua_State *L)
 {
 	{
@@ -1384,6 +1739,17 @@ prepare_lua_environment(struct mg_context *ctx,
 		lua_settable(L, LUA_REGISTRYINDEX);
 	}
 
+	/* Lua server pages store the depth of mg.include, in order
+	 * to detect recursions and prevent stack overflows. */
+	if (lua_env_type == LUA_ENV_TYPE_LUA_SERVER_PAGE) {
+		struct lsp_include_history *h;
+		lua_pushlightuserdata(L, (void *)&lua_regkey_lsp_include_history);
+		h = (struct lsp_include_history *)
+		    lua_newuserdata(L, sizeof(struct lsp_include_history));
+		lua_settable(L, LUA_REGISTRYINDEX);
+		memset(h, 0, sizeof(struct lsp_include_history));
+	}
+
 	/* Register mg module */
 	lua_newtable(L);
 
@@ -1433,6 +1799,9 @@ prepare_lua_environment(struct mg_context *ctx,
 	reg_function(L, "base64_decode", lsp_base64_decode);
 	reg_function(L, "get_response_code_text", lsp_get_response_code_text);
 	reg_function(L, "random", lsp_random);
+	reg_function(L, "get_info", lsp_get_info);
+	reg_function(L, "get_option", lsp_get_option);
+
 	if (pf_uuid_generate.f) {
 		reg_function(L, "uuid", lsp_uuid);
 	}
@@ -1510,14 +1879,13 @@ lua_error_handler(lua_State *L)
 static void *
 lua_allocator(void *ud, void *ptr, size_t osize, size_t nsize)
 {
-	(void)ud;
 	(void)osize; /* not used */
 
 	if (nsize == 0) {
 		mg_free(ptr);
 		return NULL;
 	}
-	return mg_realloc(ptr, nsize);
+	return mg_realloc_ctx(ptr, nsize, (struct mg_context *)ud);
 }
 
 
@@ -1534,7 +1902,8 @@ mg_exec_lua_script(struct mg_connection *conn,
 	conn->must_close = 1;
 
 	/* Execute a plain Lua script. */
-	if (path != NULL && (L = lua_newstate(lua_allocator, NULL)) != NULL) {
+	if (path != NULL
+	    && (L = lua_newstate(lua_allocator, (void *)(conn->ctx))) != NULL) {
 		prepare_lua_environment(
 		    conn->ctx, conn, NULL, L, path, LUA_ENV_TYPE_PLAIN_LUA_PAGE);
 		lua_pushcclosure(L, &lua_error_handler, 0);
@@ -1576,47 +1945,30 @@ handle_lsp_request(struct mg_connection *conn,
 {
 	void *p = NULL;
 	lua_State *L = NULL;
+	struct lsp_include_history *include_history;
 	int error = 1;
-	struct mg_file filesize = STRUCT_FILE_INITIALIZER;
 
 	/* Assume the script does not support keep_alive. The script may change this
 	 * by calling mg.keep_alive(true). */
 	conn->must_close = 1;
 
-	/* We need both mg_stat to get file size, and mg_fopen to get fd */
-	if (!mg_stat(conn, path, &filesize.stat)) {
-
-		/* File not found */
-		if (ls == NULL) {
-			send_http_error(conn, 500, "Error: File %s not found", path);
-		} else {
-			luaL_error(ls, "File [%s] not found", path);
-		}
-
-		goto cleanup_handle_lsp_request;
-	}
-
+	/* mg_fopen opens the file and sets the size accordingly */
 	if (!mg_fopen(conn, path, MG_FOPEN_MODE_READ, filep)) {
 
 		/* File not found or not accessible */
 		if (ls == NULL) {
-			send_http_error(conn,
-			                500,
-			                "Error: Cannot open script file %s",
-			                path);
+			mg_send_http_error(conn,
+			                   500,
+			                   "Error: Cannot open script file %s",
+			                   path);
 		} else {
-			luaL_error(ls, "Cannot  [%s] not found", path);
+			luaL_error(ls, "Cannot include [%s]: not found", path);
 		}
 
 		goto cleanup_handle_lsp_request;
 	}
 
-	/* TODO: Operations mg_fopen and mg_stat should do what their names
-	 * indicate. They should not fill in different members of the same
-	 * struct mg_file.
-	 * See Github issue #225 */
-	filep->stat.size = filesize.stat.size;
-
+	/* Map file in memory (size is known). */
 	if (filep->access.membuf == NULL
 	    && (p = mmap(NULL,
 	                 (size_t)filep->stat.size,
@@ -1627,7 +1979,7 @@ handle_lsp_request(struct mg_connection *conn,
 
 		/* mmap failed */
 		if (ls == NULL) {
-			send_http_error(
+			mg_send_http_error(
 			    conn,
 			    500,
 			    "Error: Cannot open script\nFile %s can not be mapped",
@@ -1647,9 +1999,9 @@ handle_lsp_request(struct mg_connection *conn,
 	if (ls != NULL) {
 		L = ls;
 	} else {
-		L = lua_newstate(lua_allocator, NULL);
+		L = lua_newstate(lua_allocator, (void *)(conn->ctx));
 		if (L == NULL) {
-			send_http_error(
+			mg_send_http_error(
 			    conn,
 			    500,
 			    "%s",
@@ -1661,15 +2013,24 @@ handle_lsp_request(struct mg_connection *conn,
 		    conn->ctx, conn, NULL, L, path, LUA_ENV_TYPE_LUA_SERVER_PAGE);
 	}
 
+	/* Get LSP include history table */
+	lua_pushlightuserdata(L, (void *)&lua_regkey_lsp_include_history);
+	lua_gettable(L, LUA_REGISTRYINDEX);
+	include_history = (struct lsp_include_history *)lua_touserdata(L, -1);
+
+	/* Store script name and increment depth */
+	include_history->depth++;
+	include_history->script[include_history->depth] = path;
+
 	/* Lua state is ready to use */
 	/* We're not sending HTTP headers here, Lua page must do it. */
-	error =
-	    lsp(conn,
-	        path,
-	        (filep->access.membuf == NULL) ? (const char *)p
-	                                       : (const char *)filep->access.membuf,
-	        filep->stat.size,
-	        L);
+	error = run_lsp(conn,
+	                path,
+	                (filep->access.membuf == NULL)
+	                    ? (const char *)p
+	                    : (const char *)filep->access.membuf,
+	                filep->stat.size,
+	                L);
 
 cleanup_handle_lsp_request:
 
@@ -1712,8 +2073,9 @@ lua_websocket_new(const char *script, struct mg_connection *conn)
 
 	if (*shared_websock_list == NULL) {
 		/* add ws to list */
-		*shared_websock_list = (struct mg_shared_lua_websocket_list *)
-		    mg_calloc(sizeof(struct mg_shared_lua_websocket_list), 1);
+		*shared_websock_list =
+		    (struct mg_shared_lua_websocket_list *)mg_calloc_ctx(
+		        sizeof(struct mg_shared_lua_websocket_list), 1, conn->ctx);
 		if (*shared_websock_list == NULL) {
 			mg_unlock_context(conn->ctx);
 			mg_cry(conn, "Cannot create shared websocket struct, OOM");
@@ -1724,7 +2086,7 @@ lua_websocket_new(const char *script, struct mg_connection *conn)
 		ws->script = mg_strdup(script); /* TODO (low): handle OOM */
 		pthread_mutex_init(&(ws->ws_mutex), &pthread_mutex_attr);
 		(void)pthread_mutex_lock(&(ws->ws_mutex));
-		ws->state = lua_newstate(lua_allocator, NULL);
+		ws->state = lua_newstate(lua_allocator, (void *)(conn->ctx));
 		ws->conn[0] = conn;
 		ws->references = 1;
 		prepare_lua_environment(
@@ -1892,7 +2254,7 @@ lua_websocket_close(struct mg_connection *conn, void *ws_arg)
 #endif
 
 
-lua_State *
+static lua_State *
 mg_prepare_lua_context_script(const char *file_name,
                               struct mg_context *ctx,
                               char *ebuf,
@@ -1902,6 +2264,8 @@ mg_prepare_lua_context_script(const char *file_name,
 	int lua_ret;
 	const char *lua_err_txt;
 
+	(void)ctx;
+
 	L = luaL_newstate();
 	if (L == NULL) {
 		mg_snprintf(NULL,
@@ -1916,7 +2280,8 @@ mg_prepare_lua_context_script(const char *file_name,
 
 	lua_ret = luaL_loadfile(L, file_name);
 	if (lua_ret != LUA_OK) {
-		/* Error when loading the file (e.g. file not found, out of memory, ...)
+		/* Error when loading the file (e.g. file not found,
+		 * out of memory, ...)
 		 */
 		lua_err_txt = lua_tostring(L, -1);
 		mg_snprintf(NULL,
@@ -1982,7 +2347,8 @@ lua_init_optional_libraries(void)
 {
 #if !defined(_WIN32)
 	lib_handle_uuid = dlopen("libuuid.so", RTLD_LAZY);
-	pf_uuid_generate.p = dlsym(lib_handle_uuid, "uuid_generate");
+	pf_uuid_generate.p =
+	    (lib_handle_uuid ? dlsym(lib_handle_uuid, "uuid_generate") : 0);
 #else
 	pf_uuid_generate.p = 0;
 #endif
@@ -1993,8 +2359,13 @@ static void
 lua_exit_optional_libraries(void)
 {
 #if !defined(_WIN32)
-	dlclose(lib_handle_uuid);
+	if (lib_handle_uuid) {
+		dlclose(lib_handle_uuid);
+	}
 #endif
 	pf_uuid_generate.p = 0;
 	lib_handle_uuid = NULL;
 }
+
+
+/* End of mod_lua.inl */

+ 10 - 11
src/sha1.inl

@@ -10,10 +10,10 @@ Still 100% Public Domain
 
 Corrected a problem which generated improper hash values on 16 bit machines
 Routine SHA1Update changed from
-    void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
+    void SHA1Update(SHA_CTX* context, unsigned char* data, unsigned int
 len)
 to
-    void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
+    void SHA1Update(SHA_CTX* context, unsigned char* data, unsigned
 long len)
 
 The 'len' parameter was declared an int which works fine on 32 bit machines.
@@ -73,6 +73,7 @@ move public api to sha1.h
   remove unused #ifdef sections
   make endian independent
   align buffer to 4 bytes
+  remove unused variable assignments
 */
 
 /*
@@ -92,7 +93,7 @@ typedef struct {
 	uint32_t state[5];
 	uint32_t count[2];
 	uint8_t buffer[64];
-} SHA1_CTX;
+} SHA_CTX;
 
 #define SHA1_DIGEST_SIZE 20
 
@@ -248,15 +249,12 @@ SHA1_Transform(uint32_t state[5], const uint8_t buffer[64])
 	state[2] += c;
 	state[3] += d;
 	state[4] += e;
-
-	/* Wipe variables */
-	a = b = c = d = e = 0;
 }
 
 
 /* SHA1Init - Initialize new context */
 SHA_API void
-SHA1_Init(SHA1_CTX *context)
+SHA1_Init(SHA_CTX *context)
 {
 	/* SHA1 initialization constants */
 	context->state[0] = 0x67452301;
@@ -269,7 +267,7 @@ SHA1_Init(SHA1_CTX *context)
 
 
 SHA_API void
-SHA1_Update(SHA1_CTX *context, const uint8_t *data, const uint32_t len)
+SHA1_Update(SHA_CTX *context, const uint8_t *data, const uint32_t len)
 {
 	uint32_t i, j;
 
@@ -296,7 +294,7 @@ SHA1_Update(SHA1_CTX *context, const uint8_t *data, const uint32_t len)
 
 /* Add padding and return the message digest. */
 SHA_API void
-SHA1_Final(SHA1_CTX *context, uint8_t digest[SHA1_DIGEST_SIZE])
+SHA1_Final(unsigned char *digest, SHA_CTX *context)
 {
 	uint32_t i;
 	uint8_t finalcount[8];
@@ -317,7 +315,8 @@ SHA1_Final(SHA1_CTX *context, uint8_t digest[SHA1_DIGEST_SIZE])
 	}
 
 	/* Wipe variables */
-	i = 0;
 	memset(context, '\0', sizeof(*context));
-	memset(&finalcount, '\0', sizeof(finalcount));
 }
+
+
+/* End of sha1.inl */

+ 72 - 0
src/third_party/duktape-1.8.0/AUTHORS.rst

@@ -0,0 +1,72 @@
+===============
+Duktape authors
+===============
+
+Copyright
+=========
+
+Duktape copyrights are held by its authors.  Each author has a copyright
+to their contribution, and agrees to irrevocably license the contribution
+under the Duktape ``LICENSE.txt``.
+
+Authors
+=======
+
+Please include an e-mail address, a link to your GitHub profile, or something
+similar to allow your contribution to be identified accurately.
+
+The following people have contributed code, website contents, or Wiki contents,
+and agreed to irrevocably license their contributions under the Duktape
+``LICENSE.txt`` (in order of appearance):
+
+* Sami Vaarala <sami.vaarala@iki.fi>
+* Niki Dobrev
+* Andreas Öman <andreas@lonelycoder.com>
+* László Langó <llango.u-szeged@partner.samsung.com>
+* Legimet <legimet.calc@gmail.com>
+* Karl Skomski <karl@skomski.com>
+* Bruce Pascoe <fatcerberus1@gmail.com>
+* René Hollander <rene@rene8888.at>
+* Julien Hamaide (https://github.com/crazyjul)
+* Sebastian Götte (https://github.com/jaseg)
+
+Other contributions
+===================
+
+The following people have contributed something other than code (e.g. reported
+bugs, provided ideas, etc; roughly in order of appearance):
+
+* Greg Burns
+* Anthony Rabine
+* Carlos Costa
+* Aurélien Bouilland
+* Preet Desai (Pris Matic)
+* judofyr (http://www.reddit.com/user/judofyr)
+* Jason Woofenden
+* Michał Przybyś
+* Anthony Howe
+* Conrad Pankoff
+* Jim Schimpf
+* Rajaran Gaunker (https://github.com/zimbabao)
+* Andreas Öman
+* Doug Sanden
+* Josh Engebretson (https://github.com/JoshEngebretson)
+* Remo Eichenberger (https://github.com/remoe)
+* Mamod Mehyar (https://github.com/mamod)
+* David Demelier (https://github.com/markand)
+* Tim Caswell (https://github.com/creationix)
+* Mitchell Blank Jr (https://github.com/mitchblank)
+* https://github.com/yushli
+* Seo Sanghyeon (https://github.com/sanxiyn)
+* Han ChoongWoo (https://github.com/tunz)
+* Joshua Peek (https://github.com/josh)
+* Bruce E. Pascoe (https://github.com/fatcerberus)
+* https://github.com/Kelledin
+* https://github.com/sstruchtrup
+* Michael Drake (https://github.com/tlsa)
+* https://github.com/chris-y
+* Laurent Zubiaur (https://github.com/lzubiaur)
+* Ole André Vadla Ravnås (https://github.com/oleavr)
+
+If you are accidentally missing from this list, send me an e-mail
+(``sami.vaarala@iki.fi``) and I'll fix the omission.

+ 25 - 0
src/third_party/duktape-1.8.0/LICENSE.txt

@@ -0,0 +1,25 @@
+===============
+Duktape license
+===============
+
+(http://opensource.org/licenses/MIT)
+
+Copyright (c) 2013-2017 by Duktape authors (see AUTHORS.rst)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 34 - 0
src/third_party/duktape-1.8.0/Makefile.cmdline

@@ -0,0 +1,34 @@
+#
+#  Example Makefile for building a program with embedded Duktape.
+#  The example program here is the Duktape command line tool.
+#
+
+DUKTAPE_SOURCES = src/duktape.c
+
+DUKTAPE_CMDLINE_SOURCES = \
+	examples/cmdline/duk_cmdline.c
+
+CC	= gcc
+CCOPTS	= -Os -pedantic -std=c99 -Wall -fstrict-aliasing -fomit-frame-pointer
+CCOPTS += -I./src   # duktape.h and duk_config.h must be in include path
+CCLIBS	= -lm
+
+# If you want linenoise, you can enable these.  At the moment linenoise
+# will cause some harmless compilation warnings.
+#CCOPTS += -DDUK_CMDLINE_FANCY
+#DUKTAPE_CMDLINE_SOURCES += linenoise/linenoise.c
+#CCOPTS += -I./linenoise
+#duk:	linenoise
+
+# Optional feature defines, see: http://duktape.org/guide.html#compiling
+CCOPTS += -DDUK_OPT_SELF_TESTS
+#CCOPTS += -DDUK_OPT_DEBUG
+#CCOPTS += -DDUK_OPT_DPRINT
+# ...
+
+duk:	$(DUKTAPE_SOURCES) $(DUKTAPE_CMDLINE_SOURCES)
+	$(CC) -o $@ $(DEFINES) $(CCOPTS) $(DUKTAPE_SOURCES) $(DUKTAPE_CMDLINE_SOURCES) $(CCLIBS)
+
+linenoise/linenoise.c: linenoise
+linenoise:
+	git clone https://github.com/antirez/linenoise.git

+ 4 - 0
src/third_party/duktape-1.8.0/Makefile.codepage

@@ -0,0 +1,4 @@
+codepage:
+	gcc -o $@ -std=c99 -O2 -Wall -Wextra -Isrc/ \
+		src/duktape.c examples/codepage-conv/duk_codepage_conv.c \
+		examples/codepage-conv/test.c -lm

+ 4 - 0
src/third_party/duktape-1.8.0/Makefile.coffee

@@ -0,0 +1,4 @@
+dummy:
+	coffee -c examples/coffee/globals.coffee
+	coffee -c examples/coffee/hello.coffee
+	coffee -c examples/coffee/mandel.coffee

+ 26 - 0
src/third_party/duktape-1.8.0/Makefile.dukdebug

@@ -0,0 +1,26 @@
+#
+#  Duktape command line tool with debugger support.
+#
+
+DUKTAPE_SOURCES = src/duktape.c
+
+# Windows (MinGW): use examples/debug-trans-socket/duk_trans_socket_windows.c
+# and link with -lws2_32.
+DUKTAPE_CMDLINE_SOURCES = \
+	examples/cmdline/duk_cmdline.c \
+	examples/debug-trans-socket/duk_trans_socket_unix.c
+
+CC	= gcc
+CCOPTS	= -Os -pedantic -std=c99 -Wall -fstrict-aliasing -fomit-frame-pointer
+CCOPTS += -I./src -I./examples/debug-trans-socket
+CCOPTS += -DDUK_CMDLINE_DEBUGGER_SUPPORT     # enable --debugger in ./duk
+CCOPTS += -DDUK_OPT_DEBUGGER_SUPPORT         # enable debugger support in Duktape
+CCOPTS += -DDUK_OPT_INTERRUPT_COUNTER        # prerequisite for debugging
+CCOPTS += -DDUK_OPT_DEBUGGER_FWD_PRINTALERT  # optional debugger features
+CCOPTS += -DDUK_OPT_DEBUGGER_FWD_LOGGING
+CCOPTS += -DDUK_OPT_DEBUGGER_DUMPHEAP
+CCOPTS += -DDUK_OPT_DEBUGGER_INSPECT
+CCLIBS	= -lm
+
+duk:	$(DUKTAPE_SOURCES) $(DUKTAPE_CMDLINE_SOURCES)
+	$(CC) -o $@ $(DEFINES) $(CCOPTS) $(DUKTAPE_SOURCES) $(DUKTAPE_CMDLINE_SOURCES) $(CCLIBS)

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä