(file) Return to helpers.c CVS log (file) (dir) Up to [OMI] / omi / base

   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, &microseconds);
 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, &microseconds);
 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              

ViewCVS 0.9.2