|  | @@ -6727,6 +6727,7 @@ static void mkcol(struct mg_connection *conn, const char *path)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void put_file(struct mg_connection *conn, const char *path)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	struct file file = STRUCT_FILE_INITIALIZER;
 | 
	
	
		
			
				|  | @@ -6861,6 +6862,7 @@ static void put_file(struct mg_connection *conn, const char *path)
 | 
	
		
			
				|  |  |  	mg_fclose(&file);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void delete_file(struct mg_connection *conn, const char *path)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	struct de de;
 | 
	
	
		
			
				|  | @@ -7004,6 +7006,7 @@ static void do_ssi_include(struct mg_connection *conn,
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #if !defined(NO_POPEN)
 | 
	
		
			
				|  |  |  static void do_ssi_exec(struct mg_connection *conn, char *tag)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -7040,6 +7043,7 @@ static int mg_fgetc(struct file *filep, int offset)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void send_ssi_file(struct mg_connection *conn,
 | 
	
		
			
				|  |  |                            const char *path,
 | 
	
		
			
				|  |  |                            struct file *filep,
 | 
	
	
		
			
				|  | @@ -7113,6 +7117,7 @@ static void send_ssi_file(struct mg_connection *conn,
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void handle_ssi_file_request(struct mg_connection *conn,
 | 
	
		
			
				|  |  |                                      const char *path,
 | 
	
		
			
				|  |  |                                      struct file *filep)
 | 
	
	
		
			
				|  | @@ -7188,6 +7193,7 @@ static void send_options(struct mg_connection *conn)
 | 
	
		
			
				|  |  |  	          suggest_connection_header(conn));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /* Writes PROPFIND properties for a collection element */
 | 
	
		
			
				|  |  |  static void
 | 
	
		
			
				|  |  |  print_props(struct mg_connection *conn, const char *uri, struct file *filep)
 | 
	
	
		
			
				|  | @@ -7218,6 +7224,7 @@ print_props(struct mg_connection *conn, const char *uri, struct file *filep)
 | 
	
		
			
				|  |  |  	              mtime);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void print_dav_dir_entry(struct de *de, void *data)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	char href[PATH_MAX];
 | 
	
	
		
			
				|  | @@ -7242,6 +7249,7 @@ static void print_dav_dir_entry(struct de *de, void *data)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void handle_propfind(struct mg_connection *conn,
 | 
	
		
			
				|  |  |                              const char *path,
 | 
	
		
			
				|  |  |                              struct file *filep)
 | 
	
	
		
			
				|  | @@ -7285,6 +7293,7 @@ static void handle_propfind(struct mg_connection *conn,
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void mg_lock_connection(struct mg_connection *conn)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	if (conn) {
 | 
	
	
		
			
				|  | @@ -7292,6 +7301,7 @@ void mg_lock_connection(struct mg_connection *conn)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void mg_unlock_connection(struct mg_connection *conn)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	if (conn) {
 | 
	
	
		
			
				|  | @@ -7299,6 +7309,7 @@ void mg_unlock_connection(struct mg_connection *conn)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void mg_lock_context(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	if (ctx) {
 | 
	
	
		
			
				|  | @@ -7306,6 +7317,7 @@ void mg_lock_context(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void mg_unlock_context(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	if (ctx) {
 | 
	
	
		
			
				|  | @@ -7313,14 +7325,17 @@ void mg_unlock_context(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #if defined(USE_TIMERS)
 | 
	
		
			
				|  |  |  #include "timer.inl"
 | 
	
		
			
				|  |  |  #endif /* USE_TIMERS */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #ifdef USE_LUA
 | 
	
		
			
				|  |  |  #include "mod_lua.inl"
 | 
	
		
			
				|  |  |  #endif /* USE_LUA */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #if defined(USE_WEBSOCKET)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /* START OF SHA-1 code
 | 
	
	
		
			
				|  | @@ -7340,13 +7355,16 @@ static int is_big_endian(void)
 | 
	
		
			
				|  |  |  	return ((char *)&n)[0] == 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  union char64long16 {
 | 
	
		
			
				|  |  |  	unsigned char c[64];
 | 
	
		
			
				|  |  |  	uint32_t l[16];
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static uint32_t blk0(union char64long16 *block, int i)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	/* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */
 | 
	
	
		
			
				|  | @@ -7357,6 +7375,7 @@ static uint32_t blk0(union char64long16 *block, int i)
 | 
	
		
			
				|  |  |  	return block->l[i];
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #define blk(i)                                                                 \
 | 
	
		
			
				|  |  |  	(block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15] ^ \
 | 
	
		
			
				|  |  |  	                            block->l[(i + 2) & 15] ^ block->l[i & 15],     \
 | 
	
	
		
			
				|  | @@ -7377,12 +7396,14 @@ static uint32_t blk0(union char64long16 *block, int i)
 | 
	
		
			
				|  |  |  	z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5);                        \
 | 
	
		
			
				|  |  |  	w = rol(w, 30);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  typedef struct {
 | 
	
		
			
				|  |  |  	uint32_t state[5];
 | 
	
		
			
				|  |  |  	uint32_t count[2];
 | 
	
		
			
				|  |  |  	unsigned char buffer[64];
 | 
	
		
			
				|  |  |  } SHA1_CTX;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	uint32_t a, b, c, d, e;
 | 
	
	
		
			
				|  | @@ -7483,6 +7504,7 @@ static void SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
 | 
	
		
			
				|  |  |  	memset(block, '\0', sizeof(block));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void SHA1Init(SHA1_CTX *context)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	context->state[0] = 0x67452301;
 | 
	
	
		
			
				|  | @@ -7493,6 +7515,7 @@ static void SHA1Init(SHA1_CTX *context)
 | 
	
		
			
				|  |  |  	context->count[0] = context->count[1] = 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void
 | 
	
		
			
				|  |  |  SHA1Update(SHA1_CTX *context, const unsigned char *data, uint32_t len)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -7516,6 +7539,7 @@ SHA1Update(SHA1_CTX *context, const unsigned char *data, uint32_t len)
 | 
	
		
			
				|  |  |  	memcpy(&context->buffer[j], &data[i], len - i);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void SHA1Final(unsigned char digest[20], SHA1_CTX *context)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	unsigned i;
 | 
	
	
		
			
				|  | @@ -7543,6 +7567,7 @@ static void SHA1Final(unsigned char digest[20], SHA1_CTX *context)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  /* END OF SHA1 CODE */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static int send_websocket_handshake(struct mg_connection *conn)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
 | 
	
	
		
			
				|  | @@ -7584,6 +7609,7 @@ static int send_websocket_handshake(struct mg_connection *conn)
 | 
	
		
			
				|  |  |  	return 1;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void read_websocket(struct mg_connection *conn,
 | 
	
		
			
				|  |  |                             mg_websocket_data_handler ws_data_handler,
 | 
	
		
			
				|  |  |                             void *callback_data)
 | 
	
	
		
			
				|  | @@ -7750,6 +7776,7 @@ static void read_websocket(struct mg_connection *conn,
 | 
	
		
			
				|  |  |  	mg_set_thread_name("worker");
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  int mg_websocket_write(struct mg_connection *conn,
 | 
	
		
			
				|  |  |                         int opcode,
 | 
	
		
			
				|  |  |                         const char *data,
 | 
	
	
		
			
				|  | @@ -7793,6 +7820,7 @@ int mg_websocket_write(struct mg_connection *conn,
 | 
	
		
			
				|  |  |  	return retval;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void
 | 
	
		
			
				|  |  |  handle_websocket_request(struct mg_connection *conn,
 | 
	
		
			
				|  |  |                           const char *path,
 | 
	
	
		
			
				|  | @@ -7895,6 +7923,7 @@ handle_websocket_request(struct mg_connection *conn,
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static int is_websocket_protocol(const struct mg_connection *conn)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	const char *host, *upgrade, *connection, *version, *key;
 | 
	
	
		
			
				|  | @@ -7924,8 +7953,10 @@ static int is_websocket_protocol(const struct mg_connection *conn)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  #endif /* !USE_WEBSOCKET */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static int isbyte(int n) { return n >= 0 && n <= 255; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static int parse_net(const char *spec, uint32_t *net, uint32_t *mask)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	int n, a, b, c, d, slash = 32, len = 0;
 | 
	
	
		
			
				|  | @@ -7943,6 +7974,7 @@ static int parse_net(const char *spec, uint32_t *net, uint32_t *mask)
 | 
	
		
			
				|  |  |  	return len;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static int set_throttle(const char *spec, uint32_t remote_ip, const char *uri)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	int throttle = 0;
 | 
	
	
		
			
				|  | @@ -7974,6 +8006,7 @@ static int set_throttle(const char *spec, uint32_t remote_ip, const char *uri)
 | 
	
		
			
				|  |  |  	return throttle;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static uint32_t get_remote_ip(const struct mg_connection *conn)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	if (!conn) {
 | 
	
	
		
			
				|  | @@ -7982,6 +8015,7 @@ static uint32_t get_remote_ip(const struct mg_connection *conn)
 | 
	
		
			
				|  |  |  	return ntohl(*(uint32_t *)&conn->client.rsa.sin.sin_addr);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  int mg_upload(struct mg_connection *conn, const char *destination_dir)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	/* TODO (high): completely rewrite this function. See issue #180. */
 | 
	
	
		
			
				|  | @@ -8162,6 +8196,7 @@ int mg_upload(struct mg_connection *conn, const char *destination_dir)
 | 
	
		
			
				|  |  |  	return num_uploaded_files;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static int get_first_ssl_listener_index(const struct mg_context *ctx)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	unsigned int i;
 | 
	
	
		
			
				|  | @@ -8174,6 +8209,7 @@ static int get_first_ssl_listener_index(const struct mg_context *ctx)
 | 
	
		
			
				|  |  |  	return idx;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void redirect_to_https_port(struct mg_connection *conn, int ssl_index)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	char host[1025];
 | 
	
	
		
			
				|  | @@ -8214,6 +8250,7 @@ static void redirect_to_https_port(struct mg_connection *conn, int ssl_index)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void
 | 
	
		
			
				|  |  |  mg_set_request_handler_type(struct mg_context *ctx,
 | 
	
		
			
				|  |  |                              const char *uri,
 | 
	
	
		
			
				|  | @@ -8331,6 +8368,7 @@ mg_set_request_handler_type(struct mg_context *ctx,
 | 
	
		
			
				|  |  |  	mg_unlock_context(ctx);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void mg_set_request_handler(struct mg_context *ctx,
 | 
	
		
			
				|  |  |                              const char *uri,
 | 
	
		
			
				|  |  |                              mg_request_handler handler,
 | 
	
	
		
			
				|  | @@ -8340,6 +8378,7 @@ void mg_set_request_handler(struct mg_context *ctx,
 | 
	
		
			
				|  |  |  	    ctx, uri, 0, handler == NULL, handler, NULL, NULL, NULL, NULL, cbdata);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void mg_set_websocket_handler(struct mg_context *ctx,
 | 
	
		
			
				|  |  |                                const char *uri,
 | 
	
		
			
				|  |  |                                mg_websocket_connect_handler connect_handler,
 | 
	
	
		
			
				|  | @@ -8363,6 +8402,7 @@ void mg_set_websocket_handler(struct mg_context *ctx,
 | 
	
		
			
				|  |  |  	                            cbdata);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static int get_request_handler(struct mg_connection *conn,
 | 
	
		
			
				|  |  |                                 int is_websocket_request,
 | 
	
		
			
				|  |  |                                 mg_request_handler *handler,
 | 
	
	
		
			
				|  | @@ -8450,6 +8490,7 @@ static int get_request_handler(struct mg_connection *conn,
 | 
	
		
			
				|  |  |  	return 0; /* none found */
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #if defined(USE_WEBSOCKET) && defined(MG_LEGACY_INTERFACE)
 | 
	
		
			
				|  |  |  static int
 | 
	
		
			
				|  |  |  deprecated_websocket_connect_wrapper(const struct mg_connection *conn,
 | 
	
	
		
			
				|  | @@ -8463,6 +8504,7 @@ deprecated_websocket_connect_wrapper(const struct mg_connection *conn,
 | 
	
		
			
				|  |  |  	return 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void deprecated_websocket_ready_wrapper(struct mg_connection *conn,
 | 
	
		
			
				|  |  |                                                 void *cbdata)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -8472,6 +8514,7 @@ static void deprecated_websocket_ready_wrapper(struct mg_connection *conn,
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static int deprecated_websocket_data_wrapper(
 | 
	
		
			
				|  |  |      struct mg_connection *conn, int bits, char *data, size_t len, void *cbdata)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -8484,6 +8527,7 @@ static int deprecated_websocket_data_wrapper(
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /* This is the heart of the Civetweb's logic.
 | 
	
		
			
				|  |  |   * This function is called when the request is read, parsed and validated,
 | 
	
		
			
				|  |  |   * and Civetweb must decide what action to take: serve a file, or
 | 
	
	
		
			
				|  | @@ -8902,6 +8946,7 @@ static void handle_file_based_request(struct mg_connection *conn,
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void close_all_listening_sockets(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	unsigned int i;
 | 
	
	
		
			
				|  | @@ -8975,6 +9020,7 @@ static int parse_port_string(const struct vec *vec, struct socket *so)
 | 
	
		
			
				|  |  |  	       (ch == '\0' || ch == 's' || ch == 'r' || ch == ',');
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static int set_ports_option(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	const char *list;
 | 
	
	
		
			
				|  | @@ -9186,6 +9232,7 @@ static int set_ports_option(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  	return portsOk;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static const char *header_val(const struct mg_connection *conn,
 | 
	
		
			
				|  |  |                                const char *header)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -9198,6 +9245,7 @@ static const char *header_val(const struct mg_connection *conn,
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void log_access(const struct mg_connection *conn)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	const struct mg_request_info *ri;
 | 
	
	
		
			
				|  | @@ -9266,6 +9314,7 @@ static void log_access(const struct mg_connection *conn)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /* Verify given socket address against the ACL.
 | 
	
		
			
				|  |  |   * Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed. */
 | 
	
		
			
				|  |  |  static int check_acl(struct mg_context *ctx, uint32_t remote_ip)
 | 
	
	
		
			
				|  | @@ -9299,6 +9348,7 @@ static int check_acl(struct mg_context *ctx, uint32_t remote_ip)
 | 
	
		
			
				|  |  |  	return -1;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #if !defined(_WIN32)
 | 
	
		
			
				|  |  |  static int set_uid_option(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -9338,6 +9388,7 @@ static int set_uid_option(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  #endif /* !_WIN32 */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #if !defined(NO_SSL)
 | 
	
		
			
				|  |  |  static pthread_mutex_t *ssl_mutexes;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -9352,6 +9403,7 @@ static int sslize(struct mg_connection *conn, SSL_CTX *s, int (*func)(SSL *))
 | 
	
		
			
				|  |  |  	       func(conn->ssl) == 1;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /* Return OpenSSL error message (from CRYPTO lib) */
 | 
	
		
			
				|  |  |  static const char *ssl_error(void)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -9360,6 +9412,7 @@ static const char *ssl_error(void)
 | 
	
		
			
				|  |  |  	return err == 0 ? "" : ERR_error_string(err, NULL);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void
 | 
	
		
			
				|  |  |  ssl_locking_callback(int mode, int mutex_num, const char *file, int line)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -9374,11 +9427,13 @@ ssl_locking_callback(int mode, int mutex_num, const char *file, int line)
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static unsigned long ssl_id_callback(void)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	return (unsigned long)pthread_self();
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #if !defined(NO_SSL_DL)
 | 
	
		
			
				|  |  |  static void *
 | 
	
		
			
				|  |  |  load_dll(struct mg_context *ctx, const char *dll_name, struct ssl_func *sw)
 | 
	
	
		
			
				|  | @@ -9426,12 +9481,14 @@ static void *cryptolib_dll_handle; /* Store the crypto library handle. */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #endif /* NO_SSL_DL */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #if defined(SSL_ALREADY_INITIALIZED)
 | 
	
		
			
				|  |  |  static int cryptolib_users = 1; /* Reference counter for crypto library. */
 | 
	
		
			
				|  |  |  #else
 | 
	
		
			
				|  |  |  static int cryptolib_users = 0; /* Reference counter for crypto library. */
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static int initialize_ssl(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	int i;
 | 
	
	
		
			
				|  | @@ -9474,6 +9531,7 @@ static int initialize_ssl(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  	return 1;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /* Dynamically load SSL library. Set up ctx->ssl_ctx pointer. */
 | 
	
		
			
				|  |  |  static int set_ssl_option(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -9546,6 +9604,7 @@ static int set_ssl_option(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  	return 1;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void uninitialize_ssl(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	int i;
 | 
	
	
		
			
				|  | @@ -9562,6 +9621,7 @@ static void uninitialize_ssl(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  #endif /* !NO_SSL */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static int set_gpass_option(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	if (ctx) {
 | 
	
	
		
			
				|  | @@ -9576,11 +9636,13 @@ static int set_gpass_option(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  	return 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static int set_acl_option(struct mg_context *ctx)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	return check_acl(ctx, (uint32_t)0x7f000001UL) != -1;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void reset_per_request_attributes(struct mg_connection *conn)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	if (!conn) {
 | 
	
	
		
			
				|  | @@ -9603,6 +9665,7 @@ static void reset_per_request_attributes(struct mg_connection *conn)
 | 
	
		
			
				|  |  |  	conn->internal_error = 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static int set_sock_timeout(SOCKET sock, int milliseconds)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	int r1, r2;
 | 
	
	
		
			
				|  | @@ -9637,6 +9700,7 @@ static int set_sock_timeout(SOCKET sock, int milliseconds)
 | 
	
		
			
				|  |  |  	return r1 || r2;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void close_socket_gracefully(struct mg_connection *conn)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  #if defined(_WIN32)
 | 
	
	
		
			
				|  | @@ -9686,6 +9750,7 @@ static void close_socket_gracefully(struct mg_connection *conn)
 | 
	
		
			
				|  |  |  	conn->client.sock = INVALID_SOCKET;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void close_connection(struct mg_connection *conn)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	if (!conn || !conn->ctx) {
 | 
	
	
		
			
				|  | @@ -9725,6 +9790,7 @@ static void close_connection(struct mg_connection *conn)
 | 
	
		
			
				|  |  |  	mg_unlock_connection(conn);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void mg_close_connection(struct mg_connection *conn)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	struct mg_context *client_ctx = NULL;
 | 
	
	
		
			
				|  | @@ -9760,6 +9826,7 @@ void mg_close_connection(struct mg_connection *conn)
 | 
	
		
			
				|  |  |  	mg_free(conn);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  struct mg_connection *mg_connect_client(
 | 
	
		
			
				|  |  |      const char *host, int port, int use_ssl, char *ebuf, size_t ebuf_len)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -9839,15 +9906,15 @@ struct mg_connection *mg_connect_client(
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -struct {
 | 
	
		
			
				|  |  | +static const struct {
 | 
	
		
			
				|  |  |  	const char *proto;
 | 
	
		
			
				|  |  |  	size_t proto_len;
 | 
	
		
			
				|  |  | -	int default_port;
 | 
	
		
			
				|  |  | -} static abs_uri_protocols[] = {{"http://", 7, 80},
 | 
	
		
			
				|  |  | -                                {"https://", 8, 443},
 | 
	
		
			
				|  |  | -                                {"ws://", 5, 80},
 | 
	
		
			
				|  |  | -                                {"wss://", 6, 443},
 | 
	
		
			
				|  |  | -                                {NULL, 0, 0}};
 | 
	
		
			
				|  |  | +	unsigned default_port;
 | 
	
		
			
				|  |  | +} abs_uri_protocols[] = {{"http://", 7, 80},
 | 
	
		
			
				|  |  | +                         {"https://", 8, 443},
 | 
	
		
			
				|  |  | +                         {"ws://", 5, 80},
 | 
	
		
			
				|  |  | +                         {"wss://", 6, 443},
 | 
	
		
			
				|  |  | +                         {NULL, 0, 0}};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /* Check if the uri is valid.
 | 
	
	
		
			
				|  | @@ -9945,7 +10012,7 @@ get_rel_url_at_current_server(const char *uri, const struct mg_connection *conn)
 | 
	
		
			
				|  |  |  				}
 | 
	
		
			
				|  |  |  			}
 | 
	
		
			
				|  |  |  			/* protocol found, port set */
 | 
	
		
			
				|  |  | -            break;
 | 
	
		
			
				|  |  | +			break;
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 |