소스 검색

Merge pull request #2 from bel2125/master

Update fork
hansipie 10 년 전
부모
커밋
1e9bca3831
100개의 변경된 파일749개의 추가작업 그리고 379개의 파일을 삭제
  1. 27 0
      CREDITS.md
  2. 13 5
      RELEASE_NOTES.md
  3. 41 20
      include/CivetServer.h
  4. 62 32
      include/civetweb.h
  5. 59 29
      src/CivetServer.cpp
  6. 77 41
      src/civetweb.c
  7. 2 1
      src/lua_civet.h
  8. 7 7
      src/main.c
  9. 11 9
      src/mod_lua.inl
  10. 199 0
      test/1000images.lua
  11. 168 160
      test/100images.htm
  12. 8 73
      test/ajax/echo.cgi
  13. 73 0
      test/ajax/echo.cgi.old
  14. 2 2
      test/cors.html
  15. 0 0
      test/imagetest/00.png
  16. 0 0
      test/imagetest/01.png
  17. 0 0
      test/imagetest/02.png
  18. 0 0
      test/imagetest/03.png
  19. 0 0
      test/imagetest/04.png
  20. 0 0
      test/imagetest/05.png
  21. 0 0
      test/imagetest/06.png
  22. 0 0
      test/imagetest/07.png
  23. 0 0
      test/imagetest/08.png
  24. 0 0
      test/imagetest/09.png
  25. 0 0
      test/imagetest/10.png
  26. 0 0
      test/imagetest/11.png
  27. 0 0
      test/imagetest/12.png
  28. 0 0
      test/imagetest/13.png
  29. 0 0
      test/imagetest/14.png
  30. 0 0
      test/imagetest/15.png
  31. 0 0
      test/imagetest/16.png
  32. 0 0
      test/imagetest/17.png
  33. 0 0
      test/imagetest/18.png
  34. 0 0
      test/imagetest/19.png
  35. 0 0
      test/imagetest/20.png
  36. 0 0
      test/imagetest/21.png
  37. 0 0
      test/imagetest/22.png
  38. 0 0
      test/imagetest/23.png
  39. 0 0
      test/imagetest/24.png
  40. 0 0
      test/imagetest/25.png
  41. 0 0
      test/imagetest/26.png
  42. 0 0
      test/imagetest/27.png
  43. 0 0
      test/imagetest/28.png
  44. 0 0
      test/imagetest/29.png
  45. 0 0
      test/imagetest/30.png
  46. 0 0
      test/imagetest/31.png
  47. 0 0
      test/imagetest/32.png
  48. 0 0
      test/imagetest/33.png
  49. 0 0
      test/imagetest/34.png
  50. 0 0
      test/imagetest/35.png
  51. 0 0
      test/imagetest/36.png
  52. 0 0
      test/imagetest/37.png
  53. 0 0
      test/imagetest/38.png
  54. 0 0
      test/imagetest/39.png
  55. 0 0
      test/imagetest/40.png
  56. 0 0
      test/imagetest/41.png
  57. 0 0
      test/imagetest/42.png
  58. 0 0
      test/imagetest/43.png
  59. 0 0
      test/imagetest/44.png
  60. 0 0
      test/imagetest/45.png
  61. 0 0
      test/imagetest/46.png
  62. 0 0
      test/imagetest/47.png
  63. 0 0
      test/imagetest/48.png
  64. 0 0
      test/imagetest/49.png
  65. 0 0
      test/imagetest/50.png
  66. 0 0
      test/imagetest/51.png
  67. 0 0
      test/imagetest/52.png
  68. 0 0
      test/imagetest/53.png
  69. 0 0
      test/imagetest/54.png
  70. 0 0
      test/imagetest/55.png
  71. 0 0
      test/imagetest/56.png
  72. 0 0
      test/imagetest/57.png
  73. 0 0
      test/imagetest/58.png
  74. 0 0
      test/imagetest/59.png
  75. 0 0
      test/imagetest/60.png
  76. 0 0
      test/imagetest/61.png
  77. 0 0
      test/imagetest/62.png
  78. 0 0
      test/imagetest/63.png
  79. 0 0
      test/imagetest/64.png
  80. 0 0
      test/imagetest/65.png
  81. 0 0
      test/imagetest/66.png
  82. 0 0
      test/imagetest/67.png
  83. 0 0
      test/imagetest/68.png
  84. 0 0
      test/imagetest/69.png
  85. 0 0
      test/imagetest/70.png
  86. 0 0
      test/imagetest/71.png
  87. 0 0
      test/imagetest/72.png
  88. 0 0
      test/imagetest/73.png
  89. 0 0
      test/imagetest/74.png
  90. 0 0
      test/imagetest/75.png
  91. 0 0
      test/imagetest/76.png
  92. 0 0
      test/imagetest/77.png
  93. 0 0
      test/imagetest/78.png
  94. 0 0
      test/imagetest/79.png
  95. 0 0
      test/imagetest/80.png
  96. 0 0
      test/imagetest/81.png
  97. 0 0
      test/imagetest/82.png
  98. 0 0
      test/imagetest/83.png
  99. 0 0
      test/imagetest/84.png
  100. 0 0
      test/imagetest/85.png

+ 27 - 0
CREDITS.md

@@ -2,27 +2,54 @@
 
 
 * Alex Kozlov
 * Alex Kozlov
 * bel2125
 * bel2125
+* Ben M. Ward
+* Brian Lambert
 * Brian Spratke
 * Brian Spratke
 * cdbishop
 * cdbishop
 * celeron55
 * celeron55
+* cjh
 * Daniel Oaks
 * Daniel Oaks
 * Danny Al-Gaaf
 * Danny Al-Gaaf
+* David Arnold
+* David Loffredo
 * Dialga
 * Dialga
+* Eric Tsau
 * F-Secure Corporation
 * F-Secure Corporation
+* Fernando G. Aranda
+* Grahack
+* grenclave
 * hansipie
 * hansipie
 * HariKamath Kamath
 * HariKamath Kamath
+* Jan Willem Janssen
+* Jeremy Lin
+* Jim Evans
+* jmc-
+* Jordan
 * Jordan Shelley
 * Jordan Shelley
+* kalphamon
 * Keith Kyzivat
 * Keith Kyzivat
 * Kevin Wojniak
 * Kevin Wojniak
 * Kimmo Mustonen
 * Kimmo Mustonen
+* Lianghui
+* Maarten Fremouw
+* Mark Lakata
 * Matt Clarkson
 * Matt Clarkson
 * Morgan McGuire
 * Morgan McGuire
+* Nick Hildebrant
+* Nigel Stewart
 * nihildeb
 * nihildeb
 * No Face Press
 * No Face Press
 * Paul Sokolovsky
 * Paul Sokolovsky
+* Perttu Ahola
+* Philipp Friedenberger
+* Philipp Hasper
 * Richard Screene
 * Richard Screene
+* Sage Weil
+* Sangwhan Moon
+* Scott Nations
 * Thomas Davis
 * Thomas Davis
 * Toni Wilk
 * Toni Wilk
+* Ulrich Hertlein
 * William Greathouse
 * William Greathouse
 * Yehuda Sadeh
 * Yehuda Sadeh
 
 

+ 13 - 5
RELEASE_NOTES.md

@@ -1,16 +1,24 @@
-Release Notes v1.7 (Under Development)
+Release Notes v1.7
 ===
 ===
-### Objectives: *Examples, documentation, additional API functions, rewritten handle_request method, bug fixes and updates*
+### Objectives: *Examples, documentation, additional API functions, some functions rewritten, bug fixes and updates*
 
 
 Changes
 Changes
 -------
 -------
 
 
-- URI specific callbacks for websockets
-- Add chunked transfer support (TODO: currently not working)
+- Format source with clang_format
+- Use function 'sendfile' for Linux
+- Fix for CRAMFS in Linux
+- Fix for file modification times in Windows
+- Use SO_EXCLUSIVEADDRUSE instead of SO_REUSEADDR for Windows
+- Rewrite push/pull functions
+- Allow to use Lua as shared objects (WITH_LUA_SHARED)
+- Fixes for many warnings
+- URI specific callbacks and different timeouts for websockets
+- Add chunked transfer support
 - Update LuaFileSystem
 - Update LuaFileSystem
 - Update Lua to 5.2.4
 - Update Lua to 5.2.4
 - Fix build for MinGW-x64, TDM-GCC and clang
 - Fix build for MinGW-x64, TDM-GCC and clang
-- Update SQLite to 3.8.8.3
+- Update SQLite to 3.8.10.2
 - Fix CGI variables SCRIPT_NAME and PATH_TRANSLATED
 - Fix CGI variables SCRIPT_NAME and PATH_TRANSLATED
 - Set TCP_USER_TIMEOUT to deal faster with broken connections
 - Set TCP_USER_TIMEOUT to deal faster with broken connections
 - Add a Lua form handling example
 - Add a Lua form handling example

+ 41 - 20
include/CivetServer.h

@@ -20,7 +20,8 @@ class CivetServer;
 /**
 /**
  * Exception class for thrown exceptions within the CivetHandler object.
  * Exception class for thrown exceptions within the CivetHandler object.
  */
  */
-class CIVETWEB_API CivetException : public std::runtime_error {
+class CIVETWEB_API CivetException : public std::runtime_error
+{
 	  public:
 	  public:
 	CivetException(const std::string &msg) : std::runtime_error(msg) {}
 	CivetException(const std::string &msg) : std::runtime_error(msg) {}
 };
 };
@@ -29,7 +30,8 @@ class CIVETWEB_API CivetException : public std::runtime_error {
  * Basic interface for a URI request handler.  Handlers implementations
  * Basic interface for a URI request handler.  Handlers implementations
  * must be reentrant.
  * must be reentrant.
  */
  */
-class CIVETWEB_API CivetHandler {
+class CIVETWEB_API CivetHandler
+{
 	  public:
 	  public:
 	/**
 	/**
 	 * Destructor
 	 * Destructor
@@ -87,7 +89,8 @@ class CIVETWEB_API CivetHandler {
  *
  *
  * Basic class for embedded web server.  This has an URL mapping built-in.
  * Basic class for embedded web server.  This has an URL mapping built-in.
  */
  */
-class CIVETWEB_API CivetServer {
+class CIVETWEB_API CivetServer
+{
 	  public:
 	  public:
 	/**
 	/**
 	 * Constructor
 	 * Constructor
@@ -135,7 +138,8 @@ class CIVETWEB_API CivetServer {
 	 */
 	 */
 	void addHandler(const std::string &uri, CivetHandler *handler);
 	void addHandler(const std::string &uri, CivetHandler *handler);
 
 
-	void addHandler(const std::string &uri, CivetHandler &handler) {
+	void addHandler(const std::string &uri, CivetHandler &handler)
+	{
 		addHandler(uri, &handler);
 		addHandler(uri, &handler);
 	}
 	}
 
 
@@ -206,8 +210,10 @@ class CIVETWEB_API CivetServer {
 	 *based).
 	 *based).
 	 * @return true if key was found
 	 * @return true if key was found
 	 */
 	 */
-	static bool getParam(struct mg_connection *conn, const char *name,
-	                     std::string &dst, size_t occurrence = 0);
+	static bool getParam(struct mg_connection *conn,
+	                     const char *name,
+	                     std::string &dst,
+	                     size_t occurrence = 0);
 
 
 	/**
 	/**
 	 * getParam(const std::string &, const char *, std::string &, size_t)
 	 * getParam(const std::string &, const char *, std::string &, size_t)
@@ -223,8 +229,11 @@ class CIVETWEB_API CivetServer {
 	 *based).
 	 *based).
 	 * @return true if key was found
 	 * @return true if key was found
 	 */
 	 */
-	static bool getParam(const std::string &data, const char *name,
-	                     std::string &dst, size_t occurrence = 0) {
+	static bool getParam(const std::string &data,
+	                     const char *name,
+	                     std::string &dst,
+	                     size_t occurrence = 0)
+	{
 		return getParam(data.c_str(), data.length(), name, dst, occurrence);
 		return getParam(data.c_str(), data.length(), name, dst, occurrence);
 	}
 	}
 
 
@@ -243,8 +252,11 @@ class CIVETWEB_API CivetServer {
 	 *based).
 	 *based).
 	 * @return true if key was found
 	 * @return true if key was found
 	 */
 	 */
-	static bool getParam(const char *data, size_t data_len, const char *name,
-	                     std::string &dst, size_t occurrence = 0);
+	static bool getParam(const char *data,
+	                     size_t data_len,
+	                     const char *name,
+	                     std::string &dst,
+	                     size_t occurrence = 0);
 
 
 	/**
 	/**
 	 * urlDecode(const std::string &, std::string &, bool)
 	 * urlDecode(const std::string &, std::string &, bool)
@@ -256,8 +268,10 @@ class CIVETWEB_API CivetServer {
 	 *       uses '+' as character for space, see RFC 1866 section 8.2.1
 	 *       uses '+' as character for space, see RFC 1866 section 8.2.1
 	 *       http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
 	 *       http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
 	 */
 	 */
-	static void urlDecode(const std::string &src, std::string &dst,
-	                      bool is_form_url_encoded = true) {
+	static void urlDecode(const std::string &src,
+	                      std::string &dst,
+	                      bool is_form_url_encoded = true)
+	{
 		urlDecode(src.c_str(), src.length(), dst, is_form_url_encoded);
 		urlDecode(src.c_str(), src.length(), dst, is_form_url_encoded);
 	}
 	}
 
 
@@ -272,7 +286,9 @@ class CIVETWEB_API CivetServer {
 	 *       uses '+' as character for space, see RFC 1866 section 8.2.1
 	 *       uses '+' as character for space, see RFC 1866 section 8.2.1
 	 *       http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
 	 *       http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
 	 */
 	 */
-	static void urlDecode(const char *src, size_t src_len, std::string &dst,
+	static void urlDecode(const char *src,
+	                      size_t src_len,
+	                      std::string &dst,
 	                      bool is_form_url_encoded = true);
 	                      bool is_form_url_encoded = true);
 
 
 	/**
 	/**
@@ -285,7 +301,8 @@ class CIVETWEB_API CivetServer {
 	 *       uses '+' as character for space, see RFC 1866 section 8.2.1
 	 *       uses '+' as character for space, see RFC 1866 section 8.2.1
 	 *       http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
 	 *       http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
 	 */
 	 */
-	static void urlDecode(const char *src, std::string &dst,
+	static void urlDecode(const char *src,
+	                      std::string &dst,
 	                      bool is_form_url_encoded = true);
 	                      bool is_form_url_encoded = true);
 
 
 	/**
 	/**
@@ -295,8 +312,9 @@ class CIVETWEB_API CivetServer {
 	 * @param dst - destination string
 	 * @param dst - destination string
 	 * @param append - true if string should not be cleared before encoding.
 	 * @param append - true if string should not be cleared before encoding.
 	 */
 	 */
-	static void urlEncode(const std::string &src, std::string &dst,
-	                      bool append = false) {
+	static void
+	urlEncode(const std::string &src, std::string &dst, bool append = false)
+	{
 		urlEncode(src.c_str(), src.length(), dst, append);
 		urlEncode(src.c_str(), src.length(), dst, append);
 	}
 	}
 
 
@@ -307,8 +325,8 @@ class CIVETWEB_API CivetServer {
 	 * @param dst - destination string
 	 * @param dst - destination string
 	 * @param append - true if string should not be cleared before encoding.
 	 * @param append - true if string should not be cleared before encoding.
 	 */
 	 */
-	static void urlEncode(const char *src, std::string &dst,
-	                      bool append = false);
+	static void
+	urlEncode(const char *src, std::string &dst, bool append = false);
 
 
 	/**
 	/**
 	 * urlEncode(const char *, size_t, std::string &, bool)
 	 * urlEncode(const char *, size_t, std::string &, bool)
@@ -318,11 +336,14 @@ class CIVETWEB_API CivetServer {
 	 * @param dst - destination string
 	 * @param dst - destination string
 	 * @param append - true if string should not be cleared before encoding.
 	 * @param append - true if string should not be cleared before encoding.
 	 */
 	 */
-	static void urlEncode(const char *src, size_t src_len, std::string &dst,
+	static void urlEncode(const char *src,
+	                      size_t src_len,
+	                      std::string &dst,
 	                      bool append = false);
 	                      bool append = false);
 
 
 	  protected:
 	  protected:
-	class CivetConnection {
+	class CivetConnection
+	{
 		  public:
 		  public:
 		char *postData;
 		char *postData;
 		unsigned long postDataLen;
 		unsigned long postDataLen;

+ 62 - 32
include/civetweb.h

@@ -35,7 +35,7 @@
 #define CIVETWEB_API
 #define CIVETWEB_API
 #endif
 #endif
 #elif __GNUC__ >= 4
 #elif __GNUC__ >= 4
-#define CIVETWEB_API __attribute__((visibility ("default")))
+#define CIVETWEB_API __attribute__((visibility("default")))
 #else
 #else
 #define CIVETWEB_API
 #define CIVETWEB_API
 #endif
 #endif
@@ -137,7 +137,9 @@ struct mg_callbacks {
 	     1: keep this websocket connection open.
 	     1: keep this websocket connection open.
 	     0: close this websocket connection.
 	     0: close this websocket connection.
 	   This callback is deprecated, use mg_set_websocket_handler instead. */
 	   This callback is deprecated, use mg_set_websocket_handler instead. */
-	int (*websocket_data)(struct mg_connection *, int bits, char *data,
+	int (*websocket_data)(struct mg_connection *,
+	                      int bits,
+	                      char *data,
 	                      size_t data_len);
 	                      size_t data_len);
 
 
 	/* Called when civetweb is closing a connection.  The per-context mutex is
 	/* Called when civetweb is closing a connection.  The per-context mutex is
@@ -158,7 +160,8 @@ struct mg_callbacks {
 	     NULL: do not serve file from memory, proceed with normal file open.
 	     NULL: do not serve file from memory, proceed with normal file open.
 	     non-NULL: pointer to the file contents in memory. data_len must be
 	     non-NULL: pointer to the file contents in memory. data_len must be
 	       initilized with the size of the memory block. */
 	       initilized with the size of the memory block. */
-	const char *(*open_file)(const struct mg_connection *, const char *path,
+	const char *(*open_file)(const struct mg_connection *,
+	                         const char *path,
 	                         size_t *data_len);
 	                         size_t *data_len);
 
 
 	/* Called when civetweb is about to serve Lua server page, if
 	/* Called when civetweb is about to serve Lua server page, if
@@ -297,8 +300,8 @@ CIVETWEB_API void mg_set_request_handler(struct mg_context *ctx,
 typedef int (*mg_websocket_connect_handler)(const struct mg_connection *,
 typedef int (*mg_websocket_connect_handler)(const struct mg_connection *,
                                             void *);
                                             void *);
 typedef void (*mg_websocket_ready_handler)(struct mg_connection *, void *);
 typedef void (*mg_websocket_ready_handler)(struct mg_connection *, void *);
-typedef int (*mg_websocket_data_handler)(struct mg_connection *, int, char *,
-                                         size_t, void *);
+typedef int (*mg_websocket_data_handler)(
+    struct mg_connection *, int, char *, size_t, void *);
 typedef void (*mg_websocket_close_handler)(const struct mg_connection *,
 typedef void (*mg_websocket_close_handler)(const struct mg_connection *,
                                            void *);
                                            void *);
 
 
@@ -307,7 +310,8 @@ typedef void (*mg_websocket_close_handler)(const struct mg_connection *,
    Set or remove handler functions for websocket connections.
    Set or remove handler functions for websocket connections.
    This function works similar to mg_set_request_handler - see there. */
    This function works similar to mg_set_request_handler - see there. */
 CIVETWEB_API void
 CIVETWEB_API void
-mg_set_websocket_handler(struct mg_context *ctx, const char *uri,
+mg_set_websocket_handler(struct mg_context *ctx,
+                         const char *uri,
                          mg_websocket_connect_handler connect_handler,
                          mg_websocket_connect_handler connect_handler,
                          mg_websocket_ready_handler ready_handler,
                          mg_websocket_ready_handler ready_handler,
                          mg_websocket_data_handler data_handler,
                          mg_websocket_data_handler data_handler,
@@ -391,7 +395,8 @@ mg_get_ports(const struct mg_context *ctx, size_t size, int *ports, int *ssl);
    Return:
    Return:
      1 on success, 0 on error. */
      1 on success, 0 on error. */
 CIVETWEB_API int mg_modify_passwords_file(const char *passwords_file_name,
 CIVETWEB_API int mg_modify_passwords_file(const char *passwords_file_name,
-                                          const char *domain, const char *user,
+                                          const char *domain,
+                                          const char *user,
                                           const char *password);
                                           const char *password);
 
 
 /* Return information associated with the request. */
 /* Return information associated with the request. */
@@ -417,8 +422,10 @@ CIVETWEB_API int mg_write(struct mg_connection *, const void *buf, size_t len);
     0   when the connection has been closed
     0   when the connection has been closed
     -1  on error
     -1  on error
     >0  number of bytes written on success */
     >0  number of bytes written on success */
-CIVETWEB_API int mg_websocket_write(struct mg_connection *conn, int opcode,
-                                    const char *data, size_t data_len);
+CIVETWEB_API int mg_websocket_write(struct mg_connection *conn,
+                                    int opcode,
+                                    const char *data,
+                                    size_t data_len);
 
 
 /* Blocks until unique access is obtained to this connection. Intended for use
 /* Blocks until unique access is obtained to this connection. Intended for use
    with websockets only.
    with websockets only.
@@ -470,8 +477,8 @@ enum {
 /* Send data to the client using printf() semantics.
 /* Send data to the client using printf() semantics.
    Works exactly like mg_write(), but allows to do message formatting. */
    Works exactly like mg_write(), but allows to do message formatting. */
 CIVETWEB_API int mg_printf(struct mg_connection *,
 CIVETWEB_API int mg_printf(struct mg_connection *,
-                           PRINTF_FORMAT_STRING(const char *fmt), ...)
-    PRINTF_ARGS(2, 3);
+                           PRINTF_FORMAT_STRING(const char *fmt),
+                           ...) PRINTF_ARGS(2, 3);
 
 
 /* Send contents of the entire file together with HTTP headers. */
 /* Send contents of the entire file together with HTTP headers. */
 CIVETWEB_API void mg_send_file(struct mg_connection *conn, const char *path);
 CIVETWEB_API void mg_send_file(struct mg_connection *conn, const char *path);
@@ -510,8 +517,11 @@ CIVETWEB_API const char *mg_get_header(const struct mg_connection *,
 
 
    Destination buffer is guaranteed to be '\0' - terminated if it is not
    Destination buffer is guaranteed to be '\0' - terminated if it is not
    NULL or zero length. */
    NULL or zero length. */
-CIVETWEB_API int mg_get_var(const char *data, size_t data_len,
-                            const char *var_name, char *dst, size_t dst_len);
+CIVETWEB_API int mg_get_var(const char *data,
+                            size_t data_len,
+                            const char *var_name,
+                            char *dst,
+                            size_t dst_len);
 
 
 /* Get a value of particular form variable.
 /* Get a value of particular form variable.
 
 
@@ -536,8 +546,11 @@ CIVETWEB_API int mg_get_var(const char *data, size_t data_len,
 
 
    Destination buffer is guaranteed to be '\0' - terminated if it is not
    Destination buffer is guaranteed to be '\0' - terminated if it is not
    NULL or zero length. */
    NULL or zero length. */
-CIVETWEB_API int mg_get_var2(const char *data, size_t data_len,
-                             const char *var_name, char *dst, size_t dst_len,
+CIVETWEB_API int mg_get_var2(const char *data,
+                             size_t data_len,
+                             const char *var_name,
+                             char *dst,
+                             size_t dst_len,
                              size_t occurrence);
                              size_t occurrence);
 
 
 /* Fetch value of certain cookie variable into the destination buffer.
 /* Fetch value of certain cookie variable into the destination buffer.
@@ -553,8 +566,10 @@ CIVETWEB_API int mg_get_var2(const char *data, size_t data_len,
             parameter is not found).
             parameter is not found).
         -2 (destination buffer is NULL, zero length or too small to hold the
         -2 (destination buffer is NULL, zero length or too small to hold the
             value). */
             value). */
-CIVETWEB_API int mg_get_cookie(const char *cookie, const char *var_name,
-                               char *buf, size_t buf_len);
+CIVETWEB_API int mg_get_cookie(const char *cookie,
+                               const char *var_name,
+                               char *buf,
+                               size_t buf_len);
 
 
 /* Download data from the remote web server.
 /* Download data from the remote web server.
      host: host name to connect to, e.g. "foo.com", or "10.12.40.1".
      host: host name to connect to, e.g. "foo.com", or "10.12.40.1".
@@ -572,10 +587,13 @@ CIVETWEB_API int mg_get_cookie(const char *cookie, const char *var_name,
                         "%s", "GET / HTTP/1.0\r\nHost: google.com\r\n\r\n");
                         "%s", "GET / HTTP/1.0\r\nHost: google.com\r\n\r\n");
  */
  */
 CIVETWEB_API struct mg_connection *
 CIVETWEB_API struct mg_connection *
-mg_download(const char *host, int port, int use_ssl, char *error_buffer,
+mg_download(const char *host,
+            int port,
+            int use_ssl,
+            char *error_buffer,
             size_t error_buffer_size,
             size_t error_buffer_size,
-            PRINTF_FORMAT_STRING(const char *request_fmt), ...)
-    PRINTF_ARGS(6, 7);
+            PRINTF_FORMAT_STRING(const char *request_fmt),
+            ...) PRINTF_ARGS(6, 7);
 
 
 /* Close the connection opened by mg_download(). */
 /* Close the connection opened by mg_download(). */
 CIVETWEB_API void mg_close_connection(struct mg_connection *conn);
 CIVETWEB_API void mg_close_connection(struct mg_connection *conn);
@@ -604,8 +622,11 @@ CIVETWEB_API const char *mg_version(void);
    uses '+' as character for space, see RFC 1866 section 8.2.1
    uses '+' as character for space, see RFC 1866 section 8.2.1
    http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
    http://ftp.ics.uci.edu/pub/ietf/html/rfc1866.txt
    Return: length of the decoded data, or -1 if dst buffer is too small. */
    Return: length of the decoded data, or -1 if dst buffer is too small. */
-CIVETWEB_API int mg_url_decode(const char *src, int src_len, char *dst,
-                               int dst_len, int is_form_url_encoded);
+CIVETWEB_API int mg_url_decode(const char *src,
+                               int src_len,
+                               char *dst,
+                               int dst_len,
+                               int is_form_url_encoded);
 
 
 /* URL-encode input buffer into destination buffer.
 /* URL-encode input buffer into destination buffer.
    returns the length of the resulting buffer or -1
    returns the length of the resulting buffer or -1
@@ -628,8 +649,8 @@ CIVETWEB_API char *mg_md5(char buf[33], ...);
    Example:
    Example:
      mg_cry(conn,"i like %s", "logging"); */
      mg_cry(conn,"i like %s", "logging"); */
 CIVETWEB_API void mg_cry(const struct mg_connection *conn,
 CIVETWEB_API void mg_cry(const struct mg_connection *conn,
-                         PRINTF_FORMAT_STRING(const char *fmt), ...)
-    PRINTF_ARGS(2, 3);
+                         PRINTF_FORMAT_STRING(const char *fmt),
+                         ...) PRINTF_ARGS(2, 3);
 
 
 /* utility method to compare two buffers, case incensitive. */
 /* utility method to compare two buffers, case incensitive. */
 CIVETWEB_API int mg_strncasecmp(const char *s1, const char *s2, size_t len);
 CIVETWEB_API int mg_strncasecmp(const char *s1, const char *s2, size_t len);
@@ -653,11 +674,17 @@ CIVETWEB_API int mg_strncasecmp(const char *s1, const char *s2, size_t len);
      On error, NULL. Se error_buffer for details.
      On error, NULL. Se error_buffer for details.
 */
 */
 
 
-CIVETWEB_API struct mg_connection *mg_connect_websocket_client(
-    const char *host, int port, int use_ssl, char *error_buffer,
-    size_t error_buffer_size, const char *path, const char *origin,
-    mg_websocket_data_handler data_func, mg_websocket_close_handler close_func,
-    void *user_data);
+CIVETWEB_API struct mg_connection *
+mg_connect_websocket_client(const char *host,
+                            int port,
+                            int use_ssl,
+                            char *error_buffer,
+                            size_t error_buffer_size,
+                            const char *path,
+                            const char *origin,
+                            mg_websocket_data_handler data_func,
+                            mg_websocket_close_handler close_func,
+                            void *user_data);
 
 
 /* Connect to a TCP server as a client (can be used to connect to a HTTP server)
 /* Connect to a TCP server as a client (can be used to connect to a HTTP server)
    Parameters:
    Parameters:
@@ -671,7 +698,8 @@ CIVETWEB_API struct mg_connection *mg_connect_websocket_client(
      On success, valid mg_connection object.
      On success, valid mg_connection object.
      On error, NULL. Se error_buffer for details.
      On error, NULL. Se error_buffer for details.
 */
 */
-CIVETWEB_API struct mg_connection *mg_connect_client(const char *host, int port,
+CIVETWEB_API struct mg_connection *mg_connect_client(const char *host,
+                                                     int port,
                                                      int use_ssl,
                                                      int use_ssl,
                                                      char *error_buffer,
                                                      char *error_buffer,
                                                      size_t error_buffer_size);
                                                      size_t error_buffer_size);
@@ -689,8 +717,10 @@ enum { TIMEOUT_INFINITE = -1 };
      On success, >= 0
      On success, >= 0
      On error/timeout, < 0
      On error/timeout, < 0
 */
 */
-CIVETWEB_API int mg_get_response(struct mg_connection *conn, char *ebuf,
-                                 size_t ebuf_len, int timeout);
+CIVETWEB_API int mg_get_response(struct mg_connection *conn,
+                                 char *ebuf,
+                                 size_t ebuf_len,
+                                 int timeout);
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }

+ 59 - 29
src/CivetServer.cpp

@@ -15,39 +15,44 @@
 #define UNUSED_PARAMETER(x) (void)(x)
 #define UNUSED_PARAMETER(x) (void)(x)
 #endif
 #endif
 
 
-bool CivetHandler::handleGet(CivetServer *server, struct mg_connection *conn) {
+bool CivetHandler::handleGet(CivetServer *server, struct mg_connection *conn)
+{
 	UNUSED_PARAMETER(server);
 	UNUSED_PARAMETER(server);
 	UNUSED_PARAMETER(conn);
 	UNUSED_PARAMETER(conn);
 	return false;
 	return false;
 }
 }
 
 
-bool CivetHandler::handlePost(CivetServer *server, struct mg_connection *conn) {
+bool CivetHandler::handlePost(CivetServer *server, struct mg_connection *conn)
+{
 	UNUSED_PARAMETER(server);
 	UNUSED_PARAMETER(server);
 	UNUSED_PARAMETER(conn);
 	UNUSED_PARAMETER(conn);
 	return false;
 	return false;
 }
 }
 
 
-bool CivetHandler::handlePut(CivetServer *server, struct mg_connection *conn) {
+bool CivetHandler::handlePut(CivetServer *server, struct mg_connection *conn)
+{
 	UNUSED_PARAMETER(server);
 	UNUSED_PARAMETER(server);
 	UNUSED_PARAMETER(conn);
 	UNUSED_PARAMETER(conn);
 	return false;
 	return false;
 }
 }
 
 
-bool CivetHandler::handleDelete(CivetServer *server,
-                                struct mg_connection *conn) {
+bool CivetHandler::handleDelete(CivetServer *server, struct mg_connection *conn)
+{
 	UNUSED_PARAMETER(server);
 	UNUSED_PARAMETER(server);
 	UNUSED_PARAMETER(conn);
 	UNUSED_PARAMETER(conn);
 	return false;
 	return false;
 }
 }
 
 
 bool CivetHandler::handleOptions(CivetServer *server,
 bool CivetHandler::handleOptions(CivetServer *server,
-                                 struct mg_connection *conn) {
+                                 struct mg_connection *conn)
+{
 	UNUSED_PARAMETER(server);
 	UNUSED_PARAMETER(server);
 	UNUSED_PARAMETER(conn);
 	UNUSED_PARAMETER(conn);
 	return false;
 	return false;
 }
 }
 
 
-int CivetServer::requestHandler(struct mg_connection *conn, void *cbdata) {
+int CivetServer::requestHandler(struct mg_connection *conn, void *cbdata)
+{
 	const struct mg_request_info *request_info = mg_get_request_info(conn);
 	const struct mg_request_info *request_info = mg_get_request_info(conn);
 	assert(request_info != NULL);
 	assert(request_info != NULL);
 	CivetServer *me = (CivetServer *)(request_info->user_data);
 	CivetServer *me = (CivetServer *)(request_info->user_data);
@@ -82,7 +87,8 @@ int CivetServer::requestHandler(struct mg_connection *conn, void *cbdata) {
 
 
 CivetServer::CivetServer(const char **options,
 CivetServer::CivetServer(const char **options,
                          const struct mg_callbacks *_callbacks)
                          const struct mg_callbacks *_callbacks)
-    : context(0) {
+    : context(0)
+{
 	struct mg_callbacks callbacks;
 	struct mg_callbacks callbacks;
 	memset(&callbacks, 0, sizeof(callbacks));
 	memset(&callbacks, 0, sizeof(callbacks));
 
 
@@ -101,7 +107,8 @@ CivetServer::CivetServer(const char **options,
 
 
 CivetServer::~CivetServer() { close(); }
 CivetServer::~CivetServer() { close(); }
 
 
-void CivetServer::closeHandler(const struct mg_connection *conn) {
+void CivetServer::closeHandler(const struct mg_connection *conn)
+{
 	const struct mg_request_info *request_info = mg_get_request_info(conn);
 	const struct mg_request_info *request_info = mg_get_request_info(conn);
 	assert(request_info != NULL);
 	assert(request_info != NULL);
 	CivetServer *me = (CivetServer *)(request_info->user_data);
 	CivetServer *me = (CivetServer *)(request_info->user_data);
@@ -118,15 +125,18 @@ void CivetServer::closeHandler(const struct mg_connection *conn) {
 	mg_unlock_context(me->context);
 	mg_unlock_context(me->context);
 }
 }
 
 
-void CivetServer::addHandler(const std::string &uri, CivetHandler *handler) {
+void CivetServer::addHandler(const std::string &uri, CivetHandler *handler)
+{
 	mg_set_request_handler(context, uri.c_str(), requestHandler, handler);
 	mg_set_request_handler(context, uri.c_str(), requestHandler, handler);
 }
 }
 
 
-void CivetServer::removeHandler(const std::string &uri) {
+void CivetServer::removeHandler(const std::string &uri)
+{
 	mg_set_request_handler(context, uri.c_str(), NULL, NULL);
 	mg_set_request_handler(context, uri.c_str(), NULL, NULL);
 }
 }
 
 
-void CivetServer::close() {
+void CivetServer::close()
+{
 	if (context) {
 	if (context) {
 		mg_stop(context);
 		mg_stop(context);
 		context = 0;
 		context = 0;
@@ -135,30 +145,37 @@ void CivetServer::close() {
 
 
 int CivetServer::getCookie(struct mg_connection *conn,
 int CivetServer::getCookie(struct mg_connection *conn,
                            const std::string &cookieName,
                            const std::string &cookieName,
-                           std::string &cookieValue) {
+                           std::string &cookieValue)
+{
 	// Maximum cookie length as per microsoft is 4096.
 	// Maximum cookie length as per microsoft is 4096.
 	// http://msdn.microsoft.com/en-us/library/ms178194.aspx
 	// http://msdn.microsoft.com/en-us/library/ms178194.aspx
 	char _cookieValue[4096];
 	char _cookieValue[4096];
 	const char *cookie = mg_get_header(conn, "Cookie");
 	const char *cookie = mg_get_header(conn, "Cookie");
-	int lRead = mg_get_cookie(cookie, cookieName.c_str(), _cookieValue,
-	                          sizeof(_cookieValue));
+	int lRead = mg_get_cookie(
+	    cookie, cookieName.c_str(), _cookieValue, sizeof(_cookieValue));
 	cookieValue.clear();
 	cookieValue.clear();
 	cookieValue.append(_cookieValue);
 	cookieValue.append(_cookieValue);
 	return lRead;
 	return lRead;
 }
 }
 
 
 const char *CivetServer::getHeader(struct mg_connection *conn,
 const char *CivetServer::getHeader(struct mg_connection *conn,
-                                   const std::string &headerName) {
+                                   const std::string &headerName)
+{
 	return mg_get_header(conn, headerName.c_str());
 	return mg_get_header(conn, headerName.c_str());
 }
 }
 
 
-void CivetServer::urlDecode(const char *src, std::string &dst,
-                            bool is_form_url_encoded) {
+void CivetServer::urlDecode(const char *src,
+                            std::string &dst,
+                            bool is_form_url_encoded)
+{
 	urlDecode(src, strlen(src), dst, is_form_url_encoded);
 	urlDecode(src, strlen(src), dst, is_form_url_encoded);
 }
 }
 
 
-void CivetServer::urlDecode(const char *src, size_t src_len, std::string &dst,
-                            bool is_form_url_encoded) {
+void CivetServer::urlDecode(const char *src,
+                            size_t src_len,
+                            std::string &dst,
+                            bool is_form_url_encoded)
+{
 	int i, j, a, b;
 	int i, j, a, b;
 #define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
 #define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
 
 
@@ -179,8 +196,11 @@ void CivetServer::urlDecode(const char *src, size_t src_len, std::string &dst,
 	}
 	}
 }
 }
 
 
-bool CivetServer::getParam(struct mg_connection *conn, const char *name,
-                           std::string &dst, size_t occurrence) {
+bool CivetServer::getParam(struct mg_connection *conn,
+                           const char *name,
+                           std::string &dst,
+                           size_t occurrence)
+{
 	const char *formParams = NULL;
 	const char *formParams = NULL;
 	const struct mg_request_info *ri = mg_get_request_info(conn);
 	const struct mg_request_info *ri = mg_get_request_info(conn);
 	assert(ri != NULL);
 	assert(ri != NULL);
@@ -227,8 +247,12 @@ bool CivetServer::getParam(struct mg_connection *conn, const char *name,
 	return false;
 	return false;
 }
 }
 
 
-bool CivetServer::getParam(const char *data, size_t data_len, const char *name,
-                           std::string &dst, size_t occurrence) {
+bool CivetServer::getParam(const char *data,
+                           size_t data_len,
+                           const char *name,
+                           std::string &dst,
+                           size_t occurrence)
+{
 	const char *p, *e, *s;
 	const char *p, *e, *s;
 	size_t name_len;
 	size_t name_len;
 
 
@@ -262,12 +286,16 @@ bool CivetServer::getParam(const char *data, size_t data_len, const char *name,
 	return false;
 	return false;
 }
 }
 
 
-void CivetServer::urlEncode(const char *src, std::string &dst, bool append) {
+void CivetServer::urlEncode(const char *src, std::string &dst, bool append)
+{
 	urlEncode(src, strlen(src), dst, append);
 	urlEncode(src, strlen(src), dst, append);
 }
 }
 
 
-void CivetServer::urlEncode(const char *src, size_t src_len, std::string &dst,
-                            bool append) {
+void CivetServer::urlEncode(const char *src,
+                            size_t src_len,
+                            std::string &dst,
+                            bool append)
+{
 	static const char *dont_escape = "._-$,;~()";
 	static const char *dont_escape = "._-$,;~()";
 	static const char *hex = "0123456789abcdef";
 	static const char *hex = "0123456789abcdef";
 
 
@@ -286,7 +314,8 @@ void CivetServer::urlEncode(const char *src, size_t src_len, std::string &dst,
 	}
 	}
 }
 }
 
 
-std::vector<int> CivetServer::getListeningPorts() {
+std::vector<int> CivetServer::getListeningPorts()
+{
 	std::vector<int> ports(10);
 	std::vector<int> ports(10);
 	std::vector<int> ssl(10);
 	std::vector<int> ssl(10);
 	size_t size = mg_get_ports(context, ports.size(), &ports[0], &ssl[0]);
 	size_t size = mg_get_ports(context, ports.size(), &ports[0], &ssl[0]);
@@ -295,7 +324,8 @@ std::vector<int> CivetServer::getListeningPorts() {
 	return ports;
 	return ports;
 }
 }
 
 
-CivetServer::CivetConnection::CivetConnection() {
+CivetServer::CivetConnection::CivetConnection()
+{
 	postData = NULL;
 	postData = NULL;
 	postDataLen = 0;
 	postDataLen = 0;
 }
 }

+ 77 - 41
src/civetweb.c

@@ -52,6 +52,10 @@
 #endif
 #endif
 #endif
 #endif
 
 
+#if defined(USE_LUA) && defined(USE_WEBSOCKET)
+#define USE_TIMERS
+#endif
+
 #if defined(_MSC_VER)
 #if defined(_MSC_VER)
 /* 'type cast' : conversion from 'int' to 'HANDLE' of greater size */
 /* 'type cast' : conversion from 'int' to 'HANDLE' of greater size */
 #pragma warning(disable : 4306)
 #pragma warning(disable : 4306)
@@ -292,10 +296,6 @@ typedef long off_t;
 #define sleep(x) (Sleep((x)*1000))
 #define sleep(x) (Sleep((x)*1000))
 #define rmdir(x) (_rmdir(x))
 #define rmdir(x) (_rmdir(x))
 
 
-#if defined(USE_LUA) && defined(USE_WEBSOCKET)
-#define USE_TIMERS
-#endif
-
 #if !defined(fileno)
 #if !defined(fileno)
 #define fileno(x) (_fileno(x))
 #define fileno(x) (_fileno(x))
 #endif /* !fileno MINGW #defines fileno */
 #endif /* !fileno MINGW #defines fileno */
@@ -1149,6 +1149,7 @@ typedef struct tagTHREADNAME_INFO {
 #pragma pack(pop)
 #pragma pack(pop)
 #elif defined(__linux__)
 #elif defined(__linux__)
 #include <sys/prctl.h>
 #include <sys/prctl.h>
+#include <sys/sendfile.h>
 #endif
 #endif
 
 
 #if ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12)))
 #if ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12)))
@@ -1169,7 +1170,7 @@ static void mg_set_thread_name(const char *name)
 	threadName[sizeof(threadName) - 1] = 0;
 	threadName[sizeof(threadName) - 1] = 0;
 
 
 #if defined(_WIN32)
 #if defined(_WIN32)
-	#if defined(_MSC_VER)
+#if defined(_MSC_VER)
 	/* Windows and Visual Studio Compiler */
 	/* Windows and Visual Studio Compiler */
 	__try
 	__try
 	{
 	{
@@ -1185,34 +1186,34 @@ static void mg_set_thread_name(const char *name)
 		               (ULONG_PTR *)&info);
 		               (ULONG_PTR *)&info);
 	}
 	}
 	__except(EXCEPTION_EXECUTE_HANDLER) {}
 	__except(EXCEPTION_EXECUTE_HANDLER) {}
-	#elif defined(__MINGW32__)
+#elif defined(__MINGW32__)
 	/* No option known to set thread name for MinGW */
 	/* No option known to set thread name for MinGW */
 	;
 	;
-	#endif
+#endif
 #elif defined(__linux__)
 #elif defined(__linux__)
-	/* Linux */
-	#if defined(GLIBC_CHK)
+/* Linux */
+#if defined(GLIBC_CHK)
 	(void)pthread_setname_np(pthread_self(), threadName);
 	(void)pthread_setname_np(pthread_self(), threadName);
-	#else
+#else
 	(void)prctl(PR_SET_NAME, threadName, 0, 0, 0);
 	(void)prctl(PR_SET_NAME, threadName, 0, 0, 0);
-	#endif
+#endif
 #elif defined(__APPLE__) || defined(__MACH__)
 #elif defined(__APPLE__) || defined(__MACH__)
-	/* OS X */
-	#if defined(GLIBC_CHK)
+/* OS X */
+#if defined(GLIBC_CHK)
 	(void)pthread_setname_np(threadName);
 	(void)pthread_setname_np(threadName);
-	#endif
+#endif
 #elif defined(BSD) || defined(__FreeBSD__) || defined(__OpenBSD__)
 #elif defined(BSD) || defined(__FreeBSD__) || defined(__OpenBSD__)
-	/* BSD (TODO: test) */
-	#if defined(GLIBC_CHK)
+/* BSD (TODO: test) */
+#if defined(GLIBC_CHK)
 	pthread_set_name_np(pthread_self(), threadName);
 	pthread_set_name_np(pthread_self(), threadName);
-	#endif
+#endif
 #elif defined(__AIX__) || defined(_AIX) || defined(__hpux) || defined(__sun)
 #elif defined(__AIX__) || defined(_AIX) || defined(__hpux) || defined(__sun)
-	/* pthread_set_name_np seems to be missing on AIX, hpux, sun, ... */
+/* pthread_set_name_np seems to be missing on AIX, hpux, sun, ... */
 #else
 #else
-	/* POSIX */
-	#if defined(GLIBC_CHK)
+/* POSIX */
+#if defined(GLIBC_CHK)
 	(void)pthread_setname_np(pthread_self(), threadName);
 	(void)pthread_setname_np(pthread_self(), threadName);
-	#endif
+#endif
 #endif
 #endif
 }
 }
 #else /* !defined(NO_THREAD_NAME) */
 #else /* !defined(NO_THREAD_NAME) */
@@ -5238,36 +5239,71 @@ static void send_file_data(struct mg_connection *conn,
 	offset = offset < 0 ? 0 : offset > size ? size : offset;
 	offset = offset < 0 ? 0 : offset > size ? size : offset;
 
 
 	if (len > 0 && filep->membuf != NULL && size > 0) {
 	if (len > 0 && filep->membuf != NULL && size > 0) {
+		/* file stored in memory */
 		if (len > size - offset) {
 		if (len > size - offset) {
 			len = size - offset;
 			len = size - offset;
 		}
 		}
 		mg_write(conn, filep->membuf + offset, (size_t)len);
 		mg_write(conn, filep->membuf + offset, (size_t)len);
 	} else if (len > 0 && filep->fp != NULL) {
 	} else if (len > 0 && filep->fp != NULL) {
+/* file stored on disk */
+#if defined(__linux__)
+		/* TODO (high): Test sendfile for Linux */
+		if (conn->throttle == 0 && conn->ssl == 0) {
+			off_t sf_offs = (off_t)offset;
+			ssize_t sf_sent;
+			int sf_file = fileno(filep->fp);
+
+			do {
+				/* 2147479552 (0x7FFFF000) is a limit found by experiment on 64
+				 * bit Linux (2^31 minus one memory page of 4k?). */
+				ssize_t sf_tosend =
+				    (size_t)((len < 0x7FFFF000) ? len : 0x7FFFF000);
+				sf_sent =
+				    sendfile(conn->client.sock, sf_file, &sf_offs, sf_tosend);
+				if (sf_sent > 0) {
+					conn->num_bytes_sent += sf_sent;
+					len -= sf_sent;
+					offset += sf_sent;
+				}
+
+			} while ((len > 0) && (sf_sent >= 0));
+
+			if (sf_sent > 0) {
+				return; /* OK */
+			}
+			/* sf_sent<0 means error, thus fall back to the classic way */
+			mg_cry(conn,
+			       "%s: sendfile() failed: %s (now trying read+write)",
+			       __func__,
+			       strerror(ERRNO));
+		}
+#endif
 		if (offset > 0 && fseeko(filep->fp, offset, SEEK_SET) != 0) {
 		if (offset > 0 && fseeko(filep->fp, offset, SEEK_SET) != 0) {
 			mg_cry(conn, "%s: fseeko() failed: %s", __func__, strerror(ERRNO));
 			mg_cry(conn, "%s: fseeko() failed: %s", __func__, strerror(ERRNO));
-		}
-		while (len > 0) {
-			/* Calculate how much to read from the file in the buffer */
-			to_read = sizeof(buf);
-			if ((int64_t)to_read > len) {
-				to_read = (int)len;
-			}
+		} else {
+			while (len > 0) {
+				/* Calculate how much to read from the file in the buffer */
+				to_read = sizeof(buf);
+				if ((int64_t)to_read > len) {
+					to_read = (int)len;
+				}
 
 
-			/* Read from file, exit the loop on error */
-			if ((num_read = (int)fread(buf, 1, (size_t)to_read, filep->fp)) <=
-			    0) {
-				break;
-			}
+				/* Read from file, exit the loop on error */
+				if ((num_read =
+				         (int)fread(buf, 1, (size_t)to_read, filep->fp)) <= 0) {
+					break;
+				}
 
 
-			/* Send read bytes to the client, exit the loop on error */
-			if ((num_written = mg_write(conn, buf, (size_t)num_read)) !=
-			    num_read) {
-				break;
-			}
+				/* Send read bytes to the client, exit the loop on error */
+				if ((num_written = mg_write(conn, buf, (size_t)num_read)) !=
+				    num_read) {
+					break;
+				}
 
 
-			/* Both read and were successful, adjust counters */
-			conn->num_bytes_sent += num_written;
-			len -= num_written;
+				/* Both read and were successful, adjust counters */
+				conn->num_bytes_sent += num_written;
+				len -= num_written;
+			}
 		}
 		}
 	}
 	}
 }
 }

+ 2 - 1
src/lua_civet.h

@@ -1,4 +1,5 @@
 /* "lua_civet.h" */
 /* "lua_civet.h" */
-/* Project internal header to allow main.c to call a non-public function in mod_lua.inl */
+/* Project internal header to allow main.c to call a non-public function in
+ * mod_lua.inl */
 
 
 void lua_civet_open_all_libs(lua_State *L);
 void lua_civet_open_all_libs(lua_State *L);

+ 7 - 7
src/main.c

@@ -127,7 +127,7 @@ static struct tuser_data
 #endif
 #endif
 
 
 /* backup config file */
 /* backup config file */
-#if !defined(CONFIG_FILE2) && defined(LINUX)
+#if !defined(CONFIG_FILE2) && defined(__linux__)
 #define CONFIG_FILE2 "/usr/local/etc/civetweb.conf"
 #define CONFIG_FILE2 "/usr/local/etc/civetweb.conf"
 #endif
 #endif
 
 
@@ -299,11 +299,11 @@ static const char *get_option(char **options, const char *option_name)
 	const char *opt_value = NULL;
 	const char *opt_value = NULL;
 
 
 	/* TODO (low, api makeover): options should be an array of key-value-pairs,
 	/* TODO (low, api makeover): options should be an array of key-value-pairs,
-	 * like 
-     *     struct {const char * key, const char * value} options[]
+	 * like
+	 *     struct {const char * key, const char * value} options[]
 	 * but it currently is an array with
 	 * but it currently is an array with
 	 *     options[2*i] = key, options[2*i + 1] = value
 	 *     options[2*i] = key, options[2*i + 1] = value
-     * (probably with a MG_LEGACY_INTERFACE definition)
+	 * (probably with a MG_LEGACY_INTERFACE definition)
 	 */
 	 */
 	while (options[2 * i] != NULL) {
 	while (options[2 * i] != NULL) {
 		if (strcmp(options[2 * i], option_name) == 0) {
 		if (strcmp(options[2 * i], option_name) == 0) {
@@ -340,7 +340,7 @@ static int set_option(char **options, const char *name, const char *value)
 		return 0;
 		return 0;
 	case CONFIG_TYPE_NUMBER:
 	case CONFIG_TYPE_NUMBER:
 		/* integer number > 0, e.g. number of threads */
 		/* integer number > 0, e.g. number of threads */
-		if (atol(value) < 1) {
+		if (atol(value) < 0) {
 			/* invalid number */
 			/* invalid number */
 			return 0;
 			return 0;
 		}
 		}
@@ -1813,8 +1813,8 @@ static void change_password_file()
 static int manage_service(int action)
 static int manage_service(int action)
 {
 {
 	static const char *service_name =
 	static const char *service_name =
-	    "Civetweb"; /* TODO (mid): check using server_name instead of 
-                     * service_name */
+	    "Civetweb"; /* TODO (mid): check using server_name instead of
+	                 * service_name */
 	SC_HANDLE hSCM = NULL, hService = NULL;
 	SC_HANDLE hSCM = NULL, hService = NULL;
 	SERVICE_DESCRIPTION descr;
 	SERVICE_DESCRIPTION descr;
 	char path[PATH_MAX + 20] = ""; /* Path to executable plus magic argument */
 	char path[PATH_MAX + 20] = ""; /* Path to executable plus magic argument */

+ 11 - 9
src/mod_lua.inl

@@ -8,9 +8,9 @@ mmap(void *addr, int64_t len, int prot, int flags, int fd, int offset)
 {
 {
 	/* TODO (low): This is an incomplete implementation of mmap for windows.
 	/* TODO (low): This is an incomplete implementation of mmap for windows.
 	 * Currently it is sufficient, but there are a lot of unused parameters.
 	 * Currently it is sufficient, but there are a lot of unused parameters.
-     * Better use a function "mg_map" which only has the required parameters,
-     * and implement it using mmap in Linux and CreateFileMapping in Windows.
-     * Noone should expect a full mmap for Windows here.
+	 * Better use a function "mg_map" which only has the required parameters,
+	 * and implement it using mmap in Linux and CreateFileMapping in Windows.
+	 * Noone should expect a full mmap for Windows here.
 	 */
 	 */
 	HANDLE fh = (HANDLE)_get_osfhandle(fd);
 	HANDLE fh = (HANDLE)_get_osfhandle(fd);
 	HANDLE mh = CreateFileMapping(fh, 0, PAGE_READONLY, 0, 0, 0);
 	HANDLE mh = CreateFileMapping(fh, 0, PAGE_READONLY, 0, 0, 0);
@@ -1109,14 +1109,14 @@ void lua_civet_open_all_libs(lua_State *L)
 	}
 	}
 #endif
 #endif
 #ifdef USE_LUA_BINARY
 #ifdef USE_LUA_BINARY
-    {
-        /* TODO (low): Test if this could be used as a replacement for bit32.
-         * Check again with Lua 5.3 later. */
+	{
+		/* TODO (low): Test if this could be used as a replacement for bit32.
+		 * Check again with Lua 5.3 later. */
 		extern int luaopen_binary(lua_State *);
 		extern int luaopen_binary(lua_State *);
 
 
-        luaL_requiref(L, "binary", luaopen_binary, 1);
-        lua_pop(L, 1);
-    }
+		luaL_requiref(L, "binary", luaopen_binary, 1);
+		lua_pop(L, 1);
+	}
 #endif
 #endif
 }
 }
 
 
@@ -1572,6 +1572,8 @@ static void lua_websocket_close(struct mg_connection *conn, void *ws_arg)
 	/* TODO: Delete lua_websock_data and remove it from the websocket list.
 	/* TODO: Delete lua_websock_data and remove it from the websocket list.
 	   This must only be done, when all connections are closed, and all
 	   This must only be done, when all connections are closed, and all
 	   asynchronous operations and timers are completed/expired. */
 	   asynchronous operations and timers are completed/expired. */
+	(void)shared_websock_list; /* shared_websock_list unused (see open TODO) */
+
 	(void)pthread_mutex_unlock(&ws->ws_mutex);
 	(void)pthread_mutex_unlock(&ws->ws_mutex);
 }
 }
 #endif
 #endif

+ 199 - 0
test/1000images.lua

@@ -0,0 +1,199 @@
+mg.write("HTTP/1.1 200 OK\r\n")
+mg.write("Connection: close\r\n")
+mg.write("Content-Type: text/html; charset=utf-8\r\n")
+mg.write("\r\n")
+
+t = os.time()
+
+if not mg.request_info.query_string then
+  cnt = 1000
+else
+  cnt = tonumber(mg.get_var(mg.request_info.query_string, "cnt"))
+end
+
+cnt = 100*math.floor(cnt/100)
+
+mg.write([[
+<html>
+  <head>
+    <title>]] .. cnt .. [[ images</title>
+    <script type="text/javascript">
+      var startLoad = Date.now();
+      window.onload = function () {
+        var loadTime = (Date.now()-startLoad) + " ms";
+        document.getElementById('timing').innerHTML = loadTime;
+      }
+    </script>
+  </head>
+  <body>
+    <h1>A large gallery of small images:</h1>
+    <p>
+]])
+for s=0,(cnt/100)-1 do
+local ts = (tostring(t) .. tostring(s))
+mg.write([[
+      <h2>page ]]..s..[[</h2>
+      <table>
+        <tr>
+          <td><img src="imagetest/00.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/01.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/02.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/03.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/04.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/05.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/06.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/07.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/08.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/09.png?ts=]]..ts..[["></td>
+        </tr>
+]])
+mg.write([[
+        <tr>
+          <td><img src="imagetest/10.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/11.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/12.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/13.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/14.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/15.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/16.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/17.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/18.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/19.png?ts=]]..ts..[["></td>
+        </tr>
+]])
+mg.write([[
+        <tr>
+          <td><img src="imagetest/20.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/21.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/22.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/23.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/24.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/25.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/26.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/27.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/28.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/29.png?ts=]]..ts..[["></td>
+        </tr>
+]])
+mg.write([[
+        <tr>
+          <td><img src="imagetest/20.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/21.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/22.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/23.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/24.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/25.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/26.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/27.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/28.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/29.png?ts=]]..ts..[["></td>
+        </tr>
+]])
+mg.write([[
+        <tr>
+          <td><img src="imagetest/30.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/31.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/32.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/33.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/34.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/35.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/36.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/37.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/38.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/39.png?ts=]]..ts..[["></td>
+        </tr>
+]])
+mg.write([[
+        <tr>
+          <td><img src="imagetest/40.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/41.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/42.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/43.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/44.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/45.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/46.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/47.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/48.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/49.png?ts=]]..ts..[["></td>
+        </tr>
+]])
+mg.write([[
+        <tr>
+          <td><img src="imagetest/50.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/51.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/52.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/53.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/54.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/55.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/56.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/57.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/58.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/59.png?ts=]]..ts..[["></td>
+        </tr>
+]])
+mg.write([[
+        <tr>
+          <td><img src="imagetest/60.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/61.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/62.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/63.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/64.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/65.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/66.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/67.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/68.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/69.png?ts=]]..ts..[["></td>
+        </tr>
+]])
+mg.write([[
+        <tr>
+          <td><img src="imagetest/70.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/71.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/72.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/73.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/74.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/75.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/76.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/77.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/78.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/79.png?ts=]]..ts..[["></td>
+        </tr>
+]])
+mg.write([[
+        <tr>
+          <td><img src="imagetest/80.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/81.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/82.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/83.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/84.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/85.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/86.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/87.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/88.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/89.png?ts=]]..ts..[["></td>
+        </tr>
+]])
+mg.write([[
+        <tr>
+          <td><img src="imagetest/90.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/91.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/92.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/93.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/94.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/95.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/96.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/97.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/98.png?ts=]]..ts..[["></td>
+          <td><img src="imagetest/99.png?ts=]]..ts..[["></td>
+        </tr>
+      </table>
+]])
+end
+mg.write([[
+    </p>
+    <p id="timing">
+      Test case: all images are displayed.
+    </p>
+  </body>
+</html>
+]])

+ 168 - 160
test/100images.htm

@@ -1,160 +1,168 @@
-<html>
-
-  <!-- Test case description:                              -->
-  <!-- This test contains 100 small images in a table.     -->
-  <!-- Once a browser opens the html file, it will request -->
-  <!-- all these images from the server very quickly.      -->
-  <!-- Depending on the "keep-alive" settings, it will     -->
-  <!-- either open/close 100 connections quite rapidly     -->
-  <!-- if keep-alive=no, or otherwise establish only a few -->
-  <!-- connections, typically one or two, and reuse them.  -->
-  <!-- If the test succeeds, all 100 images are displayed. -->
-
-  <!-- Bug: I saw cases where more than 40 were missing.   -->
-
-  <head>
-    <title>100 images</title>
-  </head>
-  <body>
-    <h1>A gallery of small images:</h1>
-    <p>
-      <table>
-        <tr>
-          <td><img src="imagetest/00.png"></td>
-          <td><img src="imagetest/01.png"></td>
-          <td><img src="imagetest/02.png"></td>
-          <td><img src="imagetest/03.png"></td>
-          <td><img src="imagetest/04.png"></td>
-          <td><img src="imagetest/05.png"></td>
-          <td><img src="imagetest/06.png"></td>
-          <td><img src="imagetest/07.png"></td>
-          <td><img src="imagetest/08.png"></td>
-          <td><img src="imagetest/09.png"></td>
-        </tr>
-        <tr>
-          <td><img src="imagetest/10.png"></td>
-          <td><img src="imagetest/11.png"></td>
-          <td><img src="imagetest/12.png"></td>
-          <td><img src="imagetest/13.png"></td>
-          <td><img src="imagetest/14.png"></td>
-          <td><img src="imagetest/15.png"></td>
-          <td><img src="imagetest/16.png"></td>
-          <td><img src="imagetest/17.png"></td>
-          <td><img src="imagetest/18.png"></td>
-          <td><img src="imagetest/19.png"></td>
-        </tr>
-        <tr>
-          <td><img src="imagetest/20.png"></td>
-          <td><img src="imagetest/21.png"></td>
-          <td><img src="imagetest/22.png"></td>
-          <td><img src="imagetest/23.png"></td>
-          <td><img src="imagetest/24.png"></td>
-          <td><img src="imagetest/25.png"></td>
-          <td><img src="imagetest/26.png"></td>
-          <td><img src="imagetest/27.png"></td>
-          <td><img src="imagetest/28.png"></td>
-          <td><img src="imagetest/29.png"></td>
-        </tr>
-        <tr>
-          <td><img src="imagetest/20.png"></td>
-          <td><img src="imagetest/21.png"></td>
-          <td><img src="imagetest/22.png"></td>
-          <td><img src="imagetest/23.png"></td>
-          <td><img src="imagetest/24.png"></td>
-          <td><img src="imagetest/25.png"></td>
-          <td><img src="imagetest/26.png"></td>
-          <td><img src="imagetest/27.png"></td>
-          <td><img src="imagetest/28.png"></td>
-          <td><img src="imagetest/29.png"></td>
-        </tr>
-        <tr>
-          <td><img src="imagetest/30.png"></td>
-          <td><img src="imagetest/31.png"></td>
-          <td><img src="imagetest/32.png"></td>
-          <td><img src="imagetest/33.png"></td>
-          <td><img src="imagetest/34.png"></td>
-          <td><img src="imagetest/35.png"></td>
-          <td><img src="imagetest/36.png"></td>
-          <td><img src="imagetest/37.png"></td>
-          <td><img src="imagetest/38.png"></td>
-          <td><img src="imagetest/39.png"></td>
-        </tr>
-        <tr>
-          <td><img src="imagetest/40.png"></td>
-          <td><img src="imagetest/41.png"></td>
-          <td><img src="imagetest/42.png"></td>
-          <td><img src="imagetest/43.png"></td>
-          <td><img src="imagetest/44.png"></td>
-          <td><img src="imagetest/45.png"></td>
-          <td><img src="imagetest/46.png"></td>
-          <td><img src="imagetest/47.png"></td>
-          <td><img src="imagetest/48.png"></td>
-          <td><img src="imagetest/49.png"></td>
-        </tr>
-        <tr>
-          <td><img src="imagetest/50.png"></td>
-          <td><img src="imagetest/51.png"></td>
-          <td><img src="imagetest/52.png"></td>
-          <td><img src="imagetest/53.png"></td>
-          <td><img src="imagetest/54.png"></td>
-          <td><img src="imagetest/55.png"></td>
-          <td><img src="imagetest/56.png"></td>
-          <td><img src="imagetest/57.png"></td>
-          <td><img src="imagetest/58.png"></td>
-          <td><img src="imagetest/59.png"></td>
-        </tr>
-        <tr>
-          <td><img src="imagetest/60.png"></td>
-          <td><img src="imagetest/61.png"></td>
-          <td><img src="imagetest/62.png"></td>
-          <td><img src="imagetest/63.png"></td>
-          <td><img src="imagetest/64.png"></td>
-          <td><img src="imagetest/65.png"></td>
-          <td><img src="imagetest/66.png"></td>
-          <td><img src="imagetest/67.png"></td>
-          <td><img src="imagetest/68.png"></td>
-          <td><img src="imagetest/69.png"></td>
-        </tr>
-        <tr>
-          <td><img src="imagetest/70.png"></td>
-          <td><img src="imagetest/71.png"></td>
-          <td><img src="imagetest/72.png"></td>
-          <td><img src="imagetest/73.png"></td>
-          <td><img src="imagetest/74.png"></td>
-          <td><img src="imagetest/75.png"></td>
-          <td><img src="imagetest/76.png"></td>
-          <td><img src="imagetest/77.png"></td>
-          <td><img src="imagetest/78.png"></td>
-          <td><img src="imagetest/79.png"></td>
-        </tr>
-        <tr>
-          <td><img src="imagetest/80.png"></td>
-          <td><img src="imagetest/81.png"></td>
-          <td><img src="imagetest/82.png"></td>
-          <td><img src="imagetest/83.png"></td>
-          <td><img src="imagetest/84.png"></td>
-          <td><img src="imagetest/85.png"></td>
-          <td><img src="imagetest/86.png"></td>
-          <td><img src="imagetest/87.png"></td>
-          <td><img src="imagetest/88.png"></td>
-          <td><img src="imagetest/89.png"></td>
-        </tr>
-        <tr>
-          <td><img src="imagetest/90.png"></td>
-          <td><img src="imagetest/91.png"></td>
-          <td><img src="imagetest/92.png"></td>
-          <td><img src="imagetest/93.png"></td>
-          <td><img src="imagetest/94.png"></td>
-          <td><img src="imagetest/95.png"></td>
-          <td><img src="imagetest/96.png"></td>
-          <td><img src="imagetest/97.png"></td>
-          <td><img src="imagetest/98.png"></td>
-          <td><img src="imagetest/99.png"></td>
-        </tr>
-      </table>
-    </p>
-    <p>
-      Test case: all images are displayed.
-    </p>    
-  </body>
-</html>
+<html>
+
+  <!-- Test case description:                              -->
+  <!-- This test contains 100 small images in a table.     -->
+  <!-- Once a browser opens the html file, it will request -->
+  <!-- all these images from the server very quickly.      -->
+  <!-- Depending on the "keep-alive" settings, it will     -->
+  <!-- either open/close 100 connections quite rapidly     -->
+  <!-- if keep-alive=no, or otherwise establish only a few -->
+  <!-- connections, typically one or two, and reuse them.  -->
+  <!-- If the test succeeds, all 100 images are displayed. -->
+  <!-- The loading time is measured automatically in the   -->
+  <!-- browser using JavaScript. Note that the load times  -->
+  <!-- also differs between HTTP and HTTPS.                -->
+
+  <head>
+    <title>100 images</title>
+    <script type="text/javascript">
+      var startLoad = Date.now();
+      window.onload = function () {
+        var loadTime = (Date.now()-startLoad) + " ms";
+        document.getElementById('timing').innerHTML = loadTime;
+      }
+    </script>
+  </head>
+  <body>
+    <h1>A gallery of small images:</h1>
+    <p>
+      <table>
+        <tr>
+          <td><img src="imagetest/00.png"></td>
+          <td><img src="imagetest/01.png"></td>
+          <td><img src="imagetest/02.png"></td>
+          <td><img src="imagetest/03.png"></td>
+          <td><img src="imagetest/04.png"></td>
+          <td><img src="imagetest/05.png"></td>
+          <td><img src="imagetest/06.png"></td>
+          <td><img src="imagetest/07.png"></td>
+          <td><img src="imagetest/08.png"></td>
+          <td><img src="imagetest/09.png"></td>
+        </tr>
+        <tr>
+          <td><img src="imagetest/10.png"></td>
+          <td><img src="imagetest/11.png"></td>
+          <td><img src="imagetest/12.png"></td>
+          <td><img src="imagetest/13.png"></td>
+          <td><img src="imagetest/14.png"></td>
+          <td><img src="imagetest/15.png"></td>
+          <td><img src="imagetest/16.png"></td>
+          <td><img src="imagetest/17.png"></td>
+          <td><img src="imagetest/18.png"></td>
+          <td><img src="imagetest/19.png"></td>
+        </tr>
+        <tr>
+          <td><img src="imagetest/20.png"></td>
+          <td><img src="imagetest/21.png"></td>
+          <td><img src="imagetest/22.png"></td>
+          <td><img src="imagetest/23.png"></td>
+          <td><img src="imagetest/24.png"></td>
+          <td><img src="imagetest/25.png"></td>
+          <td><img src="imagetest/26.png"></td>
+          <td><img src="imagetest/27.png"></td>
+          <td><img src="imagetest/28.png"></td>
+          <td><img src="imagetest/29.png"></td>
+        </tr>
+        <tr>
+          <td><img src="imagetest/20.png"></td>
+          <td><img src="imagetest/21.png"></td>
+          <td><img src="imagetest/22.png"></td>
+          <td><img src="imagetest/23.png"></td>
+          <td><img src="imagetest/24.png"></td>
+          <td><img src="imagetest/25.png"></td>
+          <td><img src="imagetest/26.png"></td>
+          <td><img src="imagetest/27.png"></td>
+          <td><img src="imagetest/28.png"></td>
+          <td><img src="imagetest/29.png"></td>
+        </tr>
+        <tr>
+          <td><img src="imagetest/30.png"></td>
+          <td><img src="imagetest/31.png"></td>
+          <td><img src="imagetest/32.png"></td>
+          <td><img src="imagetest/33.png"></td>
+          <td><img src="imagetest/34.png"></td>
+          <td><img src="imagetest/35.png"></td>
+          <td><img src="imagetest/36.png"></td>
+          <td><img src="imagetest/37.png"></td>
+          <td><img src="imagetest/38.png"></td>
+          <td><img src="imagetest/39.png"></td>
+        </tr>
+        <tr>
+          <td><img src="imagetest/40.png"></td>
+          <td><img src="imagetest/41.png"></td>
+          <td><img src="imagetest/42.png"></td>
+          <td><img src="imagetest/43.png"></td>
+          <td><img src="imagetest/44.png"></td>
+          <td><img src="imagetest/45.png"></td>
+          <td><img src="imagetest/46.png"></td>
+          <td><img src="imagetest/47.png"></td>
+          <td><img src="imagetest/48.png"></td>
+          <td><img src="imagetest/49.png"></td>
+        </tr>
+        <tr>
+          <td><img src="imagetest/50.png"></td>
+          <td><img src="imagetest/51.png"></td>
+          <td><img src="imagetest/52.png"></td>
+          <td><img src="imagetest/53.png"></td>
+          <td><img src="imagetest/54.png"></td>
+          <td><img src="imagetest/55.png"></td>
+          <td><img src="imagetest/56.png"></td>
+          <td><img src="imagetest/57.png"></td>
+          <td><img src="imagetest/58.png"></td>
+          <td><img src="imagetest/59.png"></td>
+        </tr>
+        <tr>
+          <td><img src="imagetest/60.png"></td>
+          <td><img src="imagetest/61.png"></td>
+          <td><img src="imagetest/62.png"></td>
+          <td><img src="imagetest/63.png"></td>
+          <td><img src="imagetest/64.png"></td>
+          <td><img src="imagetest/65.png"></td>
+          <td><img src="imagetest/66.png"></td>
+          <td><img src="imagetest/67.png"></td>
+          <td><img src="imagetest/68.png"></td>
+          <td><img src="imagetest/69.png"></td>
+        </tr>
+        <tr>
+          <td><img src="imagetest/70.png"></td>
+          <td><img src="imagetest/71.png"></td>
+          <td><img src="imagetest/72.png"></td>
+          <td><img src="imagetest/73.png"></td>
+          <td><img src="imagetest/74.png"></td>
+          <td><img src="imagetest/75.png"></td>
+          <td><img src="imagetest/76.png"></td>
+          <td><img src="imagetest/77.png"></td>
+          <td><img src="imagetest/78.png"></td>
+          <td><img src="imagetest/79.png"></td>
+        </tr>
+        <tr>
+          <td><img src="imagetest/80.png"></td>
+          <td><img src="imagetest/81.png"></td>
+          <td><img src="imagetest/82.png"></td>
+          <td><img src="imagetest/83.png"></td>
+          <td><img src="imagetest/84.png"></td>
+          <td><img src="imagetest/85.png"></td>
+          <td><img src="imagetest/86.png"></td>
+          <td><img src="imagetest/87.png"></td>
+          <td><img src="imagetest/88.png"></td>
+          <td><img src="imagetest/89.png"></td>
+        </tr>
+        <tr>
+          <td><img src="imagetest/90.png"></td>
+          <td><img src="imagetest/91.png"></td>
+          <td><img src="imagetest/92.png"></td>
+          <td><img src="imagetest/93.png"></td>
+          <td><img src="imagetest/94.png"></td>
+          <td><img src="imagetest/95.png"></td>
+          <td><img src="imagetest/96.png"></td>
+          <td><img src="imagetest/97.png"></td>
+          <td><img src="imagetest/98.png"></td>
+          <td><img src="imagetest/99.png"></td>
+        </tr>
+      </table>
+    </p>
+    <p id="timing">
+      Test case: all images are displayed.
+    </p>
+  </body>
+</html>

+ 8 - 73
test/ajax/echo.cgi

@@ -1,73 +1,8 @@
-#!/usr/bin/lua5.1
-
--- Every CGI script that returns any valid JSON object will work in the test.
--- In case you do not have not yet used CGI, you may want to use this script which is written in Lua.
--- You may download an interpreter from http://luabinaries.sourceforge.net/download.html, extract it
--- to some folder in your search path (the path of the webserver or /usr/bin on Linux), and add the
--- following lines to your .conf file.
--- cgi_interpreter c:\somewhere\lua5.1.exe
--- enable_keep_alive yes
-
-resp = "{";
-
-method = os.getenv("REQUEST_METHOD")
-uri = os.getenv("REQUEST_URI");
-query = os.getenv("QUERY_STRING");
-datalen = os.getenv("CONTENT_LENGTH");
-
-if method then
-  resp = resp .. '"method" : "' .. method .. '", ';
-end
-if uri then
-  resp = resp .. '"uri" : "' .. uri .. '", ';
-end
-if query then
-  resp = resp .. '"query" : "' .. query .. '", ';
-end
-if datalen then
-  resp = resp .. '"datalen" : "' .. datalen .. '", ';
-end
-
-resp = resp .. '"time" : "' .. os.date() .. '" ';
-
-resp = resp .. "}";
-
-
-
-
-print "Status: 200 OK"
-print "Connection: close"
---print "Connection: keep-alive"
-print "Content-Type: text/html; charset=utf-8"
-print "Cache-Control: no-cache"
---print ("Content-Length: " .. resp:len())
-print ""
-
-print (resp)
-
-
-doLogging = false
-
-if (doLogging) then
-  -- Store the POST data to a file
-  if (method == "POST") then
-    myFile = io.open("data" .. query:sub(4) .. ".txt", "wb");
-    myFile:write(resp)
-    myFile:write("\r\n\r\n")  
-    if datalen then
-      datalen = tonumber(datalen)
-      myFile:write("<<< " .. datalen .. " bytes of data >>>\r\n")
-      
-      data = io.stdin:read(datalen)
-      myFile:write(data)
-      
-      myFile:write("\r\n<<< end >>>\r\n")
-    else
-      myFile:write("<<< no data >>>\r\n")
-    end  
-    myFile:close()
-  end
-end
-
-
-
+#!/bin/sh
+
+echo "Content-Type: text/plain; charset=utf-8"
+echo "Connection: close"
+echo "Cache-Control: no-cache"
+echo ""
+
+echo "{}"

+ 73 - 0
test/ajax/echo.cgi.old

@@ -0,0 +1,73 @@
+#!/usr/bin/lua5.1
+
+-- Every CGI script that returns any valid JSON object will work in the test.
+-- In case you do not have not yet used CGI, you may want to use this script which is written in Lua.
+-- You may download an interpreter from http://luabinaries.sourceforge.net/download.html, extract it
+-- to some folder in your search path (the path of the webserver or /usr/bin on Linux), and add the
+-- following lines to your .conf file.
+-- cgi_interpreter c:\somewhere\lua5.1.exe
+-- enable_keep_alive yes
+
+resp = "{";
+
+method = os.getenv("REQUEST_METHOD")
+uri = os.getenv("REQUEST_URI");
+query = os.getenv("QUERY_STRING");
+datalen = os.getenv("CONTENT_LENGTH");
+
+if method then
+  resp = resp .. '"method" : "' .. method .. '", ';
+end
+if uri then
+  resp = resp .. '"uri" : "' .. uri .. '", ';
+end
+if query then
+  resp = resp .. '"query" : "' .. query .. '", ';
+end
+if datalen then
+  resp = resp .. '"datalen" : "' .. datalen .. '", ';
+end
+
+resp = resp .. '"time" : "' .. os.date() .. '" ';
+
+resp = resp .. "}";
+
+
+
+
+print "Status: 200 OK"
+print "Connection: close"
+--print "Connection: keep-alive"
+print "Content-Type: text/html; charset=utf-8"
+print "Cache-Control: no-cache"
+--print ("Content-Length: " .. resp:len())
+print ""
+
+print (resp)
+
+
+doLogging = false
+
+if (doLogging) then
+  -- Store the POST data to a file
+  if (method == "POST") then
+    myFile = io.open("data" .. query:sub(4) .. ".txt", "wb");
+    myFile:write(resp)
+    myFile:write("\r\n\r\n")  
+    if datalen then
+      datalen = tonumber(datalen)
+      myFile:write("<<< " .. datalen .. " bytes of data >>>\r\n")
+      
+      data = io.stdin:read(datalen)
+      myFile:write(data)
+      
+      myFile:write("\r\n<<< end >>>\r\n")
+    else
+      myFile:write("<<< no data >>>\r\n")
+    end  
+    myFile:close()
+  end
+end
+
+
+

+ 2 - 2
test/cors.html

@@ -32,7 +32,7 @@ function getTitle(text) {
 
 
 // Make the actual CORS request.
 // Make the actual CORS request.
 function makeCorsRequest(method, resource) {
 function makeCorsRequest(method, resource) {
-  var url = "http://localhost/cors.reply." + resource;
+  var url = "http://localhost:8080/cors.reply." + resource;
   var xhr = createCORSRequest(method, url);
   var xhr = createCORSRequest(method, url);
   if (!xhr) {
   if (!xhr) {
     alert('ERROR: CORS not supported');
     alert('ERROR: CORS not supported');
@@ -55,7 +55,7 @@ function makeCorsRequest(method, resource) {
 
 
 function start() {
 function start() {
   var el = document.getElementById("from");
   var el = document.getElementById("from");
-  el.innerHTML = "Test CORS from " + document.URL + " to http://localhost/cors.reply.*";
+  el.innerHTML = "Test CORS from " + document.URL + " to http://localhost:8080/cors.reply.*";
   if ((document.URL.indexOf("localhost") >= 0) || (document.URL.indexOf("127.0.0.1") >= 0)) {
   if ((document.URL.indexOf("localhost") >= 0) || (document.URL.indexOf("127.0.0.1") >= 0)) {
     alert("This CORS test is only meaningful, if you open this site with a different url than \'localhost\' (127.0.0.1).\nYou may use a different IP of the same machine.");
     alert("This CORS test is only meaningful, if you open this site with a different url than \'localhost\' (127.0.0.1).\nYou may use a different IP of the same machine.");
   }
   }

+ 0 - 0
test/imagetest/00.PNG → test/imagetest/00.png


+ 0 - 0
test/imagetest/01.PNG → test/imagetest/01.png


+ 0 - 0
test/imagetest/02.PNG → test/imagetest/02.png


+ 0 - 0
test/imagetest/03.PNG → test/imagetest/03.png


+ 0 - 0
test/imagetest/04.PNG → test/imagetest/04.png


+ 0 - 0
test/imagetest/05.PNG → test/imagetest/05.png


+ 0 - 0
test/imagetest/06.PNG → test/imagetest/06.png


+ 0 - 0
test/imagetest/07.PNG → test/imagetest/07.png


+ 0 - 0
test/imagetest/08.PNG → test/imagetest/08.png


+ 0 - 0
test/imagetest/09.PNG → test/imagetest/09.png


+ 0 - 0
test/imagetest/10.PNG → test/imagetest/10.png


+ 0 - 0
test/imagetest/11.PNG → test/imagetest/11.png


+ 0 - 0
test/imagetest/12.PNG → test/imagetest/12.png


+ 0 - 0
test/imagetest/13.PNG → test/imagetest/13.png


+ 0 - 0
test/imagetest/14.PNG → test/imagetest/14.png


+ 0 - 0
test/imagetest/15.PNG → test/imagetest/15.png


+ 0 - 0
test/imagetest/16.PNG → test/imagetest/16.png


+ 0 - 0
test/imagetest/17.PNG → test/imagetest/17.png


+ 0 - 0
test/imagetest/18.PNG → test/imagetest/18.png


+ 0 - 0
test/imagetest/19.PNG → test/imagetest/19.png


+ 0 - 0
test/imagetest/20.PNG → test/imagetest/20.png


+ 0 - 0
test/imagetest/21.PNG → test/imagetest/21.png


+ 0 - 0
test/imagetest/22.PNG → test/imagetest/22.png


+ 0 - 0
test/imagetest/23.PNG → test/imagetest/23.png


+ 0 - 0
test/imagetest/24.PNG → test/imagetest/24.png


+ 0 - 0
test/imagetest/25.PNG → test/imagetest/25.png


+ 0 - 0
test/imagetest/26.PNG → test/imagetest/26.png


+ 0 - 0
test/imagetest/27.PNG → test/imagetest/27.png


+ 0 - 0
test/imagetest/28.PNG → test/imagetest/28.png


+ 0 - 0
test/imagetest/29.PNG → test/imagetest/29.png


+ 0 - 0
test/imagetest/30.PNG → test/imagetest/30.png


+ 0 - 0
test/imagetest/31.PNG → test/imagetest/31.png


+ 0 - 0
test/imagetest/32.PNG → test/imagetest/32.png


+ 0 - 0
test/imagetest/33.PNG → test/imagetest/33.png


+ 0 - 0
test/imagetest/34.PNG → test/imagetest/34.png


+ 0 - 0
test/imagetest/35.PNG → test/imagetest/35.png


+ 0 - 0
test/imagetest/36.PNG → test/imagetest/36.png


+ 0 - 0
test/imagetest/37.PNG → test/imagetest/37.png


+ 0 - 0
test/imagetest/38.PNG → test/imagetest/38.png


+ 0 - 0
test/imagetest/39.PNG → test/imagetest/39.png


+ 0 - 0
test/imagetest/40.PNG → test/imagetest/40.png


+ 0 - 0
test/imagetest/41.PNG → test/imagetest/41.png


+ 0 - 0
test/imagetest/42.PNG → test/imagetest/42.png


+ 0 - 0
test/imagetest/43.PNG → test/imagetest/43.png


+ 0 - 0
test/imagetest/44.PNG → test/imagetest/44.png


+ 0 - 0
test/imagetest/45.PNG → test/imagetest/45.png


+ 0 - 0
test/imagetest/46.PNG → test/imagetest/46.png


+ 0 - 0
test/imagetest/47.PNG → test/imagetest/47.png


+ 0 - 0
test/imagetest/48.PNG → test/imagetest/48.png


+ 0 - 0
test/imagetest/49.PNG → test/imagetest/49.png


+ 0 - 0
test/imagetest/50.PNG → test/imagetest/50.png


+ 0 - 0
test/imagetest/51.PNG → test/imagetest/51.png


+ 0 - 0
test/imagetest/52.PNG → test/imagetest/52.png


+ 0 - 0
test/imagetest/53.PNG → test/imagetest/53.png


+ 0 - 0
test/imagetest/54.PNG → test/imagetest/54.png


+ 0 - 0
test/imagetest/55.PNG → test/imagetest/55.png


+ 0 - 0
test/imagetest/56.PNG → test/imagetest/56.png


+ 0 - 0
test/imagetest/57.PNG → test/imagetest/57.png


+ 0 - 0
test/imagetest/58.PNG → test/imagetest/58.png


+ 0 - 0
test/imagetest/59.PNG → test/imagetest/59.png


+ 0 - 0
test/imagetest/60.PNG → test/imagetest/60.png


+ 0 - 0
test/imagetest/61.PNG → test/imagetest/61.png


+ 0 - 0
test/imagetest/62.PNG → test/imagetest/62.png


+ 0 - 0
test/imagetest/63.PNG → test/imagetest/63.png


+ 0 - 0
test/imagetest/64.PNG → test/imagetest/64.png


+ 0 - 0
test/imagetest/65.PNG → test/imagetest/65.png


+ 0 - 0
test/imagetest/66.PNG → test/imagetest/66.png


+ 0 - 0
test/imagetest/67.PNG → test/imagetest/67.png


+ 0 - 0
test/imagetest/68.PNG → test/imagetest/68.png


+ 0 - 0
test/imagetest/69.PNG → test/imagetest/69.png


+ 0 - 0
test/imagetest/70.PNG → test/imagetest/70.png


+ 0 - 0
test/imagetest/71.PNG → test/imagetest/71.png


+ 0 - 0
test/imagetest/72.PNG → test/imagetest/72.png


+ 0 - 0
test/imagetest/73.PNG → test/imagetest/73.png


+ 0 - 0
test/imagetest/74.PNG → test/imagetest/74.png


+ 0 - 0
test/imagetest/75.PNG → test/imagetest/75.png


+ 0 - 0
test/imagetest/76.PNG → test/imagetest/76.png


+ 0 - 0
test/imagetest/77.PNG → test/imagetest/77.png


+ 0 - 0
test/imagetest/78.PNG → test/imagetest/78.png


+ 0 - 0
test/imagetest/79.PNG → test/imagetest/79.png


+ 0 - 0
test/imagetest/80.PNG → test/imagetest/80.png


+ 0 - 0
test/imagetest/81.PNG → test/imagetest/81.png


+ 0 - 0
test/imagetest/82.PNG → test/imagetest/82.png


+ 0 - 0
test/imagetest/83.PNG → test/imagetest/83.png


+ 0 - 0
test/imagetest/84.PNG → test/imagetest/84.png


+ 0 - 0
test/imagetest/85.PNG → test/imagetest/85.png


이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.