1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 #include <ctype.h>
26 #include "helpers.h"
27 #include "types.h"
|
28 krisbash 1.3 #include <pal/strings.h>
|
29 mike 1.1 #include "alloc.h"
|
30 krisbash 1.3 #include <pal/format.h>
31 #include "class.h"
32 #include "base64.h"
33 #include "log.h"
34 #include "messages.h"
|
35 mike 1.1
|
36 krisbash 1.3 static const ZChar* _ParseNumber(const ZChar* p, unsigned long* n)
|
37 mike 1.1 {
|
38 krisbash 1.3 ZChar* end;
|
39 mike 1.1
|
40 krisbash 1.3 *n = Tcstoul(p, &end, 10);
|
41 mike 1.1
42 if (end == p)
43 return NULL;
44
45 return end;
46 }
47
|
48 krisbash 1.3 static const ZChar* _ParseDecimalPart(
49 const ZChar* p,
|
50 mike 1.1 unsigned long* n)
51 {
|
52 krisbash 1.3 ZChar* end;
|
53 mike 1.1 int i;
|
54 krisbash 1.3 ZChar buf[7];
|
55 mike 1.1
|
56 krisbash 1.3 Tcstoul(p, &end, 10);
|
57 mike 1.1
58 if (end == p)
59 {
60 /* Zero decimal part */
61 *n = 0;
62 return p;
63 }
64
65 for (i = 0; i < 6 && p != end; i++, p++)
66 buf[i] = *p;
67
68 for (; i < 6; i++)
69 buf[i] = '0';
70
71 buf[6] = '\0';
72
|
73 krisbash 1.3 *n = Tcstoul(buf, NULL, 10);
|
74 mike 1.1
75 return end;
76 }
77
|
78 krisbash 1.3 static int _ParseWSManDuration(const ZChar* str, MI_Datetime* x)
|
79 mike 1.1 {
|
80 krisbash 1.3 const ZChar* p = str;
|
81 mike 1.1 int foundT = 0;
82 unsigned long years = 0;
83 unsigned long months = 0;
84 unsigned long days = 0;
85 unsigned long hours = 0;
86 unsigned long minutes = 0;
87 unsigned long seconds = 0;
88 unsigned long microseconds = 0;
89
90 /* xs:duration: PnYnMnDTnHnMnS */
91 if (*p != 'P')
92 return -1;
93
94 /* [xs:duration]
95 *
96 * Format: "PnYnMnDTnHnMnS", where
97 * P - period (required)
98 * nY - number of years
99 * nM - number of month
100 * nD - number of days
|
101 krisbash 1.3 * ZT - start of time section (required for the following)
|
102 mike 1.1 * nH - number of hours
103 * nM - number of minutes
104 * nS - number of seconds
105 *
106 * Examples:
107 * -P10D (rejected)
108 * -P1347M (rejected)
109 * P5Y
110 * P5Y2M10D
111 * P5Y2M10DT15H
112 * PT15H
113 * P1347Y
114 * P1347M
115 * P1Y2MT2H
116 * P0Y1347M
117 * P0Y1347M0D
118 * P1Y2M3DT10H30M
119 *
120 * Illegal:
121 * P-1347M (rejected)
122 * P1Y2MT (tolerated)
123 mike 1.1 */
124
125 p++;
126
127 while (*p)
128 {
129 unsigned long n = 0;
130
131 if (*p == 'T')
132 {
133 foundT = 1;
134 p++;
135 }
136 else if (foundT)
137 {
138 p = _ParseNumber(p, &n);
139
140 if (!p)
141 break;
142
143 switch (*p)
144 mike 1.1 {
145 case 'H':
146 hours = n;
147 break;
148 case 'M':
149 minutes = n;
150 break;
151 case 'S':
152 seconds = n;
153 break;
154 case '.':
155 {
156 p++;
157 p = _ParseDecimalPart(p, µseconds);
158
159 if (*p != 'S')
160 return -1;
161
162 seconds = n;
163 break;
164 }
165 mike 1.1 default:
166 return -1;
167 }
168
169 p++;
170 }
171 else
172 {
173 p = _ParseNumber(p, &n);
174
175 if (!p)
176 break;
177
178 switch (*p)
179 {
180 case 'Y':
181 years = n;
182 break;
183 case 'M':
184 months = n;
185 break;
186 mike 1.1 case 'D':
187 days = n;
188 break;
189 default:
190 return -1;
191 }
192
193 p++;
194 }
195 }
196
197 /* ATTN: check for overflow */
198
199 /* Normalize seconds (possibly increasing minutes) */
200 minutes += seconds / 60;
201 seconds = seconds % 60;
202
203 /* Normalize minutes (possibly increasing hours) */
204 hours += minutes / 60;
205 minutes = minutes % 60;
206
207 mike 1.1 /* Normalize hours (possibly increasing days) */
208 days += hours / 24;
209 hours = hours % 24;
210
211 /* Approximate days from years-months-days */
212 days += years * 365;
213 days += years / 4;
214 days += months * 30;
215 days += months / 2;
216
217 /* Set CIM datetime fields */
218 x->isTimestamp = MI_FALSE;
219 x->u.interval.days = (unsigned int)days;
220 x->u.interval.hours = (unsigned int)hours;
221 x->u.interval.minutes = (unsigned int)minutes;
222 x->u.interval.seconds = (unsigned int)seconds;
223 x->u.interval.microseconds = microseconds;
224
225 return (p && *p == '\0') ? 0 : -1;
226 }
227
|
228 krisbash 1.3 static const ZChar* _ParseWSManUTC(const ZChar* str, MI_Datetime* x)
|
229 mike 1.1 {
|
230 krisbash 1.3 const ZChar* p = str;
|
231 mike 1.1 unsigned long utcHours = 0;
232 unsigned long utcMinutes = 0;
233 long utcSign = 0; /* '1' is positive, '-1' is negative */
234
235 if (*p == 'Z')
236 {
237 p++;
238 return p;
239 }
240 else if (*p == '+' || *p == '-')
241 {
242 /* Parse UTC "HH:SS" */
|
243 krisbash 1.3 const ZChar* end;
|
244 mike 1.1
245 utcSign = (*p == '-') ? -1 : 1;
246
247 p++;
248 end = _ParseNumber(p, &utcHours);
249
250 if (!end || (end - p) != 2)
251 return NULL;
252
253 p = end;
254
255 if (*p != ':')
256 return NULL;
257
258 p++;
259 end = _ParseNumber(p, &utcMinutes);
260
261 if (!end || (end - p) != 2)
262 return NULL;
263
264 p = end;
265 mike 1.1 }
266 else
267 {
268 return NULL;
269 }
270
271 /* Set CIM datetime fields */
272 x->u.timestamp.utc = utcSign * ((utcHours * 60) + utcMinutes);
273
274 return p;
275 }
276
|
277 krisbash 1.3 static const ZChar* _ParseWSManDate(const ZChar* str, MI_Datetime* x)
|
278 mike 1.1 {
|
279 krisbash 1.3 const ZChar* p = str;
|
280 mike 1.1 unsigned long year = 0;
281 unsigned long month = 0;
282 unsigned long day = 0;
283
284 /* Parse YYYY */
285 {
|
286 krisbash 1.3 const ZChar* end = _ParseNumber(p, &year);
|
287 mike 1.1
288 if (!end || (end - p) != 4)
289 return NULL;
290
291 p = end;
292 }
293
294 /* Expect '-' */
295 if (*p++ != '-')
296 return NULL;
297
298 /* Parse MM */
299 {
|
300 krisbash 1.3 const ZChar* end = _ParseNumber(p, &month);
|
301 mike 1.1
302 if (!end || (end - p) != 2)
303 return NULL;
304
305 p = end;
306 }
307
308 /* Expect '-' */
309 if (*p++ != '-')
310 return NULL;
311
312 /* Parse DD */
313 {
|
314 krisbash 1.3 const ZChar* end = _ParseNumber(p, &day);
|
315 mike 1.1
316 if (!end || (end - p) != 2)
317 return NULL;
318
319 p = end;
320 }
321
322 /* Set CIM datetime fields */
323 memset(x, 0, sizeof(MI_Datetime));
324 x->isTimestamp = MI_TRUE;
325 x->u.timestamp.year = (unsigned int)year;
326 x->u.timestamp.month = (unsigned int)month;
327 x->u.timestamp.day = (unsigned int)day;
328
329 /* Parse UTC part */
330 if (*p == 'Z' || *p == '+' || *p == '-')
331 {
332 p = _ParseWSManUTC(p, x);
333
334 if (!p)
335 return NULL;
336 mike 1.1 }
337
338 return p;
339 }
340
|
341 krisbash 1.3 static const ZChar* _ParseWSManTime(const ZChar* str, MI_Datetime* x)
|
342 mike 1.1 {
|
343 krisbash 1.3 const ZChar* p = str;
|
344 mike 1.1 unsigned long hour = 0;
345 unsigned long minute = 0;
346 unsigned long second = 0;
347 unsigned long microseconds = 0;
348
349 /* Parse "HH" */
350 {
|
351 krisbash 1.3 const ZChar* end = _ParseNumber(p, &hour);
|
352 mike 1.1
353 if (!end || (end - p) != 2)
354 return NULL;
355
356 p = end;
357 }
358
359 /* Expect ':' */
360 if (*p++ != ':')
361 return NULL;
362
363 /* Parse "MM" */
364 {
|
365 krisbash 1.3 const ZChar* end = _ParseNumber(p, &minute);
|
366 mike 1.1
367 if (!end || (end - p) != 2)
368 return NULL;
369
370 p = end;
371 }
372
373 /* Expect ":" */
374 if (*p++ != ':')
375 return NULL;
376
377 /* Parse "SS" */
378 {
|
379 krisbash 1.3 const ZChar* end = _ParseNumber(p, &second);
|
380 mike 1.1
381 if (!end || (end - p) != 2)
382 return NULL;
383
384 p = end;
385 }
386
387 /* Parse decimal part */
388 if (*p == '.')
389 {
390 p++;
391 p = _ParseDecimalPart(p, µseconds);
392
393 if (!p)
394 return NULL;
395 }
396
397 /* Set CIM datetime fields */
398 x->isTimestamp = MI_TRUE;
399 x->u.timestamp.hour = (unsigned int)hour;
400 x->u.timestamp.minute = (unsigned int)minute;
401 mike 1.1 x->u.timestamp.second = (unsigned int)second;
402 x->u.timestamp.microseconds = (unsigned int)microseconds;
403
404 /* Parse UTC part */
405 if (*p == 'Z' || *p == '+' || *p == '-')
406 {
407 p = _ParseWSManUTC(p, x);
408
409 if (!p)
410 return NULL;
411 }
412
413 return p;
414 }
415
|
416 krisbash 1.3 int ParseWSManDatetime(const ZChar* str, MI_Datetime* x)
|
417 mike 1.1 {
|
418 krisbash 1.3 const ZChar* p = str;
|
419 mike 1.1
420 /* Clear datetime */
421 memset(x, 0, sizeof(MI_Datetime));
422
423 /* negative xs:duration */
424 if (*p == '-')
425 {
426 /* Negative intervals not supported by CIM */
427 return -1;
428 }
429
430 /* xs:duration: "PnYnMnDTnHnMnS" */
431 if (*p == 'P')
432 {
433 return _ParseWSManDuration(str, x);
434 }
435
436 /* xs:date: "YYYY-MM-DD" plus UTC */
437 if (isdigit(p[0]) && isdigit(p[1]) && isdigit(p[2]) && isdigit(p[3]))
438 {
439 p = _ParseWSManDate(str, x);
440 mike 1.1
441 if (!p)
442 return -1;
443
444 if (*p == '\0')
445 return 0;
446
447 /* xs:time "HH:MM:SS" plus UTC */
448 if (*p == 'T')
449 {
450 p++;
451 p = _ParseWSManTime(p, x);
452
453 if (!p)
454 return -1;
455
456 if (*p == '\0')
457 return 0;
458 }
459 }
460
461 mike 1.1 /* xs:time: "HH:MM:SS" plus UTC */
462 if (isdigit(p[0]) && isdigit(p[1]) && p[2] == ':')
463 {
464 p = _ParseWSManTime(str, x);
465
466 if (!p)
467 return -1;
468
469 if (*p == '\0')
470 return 0;
471 }
472
473 /* Failed */
474 return -1;
475 }
476
|
477 krisbash 1.3 _Use_decl_annotations_
478 void FormatWSManDatetime(const MI_Datetime* x, ZChar buffer[64])
|
479 mike 1.1 {
480 int n = 64;
481
482 *buffer = '\0';
483
484 if (x->isTimestamp)
485 {
486 /* Example output: "2010-12-31T12:30:03.123456+06:00" */
|
487 krisbash 1.3 ZChar tmpbuf[64];
488
489 /* As per section 8.2 in DSP0230_1.1.0 date (year, month, day) containing all zero's is considered valida date.
490 Time containing all zeros is also considred as valid time.
|
491 mike 1.1
|
492 krisbash 1.3 MI_Datetime cannot store asterics ('*') as part of date or time.
493 So with MI_Datetime we will never get into case of not having time or date */
494 Stprintf(tmpbuf, MI_COUNT(tmpbuf), ZT("%04u-%02u-%02u"),
495 x->u.timestamp.year,
496 x->u.timestamp.month,
497 x->u.timestamp.day);
498 Tcslcat(buffer, tmpbuf, n);
|
499 mike 1.1
|
500 krisbash 1.3 Tcslcat(buffer, ZT("T"), n);
|
501 mike 1.1
|
502 krisbash 1.3 Stprintf(tmpbuf, MI_COUNT(tmpbuf), ZT("%02u:%02u:%02u"),
503 x->u.timestamp.hour,
504 x->u.timestamp.minute,
505 x->u.timestamp.second);
506 Tcslcat(buffer, tmpbuf, n);
|
507 mike 1.1
|
508 krisbash 1.3 if (x->u.timestamp.microseconds)
|
509 mike 1.1 {
|
510 krisbash 1.3 Stprintf(tmpbuf, MI_COUNT(tmpbuf), ZT(".%06u"),
511 x->u.timestamp.microseconds);
512 Tcslcat(buffer, tmpbuf, n);
|
513 mike 1.1 }
|
514 krisbash 1.3
|
515 mike 1.1 if (x->u.timestamp.utc > 0)
516 {
|
517 krisbash 1.3 Stprintf(tmpbuf, MI_COUNT(tmpbuf), ZT("+%02u:%02u"),
|
518 mike 1.1 x->u.timestamp.utc / 60, x->u.timestamp.utc % 60);
|
519 krisbash 1.3 Tcslcat(buffer, tmpbuf, n);
|
520 mike 1.1 }
521 else if (x->u.timestamp.utc < 0)
522 {
|
523 krisbash 1.3 Stprintf(tmpbuf, MI_COUNT(tmpbuf), ZT("-%02u:%02u"),
|
524 mike 1.1 -x->u.timestamp.utc / 60, -x->u.timestamp.utc % 60);
|
525 krisbash 1.3 Tcslcat(buffer, tmpbuf, n);
526 }
527 else
528 {
529 Tcslcat(buffer, ZT("Z"), n);
|
530 mike 1.1 }
531 }
532 else
533 {
|
534 krisbash 1.3 ZChar tmpbuf[64];
|
535 mike 1.1
536 /* Example: "P1Y1M22DT10H11M12S" */
537
|
538 krisbash 1.3 Tcslcat(buffer, ZT("P"), n);
|
539 mike 1.1
540 if (x->u.interval.days)
541 {
|
542 krisbash 1.3 Stprintf(tmpbuf, MI_COUNT(tmpbuf), ZT("%uD"), x->u.interval.days);
543 Tcslcat(buffer, tmpbuf, n);
|
544 mike 1.1 }
545
546 if (x->u.interval.hours || x->u.interval.minutes ||
547 x->u.interval.seconds || x->u.interval.microseconds)
548 {
|
549 krisbash 1.3 Tcslcat(buffer, ZT("T"), n);
|
550 mike 1.1 }
551
552 if (x->u.interval.hours)
553 {
|
554 krisbash 1.3 Stprintf(tmpbuf, MI_COUNT(tmpbuf), ZT("%uH"), x->u.interval.hours);
555 Tcslcat(buffer, tmpbuf, n);
|
556 mike 1.1 }
557
558 if (x->u.interval.minutes)
559 {
|
560 krisbash 1.3 Stprintf(tmpbuf, MI_COUNT(tmpbuf), ZT("%uM"), x->u.interval.minutes);
561 Tcslcat(buffer, tmpbuf, n);
|
562 mike 1.1 }
563
564 if (x->u.interval.seconds && x->u.interval.microseconds)
565 {
|
566 krisbash 1.3 Stprintf(tmpbuf, MI_COUNT(tmpbuf), ZT("%u.%06uS"),
|
567 mike 1.1 x->u.interval.seconds, x->u.interval.microseconds);
|
568 krisbash 1.3 Tcslcat(buffer, tmpbuf, n);
|
569 mike 1.1 }
570 else if (x->u.interval.seconds && !x->u.interval.microseconds)
571 {
|
572 krisbash 1.3 Stprintf(tmpbuf, MI_COUNT(tmpbuf), ZT("%uS"), x->u.interval.seconds);
573 Tcslcat(buffer, tmpbuf, n);
|
574 mike 1.1 }
575 else if (!x->u.interval.seconds && x->u.interval.microseconds)
576 {
|
577 krisbash 1.3 Stprintf(tmpbuf, MI_COUNT(tmpbuf), ZT("0.%06uS"),
|
578 mike 1.1 x->u.interval.microseconds);
|
579 krisbash 1.3 Tcslcat(buffer, tmpbuf, n);
|
580 mike 1.1 }
581 }
582 }
583
|
584 krisbash 1.3 int StrToChar16(const ZChar* str, MI_Char16* x)
|
585 mike 1.1 {
|
586 krisbash 1.3 ZChar* end;
587 *x = (MI_Char16)Tcstoul(str, &end, 0);
|
588 mike 1.1
589 if (*end != '\0')
590 return -1;
591
592 return 0;
593 }
594
|
595 krisbash 1.3 static int _StrDatetime_CheckAsterisk_ToU32(const ZChar* s, size_t offset, size_t size, MI_Uint32* x)
|
596 mike 1.1 {
|
597 krisbash 1.3 ZChar buf[64];
598 ZChar* end;
|
599 mike 1.1
|
600 krisbash 1.3 if (size >= MI_COUNT(buf))
|
601 mike 1.1 return -1;
602
|
603 krisbash 1.3 memcpy(buf, &s[offset], size * sizeof(ZChar));
604 buf[size] = '\0';
605
606 if (buf[0] == '*')
607 {
608 size_t i;
609 MI_Boolean allAsterisk = MI_TRUE;
610 for (i = 0; i < size; ++i)
611 {
612 if (buf[i] != '*')
613 {
614 allAsterisk = MI_FALSE;
615 break;
616 }
617 }
618
619 *x = 0;
620
621 if (allAsterisk == MI_TRUE)
622 return 0;
623 else
624 krisbash 1.3 return -1;
625 }
626 else
627 {
628 *x = (MI_Uint32)Tcstoul(buf, &end, 10);
629
630 if (*end != '\0')
631 return -1;
632 }
633
634 /* Success */
|
635 mike 1.1 return 0;
636 }
637
|
638 krisbash 1.3 int StrToDatetime(const ZChar* s, MI_Datetime* x)
|
639 mike 1.1 {
|
640 krisbash 1.3 if (Tcslen(s) != 25)
|
641 mike 1.1 return -1;
642
643 memset(x, 0, sizeof(MI_Datetime));
644
645 if (s[21] == '+' || s[21] == '-')
646 {
647 MI_Uint32 utc;
648
649 /* It must be a timestamp (YYYYMMDDHHMMSS.MMMMMMSUTC) */
|
650 krisbash 1.3 if (_StrDatetime_CheckAsterisk_ToU32(s, 0, 4, &x->u.timestamp.year) != 0 ||
651 _StrDatetime_CheckAsterisk_ToU32(s, 4, 2, &x->u.timestamp.month) != 0 ||
652 _StrDatetime_CheckAsterisk_ToU32(s, 6, 2, &x->u.timestamp.day) != 0 ||
653 _StrDatetime_CheckAsterisk_ToU32(s, 8, 2, &x->u.timestamp.hour) != 0 ||
654 _StrDatetime_CheckAsterisk_ToU32(s, 10, 2, &x->u.timestamp.minute) != 0 ||
655 _StrDatetime_CheckAsterisk_ToU32(s, 12, 2, &x->u.timestamp.second) != 0 ||
|
656 mike 1.1 s[14] != '.' ||
|
657 krisbash 1.3 _StrDatetime_CheckAsterisk_ToU32(s, 15, 6, &x->u.timestamp.microseconds) != 0 ||
658 _StrDatetime_CheckAsterisk_ToU32(s, 22, 3, &utc) != 0)
|
659 mike 1.1 {
660 return -1;
661 }
662
663 if (s[21] == '+')
664 x->u.timestamp.utc = (MI_Sint32)utc;
665 else
666 x->u.timestamp.utc = -(MI_Sint32)utc;
667
668 x->isTimestamp = 1;
669 }
670 else if (s[21] == ':')
671 {
672 /* It must be an interval (DDDDDDDDHHMMSS.MMMMMM:000) */
|
673 krisbash 1.3 if (_StrDatetime_CheckAsterisk_ToU32(s, 0, 8, &x->u.interval.days) != 0 ||
674 _StrDatetime_CheckAsterisk_ToU32(s, 8, 2, &x->u.interval.hours) != 0 ||
675 _StrDatetime_CheckAsterisk_ToU32(s, 10, 2, &x->u.interval.minutes) != 0 ||
676 _StrDatetime_CheckAsterisk_ToU32(s, 12, 2, &x->u.interval.seconds) != 0 ||
|
677 mike 1.1 s[14] != '.' ||
|
678 krisbash 1.3 _StrDatetime_CheckAsterisk_ToU32(s, 15, 6, &x->u.interval.microseconds) != 0 ||
|
679 mike 1.1 s[22] != '0' || s[23] != '0' || s[24] != '0')
680 {
681 return -1;
682 }
683
684 x->isTimestamp = 0;
685 }
686 else
687 return -1;
688
689 return 0;
690 }
691
|
692 krisbash 1.3 static int _ParseDatetime(const ZChar* str, MI_Datetime* x)
|
693 mike 1.1 {
694 if (StrToDatetime(str, x) == 0)
695 return 0;
696
697 if (ParseWSManDatetime(str, x) == 0)
698 return 0;
699
700 return -1;
701 }
702
|
703 krisbash 1.3 int StrToBoolean(const ZChar* str, MI_Boolean* x)
|
704 mike 1.1 {
|
705 krisbash 1.3 if (Tcscasecmp(str, ZT("true")) == 0)
|
706 mike 1.1 *x = MI_TRUE;
|
707 krisbash 1.3 else if (Tcscasecmp(str, ZT("false")) == 0)
|
708 mike 1.1 *x = MI_FALSE;
709 else
710 return -1;
711
712 return 0;
713 }
714
|
715 krisbash 1.3 int StrToUint8(const ZChar* str, MI_Uint8* x)
|
716 mike 1.1 {
|
717 krisbash 1.3 ZChar* end;
718 *x = (MI_Uint8)Tcstoul(str, &end, 0);
|
719 mike 1.1
720 if (*end != '\0')
721 return -1;
722
723 return 0;
724 }
725
|
726 krisbash 1.3 int StrToSint8(const ZChar* str, MI_Sint8* x)
|
727 mike 1.1 {
|
728 krisbash 1.3 ZChar* end;
729 *x = (MI_Sint8)Tcstol(str, &end, 0);
|
730 mike 1.1
731 if (*end != '\0')
732 return -1;
733
734 return 0;
735 }
736
|
737 krisbash 1.3 int StrToUint16(const ZChar* str, MI_Uint16* x)
|
738 mike 1.1 {
|
739 krisbash 1.3 ZChar* end;
740 *x = (MI_Uint16)Tcstoul(str, &end, 0);
|
741 mike 1.1
742 if (*end != '\0')
743 return -1;
744
745 return 0;
746 }
747
|
748 krisbash 1.3 int StrToSint16(const ZChar* str, MI_Sint16* x)
|
749 mike 1.1 {
|
750 krisbash 1.3 ZChar* end;
751 *x = (MI_Sint16)Tcstol(str, &end, 0);
|
752 mike 1.1
753 if (*end != '\0')
754 return -1;
755
756 return 0;
757 }
758
|
759 krisbash 1.3 int StrToUint32(const ZChar* str, MI_Uint32* x)
|
760 mike 1.1 {
|
761 krisbash 1.3 ZChar* end;
762 *x = (MI_Uint32)Tcstoul(str, &end, 0);
|
763 mike 1.1
764 if (*end != '\0')
765 return -1;
766
767 return 0;
768 }
769
|
770 krisbash 1.3 int StrToSint32(const ZChar* str, MI_Sint32* x)
|
771 mike 1.1 {
|
772 krisbash 1.3 ZChar* end;
773 *x = (MI_Sint32)Tcstol(str, &end, 0);
|
774 mike 1.1
775 if (*end != '\0')
776 return -1;
777
778 return 0;
779 }
780
|
781 krisbash 1.3 int StrToUint64(const ZChar* str, MI_Uint64* x)
|
782 mike 1.1 {
|
783 krisbash 1.3 ZChar* end;
784 *x = (MI_Uint64)Tcstoull(str, &end, 0);
|
785 mike 1.1
786 if (*end != '\0')
787 return -1;
788
789 return 0;
790 }
791
|
792 krisbash 1.3 int StrToSint64(const ZChar* str, MI_Sint64* x)
|
793 mike 1.1 {
|
794 krisbash 1.3 ZChar* end;
795 *x = (MI_Sint64)Tcstoll(str, &end, 0);
|
796 mike 1.1
797 if (*end != '\0')
798 return -1;
799
800 return 0;
801 }
802
|
803 krisbash 1.3 int StrToReal32(const ZChar* str, MI_Real32* x)
|
804 mike 1.1 {
|
805 krisbash 1.3 ZChar* end;
806 *x = (MI_Real32)Tcstod(str, &end);
|
807 mike 1.1
808 if (*end != '\0')
809 return -1;
810
811 return 0;
812 }
813
|
814 krisbash 1.3 int StrToReal64(const ZChar* str, MI_Real64* x)
|
815 mike 1.1 {
|
816 krisbash 1.3 ZChar* end;
817 *x = (MI_Real64)Tcstod(str, &end);
|
818 mike 1.1
819 if (*end != '\0')
820 return -1;
821
822 return 0;
823 }
824
|
825 krisbash 1.3 typedef int (*StrToType)(const ZChar* str, void* x);
826
827 static StrToType _converters[] =
828 {
829 (StrToType)StrToBoolean,
830 (StrToType)StrToUint8,
831 (StrToType)StrToSint8,
832 (StrToType)StrToUint16,
833 (StrToType)StrToSint16,
834 (StrToType)StrToUint32,
835 (StrToType)StrToSint32,
836 (StrToType)StrToUint64,
837 (StrToType)StrToSint64,
838 (StrToType)StrToReal32,
839 (StrToType)StrToReal64,
840 (StrToType)StrToChar16,
841 (StrToType)_ParseDatetime,
842 NULL, /* STRING */
843 NULL, /* REFERENCE */
844 NULL, /* INSTANCE */
845 };
846 krisbash 1.3
|
847 mike 1.1 MI_Result MI_CALL Instance_SetElementFromString(
848 MI_Instance* self,
|
849 krisbash 1.3 const ZChar* name,
850 const ZChar* str,
851 MI_Uint32 flags)
|
852 mike 1.1 {
853 /* ATTN: check for integer value truncation (see use of Ztol) */
854 /* ATTN: implement array types! */
855 /* ATTN: implement instance and reference types! */
856 MI_Type type;
857 MI_Value value;
858
859 /* Check arguments */
860 if (!self || !name || !str)
|
861 krisbash 1.3 {
|
862 mike 1.1 MI_RETURN(MI_RESULT_INVALID_PARAMETER);
|
863 krisbash 1.3 }
|
864 mike 1.1
865 /* Obtain type of named property */
866 {
867 MI_Result r = MI_Instance_GetElement(self, name, NULL, &type,
868 NULL, NULL);
869
870 if (r != MI_RESULT_OK)
|
871 krisbash 1.3 {
|
872 mike 1.1 return r;
|
873 krisbash 1.3 }
|
874 mike 1.1 }
875
876 /* If type is array and value is string,
877 try to create a single item array from this string
878 */
879 if (0 != (MI_ARRAY_BIT & type))
|
880 krisbash 1.3 {
881 return Instance_SetElementFromStringA(self, name, &str, 1, flags);
882 }
|
883 mike 1.1
884
885 /* Convert string to value */
|
886 krisbash 1.3 if (type == MI_STRING)
|
887 mike 1.1 {
|
888 krisbash 1.3 value.string = (ZChar*)str;
889 }
890 else
891 {
892 StrToType func = _converters[Type_ScalarOf(type)];
893
894 if (func)
|
895 mike 1.1 {
|
896 krisbash 1.3 if ((*func)(str, &value) != 0)
|
897 mike 1.1 MI_RETURN(MI_RESULT_FAILED);
898 }
|
899 krisbash 1.3 else
|
900 mike 1.1 {
901 MI_RETURN(MI_RESULT_FAILED);
902 }
903 }
904
905 MI_RETURN(MI_Instance_SetElement(self, name, &value, type, 0));
906 }
907
|
908 krisbash 1.3 // Allocates the buffer inside the callback
909 static int _Base64DecCallback(
910 const void* data,
911 size_t size,
912 void* callbackData)
913 {
914 MI_Array* arr= (MI_Array*)callbackData;
915 char** str = (char**)&arr->data;
916 size_t i;
917 char* start = NULL;
918 size_t totalSize = 0;
919 size_t skipSize = 4; // Skip first 4 bytes that contains buffer size
920
921 if( *str == NULL ) // This is the first time we are called
922 {
923 // prepend length in 4 bytes
924 *str = (char*)PAL_Malloc((size + 4) * sizeof(unsigned char));
925
926 if (!*str)
927 return -1;
928 totalSize = size + 4;
929 krisbash 1.3 }
930 else
931 {
932 char *newStr = NULL;
933 unsigned int p1 = ((unsigned char)(*str)[3]);
934 unsigned int p2 = ((unsigned char)(*str)[2]) << 8;
935 unsigned int p3 = ((unsigned char)(*str)[1]) << 16;
936 unsigned int p4 = ((unsigned char)(*str)[0]) << 24;
937 totalSize = p1 + p2 + p3 + p4;
938 skipSize = totalSize;
939 totalSize += size;
940 newStr = (char*)PAL_Malloc(totalSize * sizeof(unsigned char));
941 if (!newStr)
942 {
943 PAL_Free(arr->data);
944 arr->data = NULL;
945 arr->size = 0;
946 return -1;
947 }
948 memcpy(newStr+4, (*str) + 4, skipSize-4);
949 PAL_Free(*str);
950 krisbash 1.3 *str = newStr;
951 }
952
953 start = *str;
954 {
955 unsigned char b1 = (totalSize & 0xFF000000) >> 24;
956 unsigned char b2 = (totalSize & 0x00FF0000) >> 16;
957 unsigned char b3 = (totalSize & 0x0000FF00) >> 8;
958 unsigned char b4 = (totalSize & 0x000000FF);
959 (*str)[0] = b1;
960 (*str)[1] = b2;
961 (*str)[2] = b3;
962 (*str)[3] = b4;
963 (*str) += skipSize;
964 }
965
966 for (i = 0; i < size; i++)
967 {
968 **str = ((unsigned char*)data)[i];
969 (*str)++;
970 }
971 krisbash 1.3
972 *str = start;
973 arr->size = totalSize;
974
975 return 0;
976 }
977
|
978 mike 1.1 MI_Result MI_CALL Instance_SetElementFromStringA(
979 MI_Instance* self_,
|
980 krisbash 1.3 const ZChar* name,
981 const ZChar** data,
982 MI_Uint32 size,
983 MI_Uint32 msgFlags)
|
984 mike 1.1 {
985 Instance* self = (Instance*)self_;
986 MI_Type type = MI_BOOLEAN;
987 MI_Value v;
988 MI_Result result = MI_RESULT_OK;
989 MI_Uint32 flags = 0;
990
991 /* Clear value first */
992 memset(&v, 0, sizeof(v));
993
994 /* Check arguments */
995 if (!self || !name || !data)
996 {
997 /* return instead of goto failed: 'v' is not initialized yet */
998 return MI_RESULT_INVALID_PARAMETER;
999 }
1000
1001 /* Obtain type of named property */
|
1002 krisbash 1.3 result = MI_Instance_GetElement(self_, name, NULL, &type, NULL, NULL);
1003 if (result != MI_RESULT_OK)
|
1004 mike 1.1 {
1005 /* return instead of goto failed: 'v' is not initialized yet */
|
1006 krisbash 1.3 return result;
1007 }
1008
1009 /* handling octet uint8 string */
1010 if (type == MI_UINT8A)
1011 {
1012 MI_Type qType;
1013 MI_Value qValue;
1014 MI_Uint32 qFlags, qIndex;
1015 MI_QualifierSet qSet;
1016 MI_Class * schema = NULL;
1017
1018 MI_Result result = Class_New(
1019 self->classDecl,
1020 NULL,
1021 NULL,
1022 &schema);
1023 if (result != MI_RESULT_OK || schema == NULL)
1024 {
1025 if (schema)
1026 MI_Class_Delete(schema);
1027 krisbash 1.3 return result;
1028 }
1029
1030 result = MI_Class_GetElement(schema, name, NULL, NULL, &type, NULL, &qSet, NULL, NULL);
1031 if (result != MI_RESULT_OK)
1032 {
1033 MI_Class_Delete(schema);
1034 return result;
1035 }
1036
1037 result = MI_QualifierSet_GetQualifier(&qSet, MI_T("Octetstring"), &qType, &qFlags, &qValue, &qIndex);
1038 MI_Class_Delete(schema);
1039 MI_UNUSED(qFlags);
1040 MI_UNUSED(qIndex);
1041
1042 //If the qualifier is present and set to "true", this is an OctetString.
1043 if (result == MI_RESULT_OK && qType == MI_BOOLEAN && qValue.boolean == MI_TRUE
1044 && ((msgFlags & WSMANFlag) == WSMANFlag))
1045 {
1046 size_t sizeIncoming = Tcslen(*data);
1047 size_t sizeDec = 0;
1048 krisbash 1.3
1049 #if defined(CONFIG_ENABLE_WCHAR)
1050 void* src = PAL_Calloc(sizeIncoming + 1, sizeof(char));
1051 if (!src)
1052 {
1053 return MI_RESULT_FAILED;
1054 }
1055
1056 if (StrWcslcpy((char *)src, *data, sizeIncoming + 1) >= sizeIncoming + 1)
1057 {
1058 PAL_Free(src);
1059 return MI_RESULT_FAILED;
1060 }
1061 #else
1062 char * src = (char*) *data;
1063 #endif
1064 sizeDec = Base64Dec((const void *)src, sizeIncoming, _Base64DecCallback, &v.array);
1065 #if defined(CONFIG_ENABLE_WCHAR)
1066 PAL_Free(src);
1067 #endif
1068 if (sizeDec == -1)
1069 krisbash 1.3 {
1070 trace_Base64Dec_Failed();
1071 return MI_RESULT_FAILED;
1072 }
1073 // handle an empty array
1074 else if (v.array.size == 0)
1075 {
1076 // prepend length in 4 bytes
1077 v.uint8a.data = (MI_Uint8*)PAL_Calloc(4, sizeof(MI_Uint8));
1078 if (!v.uint8a.data)
1079 {
1080 trace_OutOfMemory();
1081 return MI_RESULT_FAILED;
1082 }
1083
1084 v.uint8a.data[3] = 4;
1085 v.uint8a.size = 4;
1086 }
1087
1088 #if !defined(USE_ALLOCATOR)
1089 flags |= MI_FLAG_ADOPT;
1090 krisbash 1.3 #endif
1091
1092 result = MI_Instance_SetElement(self_, name, &v, type, flags);
1093
1094 #if defined(USE_ALLOCATOR)
1095 if (v.array.data)
1096 PAL_Free(v.array.data);
1097 #endif
1098 goto done;
1099 }
|
1100 mike 1.1 }
1101
1102 /* Allocate array (allocate extra element for possible empty array) */
1103 if (type == MI_STRINGA)
1104 {
|
1105 krisbash 1.3 v.array.data = (ZChar**)data;
|
1106 mike 1.1 v.array.size = size;
1107 }
1108 else
1109 {
1110 MI_Uint32 esize = (MI_Uint32)Type_SizeOf(Type_ScalarOf(type));
1111 v.array.data = BAlloc(self->batch, (size + 1) * esize, CALLSITE);
1112
1113 if (!v.array.data)
1114 {
|
1115 krisbash 1.3 result = MI_RESULT_SERVER_LIMITS_EXCEEDED;
|
1116 mike 1.1 goto done;
1117 }
1118
1119 v.array.size = size;
1120 flags |= MI_FLAG_ADOPT;
1121 }
1122
|
1123 krisbash 1.3 /* Convert string to array */
1124
1125 if (type != MI_STRINGA)
|
1126 mike 1.1 {
|
1127 krisbash 1.3 StrToType func = _converters[Type_ScalarOf(type)];
1128 char* ptr = v.array.data;
1129 MI_Uint32 i;
1130
1131 if (!func)
|
1132 mike 1.1 {
|
1133 krisbash 1.3 result = MI_RESULT_FAILED;
1134 goto done;
|
1135 mike 1.1 }
|
1136 krisbash 1.3
1137 for (i = 0; i < size; i++)
|
1138 mike 1.1 {
|
1139 krisbash 1.3 if ((*func)(data[i], ptr) != 0)
|
1140 mike 1.1 {
|
1141 krisbash 1.3 result = MI_RESULT_INVALID_PARAMETER;
1142 goto done;
|
1143 mike 1.1 }
|
1144 krisbash 1.3
1145 ptr += Type_SizeOf(Type_ScalarOf(type));
|
1146 mike 1.1 }
1147 }
1148
|
1149 krisbash 1.3 result = MI_Instance_SetElement(self_, name, &v, type, flags);
1150 if (result != MI_RESULT_OK)
|
1151 mike 1.1 {
1152 goto done;
1153 }
1154
1155 done:
1156
1157 if (result && v.array.data && type != MI_STRINGA)
1158 BFree(self->batch, v.array.data, CALLSITE);
1159
1160 return result;
1161 }
1162
1163 MI_Result MI_CALL Instance_GetValue(
1164 MI_Instance* self,
|
1165 krisbash 1.3 const ZChar* name,
|
1166 mike 1.1 void* value,
1167 MI_Type type)
1168 {
1169 MI_Result r;
1170 MI_Value v;
1171 MI_Type t;
1172 MI_Uint32 f;
1173
1174 r = MI_Instance_GetElement(self, name, &v, &t, &f, NULL);
1175
1176 if (r != MI_RESULT_OK)
1177 MI_RETURN(r);
1178
1179 if (t != type)
1180 MI_RETURN(MI_RESULT_TYPE_MISMATCH);
1181
1182 if (f & MI_FLAG_NULL)
1183 MI_RETURN(MI_RESULT_NOT_FOUND);
1184
1185 if (!value)
1186 MI_RETURN(MI_RESULT_INVALID_PARAMETER);
1187 mike 1.1
1188 memcpy(value, &v, Type_SizeOf(type));
1189
1190 MI_RETURN(MI_RESULT_OK);
1191 }
1192
|
1193 krisbash 1.3 _Use_decl_annotations_
1194 void DatetimeToStr(const MI_Datetime* x, ZChar buf[26])
|
1195 mike 1.1 {
1196 if (x->isTimestamp)
1197 {
|
1198 krisbash 1.3 const ZChar FMT[] = MI_T("%04d%02d%02d%02d%02d%02d.%06d%c%03d");
|
1199 mike 1.1 MI_Sint32 utc = x->u.timestamp.utc;
|
1200 krisbash 1.3 Stprintf(buf, 26, FMT,
|
1201 mike 1.1 x->u.timestamp.year,
1202 x->u.timestamp.month,
1203 x->u.timestamp.day,
1204 x->u.timestamp.hour,
1205 x->u.timestamp.minute,
1206 x->u.timestamp.second,
1207 x->u.timestamp.microseconds,
1208 utc < 0 ? '-' : '+',
1209 utc < 0 ? -utc : utc);
1210 }
1211 else
1212 {
|
1213 krisbash 1.3 const ZChar FMT[] = MI_T("%08u%02u%02u%02u.%06u:000");
1214 Stprintf(buf, 26, FMT,
|
1215 mike 1.1 x->u.interval.days,
1216 x->u.interval.hours,
1217 x->u.interval.minutes,
1218 x->u.interval.seconds,
1219 x->u.interval.microseconds);
1220 }
1221 }
|
1222 krisbash 1.3
1223 int DatetimeToUsec(
1224 const MI_Datetime* x,
1225 MI_Uint64* dateTimeAsUsec )
1226 {
1227 MI_Uint64 tally = 0; /* Accumulator for converted values*/
1228
1229 /* Check for NULL input and invalid datetime format */
1230 if ( !x ||
1231 !dateTimeAsUsec ||
1232 x->isTimestamp )
1233 {
1234 return -1;
1235 }
1236
1237 tally += x->u.interval.seconds;
1238 tally += x->u.interval.minutes * 60; /* minutes to seconds */
1239 tally += x->u.interval.hours * 60 * 60; /* hours to seconds */
1240 tally += x->u.interval.days * 24 * 60 * 60; /* days to seconds */
1241 tally *= 1000000; /* seconds to microseconds */
1242
1243 krisbash 1.3 *dateTimeAsUsec = x->u.interval.microseconds + tally;
1244 return 0;
1245 }
1246
|