FreeRDP
Loading...
Searching...
No Matches
utils/helpers.c
1
21#include <ctype.h>
22
23#include <freerdp/utils/helpers.h>
24
25#include <winpr/path.h>
26#include <winpr/file.h>
27#include <winpr/build-config.h>
28#include <freerdp/version.h>
29#include <freerdp/build-config.h>
30
31#include "../core/utils.h"
32
33static INIT_ONCE s_freerdp_app_details_once = INIT_ONCE_STATIC_INIT;
34static char s_freerdp_vendor_string[MAX_PATH] = WINPR_C_ARRAY_INIT;
35static char s_freerdp_product_string[MAX_PATH] = WINPR_C_ARRAY_INIT;
36static char s_freerdp_details_string[3ull * MAX_PATH] = WINPR_C_ARRAY_INIT;
37static WCHAR s_freerdp_details_string_w[3ull * MAX_PATH] = WINPR_C_ARRAY_INIT;
38static SSIZE_T s_freerdp_version = -1;
39static BOOL s_freerdp_app_details_are_custom = FALSE;
40
41static void updateDetailsString(void)
42{
43 const char* vendor = s_freerdp_vendor_string;
44 const char* product = s_freerdp_product_string;
45 const SSIZE_T version = s_freerdp_version;
46
47 WINPR_ASSERT(vendor);
48 WINPR_ASSERT(product);
49 if (s_freerdp_app_details_are_custom)
50 {
51 if (version < 0)
52 (void)_snprintf(s_freerdp_details_string, sizeof(s_freerdp_details_string) - 1, "%s-%s",
53 vendor, product);
54 else
55 (void)_snprintf(s_freerdp_details_string, sizeof(s_freerdp_details_string) - 1,
56 "%s-%s%" PRIdz, vendor, product, version);
57 }
58 else if (version < 0)
59 {
60 (void)_snprintf(s_freerdp_details_string, sizeof(s_freerdp_details_string) - 1, "%s",
61 product);
62 }
63 else
64 (void)_snprintf(s_freerdp_details_string, sizeof(s_freerdp_details_string) - 1, "%s%" PRIdz,
65 product, version);
66
67 (void)ConvertUtf8NToWChar(s_freerdp_details_string, sizeof(s_freerdp_details_string),
68 s_freerdp_details_string_w, sizeof(s_freerdp_details_string_w) - 1);
69}
70
71static BOOL CALLBACK init_app_details(WINPR_ATTR_UNUSED PINIT_ONCE once,
72 WINPR_ATTR_UNUSED PVOID param,
73 WINPR_ATTR_UNUSED PVOID* context)
74{
75 const size_t vlen = sizeof(FREERDP_VENDOR_STRING);
76 const size_t plen = sizeof(FREERDP_PRODUCT_STRING);
77 const char* rvlen = strncpy(s_freerdp_vendor_string, FREERDP_VENDOR_STRING, vlen);
78 const char* rplen = strncpy(s_freerdp_product_string, FREERDP_PRODUCT_STRING, plen);
79 if (!rvlen || !rplen)
80 return FALSE;
81
82#if defined(WITH_RESOURCE_VERSIONING)
83 s_freerdp_version = FREERDP_VERSION_MAJOR;
84#else
85 s_freerdp_version = -1;
86#endif
87 updateDetailsString();
88 return TRUE;
89}
90
91WINPR_ATTR_NODISCARD
92static BOOL initializeApplicationDetails(void)
93{
94 return InitOnceExecuteOnce(&s_freerdp_app_details_once, init_app_details, nullptr, nullptr);
95}
96
97BOOL freerdp_setApplicationDetails(const char* vendor, const char* product, SSIZE_T version)
98{
99 if (!initializeApplicationDetails())
100 return -1;
101
102 if (!vendor || !product)
103 return FALSE;
104 const size_t vlen = strnlen(vendor, MAX_PATH);
105 const size_t plen = strnlen(product, MAX_PATH);
106 if ((vlen == MAX_PATH) || (plen == MAX_PATH))
107 return FALSE;
108
109 if (!strncpy(s_freerdp_vendor_string, vendor, vlen + 1))
110 return FALSE;
111
112 if (!strncpy(s_freerdp_product_string, product, plen + 1))
113 return FALSE;
114
115 s_freerdp_version = version;
116 s_freerdp_app_details_are_custom = TRUE;
117
118 const char separator = PathGetSeparatorA(PATH_STYLE_NATIVE);
119 char* str = freerdp_getApplicatonDetailsCombined(separator);
120 if (!str)
121 return FALSE;
122
123 const BOOL rc = winpr_setApplicationDetails(str, "WinPR", -1);
124 free(str);
125 updateDetailsString();
126 return rc;
127}
128
129const char* freerdp_getApplicationDetailsVendor(void)
130{
131 if (!initializeApplicationDetails())
132 return nullptr;
133 return s_freerdp_vendor_string;
134}
135
136const char* freerdp_getApplicationDetailsProduct(void)
137{
138 if (!initializeApplicationDetails())
139 return nullptr;
140 return s_freerdp_product_string;
141}
142
143#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
144char* freerdp_getApplicatonDetailsRegKey(const char* fmt)
145{
146 char* val = freerdp_getApplicatonDetailsCombined('\\');
147 if (!val)
148 return nullptr;
149
150 char* str = nullptr;
151 size_t slen = 0;
152 (void)winpr_asprintf(&str, &slen, fmt, val);
153 free(val);
154 return str;
155}
156#endif
157
158char* freerdp_getApplicatonDetailsCombined(char separator)
159{
160 const SSIZE_T version = freerdp_getApplicationDetailsVersion();
161 const char* vendor = freerdp_getApplicationDetailsVendor();
162 const char* product = freerdp_getApplicationDetailsProduct();
163
164 size_t slen = 0;
165 char* str = nullptr;
166 if (version < 0)
167 {
168 (void)winpr_asprintf(&str, &slen, "%s%c%s", vendor, separator, product);
169 }
170 else
171 {
172 (void)winpr_asprintf(&str, &slen, "%s%c%s%" PRIdz, vendor, separator, product, version);
173 }
174
175 return str;
176}
177
178SSIZE_T freerdp_getApplicationDetailsVersion(void)
179{
180 if (!initializeApplicationDetails())
181 return -1;
182 return s_freerdp_version;
183}
184
185const char* freerdp_getApplicationDetailsString(void)
186{
187 return s_freerdp_details_string;
188}
189
190const WCHAR* freerdp_getApplicationDetailsStringW(void)
191{
192 return s_freerdp_details_string_w;
193}
194
195BOOL freerdp_areApplicationDetailsCustomized(void)
196{
197 return s_freerdp_app_details_are_custom;
198}
199
200#if !defined(WITH_FULL_CONFIG_PATH)
201WINPR_ATTR_MALLOC(free, 1)
202WINPR_ATTR_NODISCARD
203static char* freerdp_settings_get_legacy_config_path(const char* filename)
204{
205 char product[sizeof(FREERDP_PRODUCT_STRING)] = WINPR_C_ARRAY_INIT;
206
207 for (size_t i = 0; i < sizeof(product); i++)
208 product[i] = (char)tolower(FREERDP_PRODUCT_STRING[i]);
209
210 char* path = GetKnownSubPath(KNOWN_PATH_XDG_CONFIG_HOME, product);
211
212 if (!path)
213 return nullptr;
214
215 char* filepath = GetCombinedPath(path, filename);
216 free(path);
217 return filepath;
218}
219#endif
220
221WINPR_ATTR_NODISCARD
222WINPR_ATTR_MALLOC(free, 1) static char* getCustomConfigPath(BOOL system, const char* filename)
223{
224 eKnownPathTypes id = system ? KNOWN_PATH_SYSTEM_CONFIG_HOME : KNOWN_PATH_XDG_CONFIG_HOME;
225
226 const char* vendor = freerdp_getApplicationDetailsVendor();
227 const char* product = freerdp_getApplicationDetailsProduct();
228 const SSIZE_T version = freerdp_getApplicationDetailsVersion();
229
230 if (!vendor || !product)
231 return nullptr;
232
233 char* config = GetKnownSubPathV(id, "%s", vendor);
234 if (!config)
235 return nullptr;
236
237 char* base = nullptr;
238 if (version < 0)
239 base = GetCombinedPathV(config, "%s", product);
240 else
241 base = GetCombinedPathV(config, "%s%" PRIdz, product, version);
242 free(config);
243
244 if (!base)
245 return nullptr;
246
247 if (!filename)
248 return base;
249
250 char* path = GetCombinedPathV(base, "%s", filename);
251 free(base);
252 return path;
253}
254
255char* freerdp_GetConfigFilePath(BOOL system, const char* filename)
256{
257#if defined(FREERDP_USE_VENDOR_PRODUCT_CONFIG_DIR)
258 const BOOL customized = TRUE;
259#else
260 const BOOL customized = freerdp_areApplicationDetailsCustomized();
261#endif
262 if (customized)
263 return getCustomConfigPath(system, filename);
264
265 eKnownPathTypes id = system ? KNOWN_PATH_SYSTEM_CONFIG_HOME : KNOWN_PATH_XDG_CONFIG_HOME;
266
267 const char* vendor = freerdp_getApplicationDetailsVendor();
268 const char* product = freerdp_getApplicationDetailsProduct();
269 const SSIZE_T version = freerdp_getApplicationDetailsVersion();
270
271 if (!vendor || !product)
272 return nullptr;
273
274#if !defined(WITH_FULL_CONFIG_PATH)
275 if (!system && (_stricmp(vendor, product) == 0))
276 return freerdp_settings_get_legacy_config_path(filename);
277#endif
278
279 char* config = GetKnownPath(id);
280 if (!config)
281 return nullptr;
282
283 char* base = nullptr;
284 if (version < 0)
285 base = GetCombinedPathV(config, "%s", product);
286 else
287 base = GetCombinedPathV(config, "%s%" PRIdz, product, version);
288 free(config);
289
290 if (!base)
291 return nullptr;
292
293 if (!filename)
294 return base;
295
296 char* path = GetCombinedPathV(base, "%s", filename);
297 free(base);
298 return path;
299}
300
301WINPR_JSON* freerdp_GetJSONConfigFile(BOOL system, const char* filename)
302{
303 char* path = freerdp_GetConfigFilePath(system, filename);
304 if (!path)
305 return nullptr;
306
307 WINPR_JSON* json = WINPR_JSON_ParseFromFile(path);
308 free(path);
309 return json;
310}
WINPR_API WINPR_JSON * WINPR_JSON_ParseFromFile(const char *filename)
Parse a JSON string read from a file filename.
Definition json.c:27