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