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

ViewCVS 0.9.2