nfets 0.0.58 → 0.0.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,422 @@
1
+ #include <node_api.h>
2
+
3
+ #include <libxml/parser.h>
4
+ #include <libxml/xmlschemas.h>
5
+ #include "libxml/xmlversion.h"
6
+
7
+ #include <string.h>
8
+ #include <stdlib.h>
9
+ #include <stdio.h>
10
+ #include <sys/stat.h>
11
+
12
+ #ifdef _WIN32
13
+ #include <io.h>
14
+ #include <direct.h>
15
+ #include <windows.h>
16
+ #ifndef F_OK
17
+ #define F_OK 0
18
+ #endif
19
+ #define access _access
20
+ #define chdir _chdir
21
+ #define fileno _fileno
22
+
23
+ static char* dirname_win(char* path) {
24
+ if (path == NULL) {
25
+ return NULL;
26
+ }
27
+
28
+ if (*path == '\0') {
29
+ path[0] = '.';
30
+ path[1] = '\0';
31
+ return path;
32
+ }
33
+
34
+ size_t len = strlen(path);
35
+ while (len > 0 && (path[len - 1] == '\\' || path[len - 1] == '/')) {
36
+ len--;
37
+ path[len] = '\0';
38
+ }
39
+
40
+ if (len == 0) {
41
+ path[0] = '.';
42
+ path[1] = '\0';
43
+ return path;
44
+ }
45
+
46
+ if (len == 2 && path[1] == ':') {
47
+ path[2] = '\\';
48
+ path[3] = '\0';
49
+ return path;
50
+ }
51
+
52
+ char* last_backslash = strrchr(path, '\\');
53
+ char* last_slash = strrchr(path, '/');
54
+ char* last_sep = NULL;
55
+ if (last_backslash != NULL && last_slash != NULL) {
56
+ last_sep = (last_backslash > last_slash) ? last_backslash : last_slash;
57
+ } else if (last_backslash != NULL) {
58
+ last_sep = last_backslash;
59
+ } else if (last_slash != NULL) {
60
+ last_sep = last_slash;
61
+ }
62
+
63
+ if (last_sep == NULL) {
64
+ path[0] = '.';
65
+ path[1] = '\0';
66
+ return path;
67
+ }
68
+
69
+ if (last_sep == path || (last_sep == path + 2 && path[1] == ':')) {
70
+ last_sep[1] = '\0';
71
+ return path;
72
+ }
73
+
74
+ if (path[0] == '\\' && path[1] == '\\' && last_sep == path + 1) {
75
+ last_sep[1] = '\0';
76
+ return path;
77
+ }
78
+
79
+ *last_sep = '\0';
80
+ return path;
81
+ }
82
+
83
+ #define dirname dirname_win
84
+ #else
85
+ #include <unistd.h>
86
+ #include <libgen.h>
87
+ #endif
88
+
89
+ struct AsyncWorkData
90
+ {
91
+ napi_env env;
92
+ napi_deferred deferred;
93
+ napi_async_work work;
94
+
95
+ char *xmlStr;
96
+ char *xsdPath;
97
+ char *error;
98
+
99
+ bool result;
100
+ };
101
+
102
+ struct ValidationError
103
+ {
104
+ char *message = NULL;
105
+ };
106
+
107
+ void validationErrorCallback(void *ctx, const char *msg, ...)
108
+ {
109
+ ValidationError *error = static_cast<ValidationError *>(ctx);
110
+
111
+ char buffer[1024];
112
+
113
+ va_list args;
114
+ va_start(args, msg);
115
+ vsnprintf(buffer, sizeof(buffer), msg, args);
116
+ va_end(args);
117
+
118
+ if (error->message == NULL)
119
+ {
120
+ error->message = strdup(buffer);
121
+ }
122
+ else
123
+ {
124
+ size_t size = strlen(error->message) + strlen(buffer) + 2;
125
+ char *message = (char *)realloc(error->message, size);
126
+
127
+ error->message = message;
128
+ strcat(error->message, buffer);
129
+ }
130
+ }
131
+
132
+ bool validate_xml(const char *xmlStr, const char *xsdFilePath, char *err, size_t size)
133
+ {
134
+
135
+ if (xmlStr == NULL || strlen(xmlStr) == 0)
136
+ {
137
+ snprintf(err, size, "Please provide a valid xml content");
138
+ return false;
139
+ }
140
+
141
+ if (xsdFilePath == NULL || strlen(xsdFilePath) == 0)
142
+ {
143
+ snprintf(err, size, "Please provide a valid existing xsd path");
144
+ return false;
145
+ }
146
+
147
+ char *xsdPath = strdup(xsdFilePath);
148
+ if (xsdPath != NULL)
149
+ {
150
+ char *xsdDir = dirname(xsdPath);
151
+ if (xsdDir != NULL && access(xsdDir, F_OK) == 0)
152
+ {
153
+ chdir(xsdDir);
154
+ }
155
+ free(xsdPath);
156
+ }
157
+
158
+ FILE *file = fopen(xsdFilePath, "rb");
159
+ if (file == NULL)
160
+ {
161
+ snprintf(err, size, "Cannot open XSD file: %s", xsdFilePath);
162
+ return false;
163
+ }
164
+
165
+ struct stat fileStat;
166
+ if (fstat(fileno(file), &fileStat) != 0)
167
+ {
168
+ fclose(file);
169
+ snprintf(err, size, "Cannot get file size for XSD: %s", xsdFilePath);
170
+ return false;
171
+ }
172
+
173
+ size_t fileSize = fileStat.st_size;
174
+ char *xsdStr = (char *)malloc(fileSize);
175
+ if (xsdStr == NULL)
176
+ {
177
+ fclose(file);
178
+ snprintf(err, size, "Memory allocation failed for XSD file");
179
+ return false;
180
+ }
181
+
182
+ size_t bytesRead = fread(xsdStr, 1, fileSize, file);
183
+ fclose(file);
184
+
185
+ if (bytesRead != fileSize)
186
+ {
187
+ free(xsdStr);
188
+ snprintf(err, size, "Error reading XSD file: %s", xsdFilePath);
189
+ return false;
190
+ }
191
+
192
+ ValidationError validationErrorCtx;
193
+ xmlSetGenericErrorFunc(&validationErrorCtx, validationErrorCallback);
194
+
195
+ xmlDocPtr xml = xmlReadMemory(xmlStr, strlen(xmlStr), "noname.xml", "utf-8", 0);
196
+ if (xml == NULL)
197
+ {
198
+ snprintf(err, size, "Error processing xml content, check if your xml is valid: %s", validationErrorCtx.message);
199
+ return false;
200
+ }
201
+
202
+ xmlSchemaParserCtxtPtr schemaParserCtxt = xmlSchemaNewMemParserCtxt(xsdStr, fileSize);
203
+ if (!schemaParserCtxt)
204
+ {
205
+ snprintf(err, size, "Error creating XSD parser context");
206
+ xmlFreeDoc(xml);
207
+ return false;
208
+ }
209
+
210
+ xmlSchemaSetParserErrors(schemaParserCtxt, (xmlSchemaValidityErrorFunc)validationErrorCallback,
211
+ (xmlSchemaValidityWarningFunc)validationErrorCallback, &validationErrorCtx);
212
+
213
+ xmlSchemaPtr schema = xmlSchemaParse(schemaParserCtxt);
214
+ if (!schema)
215
+ {
216
+ snprintf(err, size, "Invalid XSD file: %s", validationErrorCtx.message);
217
+ xmlFreeDoc(xml);
218
+ xmlSchemaFreeParserCtxt(schemaParserCtxt);
219
+ return false;
220
+ }
221
+
222
+ xmlSchemaValidCtxtPtr validCtxt = xmlSchemaNewValidCtxt(schema);
223
+ if (!validCtxt)
224
+ {
225
+ snprintf(err, size, "Error creating validation context");
226
+ xmlFreeDoc(xml);
227
+ xmlSchemaFree(schema);
228
+ xmlSchemaFreeParserCtxt(schemaParserCtxt);
229
+ return false;
230
+ }
231
+
232
+ xmlSchemaSetValidErrors(validCtxt, (xmlSchemaValidityErrorFunc)validationErrorCallback,
233
+ (xmlSchemaValidityWarningFunc)validationErrorCallback, &validationErrorCtx);
234
+
235
+ bool result = false;
236
+
237
+ if (xmlSchemaValidateDoc(validCtxt, xml) == 0)
238
+ {
239
+ result = true;
240
+ }
241
+ else
242
+ {
243
+ snprintf(err, size, "Invalid xml schema: %s", validationErrorCtx.message);
244
+ }
245
+
246
+ xmlFreeDoc(xml);
247
+ xmlSchemaFree(schema);
248
+ xmlSchemaFreeValidCtxt(validCtxt);
249
+ xmlSchemaFreeParserCtxt(schemaParserCtxt);
250
+
251
+ free(xsdStr);
252
+
253
+ return result;
254
+ }
255
+
256
+ void async_validate_xml(napi_env env, void *_data)
257
+ {
258
+ struct AsyncWorkData *data = static_cast<struct AsyncWorkData *>(_data);
259
+ char err[1024] = "";
260
+
261
+ data->result = validate_xml(
262
+ data->xmlStr, data->xsdPath,
263
+ err, sizeof(err));
264
+
265
+ data->error = strdup(err);
266
+ }
267
+
268
+ void complete_async_validate_xml(napi_env env, napi_status status, void *_data)
269
+ {
270
+ AsyncWorkData *data = static_cast<struct AsyncWorkData *>(_data);
271
+
272
+ napi_value result;
273
+ napi_get_boolean(env, data->result, &result);
274
+
275
+ if (data->result)
276
+ {
277
+ napi_resolve_deferred(env, data->deferred, result);
278
+ }
279
+ else
280
+ {
281
+ napi_value error;
282
+ napi_create_string_utf8(env, data->error, NAPI_AUTO_LENGTH, &error);
283
+ napi_reject_deferred(env, data->deferred, error);
284
+ }
285
+
286
+ napi_delete_async_work(env, data->work);
287
+ free(data->error);
288
+ delete data;
289
+ }
290
+
291
+ int extract_args(napi_env env, napi_callback_info info, char **xmlStr, char **xsdPath, char *err, size_t errSize)
292
+ {
293
+ size_t argc = 2;
294
+ napi_value args[2];
295
+ napi_get_cb_info(env, info, &argc, args, NULL, NULL);
296
+
297
+ if (argc < 2)
298
+ {
299
+ snprintf(
300
+ err, errSize,
301
+ "You must provide 2 arguments: `xml content` and `xsd path`");
302
+
303
+ return 1;
304
+ }
305
+
306
+ size_t xmlLen, xsdLen;
307
+ napi_get_value_string_utf8(env, args[0], NULL, 0, &xmlLen);
308
+ napi_get_value_string_utf8(env, args[1], NULL, 0, &xsdLen);
309
+
310
+ *xmlStr = (char *)malloc(xmlLen + 1);
311
+ *xsdPath = (char *)malloc(xsdLen + 1);
312
+
313
+ napi_get_value_string_utf8(env, args[0], *xmlStr, xmlLen + 1, NULL);
314
+ napi_get_value_string_utf8(env, args[1], *xsdPath, xsdLen + 1, NULL);
315
+
316
+ return 0;
317
+ }
318
+
319
+ napi_value AsyncValidateXml(napi_env env, napi_callback_info info)
320
+ {
321
+ char *xmlStr, *xsdPath;
322
+
323
+ napi_value promise;
324
+ AsyncWorkData *data = new AsyncWorkData();
325
+
326
+ napi_status status = napi_create_promise(env, &data->deferred, &promise);
327
+
328
+ if (status != napi_ok)
329
+ {
330
+ napi_throw_error(env, NULL, "Error creating promise");
331
+ delete data;
332
+ return NULL;
333
+ }
334
+
335
+ char err[1024] = "";
336
+ if (extract_args(env, info, &xmlStr, &xsdPath, err, sizeof(err)) != 0)
337
+ {
338
+ napi_value error;
339
+ napi_create_string_utf8(env, err, sizeof(err), &error);
340
+ napi_reject_deferred(env, data->deferred, error);
341
+ delete data;
342
+ return promise;
343
+ }
344
+
345
+ data->xmlStr = xmlStr;
346
+ data->xsdPath = xsdPath;
347
+
348
+ napi_value resource_name;
349
+ napi_create_string_utf8(env, "AsyncValidateXml", -1, &resource_name);
350
+
351
+ status = napi_create_async_work(
352
+ env,
353
+ NULL,
354
+ resource_name,
355
+ async_validate_xml,
356
+ complete_async_validate_xml,
357
+ data,
358
+ &data->work);
359
+
360
+ if (status != napi_ok)
361
+ {
362
+ napi_value err;
363
+ napi_create_string_utf8(env, "Error creating AsyncWork.", NAPI_AUTO_LENGTH, &err);
364
+ napi_reject_deferred(env, data->deferred, err);
365
+ delete data;
366
+ return promise;
367
+ }
368
+
369
+ if (data->work == NULL)
370
+ {
371
+ napi_value err;
372
+ napi_create_string_utf8(env, "Async work is NULL", NAPI_AUTO_LENGTH, &err);
373
+ napi_reject_deferred(env, data->deferred, err);
374
+ delete data;
375
+ return promise;
376
+ }
377
+
378
+ napi_queue_async_work(env, data->work);
379
+
380
+ return promise;
381
+ }
382
+
383
+ napi_value ValidateXml(napi_env env, napi_callback_info info)
384
+ {
385
+ char *xmlStr, *xsdPath;
386
+ char err[1024] = "";
387
+
388
+ if (extract_args(env, info, &xmlStr, &xsdPath, err, sizeof(err)) != 0)
389
+ {
390
+ napi_throw_error(env, NULL, err);
391
+ return NULL;
392
+ }
393
+
394
+ bool valid = validate_xml(xmlStr, xsdPath, err, sizeof(err));
395
+
396
+ free(xmlStr);
397
+ free(xsdPath);
398
+
399
+ if (!valid)
400
+ {
401
+ napi_throw_error(env, NULL, err);
402
+ return NULL;
403
+ }
404
+
405
+ napi_value result;
406
+ napi_get_boolean(env, valid, &result);
407
+ return result;
408
+ }
409
+
410
+ napi_value Init(napi_env env, napi_value exports)
411
+ {
412
+ napi_value fn;
413
+ napi_create_function(env, nullptr, 0, AsyncValidateXml, nullptr, &fn);
414
+ napi_set_named_property(env, exports, "validate", fn);
415
+
416
+ napi_create_function(env, nullptr, 0, ValidateXml, nullptr, &fn);
417
+ napi_set_named_property(env, exports, "validateSync", fn);
418
+
419
+ return exports;
420
+ }
421
+
422
+ NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
package/binding.gyp ADDED
@@ -0,0 +1,92 @@
1
+ {
2
+ "targets": [
3
+ {
4
+ "target_name": "wincrypt_certificate_store",
5
+ "conditions": [
6
+ ["OS=='win'", {
7
+ "sources": [ "addons/wincrypt_certificate_store.cpp" ],
8
+ "libraries": [
9
+ "-lcrypt32",
10
+ "-lncrypt",
11
+ "-lwinhttp"
12
+ ],
13
+ "msvs_settings": {
14
+ "VCCLCompilerTool": {
15
+ "ExceptionHandling": 1
16
+ }
17
+ }
18
+ }]
19
+ ]
20
+ },
21
+ {
22
+ "target_name": "winhttp_ssl_client",
23
+ "conditions": [
24
+ ["OS=='win'", {
25
+ "sources": [ "addons/winhttp_ssl_client.cpp" ],
26
+ "libraries": [
27
+ "-lwinhttp",
28
+ "-lcrypt32"
29
+ ],
30
+ "msvs_settings": {
31
+ "VCCLCompilerTool": {
32
+ "ExceptionHandling": 1
33
+ }
34
+ }
35
+ }]
36
+ ]
37
+ },
38
+ {
39
+ "target_name": "xml_validator",
40
+ "sources": [
41
+ "addons/xml_validator.cpp"
42
+ ],
43
+ "conditions": [
44
+ ["OS=='win'", {
45
+ "include_dirs": [
46
+ "<!(cmd /c \"if defined MSYS2_LOCATION (echo %MSYS2_LOCATION%\\mingw64\\include) else (echo C:\\msys64\\mingw64\\include)\")",
47
+ "<!(cmd /c \"if defined MSYS2_LOCATION (echo %MSYS2_LOCATION%\\mingw64\\include\\libxml2) else (echo C:\\msys64\\mingw64\\include\\libxml2)\")"
48
+ ],
49
+ "library_dirs": [
50
+ "<!(cmd /c \"if defined MSYS2_LOCATION (echo %MSYS2_LOCATION%\\mingw64\\lib) else (echo C:\\msys64\\mingw64\\lib)\")"
51
+ ],
52
+ "libraries": [
53
+ "libxml2.dll.a"
54
+ ],
55
+ "defines": [
56
+ "WIN32"
57
+ ],
58
+ "copies": [
59
+ {
60
+ "destination": "<(PRODUCT_DIR)",
61
+ "files": [
62
+ "<!(cmd /c \"if defined MSYS2_LOCATION (echo %MSYS2_LOCATION%\\mingw64\\bin\\libiconv-2.dll) else (echo C:\\msys64\\mingw64\\bin\\libiconv-2.dll)\")",
63
+ "<!(cmd /c \"if defined MSYS2_LOCATION (echo %MSYS2_LOCATION%\\mingw64\\bin\\zlib1.dll) else (echo C:\\msys64\\mingw64\\bin\\zlib1.dll)\")",
64
+ "<!(cmd /c \"if defined MSYS2_LOCATION (if exist %MSYS2_LOCATION%\\mingw64\\bin\\libxml2-16.dll (echo %MSYS2_LOCATION%\\mingw64\\bin\\libxml2-16.dll) else (echo %MSYS2_LOCATION%\\mingw64\\bin\\libxml2-2.dll)) else (if exist C:\\msys64\\mingw64\\bin\\libxml2-16.dll (echo C:\\msys64\\mingw64\\bin\\libxml2-16.dll) else (echo C:\\msys64\\mingw64\\bin\\libxml2-2.dll))\")"
65
+ ]
66
+ }
67
+ ]
68
+ }],
69
+ ["OS=='mac'", {
70
+ "include_dirs": [
71
+ "<!(pkg-config --cflags-only-I libxml-2.0 2>/dev/null | sed 's/-I//g' || echo '/usr/include/libxml2')"
72
+ ],
73
+ "libraries": [
74
+ "<!(LIBDIR=$(pkg-config --variable=libdir libxml-2.0 2>/dev/null || echo ''); if [ -n \"$LIBDIR\" ] && [ -f \"$LIBDIR/libxml2.a\" ]; then echo \"$LIBDIR/libxml2.a\"; elif [ -f \"/opt/homebrew/lib/libxml2.a\" ]; then echo \"/opt/homebrew/lib/libxml2.a\"; elif [ -f \"/usr/local/lib/libxml2.a\" ]; then echo \"/usr/local/lib/libxml2.a\"; else pkg-config --libs libxml-2.0 2>/dev/null || echo '-lxml2'; fi)"
75
+ ]
76
+ }],
77
+ ["OS=='linux'", {
78
+ "include_dirs": [
79
+ "<!(pkg-config --cflags-only-I libxml-2.0 2>/dev/null | sed 's/-I//g' || echo '/usr/include/libxml2')"
80
+ ],
81
+ "libraries": [
82
+ "<!@(pkg-config --libs libxml-2.0 2>/dev/null || echo '-lxml2')"
83
+ ],
84
+ "ldflags": [
85
+ "-lxml2",
86
+ "-Wl,-Bdynamic"
87
+ ]
88
+ }]
89
+ ]
90
+ }
91
+ ]
92
+ }
Binary file