diff --git a/client/SDL/common/sdl_prefs.cpp b/client/SDL/common/sdl_prefs.cpp index a08ddc6bb..30cbf3059 100644 --- a/client/SDL/common/sdl_prefs.cpp +++ b/client/SDL/common/sdl_prefs.cpp @@ -41,10 +41,7 @@ namespace fs = std::experimental::filesystem; SdlPref::WINPR_JSONPtr SdlPref::get() { auto config = get_pref_file(); - - std::ifstream ifs(config); - std::string content((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); - return { WINPR_JSON_ParseWithLength(content.c_str(), content.size()), WINPR_JSON_Delete }; + return { WINPR_JSON_ParseFromFile(config.c_str()), WINPR_JSON_Delete }; } WINPR_JSON* SdlPref::get_item(const std::string& key) diff --git a/include/freerdp/utils/helpers.h b/include/freerdp/utils/helpers.h index 5f5b8d2f7..68d9898fd 100644 --- a/include/freerdp/utils/helpers.h +++ b/include/freerdp/utils/helpers.h @@ -21,6 +21,8 @@ #pragma once #include +#include + #include /** @brief Return the absolute path of a configuration file (the path of the configuration @@ -38,3 +40,15 @@ */ WINPR_ATTR_MALLOC(free, 1) FREERDP_API char* freerdp_GetConfigFilePath(BOOL system, const char* filename); + +/** @brief return a parsed JSON for a given config file name. + * + * @param system a boolean indicating the configuration base, \b TRUE for system configuration, + * \b FALSE for user configuration + * @param filename an optional configuration file name to append. + * + * @return A parsed \b WINPR_JSON object or \b NULL in case of any failure. + * @since version 3.16.0 + */ +WINPR_ATTR_MALLOC(WINPR_JSON_Delete, 1) +FREERDP_API WINPR_JSON* freerdp_GetJSONConfigFile(BOOL system, const char* filename); diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c index 22551437d..965dcc794 100644 --- a/libfreerdp/crypto/tls.c +++ b/libfreerdp/crypto/tls.c @@ -1498,42 +1498,6 @@ static int tls_config_parse_bool(WINPR_JSON* json, const char* opt) return 0; } -static char* tls_config_read(const char* configfile) -{ - char* data = NULL; - FILE* fp = winpr_fopen(configfile, "r"); - if (!fp) - return NULL; - - const int rc = fseek(fp, 0, SEEK_END); - if (rc != 0) - goto fail; - - const INT64 size = _ftelli64(fp); - if (size <= 0) - goto fail; - - const int rc2 = fseek(fp, 0, SEEK_SET); - if (rc2 != 0) - goto fail; - - data = calloc((size_t)size + 1, sizeof(char)); - if (!data) - goto fail; - - const size_t read = fread(data, 1, (size_t)size, fp); - if (read != (size_t)size) - { - free(data); - data = NULL; - goto fail; - } - -fail: - fclose(fp); - return data; -} - static int tls_config_check_allowed_hashed(const char* configfile, const rdpCertificate* cert, WINPR_JSON* json) { @@ -1604,26 +1568,12 @@ static int tls_config_check_certificate(const rdpCertificate* cert, BOOL* pAllow WINPR_ASSERT(pAllowUserconfig); int rc = 0; - char* configfile = freerdp_GetConfigFilePath(TRUE, "certificates.json"); - WINPR_JSON* json = NULL; + const char configfile[] = "certificates.json"; + WINPR_JSON* json = freerdp_GetJSONConfigFile(TRUE, configfile); - if (!configfile) - { - WLog_DBG(TAG, "No configuration file for certificate handling, asking user"); - goto fail; - } - - char* configdata = tls_config_read(configfile); - if (!configdata) - { - WLog_DBG(TAG, "Configuration file for certificate handling, asking user"); - goto fail; - } - json = WINPR_JSON_Parse(configdata); if (!json) { - WLog_DBG(TAG, "No valid configuration file '%s' for certificate handling, asking user", - configfile); + WLog_DBG(TAG, "No or no valid configuration file for certificate handling, asking user"); goto fail; } @@ -1659,7 +1609,6 @@ fail: *pAllowUserconfig = (rc == 0); WINPR_JSON_Delete(json); - free(configfile); return rc; } diff --git a/libfreerdp/locale/keyboard_layout.c b/libfreerdp/locale/keyboard_layout.c index a7a3008fe..6d3a117dd 100644 --- a/libfreerdp/locale/keyboard_layout.c +++ b/libfreerdp/locale/keyboard_layout.c @@ -924,7 +924,7 @@ static BOOL load_layout_file(void) if (!fp) goto end; (void)fprintf(fp, "%s", str); - fclose(fp); + (void)fclose(fp); } end: free(str); @@ -1006,54 +1006,9 @@ static void clear_layout_tables(void) static WINPR_JSON* load_layouts_from_file(const char* filename) { - INT64 jstrlen = 0; - char* jstr = NULL; - WINPR_JSON* json = NULL; - FILE* fp = winpr_fopen(filename, "r"); - if (!fp) - { - WLog_WARN(TAG, "resource file '%s' does not exist or is not readable", filename); - return NULL; - } - - if (_fseeki64(fp, 0, SEEK_END) < 0) - { - WLog_WARN(TAG, "resource file '%s' seek failed", filename); - goto end; - } - jstrlen = _ftelli64(fp); - if (jstrlen < 0) - { - WLog_WARN(TAG, "resource file '%s' invalid length %" PRId64, filename, jstrlen); - goto end; - } - if (_fseeki64(fp, 0, SEEK_SET) < 0) - { - WLog_WARN(TAG, "resource file '%s' seek failed", filename); - goto end; - } - - jstr = calloc((size_t)jstrlen + 1, sizeof(char)); - if (!jstr) - { - WLog_WARN(TAG, "resource file '%s' failed to allocate buffer of size %" PRId64, filename, - jstrlen); - goto end; - } - - if (fread(jstr, (size_t)jstrlen, sizeof(char), fp) != 1) - { - WLog_WARN(TAG, "resource file '%s' failed to read buffer of size %" PRId64, filename, - jstrlen); - goto end; - } - - json = WINPR_JSON_ParseWithLength(jstr, (size_t)jstrlen); + WINPR_JSON* json = WINPR_JSON_ParseFromFile(filename); if (!json) WLog_WARN(TAG, "resource file '%s' is not a valid JSON file", filename); -end: - fclose(fp); - free(jstr); return json; } diff --git a/libfreerdp/utils/helpers.c b/libfreerdp/utils/helpers.c index 6efefaf5c..c92254754 100644 --- a/libfreerdp/utils/helpers.c +++ b/libfreerdp/utils/helpers.c @@ -59,3 +59,14 @@ char* freerdp_GetConfigFilePath(BOOL system, const char* filename) free(base); return path; } + +WINPR_JSON* freerdp_GetJSONConfigFile(BOOL system, const char* filename) +{ + char* path = freerdp_GetConfigFilePath(system, filename); + if (!path) + return NULL; + + WINPR_JSON* json = WINPR_JSON_ParseFromFile(path); + free(path); + return json; +} diff --git a/winpr/include/winpr/json.h b/winpr/include/winpr/json.h index b3116ea93..14a2433d8 100644 --- a/winpr/include/winpr/json.h +++ b/winpr/include/winpr/json.h @@ -77,6 +77,26 @@ extern "C" WINPR_ATTR_MALLOC(WINPR_JSON_Delete, 1) WINPR_API WINPR_JSON* WINPR_JSON_ParseWithLength(const char* value, size_t buffer_length); + /** + * @brief Parse a JSON string read from a file \b filename + * + * @param filename the name of the file to read from + * @return A @ref WINPR_JSON object holding the parsed string or \b NULL if failed + * @since version 3.16.0 + */ + WINPR_ATTR_MALLOC(WINPR_JSON_Delete, 1) + WINPR_API WINPR_JSON* WINPR_JSON_ParseFromFile(const char* filename); + + /** + * @brief Parse a JSON string read from a \b FILE + * + * @param fp a \b FILE pointer to read from. + * @return A @ref WINPR_JSON object holding the parsed string or \b NULL if failed + * @since version 3.16.0 + */ + WINPR_ATTR_MALLOC(WINPR_JSON_Delete, 1) + WINPR_API WINPR_JSON* WINPR_JSON_ParseFromFileFP(FILE* fp); + /** * @brief Get the number of arrayitems from an array * diff --git a/winpr/libwinpr/timezone/TimeZoneNameMapUtils.c b/winpr/libwinpr/timezone/TimeZoneNameMapUtils.c index be5eed9be..666fa93c7 100644 --- a/winpr/libwinpr/timezone/TimeZoneNameMapUtils.c +++ b/winpr/libwinpr/timezone/TimeZoneNameMapUtils.c @@ -149,54 +149,9 @@ static BOOL tz_parse_json_entry(WINPR_JSON* json, size_t pos, TimeZoneNameMapEnt static WINPR_JSON* load_timezones_from_file(const char* filename) { - INT64 jstrlen = 0; - char* jstr = NULL; - WINPR_JSON* json = NULL; - FILE* fp = winpr_fopen(filename, "r"); - if (!fp) - { - WLog_WARN(TAG, "Timezone resource file '%s' does not exist or is not readable", filename); - return NULL; - } - - if (_fseeki64(fp, 0, SEEK_END) < 0) - { - WLog_WARN(TAG, "Timezone resource file '%s' seek failed", filename); - goto end; - } - jstrlen = _ftelli64(fp); - if (jstrlen < 0) - { - WLog_WARN(TAG, "Timezone resource file '%s' invalid length %" PRId64, filename, jstrlen); - goto end; - } - if (_fseeki64(fp, 0, SEEK_SET) < 0) - { - WLog_WARN(TAG, "Timezone resource file '%s' seek failed", filename); - goto end; - } - - jstr = calloc(WINPR_ASSERTING_INT_CAST(size_t, jstrlen + 1), sizeof(char)); - if (!jstr) - { - WLog_WARN(TAG, "Timezone resource file '%s' failed to allocate buffer of size %" PRId64, - filename, jstrlen); - goto end; - } - - if (fread(jstr, WINPR_ASSERTING_INT_CAST(size_t, jstrlen), sizeof(char), fp) != 1) - { - WLog_WARN(TAG, "Timezone resource file '%s' failed to read buffer of size %" PRId64, - filename, jstrlen); - goto end; - } - - json = WINPR_JSON_ParseWithLength(jstr, WINPR_ASSERTING_INT_CAST(size_t, jstrlen)); + WINPR_JSON* json = WINPR_JSON_ParseFromFile(filename); if (!json) WLog_WARN(TAG, "Timezone resource file '%s' is not a valid JSON file", filename); -end: - fclose(fp); - free(jstr); return json; } #endif diff --git a/winpr/libwinpr/utils/json/json.c b/winpr/libwinpr/utils/json/json.c index e232dee20..e90b8d9c6 100644 --- a/winpr/libwinpr/utils/json/json.c +++ b/winpr/libwinpr/utils/json/json.c @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -679,3 +680,41 @@ char* WINPR_JSON_PrintUnformatted(WINPR_JSON* item) return NULL; #endif } + +WINPR_JSON* WINPR_JSON_ParseFromFile(const char* filename) +{ + FILE* fp = winpr_fopen(filename, "r"); + if (!fp) + return NULL; + WINPR_JSON* json = WINPR_JSON_ParseFromFileFP(fp); + (void)fclose(fp); + return json; +} + +WINPR_JSON* WINPR_JSON_ParseFromFileFP(FILE* fp) +{ + if (!fp) + return NULL; + + if (fseek(fp, 0, SEEK_END) != 0) + return NULL; + + const INT64 size = _ftelli64(fp); + if (size < 0) + return NULL; + + if (fseek(fp, 0, SEEK_SET) != 0) + return NULL; + + const size_t usize = WINPR_ASSERTING_INT_CAST(size_t, size); + char* str = calloc(usize + 1, sizeof(char)); + if (!str) + return NULL; + + WINPR_JSON* json = NULL; + const size_t s = fread(str, sizeof(char), usize, fp); + if (s == usize) + json = WINPR_JSON_ParseWithLength(str, usize); + free(str); + return json; +}