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

   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 <assert.h>
  26           #include <ctype.h>
  27           #include "wsmanparser.h"
  28           #include "wsbuf.h"
  29           #include <base/log.h>
  30           #include <base/result.h>
  31 krisbash 1.4 #include <pal/strings.h>
  32              #include <pal/format.h>
  33              #include <indication/common/indicommon.h>
  34              #include <base/helpers.h>
  35              
  36              #if defined(CONFIG_ENABLE_WCHAR)
  37              # define HASHSTR_CHAR TChar
  38              # define HASHSTR_T(STR) L##STR
  39              # define HASHSTR_STRCMP wcscmp
  40              #endif
  41 mike     1.1 
  42              #include "wstags.h"
  43 krisbash 1.4 
  44              #if defined(CONFIG_FAVORSIZE)
  45              # include "wstags_small.inc"
  46              #else
  47              # include "wstags_quick.inc"
  48              #endif
  49              
  50 mike     1.1 #include <wsman/uri.h>
  51              
  52 krisbash 1.4 //#if 0
  53 mike     1.1 #define ENABLE_TRACING
  54 krisbash 1.4 //#endif
  55 mike     1.1 
  56 krisbash 1.4 #define TRACE_RETURN
  57 mike     1.1 
  58              #if defined(TRACE_RETURN)
  59              # define RETURN(X) \
  60                  do \
  61                  { \
  62 krisbash 1.4         trace_WsmanReturn( __FILE__, __LINE__ ); \
  63 mike     1.1         return X; \
  64                  } \
  65                  while (0)
  66              #else
  67              # define RETURN(X) return X
  68              #endif
  69              
  70              /*
  71              **==============================================================================
  72              **
  73              ** Local definitions:
  74              **
  75              **==============================================================================
  76              */
  77              static int _GetInstance(
  78                  XML* xml, 
  79                  XML_Elem *start,
  80                  Batch*  dynamicBatch,
  81                  MI_Instance** dynamicInstanceParams);
  82              
  83 krisbash 1.4 static int _GetReference(
  84                  XML* xml, 
  85                  XML_Elem *start,
  86                  Batch*  dynamicBatch,
  87                  MI_Instance** dynamicInstanceParams);
  88              
  89 mike     1.1 /****************************************************************************************/
  90              /* soap processing */
  91              
  92              static int _MustUnderstandCanBeIgnored(
  93                  const XML_Elem* e)
  94              {
  95                  size_t i;
  96                  for (i = 0; i < e->attrsSize; i++)
  97                  {
  98 krisbash 1.4         if (e->attrs[i].name.namespaceId == MI_T('s') &&
  99                          Tcscmp(e->attrs[i].name.data, PAL_T("mustUnderstand")) == 0 &&
 100                          Tcscmp(e->attrs[i].value, PAL_T("true")) == 0)
 101 mike     1.1         {
 102                          RETURN(-1);
 103                      }
 104                  }
 105                  return 0;
 106              }
 107              
 108 krisbash 1.4 static MI_Boolean IsValidClassname(const TChar* classname)
 109 mike     1.1 {
 110 krisbash 1.4     const TChar* p = classname;
 111 mike     1.1 
 112 krisbash 1.4     if (!isalpha((unsigned int)(*p)) && *p != '_')
 113 mike     1.1         return MI_FALSE;
 114              
 115                  p++;
 116              
 117                  for (; *p; p++)
 118                  {
 119 krisbash 1.4         if (!isalnum((unsigned int)(*p)) && *p != '_')
 120 mike     1.1             return MI_FALSE;
 121                  }
 122              
 123                  return MI_TRUE;
 124              }
 125              
 126 krisbash 1.4 static int _ParseBooleanOption(_In_ XML_Elem *e, _Inout_ MI_Boolean *ptrToOption)
 127              {
 128                  if(Tcscasecmp(e->data.data, PAL_T("true")) == 0)
 129                  {
 130                      *ptrToOption = 1;
 131                  }
 132                  else if(Tcscasecmp(e->data.data, PAL_T("false")) == 0)
 133                  {
 134                      *ptrToOption = 0;
 135                  }
 136                  else
 137                      RETURN(-1);
 138              
 139                  return 0;
 140              }
 141              
 142              static int _GetOption(
 143                  _In_ XML* xml,
 144                  _In_ XML_Elem *e,
 145                  _Inout_ WSMAN_WSHeader* wsheader)
 146 mike     1.1 {
 147                  size_t i;
 148              
 149                  for (i = 0; i < e->attrsSize; i++)
 150                  {
 151                      /* To support GetClass */
 152 krisbash 1.4         if ((e->attrs[i].name.namespaceId == 0) && 
 153                          Tcscmp(e->attrs[i].name.data, PAL_T("Name")) == 0)
 154 mike     1.1         {
 155 krisbash 1.4             int valueHash = 0;
 156                          
 157                          if (XML_Expect(xml, e, XML_CHARS, 0, NULL) != 0)
 158 mike     1.1                 RETURN(-1);
 159              
 160 krisbash 1.4             valueHash = HashStr(0, e->attrs[i].value, e->attrs[i].valueSize);
 161 mike     1.1 
 162 krisbash 1.4             // the WSMAN_OPTION_WMI_* is to check for these options included as custom options
 163                          if((valueHash == WSMAN_OPTION_INCLUDE_INHERITANCE_HIERARCHY) ||
 164                              (valueHash == WSMAN_OPTION_WMI_INCLUDE_INHERITANCE_HIERARCHY))
 165                          {
 166                              if(_ParseBooleanOption(e, &(wsheader->includeInheritanceHierarchy)) != 0)
 167                                  RETURN(-1);
 168                          }
 169                          else if((valueHash == WSMAN_OPTION_INCLUDE_INHERITED_ELEMENTS) || 
 170                                  (valueHash == WSMAN_OPTION_WMI_INCLUDE_INHERITED_ELEMENTS))
 171                          {
 172                              if(_ParseBooleanOption(e, &(wsheader->includeInheritedElements)) != 0)
 173                                  RETURN(-1);
 174                          }
 175                          else if((valueHash == WSMAN_OPTION_INCLUDE_QUALIFIERS) || 
 176                                  (valueHash == WSMAN_OPTION_WMI_INCLUDE_QUALIFIERS))
 177                          {
 178                              if(_ParseBooleanOption(e, &(wsheader->includeQualifiers)) != 0)
 179                                  RETURN(-1);
 180                          }
 181                          else if((valueHash == WSMAN_OPTION_INCLUDE_CLASS_ORIGIN) || 
 182                                  (valueHash == WSMAN_OPTION_WMI_INCLUDE_CLASS_ORIGIN))
 183 krisbash 1.4             {
 184                              if(_ParseBooleanOption(e, &(wsheader->includeClassOrigin)) != 0)
 185                                  RETURN(-1);
 186                          }
 187                          else if(valueHash == WSMAN_OPTION_MSFTWINRM_USE_PRECISE_ARRAYS)
 188                          {
 189                              if(_ParseBooleanOption(e, &(wsheader->usePreciseArrays)) != 0)
 190                                  RETURN(-1);
 191                          }
 192                      }
 193                      else
 194                          continue;
 195              
 196                      if (XML_Expect(xml, e, XML_END, PAL_T('w'), PAL_T("Option")) != 0)
 197                          RETURN(-1);
 198              
 199                      break;
 200                  }
 201              
 202                  return 0;
 203              }
 204 krisbash 1.4 
 205              static int _GetOptionSet(
 206                  XML* xml,
 207                  WSMAN_WSHeader* wsheader)
 208              {
 209                  XML_Elem e;
 210              
 211                  if (XML_Expect(xml, &e, XML_START, PAL_T('w'), PAL_T("Option")) != 0)
 212                      RETURN(-1);
 213              
 214                  /* iterate through all option tags */
 215                  for (;;)
 216                  {
 217                      if (0 != _GetOption(
 218                          xml,
 219                          &e,
 220                          wsheader))
 221                          RETURN(-1);
 222              
 223                      /**/
 224                      if (XML_Next(xml, &e) != 0)
 225 krisbash 1.4             RETURN(-1);
 226              
 227                      if (XML_END == e.type)
 228                          break;
 229                  }
 230              
 231                  return 0;
 232              }
 233 mike     1.1 
 234 krisbash 1.4 static int _GetSelector(
 235                  _In_ XML* xml,
 236                  _In_ XML_Elem *e,
 237                  _Inout_ const TChar** ns,
 238                  _Inout_ const TChar** classname,
 239                  _Inout_ MI_Instance** instance,
 240                  _Inout_ Batch** batch)
 241              {
 242                  size_t i;
 243 mike     1.1 
 244 krisbash 1.4     /* expecting namespace or key */
 245                  for (i = 0; i < e->attrsSize; i++)
 246                  {
 247                      /* To support GetClass */
 248                      if((e->attrs[i].name.namespaceId == 0) && 
 249                         (Tcscmp(e->attrs[i].name.data, PAL_T("Name")) == 0))
 250 mike     1.1         {
 251 krisbash 1.4             if (Tcscmp(e->attrs[i].value, PAL_T("ClassName")) == 0)
 252                          {
 253                              if (XML_Expect(xml, e, XML_CHARS, 0, NULL) != 0)
 254                                  RETURN(-1);
 255 mike     1.1 
 256 krisbash 1.4                 if (!IsValidClassname(e->data.data))
 257                                  RETURN(-1);
 258                              *classname = e->data.data;
 259                          }
 260                          else if(Tcscmp(e->attrs[i].value, PAL_T("__cimnamespace")) == 0)
 261                          {
 262                              /* namespace */
 263                              if (XML_Expect(xml, e, XML_CHARS, 0, NULL) != 0)
 264                                  RETURN(-1);
 265 mike     1.1 
 266 krisbash 1.4                 *ns = e->data.data;
 267                          }
 268                          else
 269                          {
 270                              /* keys */
 271                              const TChar* propName = e->attrs[i].value;
 272 mike     1.1 
 273 krisbash 1.4                 MI_Boolean selectorIsReference = MI_FALSE;
 274 mike     1.1 
 275 krisbash 1.4                 if (XML_Next(xml, e) != 0)
 276 mike     1.1                 {
 277 krisbash 1.4                     XML_Raise(xml, WSMAN_ERROR_BAD_SELECTOR);
 278 mike     1.1                     RETURN(-1);
 279                              }
 280              
 281 krisbash 1.4                 if((e->type == XML_START) &&
 282                                 (e->data.namespaceId == MI_T('a')) &&
 283                                 (Tcscmp(PAL_T("EndpointReference"), e->data.data) == 0))
 284 mike     1.1                 {
 285 krisbash 1.4                     if (XML_Next(xml, e) != 0)
 286                                  {
 287                                      XML_Raise(xml, WSMAN_ERROR_BAD_EPR_IN_SELECTOR);
 288                                      RETURN(-1);
 289                                  }       
 290              
 291                                  selectorIsReference = MI_TRUE;
 292 mike     1.1                 }
 293 krisbash 1.4                 else if(e->type != XML_CHARS) 
 294                              {
 295                                  XML_Raise(xml, WSMAN_ERROR_BAD_SELECTOR);
 296                                  RETURN(-1);
 297                              }                        
 298 mike     1.1 
 299 krisbash 1.4                 /* allocate batch and instance if needed */
 300                              if (!(*instance))
 301                              {
 302                                  MI_Result r;
 303                                  TChar* cn;
 304 mike     1.1 
 305 krisbash 1.4                     /* verify that we already received classname */
 306                                  if (!(*classname))
 307                                  {
 308                                      XML_Raise(
 309                                          xml, 
 310                                          WSMAN_ERROR_NO_CLASS_NAME_IN_SELECTOR);
 311                                      RETURN(-1);
 312                                  }
 313              
 314                                  /* Destroy old batch if it exists (from previous operation) */
 315                                  if (*batch)
 316                                  {
 317                                      Batch_Destroy(*batch);
 318                                  }
 319              
 320                                  *batch = Batch_New(BATCH_MAX_PAGES);
 321              
 322                                  if (!(*batch))
 323                                      RETURN(-1);
 324              
 325                                  cn = Batch_Tcsdup(*batch, *classname);
 326 krisbash 1.4                     if (!cn)
 327                                      RETURN(-1);
 328              
 329                                  r = Instance_NewDynamic(instance, cn, MI_FLAG_CLASS, *batch);
 330              
 331                                  if (MI_RESULT_OK != r)
 332                                      RETURN(-1);
 333                              }
 334 mike     1.1 
 335 krisbash 1.4                 /* add next property to the instance */
 336                              {
 337                                  const TChar* wpropName;
 338                                  MI_Result r;
 339                                  MI_Value value;
 340 mike     1.1 
 341 krisbash 1.4                     if (!(*batch))
 342                                  {
 343                                      *batch = Batch_New(BATCH_MAX_PAGES);
 344              
 345                                      if (!(*batch))
 346                                          RETURN(-1);
 347                                  }
 348 mike     1.1 
 349 krisbash 1.4                     wpropName = Batch_Tcsdup(*batch, propName);
 350                                  if (!wpropName)
 351                                      RETURN(-1);
 352 mike     1.1 
 353 krisbash 1.4                     if(selectorIsReference)
 354                                  {
 355                                      value.instance = 0;
 356                                      if (0 != _GetReference(xml, e, *batch, &(value.instance)))
 357                                          RETURN(-1);                
 358                                  }
 359                                  else
 360                                  {
 361                                      value.string = Batch_Tcsdup(*batch, e->data.data);
 362                                      if (!value.string)
 363                                          RETURN(-1);
 364                                  }
 365 mike     1.1 
 366 krisbash 1.4                     // Set the property.
 367                                  r = MI_Instance_AddElement(*instance, wpropName, &value, 
 368                                      (selectorIsReference ? MI_REFERENCE : MI_STRING), MI_FLAG_BORROW | MI_FLAG_KEY);
 369 mike     1.1 
 370 krisbash 1.4                     if (MI_RESULT_OK != r)
 371                                      RETURN(-1);
 372                              }
 373 mike     1.1             }
 374                      }
 375                      else
 376                          continue;
 377              
 378 krisbash 1.4         if (XML_Expect(xml, e, XML_END, PAL_T('w'), PAL_T("Selector")) != 0)
 379 mike     1.1             RETURN(-1);
 380              
 381                      break;
 382                  }
 383              
 384                  return 0;
 385              }
 386              
 387              static int _GetSelectorSet(
 388                  XML* xml,
 389                  WSMAN_WSHeader* wsheader)
 390              {
 391                  XML_Elem e;
 392              
 393 krisbash 1.4     if (XML_Expect(xml, &e, XML_START, PAL_T('w'), PAL_T("Selector")) != 0)
 394 mike     1.1         RETURN(-1);
 395              
 396                  /* iterate through all selector tags */
 397                  for (;;)
 398                  {
 399                      if (0 != _GetSelector(
 400                          xml, 
 401                          &e, 
 402                          &wsheader->rqtNamespace,
 403 krisbash 1.4             &wsheader->rqtClassname,
 404 mike     1.1             &wsheader->instance,
 405                          &wsheader->instanceBatch))
 406                          RETURN(-1);
 407              
 408                      /**/
 409                      if (XML_Next(xml, &e) != 0)
 410                          RETURN(-1);
 411              
 412                      if (XML_END == e.type)
 413                          break;
 414              
 415                  }
 416              
 417                  return 0;
 418              }
 419              
 420              static int _GetReferenceParameters(
 421 krisbash 1.4     _In_ XML* xml, 
 422                  _In_ Batch*  dynamicBatch,
 423                  _Inout_ MI_Instance** dynamicInstanceParams)
 424 mike     1.1 {
 425                  XML_Elem e;
 426 krisbash 1.4     const TChar* classname = NULL;
 427                  const TChar* nameSpace = NULL;
 428 mike     1.1 
 429                  /* extract ResourceURI and SelectorSet */
 430                  for (;;)
 431                  {
 432                      if (XML_Next(xml, &e) != 0)
 433                          RETURN(-1);
 434              
 435 krisbash 1.4         if (e.type == XML_CHARS)
 436                      {
 437                          continue;
 438                      }
 439              
 440 mike     1.1         if (XML_END == e.type)
 441                          break;
 442              
 443 krisbash 1.4         if (PAL_T('w') == e.data.namespaceId &&
 444                          0 == Tcscmp(PAL_T("ResourceURI"), e.data.data))
 445 mike     1.1         {
 446 krisbash 1.4             if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
 447                              RETURN(-1);
 448                          if (XML_StripWhitespace(&e) != 0)
 449 mike     1.1                 RETURN(-1);
 450 krisbash 1.4             classname = Tcsrchr(e.data.data, '/');
 451 mike     1.1 
 452                          /* skip '/' */
 453 krisbash 1.4             if (classname)
 454 mike     1.1                 classname++;
 455              
 456 krisbash 1.4             if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("ResourceURI")) != 0)
 457 mike     1.1                 RETURN(-1);
 458              
 459                          continue;
 460                      }
 461              
 462 krisbash 1.4         if (PAL_T('w') == e.data.namespaceId &&
 463                          0 == Tcscmp(PAL_T("SelectorSet"), e.data.data))
 464 mike     1.1         {
 465                          /* Allocate an instance */
 466                          if (!*dynamicInstanceParams)
 467                          {
 468                              MI_Result r;
 469 krisbash 1.4                 const TChar* cn;
 470 mike     1.1 
 471                              if (!classname)
 472                              {
 473 krisbash 1.4                     XML_Raise(xml, WSMAN_ERROR_NO_RESOURCE_URI);
 474 mike     1.1                     RETURN(-1);
 475                              }
 476              
 477 krisbash 1.4                 cn = Batch_Tcsdup(dynamicBatch, classname);
 478                              if (!cn)
 479                              {
 480                                  XML_Raise(xml, WSMAN_ERROR_OUTOFMEMORY);
 481                                  RETURN(-1);
 482                              }
 483 mike     1.1 
 484                              r = Instance_NewDynamic(dynamicInstanceParams, cn, MI_FLAG_CLASS, dynamicBatch);
 485                              if (MI_RESULT_OK != r)
 486                                  RETURN(-1);
 487                          }
 488              
 489                          /* iterate through all selector tags */
 490                          for (;;)
 491                          {
 492 krisbash 1.4                 const TChar* ns = NULL;
 493                              const TChar* cn = NULL;
 494 mike     1.1 
 495                              if (_GetSelector(
 496                                  xml, 
 497                                  &e, 
 498                                  &ns, 
 499 krisbash 1.4                     &cn, 
 500 mike     1.1                     dynamicInstanceParams, 
 501                                  &dynamicBatch) != 0)
 502                              {
 503                                  RETURN(-1);
 504                              }
 505              
 506                              if (ns)
 507                              {
 508                                  nameSpace = ns;
 509                              }
 510              
 511                              /**/
 512                              if (XML_Next(xml, &e) != 0)
 513                                  RETURN(-1);
 514              
 515 krisbash 1.4                 if (e.type == XML_CHARS)
 516                              {
 517                                  if (XML_Next(xml, &e) != 0)
 518                                      RETURN(-1);
 519                              }
 520 mike     1.1                 if (XML_END == e.type)
 521                                  break;
 522              
 523                          }
 524                          continue;
 525                      }
 526                  }
 527              
 528                  if (nameSpace)
 529                      (*dynamicInstanceParams)->nameSpace = nameSpace;
 530              
 531                  return 0;
 532              }
 533              
 534              static int _GetReference(
 535                  XML* xml, 
 536                  XML_Elem *start,
 537                  Batch*  dynamicBatch,
 538                  MI_Instance** dynamicInstanceParams)
 539              {
 540                  XML_Elem e;
 541 mike     1.1 
 542                  e = *start;
 543              
 544                  /* extract all parameters */
 545                  for (;;)
 546                  {
 547 krisbash 1.4         if (e.data.namespaceId != MI_T('a') ||
 548                          0 != Tcscmp(PAL_T("ReferenceParameters"), e.data.data))
 549 mike     1.1         {
 550                          if (XML_Skip(xml) != 0)
 551                              RETURN(-1);
 552              
 553                          if (XML_Next(xml, &e) != 0)
 554                              RETURN(-1);
 555 krisbash 1.4             if (e.type == XML_CHARS)
 556                          {
 557                              if (XML_Next(xml, &e) != 0)
 558                                  RETURN(-1);
 559                              continue;
 560                          }
 561 mike     1.1             if (e.type == XML_END)
 562                              break;
 563              
 564                          continue;
 565                      }
 566              
 567                      if (0 != _GetReferenceParameters(xml, dynamicBatch, dynamicInstanceParams))
 568                          RETURN(-1);
 569              
 570                      if (XML_Next(xml, &e) != 0)
 571                          RETURN(-1);
 572              
 573 krisbash 1.4         if (e.type == XML_CHARS)
 574                      {
 575                          if (XML_Next(xml, &e) != 0)
 576                              RETURN(-1);
 577                      }
 578 mike     1.1         if (e.type == XML_END)
 579                          break;
 580                  }
 581              
 582                  return 0;
 583              }
 584              
 585 krisbash 1.4 /*
 586              **==============================================================================
 587              **
 588              ** _GetSingleProperty()
 589              **
 590              **     This function gets a instance property. The caller has already counsumed
 591              **     the start property element. This function reads the value and the 
 592              **     closing property element.
 593              **
 594              **==============================================================================
 595              */
 596              
 597 mike     1.1 static int _GetSingleProperty(
 598                  XML* xml,
 599 krisbash 1.4     XML_Elem* start,
 600 mike     1.1     Batch*  dynamicBatch,
 601 krisbash 1.4     MI_Char nsId,
 602                  const TChar* propNameChar,
 603 mike     1.1     MI_Value* value,
 604 krisbash 1.4     MI_Type* type,
 605                  MI_Boolean* null)
 606 mike     1.1 {
 607                  XML_Elem e;
 608              
 609                  if (XML_Next(xml, &e) != 0)
 610                      RETURN(-1);
 611              
 612 krisbash 1.4     while(1)
 613 mike     1.1     {
 614 krisbash 1.4         if (e.type == XML_END)
 615                      {
 616                          if (nsId != e.data.namespaceId || 
 617                              Tcscmp(propNameChar, e.data.data) != 0)
 618                          {
 619                              trace_OpenCloseMismatch(tcs(propNameChar), tcs(e.data.data));
 620                              RETURN(-1);
 621                          }
 622              
 623                          /* Check whether this attribute is null or just empty */
 624                          {
 625                              const TChar* p = XML_Elem_GetAttr(&e, PAL_T('x'), PAL_T("nil"));
 626 mike     1.1 
 627 krisbash 1.4                 if (p && Tcscmp(p, PAL_T("true")) == 0)
 628                              {
 629                                  *null = MI_TRUE;
 630                              }
 631                              else
 632                              {
 633                                  *null = MI_FALSE;
 634                                  *type = MI_STRING;
 635                                  value->string = PAL_T("");
 636                              }
 637                          }
 638              
 639                          return 0;
 640                      }
 641                      else if (e.type == XML_CHARS)
 642                      {
 643                          XML_Elem tmpElem;
 644              
 645                          /* Check to make sure there isn't a start element next */
 646                          if (XML_Next(xml, &tmpElem) != 0)
 647                          {
 648 krisbash 1.4                 RETURN(-1);
 649                          }
 650                          if (tmpElem.type == XML_START)
 651                          {
 652                              /* This means we have text and a child element. Use the child element for now */
 653                              e = tmpElem;
 654                              continue;
 655                          }
 656                          if (XML_PutBack(xml, &tmpElem) != 0)
 657                          {
 658                              RETURN(-1);
 659                          }
 660              
 661                          /* Plain string property */
 662                          value->string = Batch_Tcsdup(dynamicBatch, e.data.data);
 663                          if (!value->string)
 664                              RETURN(-1);
 665                          *type = MI_STRING;
 666              
 667                          if (XML_Expect(xml, &e, XML_END, nsId, propNameChar) != 0)
 668                              RETURN(-1);
 669 krisbash 1.4 
 670                          *null = MI_FALSE;
 671                          return 0;
 672                      }
 673                      else if ('a' == e.data.namespaceId)
 674                      {
 675                          /* Reference as </adddress></ReferenceParameters>*/
 676                          value->instance = 0;
 677                          if (0 != _GetReference(xml, &e, dynamicBatch, &value->instance))
 678                              RETURN(-1);
 679              
 680                          *type = MI_REFERENCE;
 681                          *null = MI_FALSE;
 682                          return 0;
 683                      }
 684                      else
 685                      {
 686                          if (e.type == XML_START)
 687                          {
 688                              if (Tcscasecmp(e.data.data, PAL_T("CIM_DateTime")) == 0)
 689                              {
 690 krisbash 1.4                     /* DateTime property XML*/
 691                                  /* <p0:datetimeProperty xsi:type="cim:cimDateTime"> */
 692                                  /*     <CIM_DateTime>19990929195959.000000-420</CIM_DateTime> */
 693                                  /* </p0:datetimeProperty> */
 694                                  if (XML_Next(xml, &e) != 0)
 695                                  RETURN(-1);
 696                                  if (e.type == XML_CHARS)
 697                                  {
 698                                      value->string = Batch_Tcsdup(dynamicBatch, e.data.data);
 699                                      if (!value->string)
 700                                          RETURN(-1);
 701                                      *type = MI_STRING;
 702                                  }
 703                                  else
 704                                      RETURN(-1);
 705              
 706                                  if (XML_Expect(xml, &e, XML_END, 0, PAL_T("CIM_DateTime")) != 0)
 707                                      RETURN(-1);
 708              
 709                                  if (XML_Expect(xml, &e, XML_END, nsId, propNameChar) != 0)
 710                                      RETURN(-1);
 711 mike     1.1 
 712 krisbash 1.4                     *null = MI_FALSE;
 713                                  return 0;
 714                              }
 715                          }
 716                          /* Embedded instance */
 717                          value->instance = 0;
 718                          XML_PutBack(xml, &e);
 719 mike     1.1 
 720 krisbash 1.4             if (0 != _GetInstance(xml, start, dynamicBatch, &value->instance))
 721                              RETURN(-1);
 722 mike     1.1 
 723              
 724 krisbash 1.4             *type = MI_INSTANCE;
 725 mike     1.1 
 726 krisbash 1.4             *null = MI_FALSE;
 727                          return 0;
 728                      }
 729                  }
 730 mike     1.1 }
 731              
 732              static int _AddValueToArray(
 733                  Batch*  dynamicBatch,
 734                  MI_Value* valueA,
 735                  MI_Type typeA,
 736                  const MI_Value* value,
 737                  MI_Type type)
 738              {
 739                  /* does type match? */
 740                  if ((type | MI_ARRAY_BIT) != typeA)
 741                      RETURN(-1);
 742              
 743                  /* do we need to realloc array? */
 744                  if ((valueA->array.size % 16) == 0)
 745                  {
 746                      void* newData = Batch_Get(dynamicBatch, (valueA->array.size + 16) * sizeof(void*));
 747              
 748                      if (!newData)
 749                          RETURN(-1);
 750              
 751 mike     1.1         if (valueA->array.size)
 752                          memcpy(newData, valueA->array.data, valueA->array.size * sizeof(void*));
 753              
 754                      valueA->array.data = newData;
 755                  }
 756              
 757                  if (type == MI_STRING)
 758                      valueA->stringa.data[valueA->stringa.size] = value->string;
 759                  else
 760                      valueA->instancea.data[valueA->instancea.size] = value->instance;
 761              
 762                  valueA->array.size++;
 763                  return 0;
 764              }
 765              
 766              static int _GetInstance(
 767                  XML* xml, 
 768                  XML_Elem *start,
 769                  Batch*  dynamicBatch,
 770                  MI_Instance** dynamicInstanceParams)
 771              {
 772 mike     1.1     XML_Elem e;
 773 krisbash 1.4     const TChar* propNameA = 0;
 774 mike     1.1     MI_Value valueA;
 775                  MI_Type typeA = MI_BOOLEAN;
 776 krisbash 1.4     const TChar* propNamePrev = 0;
 777 mike     1.1     MI_Value valuePrev;
 778                  MI_Type typePrev = MI_BOOLEAN;
 779              
 780                  memset(&valueA, 0, sizeof(valueA));
 781              
 782                  /* extract all parameters */
 783                  for (;;)
 784                  {
 785                      if (XML_Next(xml, &e) != 0)
 786                          RETURN(-1);
 787              
 788 krisbash 1.4         /* Look for closing instance element */
 789              
 790                      if (e.type == XML_END && Tcscmp(e.data.data, start->data.data) == 0)
 791                      {
 792 mike     1.1             break;
 793 krisbash 1.4         }
 794 mike     1.1 
 795                      /* skip possible comments */
 796                      if (e.type != XML_START)
 797                          continue;
 798              
 799                      /* allocate new instance if needed */
 800                      if (!*dynamicInstanceParams)
 801                      {
 802                          MI_Result r;
 803 krisbash 1.4             TChar* cn = NULL;
 804              
 805                          // We are trying to parse an Instance, The type of the instance may be specified
 806                          // as a attribute Type or it is same as the element name. We'll attempt to get the
 807                          // type from attribute ... if not we'll use the element name.
 808                          // TODO: At this time we don't have the NS support in the XML parser, so using hardcoded
 809                          // 'xsi:type (good for windows client) once we get the NS support this code should be
 810                          // updated.
 811                          const TChar* typeName = XML_Elem_GetAttr(start, PAL_T('x'), PAL_T("type"));
 812              
 813                          if(typeName)
 814                          {
 815                              TChar* typeStart;
 816                              cn = Batch_Tcsdup(dynamicBatch, typeName);
 817              
 818                              if (!cn)
 819                              {
 820                                  trace_BatchTcsDup_Failed();
 821                                  RETURN(-1);
 822                              }
 823              
 824 krisbash 1.4                 // Trim the _Type from the name.
 825                              typeStart = Tcsrchr(cn, '_');
 826                              if( typeStart )
 827                              {
 828                                  *typeStart = PAL_T('\0');
 829              
 830                                  /* trim namespace start too */
 831                                  {
 832                                      TChar* afterColon;
 833                                      afterColon = Tcschr(cn, PAL_T(':'));
 834                                      if (afterColon)
 835                                      {
 836                                          afterColon++;
 837                                          cn = afterColon;
 838                                      }
 839                                  }
 840                              }
 841                              else
 842                              {
 843                                  trace_XsiTypeInvalidValue( cn );
 844                                  RETURN(-1);
 845 krisbash 1.4                     // cn is allocated on the batch, so it will be release along with it anyway
 846                              }
 847                          }
 848                          else
 849                          {
 850                              cn = Batch_Tcsdup(dynamicBatch, start->data.data);
 851                              if (!cn)
 852                              {
 853                                  trace_BatchTcsDup_Failed();
 854                                  RETURN(-1);
 855                              }
 856                          }
 857              
 858                          r = Instance_NewDynamic(
 859                              dynamicInstanceParams, 
 860                              cn, 
 861                              MI_FLAG_CLASS, 
 862                              dynamicBatch);
 863 mike     1.1 
 864                          if (MI_RESULT_OK != r)
 865                              RETURN(-1);
 866                      }
 867              
 868                      /* add next property to the instance */
 869 krisbash 1.4         if (e.data.size > 0) /* element name should have some data in it */
 870 mike     1.1         {
 871                          MI_Result r;
 872                          MI_Value value;
 873                          MI_Type type = MI_BOOLEAN;
 874 krisbash 1.4             const TChar* propNameChar;
 875                          const TChar* propName;
 876                          MI_Boolean null;
 877 mike     1.1 
 878 krisbash 1.4             propNameChar = e.data.data;
 879 mike     1.2 
 880                          /* Position propName one beyond ':' character */
 881 krisbash 1.4             propName = Batch_Tcsdup(dynamicBatch, propNameChar);
 882              
 883                          if (!propName)
 884 mike     1.2             {
 885 krisbash 1.4                 trace_BatchTcsDup_Failed();
 886                              RETURN(-1);
 887 mike     1.2             }
 888 mike     1.1 
 889                          type = MI_BOOLEAN;
 890              
 891 krisbash 1.4             if (_GetSingleProperty(
 892                              xml,
 893                              &e,
 894                              dynamicBatch, 
 895                              e.data.namespaceId,
 896                              propNameChar, 
 897                              &value, 
 898                              &type,
 899                              &null) != 0)
 900                          {
 901                              trace_GetSingleProperty_Failed( tcs(propNameChar) );
 902 mike     1.1                 RETURN(-1);
 903 krisbash 1.4             }
 904              
 905                          if (null)
 906                          {
 907                              /* Skip null attributes */
 908                              continue;
 909                          }
 910 mike     1.1 
 911                          /* Did we collect array's items? */
 912                          if (propNameA)
 913                          {
 914                              /* if we have array and new property matches array - add new item to the array */
 915 krisbash 1.4                 if (0 == Tcscmp(propNameA, propName))
 916 mike     1.1                 {
 917                                  if (0 != _AddValueToArray(dynamicBatch, &valueA, typeA, &value, type))
 918                                      RETURN(-1);
 919                              }
 920                              else
 921                              {
 922                                  r = MI_Instance_AddElement(*dynamicInstanceParams, propNameA, &valueA, 
 923                                      typeA, MI_FLAG_BORROW);
 924              
 925                                  if (MI_RESULT_OK != r)
 926                                      RETURN(-1);
 927              
 928                                  /* Clear array prop name */
 929                                  propNameA = 0;
 930              
 931                                  propNamePrev = propName;
 932                                  valuePrev = value;
 933                                  typePrev = type;
 934                              }
 935                          }
 936                          else if (propNamePrev)
 937 mike     1.1             {
 938                              /* Check if name is the same and we need to create an array */
 939 krisbash 1.4                 if (0 == Tcscmp(propNamePrev, propName))
 940 mike     1.1                 {
 941                                  /* create array */
 942                                  valueA.array.size = 0;
 943                                  valueA.array.data = 0;
 944              
 945                                  typeA = type | MI_ARRAY_BIT;
 946                                  propNameA = propName;
 947              
 948                                  if (0 != _AddValueToArray(dynamicBatch, &valueA, typeA, &valuePrev, typePrev))
 949                                      RETURN(-1);
 950              
 951                                  if (0 != _AddValueToArray(dynamicBatch, &valueA, typeA, &value, type))
 952                                      RETURN(-1);
 953              
 954                              }
 955                              else
 956                              {
 957 krisbash 1.4                     r = MI_Instance_AddElement(
 958                                      *dynamicInstanceParams, 
 959                                      propNamePrev, 
 960                                      &valuePrev, 
 961                                      typePrev, 
 962                                      MI_FLAG_BORROW);
 963 mike     1.1 
 964 mike     1.2                     /* Note that the MI_RESULT_ALREADY_EXISTS error is okay
 965                                   * for key properties added when the selector set was
 966                                   * parsed earlier.
 967                                   */
 968                                  if (r != MI_RESULT_OK && r != MI_RESULT_ALREADY_EXISTS)
 969                                  {
 970 mike     1.1                         RETURN(-1);
 971 mike     1.2                     }
 972 mike     1.1 
 973                                  propNamePrev = propName;
 974                                  valuePrev = value;
 975                                  typePrev = type;
 976                             }
 977              
 978                          }
 979                          else
 980                          {
 981                              /* collecting first item */
 982                              propNamePrev = propName;
 983                              valuePrev = value;
 984                              typePrev = type;
 985                          }
 986                      }
 987                  }
 988              
 989                  /* if last property was array - add it */
 990                  if (propNameA)
 991                  {
 992                      MI_Result r;
 993 mike     1.1 
 994                      r = MI_Instance_AddElement(*dynamicInstanceParams, propNameA, &valueA, 
 995                          typeA, MI_FLAG_BORROW);
 996              
 997                      if (MI_RESULT_OK != r)
 998                          RETURN(-1);
 999                  }
1000                  else if (propNamePrev)
1001                  {
1002                      MI_Result r;
1003              
1004                      r = MI_Instance_AddElement(*dynamicInstanceParams, propNamePrev, &valuePrev, 
1005                          typePrev, MI_FLAG_BORROW);
1006              
1007 krisbash 1.4         /* Note that the MI_RESULT_ALREADY_EXISTS error is okay
1008                      * for key properties added when the selector set was
1009                      * parsed earlier.
1010                      */
1011                      if (r != MI_RESULT_OK && r != MI_RESULT_ALREADY_EXISTS)
1012                      {
1013 mike     1.1             RETURN(-1);
1014 krisbash 1.4         }
1015 mike     1.1     }
1016              
1017                  /* check closing tag */
1018 krisbash 1.4     if (Tcscmp(e.data.data, start->data.data) != 0)
1019 mike     1.1         RETURN(-1);
1020              
1021                  return 0;
1022              }
1023              
1024              int WS_ParseWSHeader(
1025                  XML* xml,
1026 krisbash 1.4     WSMAN_WSHeader* wsheader,
1027                  UserAgent userAgent)
1028 mike     1.1 {
1029                  XML_Elem e;
1030              
1031 krisbash 1.4     if (wsheader->instanceBatch)
1032                  {
1033                      Batch_Delete(wsheader->instanceBatch);
1034                  }
1035 mike     1.1     memset(wsheader, 0, sizeof(WSMAN_WSHeader));
1036              
1037 krisbash 1.4     // WinRM client assumes that ClassOrigin is true by default on the server
1038                  // by standards, a wsman option is false by default so in non-WinRM case,
1039                  // the includeClassOrigin and all others are set to 0
1040                  wsheader->includeClassOrigin = (userAgent == USERAGENT_WINRM) ? 1 : 0;
1041                  wsheader->includeInheritanceHierarchy = 0;
1042                  wsheader->includeInheritedElements = 0;
1043                  wsheader->includeQualifiers = 0;
1044              
1045 mike     1.1     /* Expect <s:Header> */
1046 krisbash 1.4     if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Header")) != 0)
1047 mike     1.1         RETURN(-1);
1048              
1049                  for (;;)
1050                  {
1051                      if (XML_Next(xml, &e) != 0)
1052                          RETURN(-1);
1053              
1054                      if (e.type == XML_END)// && strcmp(e.data, "s:Header") == 0)
1055                      {
1056 krisbash 1.4             int tag = HashStr(e.data.namespaceId, e.data.data, e.data.size);
1057 mike     1.1 
1058                          if (WSMANTAG_HEADER != tag)
1059                          {
1060 krisbash 1.4                 trace_Wsman_UnexpectedCloseTag(tcs(e.data.data));
1061 mike     1.1                 RETURN(-1);
1062                          }
1063                          //printf("DONE\n");
1064                          break;
1065                      }
1066              
1067                      /* skip possible comments */
1068                      if (e.type != XML_START)
1069                          continue;
1070              
1071 krisbash 1.4         switch (HashStr(e.data.namespaceId, e.data.data, e.data.size))
1072 mike     1.1         {
1073                          case WSMANTAG_TO:
1074                          {
1075 krisbash 1.4                 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1076 mike     1.1                     RETURN(-1);
1077              
1078 krisbash 1.4                 if (XML_Expect(xml, &e, XML_END, PAL_T('a'), PAL_T("To")) != 0)
1079 mike     1.1                     RETURN(-1);
1080                          }
1081                          break;
1082              
1083                          case WSMANTAG_RESOURCE_URI:
1084                          {
1085 krisbash 1.4                 int resourceUriHash = 0;
1086                              
1087                              if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1088 mike     1.1                     RETURN(-1);
1089 krisbash 1.4                 
1090                              if (XML_StripWhitespace(&e) != 0)
1091                                  RETURN(-1);
1092              
1093                              wsheader->schemaRequestType = NOT_A_SCHEMA_REQUEST;
1094 mike     1.1 
1095 krisbash 1.4                 resourceUriHash = HashStr(0, e.data.data, e.data.size);
1096              
1097                              if(resourceUriHash == WSMAN_RESOURCE_URI_CIM_XML_SCHEMA)
1098                              {
1099                                  wsheader->schemaRequestType = CIM_XML_SCHEMA_REQUEST;                
1100                              }
1101                              else if(resourceUriHash == WSMAN_RESOURCE_URI_WS_CIM_SCHEMA)
1102                              {
1103                                  wsheader->schemaRequestType = WS_CIM_SCHEMA_REQEUST;                
1104                              }
1105              
1106                              wsheader->rqtClassname = Tcsrchr(e.data.data, '/');
1107 mike     1.1                 /* skip '/' */
1108                              if (wsheader->rqtClassname) 
1109                                  wsheader->rqtClassname++;
1110              
1111 krisbash 1.4                 if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("ResourceURI")) != 0)
1112 mike     1.1                     RETURN(-1);
1113                          }
1114                          break;
1115              
1116                          case WSMANTAG_REPLY_TO:
1117                          {
1118 krisbash 1.4                 while (1)
1119                              {
1120                                  if (XML_Next(xml, &e) != 0)
1121                                      RETURN(-1);
1122                                  /* skip whitespace and comments */
1123                                  if (e.type == XML_START)
1124                                      break;
1125                              }
1126                              if (HashStr(e.data.namespaceId, e.data.data, e.data.size) != WSMANTAG_ADDRESS)
1127 mike     1.1                     RETURN(-1);
1128              
1129 krisbash 1.4                 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1130 mike     1.1                     RETURN(-1);
1131              
1132 krisbash 1.4                 if (XML_Expect(xml, &e, XML_END, PAL_T('a'), PAL_T("Address")) != 0)
1133                                  RETURN(-1);
1134              
1135                              while (1)
1136                              {
1137                                  if (XML_Next(xml, &e) != 0)
1138                                      RETURN(-1);
1139                                  /* skip whitespace and comments */
1140                                  if (e.type == XML_END)
1141                                      break;
1142                              }
1143                              if (e.type != XML_END && HashStr(e.data.namespaceId, e.data.data, e.data.size) != WSMANTAG_REPLY_TO)
1144 mike     1.1                     RETURN(-1);
1145                          }
1146                          break;
1147              
1148                          case WSMANTAG_ACTION:
1149                          {
1150                              wsheader->foundAction = MI_TRUE;
1151              
1152 krisbash 1.4                 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1153                                  RETURN(-1);
1154              
1155                              if (XML_StripWhitespace(&e) != 0)
1156 mike     1.1                     RETURN(-1);
1157              
1158 krisbash 1.4                 wsheader->rqtAction = HashStr(e.data.namespaceId, e.data.data, e.data.size);
1159 mike     1.1 
1160                              if (0 == wsheader->rqtAction)
1161                              {
1162 krisbash 1.4                     TChar* s;
1163 mike     1.1                     /* DSP0226; 9: Custom Actions (Methods) just need to have unique URI.
1164                                      We are assuming it has format like http://<server>/wbem/wscim/1/cim-schema/2/<class-name>/<method-name> */
1165              
1166 krisbash 1.4                     if (0 != Tcsncmp(e.data.data, PAL_T("http://"), 7))
1167 mike     1.1                         RETURN(-1);
1168              
1169 krisbash 1.4                     wsheader->rqtServer = e.data.data + 7;
1170 mike     1.1 
1171 krisbash 1.4                     s = Tcschr(wsheader->rqtServer, '/');
1172 mike     1.1 
1173                                  if (!s)
1174                                      RETURN(-1);
1175              
1176                                  *s = 0;
1177                                  s++;
1178              
1179 krisbash 1.4                     if (0 != Tcsncmp(s, PAL_T("wbem/wscim/1/cim-schema/2/"), 26))
1180 mike     1.1                         RETURN(-1);
1181              
1182                                  s += 26;
1183              
1184                                  wsheader->rqtClassname = s;
1185 krisbash 1.4                     s = Tcschr(s, '/');
1186 mike     1.1 
1187                                  if (!s)
1188                                      RETURN(-1);
1189              
1190                                  *s = 0;
1191                                  s++;
1192                                  wsheader->rqtMethod = s;
1193                              }
1194              
1195 krisbash 1.4                 if (XML_Expect(xml, &e, XML_END, PAL_T('a'), PAL_T("Action")) != 0)
1196 mike     1.1                     RETURN(-1);
1197                          }
1198                          break;
1199              
1200                          case WSMANTAG_SELECTOR_SET:
1201                          {
1202                              if (_GetSelectorSet(xml, wsheader) != 0)
1203                                  RETURN(-1);
1204                          }
1205                          break;
1206              
1207 krisbash 1.4             case WSMANTAG_OPTION_SET:
1208                          {
1209                              if (_GetOptionSet(xml, wsheader) != 0)
1210                                  RETURN(-1);
1211                          }
1212                          break;
1213              
1214 mike     1.1             case WSMANTAG_MESSAGE_ID:
1215                          {
1216 krisbash 1.4                 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1217                                  RETURN(-1);
1218                              if (XML_StripWhitespace(&e) != 0)
1219                                  RETURN(-1);
1220                              wsheader->rqtMessageID = e.data.data;
1221              
1222                              if (XML_Expect(xml, &e, XML_END, PAL_T('a'), PAL_T("MessageID")) != 0)
1223                                  RETURN(-1);
1224                          }
1225                          break;
1226              
1227                          case WSMANTAG_MAX_ENVELOPE_SIZE:
1228                          {
1229                              if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1230                                  RETURN(-1);
1231                              if (XML_StripWhitespace(&e) != 0)
1232 mike     1.1                     RETURN(-1);
1233              
1234 krisbash 1.4                 wsheader->maxEnvelopeSize = (MI_Uint32)Tcstoull(
1235                                  e.data.data, NULL, 10);
1236 mike     1.1 
1237 krisbash 1.4                 if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("MaxEnvelopeSize")) != 0)
1238 mike     1.1                     RETURN(-1);
1239                          }
1240                          break;
1241              
1242 krisbash 1.4 #ifndef DISABLE_INDICATION
1243                          case WSMANTAG_OPERATION_TIMEOUT:
1244                          {
1245                              /* Expect an xs:duration of form: PnYnMnDTnHnMnS */
1246                              if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1247                                  RETURN(-1);
1248              
1249                              if (XML_StripWhitespace(&e) != 0)
1250                                  RETURN(-1);
1251              
1252                              if (-1 == ParseWSManDatetime( e.data.data, &wsheader->operationTimeout.value ) )
1253                                  RETURN(-1);
1254                              
1255                              wsheader->operationTimeout.exists = MI_TRUE;
1256              
1257                              if (XML_Expect(xml, &e, XML_END, MI_T('w'), MI_T("OperationTimeout")) != 0)
1258                                  RETURN(-1);
1259                          }
1260                          break;
1261                          
1262                          case WSMANTAG_SUBSCRIBE_IDENTIFIER:
1263 mike     1.1             {
1264 krisbash 1.4                 /* For unsubscribe, parse subscribe identifier from header */
1265                              if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1266 mike     1.1                     RETURN(-1);
1267              
1268 krisbash 1.4                 wsheader->contextID = (MI_Uint32)Tcstoull(e.data.data, NULL, 10);
1269                              trace_WsmanUnsubscribe( wsheader->contextID );
1270 mike     1.1 
1271 krisbash 1.4                 if (XML_Expect(xml, &e, XML_END, MI_T('e'), MI_T("Identifier")) != 0)
1272 mike     1.1                     RETURN(-1);
1273                          }
1274                          break;
1275 krisbash 1.4 #endif /* ifndef DISABLE_INDICATION */
1276 mike     1.1 
1277                          default:
1278                          {
1279                              if (_MustUnderstandCanBeIgnored(&e) != 0)
1280                              {
1281 krisbash 1.4                     wsheader->unknownMandatoryTag = e.data.data;
1282                                  trace_Wsman_UnknownMandatoryTag(tcs(e.data.data));
1283 mike     1.1                     /* validate header will send correct repsonse to the client */
1284                              }
1285              
1286                              if (XML_Skip(xml) != 0)
1287                                  RETURN(-1);
1288                          }
1289                          break;
1290              
1291                      }
1292                  }
1293 krisbash 1.4     /* DMTF standard requires default namespace to be used */
1294                  /* if _cimnamespace selector is not specified as part of request */
1295                  if (!wsheader->rqtNamespace)
1296                      wsheader->rqtNamespace = DEFAULT_CIMNAMESPACE;
1297 mike     1.1     return 0;
1298              }
1299              
1300              int WS_ParseSoapEnvelope(XML* xml)
1301              {
1302                  XML_Elem e;
1303              
1304                  /* Ignore the processing instruction (if any) */
1305                  {
1306                      if (XML_Next(xml, &e) != 0)
1307                      {
1308 krisbash 1.4             XML_Raise(xml, XML_ERROR_ELEMENT_EXPECTED);
1309 mike     1.1             RETURN(-1);
1310                      }
1311              
1312                      if (e.type != XML_INSTRUCTION)
1313                      {
1314                          if (XML_PutBack(xml, &e) != 0)
1315                              RETURN(-1);
1316                      }
1317                  }
1318              
1319                  /* Expect <s:Envelope> */
1320 krisbash 1.4     if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Envelope")) != 0)
1321 mike     1.1         RETURN(-1);
1322              
1323                  return 0;
1324              }
1325              
1326 krisbash 1.4 static const TChar* _ExpectCharsAndEnd(
1327 mike     1.1     XML* xml,
1328 krisbash 1.4     TChar nsId,
1329                  const TChar* name)
1330 mike     1.1 {
1331                  XML_Elem e;
1332 krisbash 1.4     const TChar* chars;
1333 mike     1.1 
1334 krisbash 1.4     if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1335 mike     1.1         return NULL;
1336              
1337 krisbash 1.4     chars = e.data.data;
1338 mike     1.1 
1339 krisbash 1.4     if (XML_Expect(xml, &e, XML_END, nsId, name) != 0)
1340 mike     1.1         return NULL;
1341              
1342                  return chars;
1343              }
1344              
1345              /*
1346              **==============================================================================
1347              **
1348              ** _ParseAssociationFilterObject()
1349              **
1350              ** Example:
1351              **   <b:Object>
1352              **     <a:Address>
1353              **       http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
1354              **     </a:Address>
1355              **     <a:ReferenceParameters>
1356              **       <w:ResourceURI>
1357              **         http://schemas.microsoft.com/wbem/wscim/1/cim-schema/2/ABC_Widget
1358              **       </w:ResourceURI>
1359              **       <w:SelectorSet>
1360              **         <w:Selector Name="__cimnamespace">
1361 mike     1.1 **           root/cimv2
1362              **         </w:Selector>
1363              **         <w:Selector Name="Key">
1364              **           1001
1365              **         </w:Selector>
1366              **       </w:SelectorSet>
1367              **     </a:ReferenceParameters>
1368              **   </b:Object>
1369              *
1370              **==============================================================================
1371              */
1372              
1373              static int _ParseAssociationFilterObject(
1374                  XML* xml, 
1375                  Batch* batch,
1376                  WSMAN_AssociationFilter* filter)
1377              {
1378                  XML_Elem e;
1379              
1380                  /* Parse child elements */
1381              
1382 mike     1.1     for (;;)
1383                  {
1384                      /* Get next element */
1385              
1386                      if (XML_Next(xml, &e) != 0)
1387                          RETURN(-1);
1388              
1389                      /* Put it back and break out if not a start tag */
1390              
1391                      if (e.type != XML_START)
1392                      {
1393                          if (XML_PutBack(xml, &e) != 0)
1394                              RETURN(-1);
1395              
1396                          break;
1397                      }
1398              
1399                      /* Handle "Object" tag */
1400              
1401 krisbash 1.4         if (PAL_T('a') == e.data.namespaceId && 
1402                          Tcscmp(e.data.data, PAL_T("ReferenceParameters")) == 0)
1403 mike     1.1         {
1404                          if (_GetReferenceParameters(
1405                              xml, 
1406                              batch, 
1407                              &filter->referenceParameters) != 0)
1408                          {
1409                              RETURN(-1);
1410                          }
1411                      }
1412 krisbash 1.4         else if (PAL_T('a') == e.data.namespaceId &&
1413                          Tcscmp(e.data.data, PAL_T("Address")) == 0)
1414 mike     1.1         {
1415 krisbash 1.4             filter->address = _ExpectCharsAndEnd(xml, PAL_T('a'), PAL_T("Address"));
1416 mike     1.1 
1417                          if (!filter->address)
1418                              RETURN(-1);
1419                      }
1420                      else
1421                      {
1422                          if (XML_Skip(xml) != 0)
1423                              RETURN(-1);
1424                      }
1425                  }
1426              
1427                  /* Expect </Object> */
1428              
1429 krisbash 1.4     if (XML_Expect(xml, &e, XML_END, PAL_T('b'), PAL_T("Object")) != 0)
1430 mike     1.1         RETURN(-1);
1431              
1432                  return 0;
1433              }
1434              
1435              /*
1436              **==============================================================================
1437              **
1438              ** _ParseAssociationFilter()
1439              **
1440              ** Example:
1441              **   <b:AssociatedInstances>
1442              **     <b:Object>
1443              **       <a:Address>
1444              **         http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
1445              **       </a:Address>
1446              **       <a:ReferenceParameters>
1447              **         <w:ResourceURI>
1448              **           http://schemas.microsoft.com/wbem/wscim/1/cim-schema/2/ABC_Widget
1449              **         </w:ResourceURI>
1450              **         <w:SelectorSet>
1451 mike     1.1 **           <w:Selector Name="__cimnamespace">
1452              **             root/cimv2
1453              **           </w:Selector>
1454              **           <w:Selector Name="Key">
1455              **             1001
1456              **           </w:Selector>
1457              **         </w:SelectorSet>
1458              **       </a:ReferenceParameters>
1459              **       </b:Object>
1460              **       <b:AssociationClassName>
1461              **           ABC_Connector
1462              **       </b:AssociationClassName>
1463              **       <b:Role>
1464              **           Component
1465              **       </b:Role>
1466              **     <b:ResultClassName>
1467              **       ABC_Gadget
1468              **     </b:ResultClassName>
1469              **     <b:ResultRole>
1470              **       Part
1471              **     </b:ResultRole>
1472 mike     1.1 **   </b:AssociatedInstances>
1473              **
1474              **==============================================================================
1475              */
1476              
1477              static int _ParseAssociationFilter(
1478                  XML* xml, 
1479                  Batch* batch,
1480                  WSMAN_AssociationFilter* filter)
1481              {
1482                  XML_Elem e;
1483              
1484                  /* Expect <AssociatedInstances> */
1485              
1486 krisbash 1.4     if (XML_Next(xml, &e) != 0 || e.type != XML_START )
1487                  {
1488                  	RETURN(-1);
1489                  }
1490              
1491                  if (PAL_T('b') == e.data.namespaceId &&
1492                      Tcscmp(e.data.data, PAL_T("AssociatedInstances")) == 0)
1493                  {
1494                  	filter->isAssosiatorOperation = MI_TRUE;
1495                  }
1496                  else if (PAL_T('b') == e.data.namespaceId &&
1497                      Tcscmp(e.data.data, PAL_T("AssociationInstances")) == 0)
1498                  {
1499                  	filter->isAssosiatorOperation = MI_FALSE;
1500                  }
1501                  else
1502 mike     1.1         RETURN(-1);
1503              
1504                  /* Parse child elements */
1505              
1506                  for (;;)
1507                  {
1508                      /* Get next element */
1509              
1510                      if (XML_Next(xml, &e) != 0)
1511                          RETURN(-1);
1512              
1513                      /* Put it back and break out if not a start tag */
1514              
1515                      if (e.type != XML_START)
1516                      {
1517                          if (XML_PutBack(xml, &e) != 0)
1518                              RETURN(-1);
1519              
1520                          break;
1521                      }
1522              
1523 mike     1.1         /* Handle "Object" tag */
1524              
1525 krisbash 1.4         if (PAL_T('b') == e.data.namespaceId &&
1526                          Tcscmp(e.data.data, PAL_T("Object")) == 0)
1527 mike     1.1         {
1528                          if (_ParseAssociationFilterObject(xml, batch, filter) != 0)
1529                              RETURN(-1);
1530                      }
1531 krisbash 1.4         else if (PAL_T('b') == e.data.namespaceId &&
1532                          Tcscmp(e.data.data, PAL_T("AssociationClassName")) == 0)
1533 mike     1.1         {
1534                          filter->associationClassName = _ExpectCharsAndEnd(
1535 krisbash 1.4                 xml, PAL_T('b'), PAL_T("AssociationClassName"));
1536 mike     1.1 
1537                          if (!filter->associationClassName)
1538                              RETURN(-1);
1539                      }
1540 krisbash 1.4         else if (PAL_T('b') == e.data.namespaceId &&
1541                          Tcscmp(e.data.data, PAL_T("Role")) == 0)
1542 mike     1.1         {
1543 krisbash 1.4             filter->role = _ExpectCharsAndEnd(xml, PAL_T('b'), PAL_T("Role"));
1544 mike     1.1 
1545                          if (!filter->role)
1546                              RETURN(-1);
1547                      }
1548 krisbash 1.4         else if (PAL_T('b') == e.data.namespaceId &&
1549                          Tcscmp(e.data.data, PAL_T("ResultClassName")) == 0)
1550 mike     1.1         {
1551                          filter->resultClassName = _ExpectCharsAndEnd(
1552                              xml, 
1553 krisbash 1.4                 PAL_T('b'),
1554                              PAL_T("ResultClassName"));
1555 mike     1.1 
1556                          if (!filter->resultClassName)
1557                              RETURN(-1);
1558                      }
1559 krisbash 1.4         else if (PAL_T('b') == e.data.namespaceId &&
1560                          Tcscmp(e.data.data, PAL_T("ResultRole")) == 0)
1561 mike     1.1         {
1562                          filter->resultRole = _ExpectCharsAndEnd(
1563                              xml, 
1564 krisbash 1.4                 PAL_T('b'),
1565                              PAL_T("ResultRole"));
1566 mike     1.1 
1567                          if (!filter->resultRole)
1568                              RETURN(-1);
1569                      }
1570                      else
1571                      {
1572                          if (XML_Skip(xml) != 0)
1573                              RETURN(-1);
1574                      }
1575                  }
1576              
1577 krisbash 1.4     if(filter->isAssosiatorOperation == MI_TRUE)
1578                  {
1579                  	/* Expect </AssociatedInstances> */
1580                  	if (XML_Expect(xml, &e, XML_END, PAL_T('b'), PAL_T("AssociatedInstances")) != 0)
1581                  		RETURN(-1);
1582                  }
1583                  else
1584                  {
1585                  	/* Expect </AssociationInstances> */
1586                  	if (XML_Expect(xml, &e, XML_END, PAL_T('b'), PAL_T("AssociationInstances")) != 0)
1587                  		RETURN(-1);
1588                  }
1589              
1590                  return 0;
1591              }
1592              
1593              /* Parse query dialect */
1594              static const ZChar* _WS_ParseDialect(
1595                  _In_z_ const ZChar* dialect,
1596                  MI_Boolean isSubscribe)
1597              {
1598 krisbash 1.4     /* See DSP0202.pdf */
1599                  if (Tcscasecmp(ZT("http://schemas.dmtf.org/wbem/cql/1/dsp0202.pdf"), dialect) == 0)
1600                      return MI_QUERY_DIALECT_CQL;
1601              
1602                  if (Tcscasecmp(ZT("http://schemas.microsoft.com/wbem/wsman/1/WQL"), dialect) == 0)
1603                      return MI_QUERY_DIALECT_WQL;
1604 mike     1.1 
1605 krisbash 1.4     /* Event stream dialect is not supported yet */
1606                  /* if (isSubscribe && Tcscasecmp(ZT("http://schemas.microsoft.com/wbem/wsman/1/MINT"), dialect) == 0)
1607                      return QUERY_LANGUAGE_EVENTSTREAM; */
1608 mike     1.1 
1609 krisbash 1.4     if (isSubscribe)
1610                      return dialect;
1611 mike     1.1 
1612 krisbash 1.4     return NULL;
1613 mike     1.1 }
1614              
1615              int WS_ParseEnumerateBody(
1616                  XML* xml, 
1617                  Batch** batch,
1618                  WSMAN_WSEnumeratePullBody* wsenumbody)
1619              {
1620                  XML_Elem e;
1621              
1622                  memset(wsenumbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
1623              
1624                  /* Allocate batch (owned by WSMAN_ConnectionData object */
1625              
1626                  if (*batch == NULL)
1627                  {
1628                      *batch = Batch_New(BATCH_MAX_PAGES);
1629              
1630                      if (!*batch)
1631                          RETURN(-1);
1632                  }
1633              
1634 mike     1.1     /* Expect <s:Body> */
1635 krisbash 1.4     if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0)
1636 mike     1.1         RETURN(-1);
1637              
1638                  /* Expect <n:Enumerate> */
1639 krisbash 1.4     if (XML_Expect(xml, &e, XML_START, PAL_T('n'), PAL_T("Enumerate")) != 0)
1640 mike     1.1         RETURN(-1);
1641              
1642                  for (;;)
1643                  {
1644                      if (XML_Next(xml, &e) != 0)
1645                          RETURN(-1);
1646              
1647                      if (e.type == XML_END)
1648                      {
1649 krisbash 1.4             int tag = HashStr(e.data.namespaceId, e.data.data, e.data.size);
1650 mike     1.1 
1651                          if (WSMANTAG_ENUM_ENUMERATE != tag)
1652                          {
1653 krisbash 1.4                 trace_Wsman_UnexpectedCloseTag(tcs(e.data.data));
1654 mike     1.1                 RETURN(-1);
1655                          }
1656                          break;
1657                      }
1658              
1659                      /* skip possible comments */
1660                      if (e.type != XML_START)
1661                          continue;
1662              
1663 krisbash 1.4         switch (HashStr(e.data.namespaceId, e.data.data, e.data.size))
1664 mike     1.1         {
1665                      case WSMANTAG_ENUM_MAX_ELEMENTS:
1666                          {
1667 krisbash 1.4                 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1668 mike     1.1                     RETURN(-1);
1669              
1670 krisbash 1.4                 wsenumbody->maxElements = (MI_Uint32)Tcstoull(e.data.data, NULL, 10);
1671 mike     1.1 
1672 krisbash 1.4                 if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("MaxElements")) != 0)
1673 mike     1.1                     RETURN(-1);
1674                          }
1675                          break;
1676              
1677                      case WSMANTAG_ENUM_OPTIMIZE_ENUMERATION:
1678                          {
1679                              wsenumbody->allowOptimization = MI_TRUE;
1680              
1681                              if (XML_Skip(xml) != 0)
1682                                  RETURN(-1);
1683                          }
1684                          break;
1685              
1686                      case WSMANTAG_ENUM_POLYMORPHISM_MODE:
1687                          {
1688 krisbash 1.4                 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1689 mike     1.1                     RETURN(-1);
1690              
1691 krisbash 1.4                 wsenumbody->polymorphismMode = HashStr(e.data.namespaceId, e.data.data, e.data.size);
1692 mike     1.1 
1693 krisbash 1.4                 if (XML_Expect(xml, &e, XML_END, PAL_T('b'), PAL_T("PolymorphismMode")) != 0)
1694 mike     1.1                     RETURN(-1);
1695                          }
1696                          break;
1697              
1698                      case WSMANTAG_ENUM_MODE:
1699                          {
1700 krisbash 1.4                 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1701 mike     1.1                     RETURN(-1);
1702              
1703 krisbash 1.4                 wsenumbody->enumerationMode = HashStr(e.data.namespaceId, e.data.data, e.data.size);
1704 mike     1.1 
1705 krisbash 1.4                 if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("EnumerationMode")) != 0)
1706 mike     1.1                     RETURN(-1);
1707                          }
1708                          break;
1709              
1710                      /* 
1711                       * Examples:
1712                       *   <w:Filter Dialect="http://microsoft.com/wbem/wsman/1/WQL">
1713                       *     SELECT Weight FROM Widget WHERE Key = 1001
1714                       *   </w:Filter>
1715                       *
1716                       *   <w:Filter Dialect="http://microsoft.com/wbem/wsman/1/WQL">
1717                       *     <b:AssociatedInstances>
1718                       *       ...
1719                       *     </b:AssociatedInstances>
1720                       *   </w:Filter>
1721                       */
1722                      case WSMANTAG_ENUM_FILTER:
1723                          {
1724 krisbash 1.4                 const TChar* dialect;
1725 mike     1.1 
1726                              /* Get 'Dialect' attribute? */
1727 krisbash 1.4                 dialect = XML_Elem_GetAttr(&e, 0, PAL_T("Dialect"));
1728 mike     1.1                 if (!dialect)
1729                              {
1730 krisbash 1.4                     trace_Wsman_FilterTagMissingDialectAttribute();
1731 mike     1.1                     RETURN(-1);
1732                              }
1733              
1734                              /* Parse the association filter */
1735 krisbash 1.4                 if (Tcscasecmp(dialect, URI_CIMBINDING PAL_T("/associationFilter")) == 0)
1736 mike     1.1                 {
1737 krisbash 1.4                     wsenumbody->dialect = PAL_T("associationFilter");
1738                                  wsenumbody->foundAssociationOperation = MI_TRUE;
1739 mike     1.1 
1740 krisbash 1.4                     if (_ParseAssociationFilter(xml, *batch, &wsenumbody->associationFilter) != 0)
1741 mike     1.1                     {
1742                                      RETURN(-1);
1743                                  }
1744                              }
1745                              else
1746                              {
1747 krisbash 1.4                     /* Parse the dialect */
1748                                  wsenumbody->dialect = _WS_ParseDialect(dialect, MI_FALSE);
1749              
1750                                  if (!wsenumbody->dialect)
1751                                  {
1752                                      trace_WsmanEnum_UnknownDialect(tcs(dialect));
1753                                      RETURN(-1);
1754                                  }
1755              
1756 mike     1.1                     /* Get the filter text */
1757 krisbash 1.4                     if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1758 mike     1.1                         RETURN(-1);
1759              
1760 krisbash 1.4                     wsenumbody->filter = e.data.data;
1761 mike     1.1                 }
1762              
1763                              /* Check for closing </w:Filter> tag */
1764 krisbash 1.4                 if (XML_Expect(xml, &e, XML_END, PAL_T('w'), PAL_T("Filter")) != 0)
1765 mike     1.1                     RETURN(-1);
1766                          }
1767                          break;
1768              
1769                      default:
1770                          {
1771                              if (_MustUnderstandCanBeIgnored(&e) != 0)
1772                              {
1773 krisbash 1.4                     trace_Wsman_UnknownMandatoryTag(tcs(e.data.data));
1774 mike     1.1                     RETURN(-1);
1775                              }
1776              
1777                              if (XML_Skip(xml) != 0)
1778                                  RETURN(-1);
1779                          }
1780                          break;
1781              
1782                      }
1783                  }
1784              
1785                  /* Expect <s:Body> */
1786 krisbash 1.4     if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0)
1787 mike     1.1         RETURN(-1);
1788              
1789                  /* Expect </s:Envelope> */
1790 krisbash 1.4     if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0)
1791 mike     1.1         RETURN(-1);
1792              
1793                  return 0;
1794              }
1795              
1796              int WS_ParseInvokeBody(
1797                  XML* xml, 
1798                  Batch*  dynamicBatch,
1799                  MI_Instance** dynamicInstanceParams)
1800              {
1801                  XML_Elem e;
1802              
1803                  *dynamicInstanceParams = 0;
1804              
1805                  /* Expect <s:Body> */
1806 krisbash 1.4     if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0)
1807 mike     1.1         RETURN(-1);
1808              
1809                  /* Expect <?:?> parameter's tag */
1810                  for (;;)
1811                  {
1812                      if (XML_Next(xml, &e) != 0)
1813                          RETURN(-1);
1814              
1815                      /* empty body? can be valid for methods without parameters */
1816                      if (e.type == XML_END)
1817                          return 0;
1818              
1819                      if (e.type == XML_START)
1820                          break;
1821                  }
1822              
1823                  if (0 != _GetInstance(xml, &e, dynamicBatch, dynamicInstanceParams))
1824                      RETURN(-1);
1825              
1826              
1827                  /* Expect <s:Body> */
1828 krisbash 1.4     if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0)
1829 mike     1.1         RETURN(-1);
1830              
1831                  /* Expect </s:Envelope> */
1832 krisbash 1.4     if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0)
1833 mike     1.1         RETURN(-1);
1834              
1835                  return 0;
1836              }
1837              
1838              int WS_ParseCreateBody(
1839                  XML* xml, 
1840                  Batch*  dynamicBatch,
1841                  MI_Instance** dynamicInstanceParams)
1842              {
1843                  XML_Elem e;
1844              
1845                  /* Expect <s:Body> */
1846 krisbash 1.4     if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0)
1847 mike     1.1         RETURN(-1);
1848              
1849                  /* Expect <?:?> parameter's tag */
1850                  if (XML_Next(xml, &e) != 0)
1851                      RETURN(-1);
1852              
1853                  if (0 != _GetInstance(xml, &e, dynamicBatch, dynamicInstanceParams))
1854                      RETURN(-1);
1855              
1856                  /* Expect <s:Body> */
1857 krisbash 1.4     if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0)
1858 mike     1.1         RETURN(-1);
1859              
1860                  /* Expect </s:Envelope> */
1861 krisbash 1.4     if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0)
1862 mike     1.1         RETURN(-1);
1863              
1864                  return 0;
1865              }
1866              
1867              int WS_ParsePullBody(
1868                  XML* xml, 
1869                  WSMAN_WSEnumeratePullBody* wsenumpullbody)
1870              {
1871                  XML_Elem e;
1872              
1873                  memset(wsenumpullbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
1874              
1875                  /* Expect <s:Body> */
1876 krisbash 1.4     if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0)
1877 mike     1.1         RETURN(-1);
1878              
1879                  /* Expect <n:Enumerate> */
1880 krisbash 1.4     if (XML_Expect(xml, &e, XML_START, PAL_T('n'), PAL_T("Pull")) != 0)
1881 mike     1.1         RETURN(-1);
1882              
1883                  for (;;)
1884                  {
1885                      if (XML_Next(xml, &e) != 0)
1886                          RETURN(-1);
1887              
1888                      if (e.type == XML_END)
1889                      {
1890 krisbash 1.4             int tag = HashStr(e.data.namespaceId, e.data.data, e.data.size);
1891 mike     1.1 
1892                          if (WSMANTAG_ENUM_PULL != tag)
1893                          {
1894 krisbash 1.4                 trace_Wsman_UnexpectedCloseTag(tcs(e.data.data));
1895 mike     1.1                 RETURN(-1);
1896                          }
1897                          break;
1898                      }
1899              
1900                      /* skip possible comments */
1901                      if (e.type != XML_START)
1902                          continue;
1903              
1904 krisbash 1.4         switch (HashStr(e.data.namespaceId, e.data.data, e.data.size))
1905 mike     1.1         {
1906                      case WSMANTAG_PULL_MAX_ELEMENTS:
1907                          {
1908 krisbash 1.4                 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1909                                  RETURN(-1);
1910              
1911                              wsenumpullbody->maxElements = (MI_Uint32)Tcstoull(e.data.data, NULL, 10);
1912                              if (XML_Expect(xml, &e, XML_END, PAL_T('n'), PAL_T("MaxElements")) != 0)
1913                                  RETURN(-1);
1914                          }
1915                          break;
1916              
1917                      case WSMANTAG_MAX_TIME:
1918                          {
1919                              if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1920                                  RETURN(-1);
1921              
1922                              if (-1 == ParseWSManDatetime( e.data.data, &wsenumpullbody->maxTime.value ) )
1923                                  RETURN(-1);
1924              
1925                              wsenumpullbody->maxTime.exists = MI_TRUE;
1926              
1927                              if (XML_Expect(xml, &e, XML_END, PAL_T('n'), PAL_T("MaxTime")) != 0)
1928                                  RETURN(-1);
1929 krisbash 1.4             }
1930                          break;
1931              
1932                      case WSMANTAG_MAX_CHARACTERS:
1933                          {
1934                              if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1935 mike     1.1                     RETURN(-1);
1936              
1937 krisbash 1.4                 wsenumpullbody->maxCharacters.value = Tcstoull(e.data.data, NULL, 10);
1938                              wsenumpullbody->maxCharacters.exists = MI_TRUE;
1939 mike     1.1 
1940 krisbash 1.4                 if (XML_Expect(xml, &e, XML_END, PAL_T('n'), PAL_T("MaxCharacters")) != 0)
1941 mike     1.1                     RETURN(-1);
1942                          }
1943                          break;
1944              
1945                      case WSMANTAG_PULL_ENUMERATION_CONTEXT:
1946                          {
1947 krisbash 1.4                 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
1948 mike     1.1                     RETURN(-1);
1949              
1950 krisbash 1.4                 wsenumpullbody->enumerationContextID = (MI_Uint32)Tcstoull(
1951                                  e.data.data, NULL, 10);
1952 mike     1.1 
1953 krisbash 1.4                 if (XML_Expect(xml, &e, XML_END, PAL_T('n'), PAL_T("EnumerationContext")) != 0)
1954 mike     1.1                     RETURN(-1);
1955                          }
1956                          break;
1957              
1958                      default:
1959                          {
1960                              if (_MustUnderstandCanBeIgnored(&e) != 0)
1961                              {
1962 krisbash 1.4                     trace_Wsman_UnknownMandatoryTag(tcs(e.data.data));
1963 mike     1.1                     RETURN(-1);
1964                              }
1965              
1966                              if (XML_Skip(xml) != 0)
1967                                  RETURN(-1);
1968                          }
1969                          break;
1970              
1971                      }
1972                  }
1973              
1974                  /* Expect <s:Body> */
1975 krisbash 1.4     if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0)
1976 mike     1.1         RETURN(-1);
1977              
1978                  /* Expect </s:Envelope> */
1979 krisbash 1.4     if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0)
1980 mike     1.1         RETURN(-1);
1981              
1982                  return 0;
1983              }
1984              
1985              int WS_ParseReleaseBody(
1986                  XML* xml, 
1987                  WSMAN_WSEnumeratePullBody* wsenumpullbody)
1988              {
1989                  XML_Elem e;
1990              
1991                  memset(wsenumpullbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
1992              
1993                  /* Expect <s:Body> */
1994 krisbash 1.4     if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0)
1995 mike     1.1         RETURN(-1);
1996              
1997                  /* Expect <n:Release> */
1998 krisbash 1.4     if (XML_Expect(xml, &e, XML_START, PAL_T('n'), PAL_T("Release")) != 0)
1999 mike     1.1         RETURN(-1);
2000              
2001                  for (;;)
2002                  {
2003                      if (XML_Next(xml, &e) != 0)
2004                          RETURN(-1);
2005              
2006                      if (e.type == XML_END)
2007                      {
2008 krisbash 1.4             int tag = HashStr(e.data.namespaceId, e.data.data, e.data.size);
2009 mike     1.1 
2010                          if (WSMANTAG_ENUM_RELEASE != tag)
2011                          {
2012 krisbash 1.4                 trace_Wsman_UnexpectedCloseTag(tcs(e.data.data));
2013 mike     1.1                 RETURN(-1);
2014                          }
2015                          break;
2016                      }
2017              
2018                      /* skip possible comments */
2019                      if (e.type != XML_START)
2020                          continue;
2021              
2022 krisbash 1.4         switch (HashStr(e.data.namespaceId, e.data.data, e.data.size))
2023 mike     1.1         {
2024                      case WSMANTAG_PULL_ENUMERATION_CONTEXT:
2025                          {
2026 krisbash 1.4                 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
2027 mike     1.1                     RETURN(-1);
2028              
2029 krisbash 1.4                 wsenumpullbody->enumerationContextID = (MI_Uint32)Tcstoull(
2030                                  e.data.data, NULL, 10);
2031 mike     1.1 
2032 krisbash 1.4                 if (XML_Expect(xml, &e, XML_END, PAL_T('n'), PAL_T("EnumerationContext")) != 0)
2033 mike     1.1                     RETURN(-1);
2034                          }
2035                          break;
2036              
2037                      default:
2038                          {
2039                              if (_MustUnderstandCanBeIgnored(&e) != 0)
2040                              {
2041 krisbash 1.4                     trace_Wsman_UnknownMandatoryTag(tcs(e.data.data));
2042 mike     1.1                     RETURN(-1);
2043                              }
2044              
2045                              if (XML_Skip(xml) != 0)
2046                                  RETURN(-1);
2047                          }
2048                          break;
2049              
2050                      }
2051                  }
2052              
2053                  /* Expect <s:Body> */
2054 krisbash 1.4     if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0)
2055 mike     1.1         RETURN(-1);
2056              
2057                  /* Expect </s:Envelope> */
2058 krisbash 1.4     if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0)
2059 mike     1.1         RETURN(-1);
2060              
2061                  return 0;
2062              }
2063              
2064              int WS_ParseIdentifyBody(
2065                  XML* xml)
2066              {
2067                  XML_Elem e;
2068              
2069 krisbash 1.4     if (XML_Expect(xml, &e, XML_START, PAL_T('s'), PAL_T("Body")) != 0)
2070                      RETURN(-1);
2071              
2072                  if (XML_Expect(xml, &e, XML_START, PAL_T('i'), PAL_T("Identify")) != 0)
2073                      RETURN(-1);
2074              
2075                  if (XML_Expect(xml, &e, XML_END, PAL_T('i'), PAL_T("Identify")) != 0)
2076                      RETURN(-1);
2077              
2078                  if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Body")) != 0)
2079                      RETURN(-1);
2080              
2081                  if (XML_Expect(xml, &e, XML_END, PAL_T('s'), PAL_T("Envelope")) != 0)
2082                      RETURN(-1);
2083              
2084                  return 0;
2085              }
2086              
2087              
2088              #ifndef DISABLE_INDICATION
2089              
2090 krisbash 1.4 typedef enum _SubscribeSequence
2091              {
2092                  SubscribeSequence_NONE = 0,
2093                  SubscribeSequence_EXPIRES = 1,
2094                  SubscribeSequence_FILTER = 2,
2095                  SubscribeSequence_END = 3
2096              } SubscribeSequence;
2097              
2098              /* Parse subscribe body, One example,
2099                  <s:Body>
2100                      <e:Subscribe>
2101                          <e:Delivery Mode="http://schemas.dmtf.org/wbem/wsman/1/wsman/Pull">
2102                              <w:Heartbeats>PT60.000S</w:Heartbeats>
2103                              <w:Locale xml:lang="en-US" s:mustUnderstand="false"/>
2104                              <p:DataLocale xml:lang="en-US" s:mustUnderstand="false"/>
2105                              <w:ContentEncoding>UTF-16</w:ContentEncoding>
2106                          </e:Delivery>
2107                          <e:Expires>
2108                              "PT60.000S"
2109                          </e:Expires>
2110                          <w:Filter Dialect="http://schemas.microsoft.com/wbem/wsman/1/WQL">
2111 krisbash 1.4                 Select * from My_Alarm"
2112                          </w:Filter>
2113                      </e:Subscribe>
2114                  </s:Body>
2115              */
2116              int WS_ParseSubscribeBody(
2117                  XML* xml, 
2118                  WSMAN_WSEnumeratePullBody* wssubbody)
2119              {
2120                  XML_Elem e;
2121                  SubscribeSequence sequenceState = SubscribeSequence_NONE;
2122              
2123                  memset(wssubbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
2124              
2125                  /* Expect <s:Body> */
2126                  if (XML_Expect(xml, &e, XML_START, ZT('s'), ZT("Body")) != 0)
2127                      RETURN(-1);
2128              
2129                  /* Expect <e:Subscribe> */
2130                  if (XML_Expect(xml, &e, XML_START, ZT('e'), ZT("Subscribe")) != 0)
2131                      RETURN(-1);
2132 krisbash 1.4 
2133                  /* A subscribe message body is made up of an xs:sequence of the following:
2134                   * 1 - EndTo    (Optional)
2135                   * 2 - Delivery
2136                   * 3 - Expires  (Optional)
2137                   * 4 - Filter   (Optional)
2138                   */
2139              
2140                  /* Expect <e:Delivery> */
2141                  if (XML_Expect(xml, &e, XML_START, ZT('e'), ZT("Delivery")) != 0)
2142                      RETURN(-1);
2143              
2144                  {
2145                      const XML_Char* mode = NULL;
2146                      
2147                      /* Read 'Mode' attribute */
2148                      mode = XML_Elem_GetAttr(&e, 0, ZT("Mode"));
2149                      if (mode)
2150                      {
2151                          int tag = HashStr( 0, mode, Tcslen(mode));
2152                          if (WSMAN_DELIVERY_MODE_PULL != tag)
2153 krisbash 1.4             {
2154                              trace_Wsman_UnsupportedDeliveryMode(mode);
2155                              RETURN(-1);
2156                          }
2157                          else
2158                          {
2159                              trace_Wsman_DeliveryMode(mode);
2160                          }
2161                      }
2162                      else
2163                      {
2164                          trace_Wsman_ExpectedDeliveryMode();
2165                          RETURN(-1);
2166                      }
2167                  }
2168                  
2169                  for (;;)
2170                  {
2171                      if (XML_Next(xml, &e) != 0)
2172                          RETURN(-1);
2173              
2174 krisbash 1.4         if (e.type == XML_END)
2175                      {
2176                          int tag = HashStr(e.data.namespaceId, e.data.data, e.data.size);
2177              
2178                          /* The end tag for Delivery was encountered, so jump out of the loop. */
2179                          if (WSMANTAG_SUBSCRIBE_DELIVER != tag)
2180                          {
2181                              trace_Wsman_UnexpectedCloseTagWithNamespace(e.data.namespaceId, e.data.data);
2182                              RETURN(-1);
2183                          }
2184                          break;
2185                      }
2186              
2187                      /* skip possible comments */
2188                      if (e.type != XML_START)
2189                          continue;
2190              
2191                      switch (HashStr(e.data.namespaceId, e.data.data, e.data.size))
2192                      {
2193                      case WSMANTAG_SUBSCRIBE_HEARTBEATS:
2194                          {
2195 krisbash 1.4                 if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
2196                                  RETURN(-1);
2197              
2198                              if (XML_StripWhitespace(&e) != 0)
2199                                  RETURN(-1);
2200                              
2201                              if (-1 == ParseWSManDatetime( e.data.data, &wssubbody->heartbeat.value ) )
2202                                  RETURN(-1);
2203              
2204                              wssubbody->heartbeat.exists = MI_TRUE;
2205              
2206                              if (XML_Expect(xml, &e, XML_END, ZT('w'), ZT("Heartbeats")) != 0)
2207                                  RETURN(-1);
2208                          }
2209                          break;
2210              
2211                       case WSMANTAG_SUBSCRIBE_CONTENTENCODING:
2212                          {
2213                              if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
2214                                  RETURN(-1);
2215              
2216 krisbash 1.4                 if (XML_Expect(xml, &e, XML_END, ZT('w'), ZT("ContentEncoding")) != 0)
2217                                  RETURN(-1);
2218                          }
2219                          break;
2220              
2221                      case WSMANTAG_SUBSCRIBE_CONNECTION_RETRY:
2222                         {
2223                             if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
2224                                 RETURN(-1);
2225              
2226                              if (XML_StripWhitespace(&e) != 0)
2227                                  RETURN(-1);
2228                              
2229                              if (-1 == ParseWSManDatetime( e.data.data, &wssubbody->connectionRetry.value ) )
2230                                  RETURN(-1);
2231                              
2232                              wssubbody->connectionRetry.exists = MI_TRUE;
2233              
2234                             if (XML_Expect(xml, &e, XML_END, ZT('w'), ZT("ConnectionRetry")) != 0)
2235                                 RETURN(-1);
2236                         }
2237 krisbash 1.4            break;
2238              
2239                      default:
2240                          {
2241                              if (_MustUnderstandCanBeIgnored(&e) != 0)
2242                              {
2243                                  trace_Wsman_UnknownMandatoryTagWithNamespace(e.data.namespaceId, e.data.data);
2244                                  RETURN(-1);
2245                              }
2246              
2247                              if (XML_Skip(xml) != 0)
2248                                  RETURN(-1);
2249                          }
2250                          break;
2251              
2252                      }
2253                  }
2254              
2255                  for (;;)
2256                  {
2257                      /* Get the next element and check for proper order of optional tags 
2258 krisbash 1.4          * within the sequence. This loop ensures order and stops when it 
2259                       * hits a parse error or encounters the body end tag.*/
2260                      if (XML_Next(xml, &e) != 0)
2261                          RETURN(-1);
2262              
2263                      if (e.type == XML_START)
2264                      {
2265                          switch (HashStr(e.data.namespaceId, e.data.data, e.data.size))
2266                          {
2267                          case WSMANTAG_EXPIRES:
2268                              {
2269                                  /* Parse Expires (if present) */
2270                                  if (sequenceState >= SubscribeSequence_EXPIRES)
2271                                      RETURN(-1);
2272                                  sequenceState = SubscribeSequence_EXPIRES;
2273              
2274                                  /* Expect an xs:duration of form: PnYnMnDTnHnMnS */
2275                                  if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
2276                                      RETURN(-1);
2277                                  
2278                                  if (XML_StripWhitespace(&e) != 0)
2279 krisbash 1.4                         RETURN(-1);
2280                                  
2281                                  if (-1 == ParseWSManDatetime( e.data.data, &wssubbody->expires.value ) )
2282                                      RETURN(-1);
2283              
2284                                  wssubbody->expires.exists = MI_TRUE;
2285              
2286                                  /* Check for closing </w:Expires> tag */
2287                                  if (XML_Expect(xml, &e, XML_END, ZT('e'), ZT("Expires")) != 0)
2288                                      RETURN(-1);
2289                              }
2290                              break;
2291                          case WSMANTAG_ENUM_FILTER:
2292                              {
2293                                  /* Parse filter and dialect */
2294                                  const XML_Char* dialect;
2295                                  if (sequenceState >= SubscribeSequence_FILTER)
2296                                      RETURN(-1);
2297                                  sequenceState = SubscribeSequence_FILTER;
2298              
2299                                  /* Read 'Dialect' attribute */
2300 krisbash 1.4                     dialect = XML_Elem_GetAttr(&e, 0, ZT("Dialect"));
2301                                  if (!dialect)
2302                                  {
2303                                      trace_Wsman_FilterTagMissingDialectAttribute();
2304                                      RETURN(-1);
2305                                  }
2306                                  wssubbody->dialect = _WS_ParseDialect(dialect, MI_TRUE);
2307                                  if (!wssubbody->dialect)
2308                                  {
2309                                      trace_Wsman_UnknownDialect(dialect);
2310                                      RETURN(-1);
2311                                  }
2312                                  else
2313                                      trace_Wsman_SubscribeDialect(dialect);
2314              
2315                                  /* Get the filter text */
2316                                  if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
2317                                      RETURN(-1);
2318              
2319                                  wssubbody->filter = e.data.data;
2320                                  trace_Wsman_SubscribeFilter(wssubbody->filter);
2321 krisbash 1.4 
2322                                  /* Check for closing </w:Filter> tag */
2323                                  if (XML_Expect(xml, &e, XML_END, ZT('w'), ZT("Filter")) != 0)
2324                                      RETURN(-1);                
2325                              }
2326                              break;
2327                          case WSMANTAG_SEND_BOOKMARKS:
2328                              {
2329                                  wssubbody->sendBookmarks = MI_TRUE;
2330              
2331                                  if (XML_Skip(xml) != 0)
2332                                      RETURN(-1);
2333                              }
2334                              break;
2335                          case WSMANTAG_BOOKMARK:
2336                              {
2337                                  /* Parse Bookmark */
2338                                  if (XML_Expect(xml, &e, XML_CHARS, 0, NULL) != 0)
2339                                      RETURN(-1);
2340                                  
2341                                  if (XML_StripWhitespace(&e) != 0)
2342 krisbash 1.4                         RETURN(-1);
2343                                  
2344                                  wssubbody->initialBookmark = e.data.data;
2345                                  
2346                                  if (XML_Expect(xml, &e, XML_END, ZT('w'), ZT("Bookmark")) != 0)
2347                                      RETURN(-1);
2348                              }
2349                              break;
2350                          default:
2351                              RETURN(-1);
2352                          }
2353                      }
2354                      else if (e.type == XML_END)
2355                      {
2356                          /* Expect </e:Subscribe> */
2357                          if (ZT('e') == e.data.namespaceId &&
2358                              Tcscmp(e.data.data, ZT("Subscribe")) == 0)
2359                          {
2360                              sequenceState = SubscribeSequence_END;
2361                              /* We reached the end of the subscribe body an the end of the
2362                               * xs:sequence.  Jump out to proceed. */
2363 krisbash 1.4                 break;
2364                          }
2365                          else
2366                              RETURN(-1);
2367                      }
2368                      else
2369                          RETURN(-1);
2370                  }
2371              
2372                  /* Expect </s:Body> */
2373                  if (XML_Expect(xml, &e, XML_END, ZT('s'), ZT("Body")) != 0)
2374                      RETURN(-1);
2375              
2376                  /* Expect </s:Envelope> */
2377                  if (XML_Expect(xml, &e, XML_END, ZT('s'), ZT("Envelope")) != 0)
2378                      RETURN(-1);
2379              
2380                  return 0;
2381              }
2382              
2383              /* Unsubcribe message sample:
2384 krisbash 1.4 <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:n="http://schemas.xmlsoap.org/ws/2004/09/enumeration" xmlns:w="http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd" xmlns:p="http://schemas.microsoft.com/wbem/wsman/1/wsman.xsd">
2385                  <s:Header>
2386                      <a:To>http://localhost:5985/wsman</a:To>
2387                      <a:ReplyTo>
2388                          <a:Address s:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
2389                      </a:ReplyTo>
2390                      <a:Action s:mustUnderstand="true">http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe</a:Action>
2391                      ......
2392                      <e:Identifier xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing">0860D524-6F0A-46FE-B95E-7CB0C1A2C1B8</e:Identifier>
2393                  </s:Header>
2394                  <s:Body>
2395                      <e:Unsubscribe/>
2396                  </s:Body>
2397              </s:Envelope>
2398              */
2399              int WS_ParseUnsubscribeBody(
2400                  XML* xml, 
2401                  WSMAN_WSEnumeratePullBody* wsunsubbody)
2402              {
2403                  XML_Elem e;
2404              
2405 krisbash 1.4     memset(wsunsubbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
2406              
2407                  /* Expect <s:Body> */
2408                  if (XML_Expect(xml, &e, XML_START, ZT('s'), ZT("Body")) != 0)
2409 mike     1.1         RETURN(-1);
2410              
2411 krisbash 1.4     /* Expect <e:Subscribe> */
2412                  if (XML_Expect(xml, &e, XML_START, MI_T('e'), ZT("Unsubscribe")) != 0)
2413 mike     1.1         RETURN(-1);
2414              
2415 krisbash 1.4     /* Expect </e:Subscribe> */
2416                  if (XML_Expect(xml, &e, XML_END, MI_T('e'), ZT("Unsubscribe")) != 0)
2417 mike     1.1         RETURN(-1);
2418              
2419 krisbash 1.4     /* Expect <s:Body> */
2420                  if (XML_Expect(xml, &e, XML_END, MI_T('s'), ZT("Body")) != 0)
2421 mike     1.1         RETURN(-1);
2422              
2423 krisbash 1.4     /* Expect </s:Envelope> */
2424                  if (XML_Expect(xml, &e, XML_END, MI_T('s'), ZT("Envelope")) != 0)
2425 mike     1.1         RETURN(-1);
2426              
2427                  return 0;
2428              }
2429 krisbash 1.4 
2430              #endif /* #ifndef DISABLE_INDICATION */

ViewCVS 0.9.2