|  | @@ -18917,22 +18917,30 @@ mg_check_feature(unsigned feature)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/* strcat with additional NULL check to avoid clang scan-build warning. */
 | 
	
		
			
				|  |  | -#define strcat0(a, b)                                                          \
 | 
	
		
			
				|  |  | -	{                                                                          \
 | 
	
		
			
				|  |  | -		if ((a != NULL) && (b != NULL)) {                                      \
 | 
	
		
			
				|  |  | -			strcat(a, b);                                                      \
 | 
	
		
			
				|  |  | -		}                                                                      \
 | 
	
		
			
				|  |  | +static size_t
 | 
	
		
			
				|  |  | +mg_str_append(char **dst, char *end, const char *src)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	size_t len = strlen(src);
 | 
	
		
			
				|  |  | +	if (*dst != end) {
 | 
	
		
			
				|  |  | +		/* Append src if enough space, or close dst. */
 | 
	
		
			
				|  |  | +		if ((size_t)(end - *dst) > len) {
 | 
	
		
			
				|  |  | +			strcpy(*dst, src);
 | 
	
		
			
				|  |  | +			*dst += len;
 | 
	
		
			
				|  |  | +		} else {
 | 
	
		
			
				|  |  | +			*dst = end;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | +	return len;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /* Get system information. It can be printed or stored by the caller.
 | 
	
		
			
				|  |  |   * Return the size of available information. */
 | 
	
		
			
				|  |  | -static int
 | 
	
		
			
				|  |  | -mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  | +int
 | 
	
		
			
				|  |  | +mg_get_system_info(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -	char block[256];
 | 
	
		
			
				|  |  | -	int system_info_length = 0;
 | 
	
		
			
				|  |  | +	char *end, block[256];
 | 
	
		
			
				|  |  | +	size_t system_info_length = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #if defined(_WIN32)
 | 
	
		
			
				|  |  |  	const char *eol = "\r\n";
 | 
	
	
		
			
				|  | @@ -18940,20 +18948,15 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  	const char *eol = "\n";
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	const char *eoobj = "}";
 | 
	
		
			
				|  |  | -	int reserved_len = (int)strlen(eoobj) + (int)strlen(eol);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  	if ((buffer == NULL) || (buflen < 1)) {
 | 
	
		
			
				|  |  |  		buflen = 0;
 | 
	
		
			
				|  |  |  	} else {
 | 
	
		
			
				|  |  |  		*buffer = 0;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | +	end = buffer + buflen;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	mg_snprintf(NULL, NULL, block, sizeof(block), "{%s", eol);
 | 
	
		
			
				|  |  | -	system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -	if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -		strcat0(buffer, block);
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | +	system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/* Server version */
 | 
	
		
			
				|  |  |  	{
 | 
	
	
		
			
				|  | @@ -18965,10 +18968,7 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            "\"version\" : \"%s\",%s",
 | 
	
		
			
				|  |  |  		            version,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/* System info */
 | 
	
	
		
			
				|  | @@ -19002,10 +19002,7 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            (unsigned)dwMajorVersion,
 | 
	
		
			
				|  |  |  		            (unsigned)dwMinorVersion,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		mg_snprintf(NULL,
 | 
	
		
			
				|  |  |  		            NULL,
 | 
	
	
		
			
				|  | @@ -19016,10 +19013,7 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            (unsigned)si.dwNumberOfProcessors,
 | 
	
		
			
				|  |  |  		            (unsigned)si.dwActiveProcessorMask,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  #else
 | 
	
		
			
				|  |  |  		struct utsname name;
 | 
	
		
			
				|  |  |  		memset(&name, 0, sizeof(name));
 | 
	
	
		
			
				|  | @@ -19035,10 +19029,7 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            name.release,
 | 
	
		
			
				|  |  |  		            name.machine,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -19063,10 +19054,7 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            mg_check_feature(MG_FEATURES_CACHE) ? " Cache" : "",
 | 
	
		
			
				|  |  |  		            mg_check_feature(MG_FEATURES_STATS) ? " Stats" : "",
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #if defined(USE_LUA)
 | 
	
		
			
				|  |  |  		mg_snprintf(NULL,
 | 
	
	
		
			
				|  | @@ -19077,10 +19065,7 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            (unsigned)LUA_VERSION_NUM,
 | 
	
		
			
				|  |  |  		            LUA_RELEASE,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  #if defined(USE_DUKTAPE)
 | 
	
		
			
				|  |  |  		mg_snprintf(NULL,
 | 
	
	
		
			
				|  | @@ -19092,10 +19077,7 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            ((unsigned)DUK_VERSION / 100) % 100,
 | 
	
		
			
				|  |  |  		            (unsigned)DUK_VERSION % 100,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -19122,10 +19104,7 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -19141,10 +19120,7 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            (unsigned)_MSC_VER,
 | 
	
		
			
				|  |  |  		            (unsigned)_MSC_FULL_VER,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  #elif defined(__MINGW64__)
 | 
	
		
			
				|  |  |  		mg_snprintf(NULL,
 | 
	
		
			
				|  |  |  		            NULL,
 | 
	
	
		
			
				|  | @@ -19154,10 +19130,7 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            (unsigned)__MINGW64_VERSION_MAJOR,
 | 
	
		
			
				|  |  |  		            (unsigned)__MINGW64_VERSION_MINOR,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  		mg_snprintf(NULL,
 | 
	
		
			
				|  |  |  		            NULL,
 | 
	
		
			
				|  |  |  		            block,
 | 
	
	
		
			
				|  | @@ -19166,10 +19139,7 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            (unsigned)__MINGW32_MAJOR_VERSION,
 | 
	
		
			
				|  |  |  		            (unsigned)__MINGW32_MINOR_VERSION,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  #elif defined(__MINGW32__)
 | 
	
		
			
				|  |  |  		mg_snprintf(NULL,
 | 
	
		
			
				|  |  |  		            NULL,
 | 
	
	
		
			
				|  | @@ -19179,10 +19149,7 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            (unsigned)__MINGW32_MAJOR_VERSION,
 | 
	
		
			
				|  |  |  		            (unsigned)__MINGW32_MINOR_VERSION,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  #elif defined(__clang__)
 | 
	
		
			
				|  |  |  		mg_snprintf(NULL,
 | 
	
		
			
				|  |  |  		            NULL,
 | 
	
	
		
			
				|  | @@ -19194,10 +19161,7 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            __clang_patchlevel__,
 | 
	
		
			
				|  |  |  		            __clang_version__,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  #elif defined(__GNUC__)
 | 
	
		
			
				|  |  |  		mg_snprintf(NULL,
 | 
	
		
			
				|  |  |  		            NULL,
 | 
	
	
		
			
				|  | @@ -19208,10 +19172,7 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            (unsigned)__GNUC_MINOR__,
 | 
	
		
			
				|  |  |  		            (unsigned)__GNUC_PATCHLEVEL__,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  #elif defined(__INTEL_COMPILER)
 | 
	
		
			
				|  |  |  		mg_snprintf(NULL,
 | 
	
		
			
				|  |  |  		            NULL,
 | 
	
	
		
			
				|  | @@ -19220,10 +19181,7 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            "\"compiler\" : \"Intel C/C++: %u\",%s",
 | 
	
		
			
				|  |  |  		            (unsigned)__INTEL_COMPILER,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  #elif defined(__BORLANDC__)
 | 
	
		
			
				|  |  |  		mg_snprintf(NULL,
 | 
	
		
			
				|  |  |  		            NULL,
 | 
	
	
		
			
				|  | @@ -19232,10 +19190,7 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            "\"compiler\" : \"Borland C: 0x%x\",%s",
 | 
	
		
			
				|  |  |  		            (unsigned)__BORLANDC__,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  #elif defined(__SUNPRO_C)
 | 
	
		
			
				|  |  |  		mg_snprintf(NULL,
 | 
	
		
			
				|  |  |  		            NULL,
 | 
	
	
		
			
				|  | @@ -19244,10 +19199,7 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            "\"compiler\" : \"Solaris: 0x%x\",%s",
 | 
	
		
			
				|  |  |  		            (unsigned)__SUNPRO_C,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  #else
 | 
	
		
			
				|  |  |  		mg_snprintf(NULL,
 | 
	
		
			
				|  |  |  		            NULL,
 | 
	
	
		
			
				|  | @@ -19255,10 +19207,7 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            sizeof(block),
 | 
	
		
			
				|  |  |  		            "\"compiler\" : \"other\",%s",
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -19285,34 +19234,25 @@ mg_get_system_info_impl(char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            (unsigned)sizeof(size_t),
 | 
	
		
			
				|  |  |  		            (unsigned)sizeof(time_t),
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  | -		system_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/* Terminate string */
 | 
	
		
			
				|  |  | -	if ((buflen > 0) && buffer && buffer[0]) {
 | 
	
		
			
				|  |  | -		if (system_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, eoobj);
 | 
	
		
			
				|  |  | -			strcat0(buffer, eol);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	system_info_length += reserved_len;
 | 
	
		
			
				|  |  | +	mg_snprintf(NULL, NULL, block, sizeof(block), "}%s", eol);
 | 
	
		
			
				|  |  | +	system_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	return system_info_length;
 | 
	
		
			
				|  |  | +	return (int)system_info_length;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#if defined(USE_SERVER_STATS)
 | 
	
		
			
				|  |  |  /* Get context information. It can be printed or stored by the caller.
 | 
	
		
			
				|  |  |   * Return the size of available information. */
 | 
	
		
			
				|  |  | -static int
 | 
	
		
			
				|  |  | -mg_get_context_info_impl(const struct mg_context *ctx, char *buffer, int buflen)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +int
 | 
	
		
			
				|  |  | +mg_get_context_info(const struct mg_context *ctx, char *buffer, int buflen)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -	char block[256];
 | 
	
		
			
				|  |  | -	int context_info_length = 0;
 | 
	
		
			
				|  |  | +#if defined(USE_SERVER_STATS)
 | 
	
		
			
				|  |  | +	char *end, block[256];
 | 
	
		
			
				|  |  | +	size_t context_info_length = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #if defined(_WIN32)
 | 
	
		
			
				|  |  |  	const char *eol = "\r\n";
 | 
	
	
		
			
				|  | @@ -19321,20 +19261,15 @@ mg_get_context_info_impl(const struct mg_context *ctx, char *buffer, int buflen)
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  	struct mg_memory_stat *ms = get_memory_stat((struct mg_context *)ctx);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	const char *eoobj = "}";
 | 
	
		
			
				|  |  | -	int reserved_len = (int)strlen(eoobj) + (int)strlen(eol);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  	if ((buffer == NULL) || (buflen < 1)) {
 | 
	
		
			
				|  |  |  		buflen = 0;
 | 
	
		
			
				|  |  |  	} else {
 | 
	
		
			
				|  |  |  		*buffer = 0;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | +	end = buffer + buflen;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	mg_snprintf(NULL, NULL, block, sizeof(block), "{%s", eol);
 | 
	
		
			
				|  |  | -	context_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -	if (context_info_length < buflen) {
 | 
	
		
			
				|  |  | -		strcat0(buffer, block);
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | +	context_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if (ms) { /* <-- should be always true */
 | 
	
		
			
				|  |  |  		/* Memory information */
 | 
	
	
		
			
				|  | @@ -19357,10 +19292,7 @@ mg_get_context_info_impl(const struct mg_context *ctx, char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            (ctx ? "," : ""),
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		context_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (context_info_length + reserved_len < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		context_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if (ctx) {
 | 
	
	
		
			
				|  | @@ -19390,10 +19322,7 @@ mg_get_context_info_impl(const struct mg_context *ctx, char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            eol,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		context_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (context_info_length + reserved_len < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		context_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		/* Requests information */
 | 
	
		
			
				|  |  |  		mg_snprintf(NULL,
 | 
	
	
		
			
				|  | @@ -19408,10 +19337,7 @@ mg_get_context_info_impl(const struct mg_context *ctx, char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            eol,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		context_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (context_info_length + reserved_len < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		context_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		/* Data information */
 | 
	
		
			
				|  |  |  		mg_snprintf(NULL,
 | 
	
	
		
			
				|  | @@ -19429,10 +19355,7 @@ mg_get_context_info_impl(const struct mg_context *ctx, char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            eol,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		context_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (context_info_length + reserved_len < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		context_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		/* Execution time information */
 | 
	
		
			
				|  |  |  		gmt_time_string(start_time_str,
 | 
	
	
		
			
				|  | @@ -19458,39 +19381,37 @@ mg_get_context_info_impl(const struct mg_context *ctx, char *buffer, int buflen)
 | 
	
		
			
				|  |  |  		            eol,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		context_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (context_info_length + reserved_len < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		context_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/* Terminate string */
 | 
	
		
			
				|  |  | -	if ((buflen > 0) && buffer && buffer[0]) {
 | 
	
		
			
				|  |  | -		if (context_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, eoobj);
 | 
	
		
			
				|  |  | -			strcat0(buffer, eol);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	context_info_length += reserved_len;
 | 
	
		
			
				|  |  | +	mg_snprintf(NULL, NULL, block, sizeof(block), "}%s", eol);
 | 
	
		
			
				|  |  | +	context_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	return context_info_length;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | +	return (int)context_info_length;
 | 
	
		
			
				|  |  | +#else
 | 
	
		
			
				|  |  | +	(void)ctx;
 | 
	
		
			
				|  |  | +	if ((buffer != NULL) && (buflen > 0)) {
 | 
	
		
			
				|  |  | +		*buffer = 0;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #if defined(MG_EXPERIMENTAL_INTERFACES)
 | 
	
		
			
				|  |  |  /* Get connection information. It can be printed or stored by the caller.
 | 
	
		
			
				|  |  |   * Return the size of available information. */
 | 
	
		
			
				|  |  | -static int
 | 
	
		
			
				|  |  | -mg_get_connection_info_impl(const struct mg_context *ctx,
 | 
	
		
			
				|  |  | -                            int idx,
 | 
	
		
			
				|  |  | -                            char *buffer,
 | 
	
		
			
				|  |  | -                            int buflen)
 | 
	
		
			
				|  |  | +int
 | 
	
		
			
				|  |  | +mg_get_connection_info(const struct mg_context *ctx,
 | 
	
		
			
				|  |  | +                       int idx,
 | 
	
		
			
				|  |  | +                       char *buffer,
 | 
	
		
			
				|  |  | +                       int buflen)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	const struct mg_connection *conn;
 | 
	
		
			
				|  |  |  	const struct mg_request_info *ri;
 | 
	
		
			
				|  |  | -	char block[256];
 | 
	
		
			
				|  |  | -	int connection_info_length = 0;
 | 
	
		
			
				|  |  | +	char *end, block[256];
 | 
	
		
			
				|  |  | +	size_t connection_info_length = 0;
 | 
	
		
			
				|  |  |  	int state = 0;
 | 
	
		
			
				|  |  |  	const char *state_str = "unknown";
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -19500,14 +19421,12 @@ mg_get_connection_info_impl(const struct mg_context *ctx,
 | 
	
		
			
				|  |  |  	const char *eol = "\n";
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	const char *eoobj = "}";
 | 
	
		
			
				|  |  | -	int reserved_len = (int)strlen(eoobj) + (int)strlen(eol);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  	if ((buffer == NULL) || (buflen < 1)) {
 | 
	
		
			
				|  |  |  		buflen = 0;
 | 
	
		
			
				|  |  |  	} else {
 | 
	
		
			
				|  |  |  		*buffer = 0;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | +	end = buffer + buflen;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	if ((ctx == NULL) || (idx < 0)) {
 | 
	
		
			
				|  |  |  		/* Parameter error */
 | 
	
	
		
			
				|  | @@ -19525,10 +19444,7 @@ mg_get_connection_info_impl(const struct mg_context *ctx,
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/* Initialize output string */
 | 
	
		
			
				|  |  |  	mg_snprintf(NULL, NULL, block, sizeof(block), "{%s", eol);
 | 
	
		
			
				|  |  | -	connection_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -	if (connection_info_length < buflen) {
 | 
	
		
			
				|  |  | -		strcat0(buffer, block);
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | +	connection_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/* Init variables */
 | 
	
		
			
				|  |  |  	ri = &(conn->request_info);
 | 
	
	
		
			
				|  | @@ -19598,10 +19514,7 @@ mg_get_connection_info_impl(const struct mg_context *ctx,
 | 
	
		
			
				|  |  |  		            eol,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		connection_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (connection_info_length + reserved_len < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		connection_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/* Request info */
 | 
	
	
		
			
				|  | @@ -19626,10 +19539,7 @@ mg_get_connection_info_impl(const struct mg_context *ctx,
 | 
	
		
			
				|  |  |  		            eol,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		connection_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (connection_info_length + reserved_len < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		connection_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/* Execution time information */
 | 
	
	
		
			
				|  | @@ -19662,10 +19572,7 @@ mg_get_connection_info_impl(const struct mg_context *ctx,
 | 
	
		
			
				|  |  |  		            eol,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		connection_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (connection_info_length + reserved_len < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		connection_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/* Remote user name */
 | 
	
	
		
			
				|  | @@ -19682,10 +19589,7 @@ mg_get_connection_info_impl(const struct mg_context *ctx,
 | 
	
		
			
				|  |  |  		            eol,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		connection_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (connection_info_length + reserved_len < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		connection_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/* Data block */
 | 
	
	
		
			
				|  | @@ -19705,10 +19609,7 @@ mg_get_connection_info_impl(const struct mg_context *ctx,
 | 
	
		
			
				|  |  |  		            eol,
 | 
	
		
			
				|  |  |  		            eol);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -		connection_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -		if (connection_info_length + reserved_len < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, block);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | +		connection_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/* State */
 | 
	
	
		
			
				|  | @@ -19720,77 +19621,13 @@ mg_get_connection_info_impl(const struct mg_context *ctx,
 | 
	
		
			
				|  |  |  	            state_str,
 | 
	
		
			
				|  |  |  	            eol);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	connection_info_length += (int)strlen(block);
 | 
	
		
			
				|  |  | -	if (connection_info_length + reserved_len < buflen) {
 | 
	
		
			
				|  |  | -		strcat0(buffer, block);
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | +	connection_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	/* Terminate string */
 | 
	
		
			
				|  |  | -	if ((buflen > 0) && buffer && buffer[0]) {
 | 
	
		
			
				|  |  | -		if (connection_info_length < buflen) {
 | 
	
		
			
				|  |  | -			strcat0(buffer, eoobj);
 | 
	
		
			
				|  |  | -			strcat0(buffer, eol);
 | 
	
		
			
				|  |  | -		}
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	connection_info_length += reserved_len;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	return connection_info_length;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/* Get system information. It can be printed or stored by the caller.
 | 
	
		
			
				|  |  | - * Return the size of available information. */
 | 
	
		
			
				|  |  | -int
 | 
	
		
			
				|  |  | -mg_get_system_info(char *buffer, int buflen)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -	if ((buffer == NULL) || (buflen < 1)) {
 | 
	
		
			
				|  |  | -		return mg_get_system_info_impl(NULL, 0);
 | 
	
		
			
				|  |  | -	} else {
 | 
	
		
			
				|  |  | -		/* Reset buffer, so we can always use strcat. */
 | 
	
		
			
				|  |  | -		buffer[0] = 0;
 | 
	
		
			
				|  |  | -		return mg_get_system_info_impl(buffer, buflen);
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +	mg_snprintf(NULL, NULL, block, sizeof(block), "}%s", eol);
 | 
	
		
			
				|  |  | +	connection_info_length += mg_str_append(&buffer, end, block);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/* Get context information. It can be printed or stored by the caller.
 | 
	
		
			
				|  |  | - * Return the size of available information. */
 | 
	
		
			
				|  |  | -int
 | 
	
		
			
				|  |  | -mg_get_context_info(const struct mg_context *ctx, char *buffer, int buflen)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -#if defined(USE_SERVER_STATS)
 | 
	
		
			
				|  |  | -	if ((buffer == NULL) || (buflen < 1)) {
 | 
	
		
			
				|  |  | -		return mg_get_context_info_impl(ctx, NULL, 0);
 | 
	
		
			
				|  |  | -	} else {
 | 
	
		
			
				|  |  | -		/* Reset buffer, so we can always use strcat. */
 | 
	
		
			
				|  |  | -		buffer[0] = 0;
 | 
	
		
			
				|  |  | -		return mg_get_context_info_impl(ctx, buffer, buflen);
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -#else
 | 
	
		
			
				|  |  | -	(void)ctx;
 | 
	
		
			
				|  |  | -	if ((buffer != NULL) && (buflen > 0)) {
 | 
	
		
			
				|  |  | -		buffer[0] = 0;
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	return 0;
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#if defined(MG_EXPERIMENTAL_INTERFACES)
 | 
	
		
			
				|  |  | -int
 | 
	
		
			
				|  |  | -mg_get_connection_info(const struct mg_context *ctx,
 | 
	
		
			
				|  |  | -                       int idx,
 | 
	
		
			
				|  |  | -                       char *buffer,
 | 
	
		
			
				|  |  | -                       int buflen)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -	if ((buffer == NULL) || (buflen < 1)) {
 | 
	
		
			
				|  |  | -		return mg_get_connection_info_impl(ctx, idx, NULL, 0);
 | 
	
		
			
				|  |  | -	} else {
 | 
	
		
			
				|  |  | -		/* Reset buffer, so we can always use strcat. */
 | 
	
		
			
				|  |  | -		buffer[0] = 0;
 | 
	
		
			
				|  |  | -		return mg_get_connection_info_impl(ctx, idx, buffer, buflen);
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | +	return (int)connection_info_length;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 |