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

   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 "wsmanparser.h"
  27           #include "wsmanbuffer.h"
  28           //#include "http.h"
  29           //#include "time.h"
  30           //#include <xml/xml.h>
  31           //#include <base/buf.h>
  32           #include <base/log.h>
  33           #include <base/result.h>
  34           #include <base/strings.h>
  35           
  36           #include "wstags.h"
  37           #include "wstags.inc"
  38           #include "uri.h"
  39           
  40           #define T MI_T
  41           
  42           #if 0
  43 mike  1.1 #define ENABLE_TRACING
  44           #endif
  45           
  46           #ifdef  ENABLE_TRACING
  47           #define PRINTF(a)  printf a
  48           #else
  49           #define PRINTF(a)
  50           #endif
  51           
  52           /*
  53           **==============================================================================
  54           **
  55           ** Local definitions:
  56           **
  57           **==============================================================================
  58           */
  59           static int _GetInstance(
  60               XML* xml, 
  61               XML_Elem *start,
  62               Batch*  dynamicBatch,
  63               MI_Instance** dynamicInstanceParams);
  64 mike  1.1 
  65           /****************************************************************************************/
  66           /* soap processing */
  67           
  68           static int _MustUnderstandCanBeIgnored(
  69               const XML_Elem* e)
  70           {
  71               size_t i;
  72               for (i = 0; i < e->attrsSize; i++)
  73               {
  74                   if (strcmp(e->attrs[i].name, "s:mustUnderstand") == 0 &&
  75                       strcmp(e->attrs[i].value, "true") == 0)
  76                   {
  77                       return -1;
  78                   }
  79               }
  80               return 0;
  81           }
  82           
  83           static int _GetSelector(
  84               XML* xml,
  85 mike  1.1     XML_Elem *e,
  86               const char** ns,
  87               const char* classname,
  88               MI_Instance** instance,
  89               Batch** batch)
  90           {
  91               size_t i;
  92           
  93               /* expecting namespace or key */
  94               for (i = 0; i < e->attrsSize; i++)
  95               {
  96                   if (strcmp(e->attrs[i].name, "Name") == 0 &&
  97                       strcmp(e->attrs[i].value, "__cimnamespace") == 0)
  98                   {
  99                       /* namespace */
 100                       if (XML_Expect(xml, e, XML_CHARS, NULL) != 0)
 101                           return -1;
 102           
 103                       PRINTF(("a:Selector:namespace{%s}\n", e->data));
 104                       *ns = e->data;
 105                   }
 106 mike  1.1         else if (strcmp(e->attrs[i].name, "Name") == 0)
 107                   {
 108                       /* keys */
 109                       const char* propName = e->attrs[i].value;
 110           
 111                       if (XML_Expect(xml, e, XML_CHARS, NULL) != 0)
 112                           return -1;
 113           
 114                       PRINTF(("a:Selector:namespace{%s}\n", e->data));
 115           
 116                       /* allocate batch and instance if needed */
 117                       if (!(*instance))
 118                       {
 119                           MI_Result r;
 120                           MI_Char* cn;
 121           
 122                           /* verify that we already received classname */
 123                           if (!classname)
 124                           {
 125                               XML_Raise(xml, "class-name was not found druing selector parsing");
 126                               return -1;
 127 mike  1.1                 }
 128           
 129                           /* Destroy old batch if it exists (from previous operation) */
 130                           if (*batch)
 131                           {
 132                               Batch_Destroy(*batch);
 133                           }
 134           
 135                           *batch = Batch_New(BATCH_MAX_PAGES);
 136           
 137                           if (!(*batch))
 138                               return -1;
 139           
 140                           cn = Batch_Strdup2(*batch, classname);
 141           
 142                           r = Instance_NewDynamic(instance, cn, MI_FLAG_CLASS, *batch);
 143                           if (MI_RESULT_OK != r)
 144                               return -1;
 145                       }
 146           
 147                       /* add next property to the instance */
 148 mike  1.1             {
 149                           const MI_Char* wpropName = Batch_Strdup2(*batch, propName);
 150                           MI_Result r;
 151                           MI_Value value;
 152           
 153                           value.string = Batch_Strdup2(*batch, e->data);
 154           
 155                           // Set the property.
 156                           r = MI_Instance_AddElement(*instance, wpropName, &value, 
 157                               MI_STRING, MI_FLAG_BORROW | MI_FLAG_KEY);
 158           
 159                           if (MI_RESULT_OK != r)
 160                               return -1;
 161                       }
 162                   }
 163                   else
 164                       continue;
 165           
 166                   if (XML_Expect(xml, e, XML_END, "w:Selector") != 0)
 167                       return -1;
 168           
 169 mike  1.1         break;
 170               }
 171           
 172               return 0;
 173           }
 174           
 175           static int _GetSelectorSet(
 176               XML* xml,
 177               WSMAN_WSHeader* wsheader)
 178           {
 179               XML_Elem e;
 180           
 181               if (XML_Expect(xml, &e, XML_START, "w:Selector") != 0)
 182                   return -1;
 183           
 184               /* iterate through all selector tags */
 185               for (;;)
 186               {
 187                   if (0 != _GetSelector(
 188                       xml, 
 189                       &e, 
 190 mike  1.1             &wsheader->rqtNamespace,
 191                       wsheader->rqtClassname,
 192                       &wsheader->instance,
 193                       &wsheader->instanceBatch))
 194                       return -1;
 195           
 196                   /**/
 197                   if (XML_Next(xml, &e) != 0)
 198                       return -1;
 199           
 200                   if (XML_END == e.type)
 201                       break;
 202           
 203               }
 204           
 205               return 0;
 206           }
 207           
 208           static int _GetReferenceParameters(
 209               XML* xml, 
 210               Batch*  dynamicBatch,
 211 mike  1.1     MI_Instance** dynamicInstanceParams)
 212           {
 213               XML_Elem e;
 214               const char* classname = 0;
 215               const char* nameSpace = NULL;
 216           
 217               /* extract ResourceURI and SelectorSet */
 218               for (;;)
 219               {
 220                   if (XML_Next(xml, &e) != 0)
 221                       return -1;
 222           
 223                   if (XML_END == e.type)
 224                       break;
 225           
 226                   if (0 == strcmp("w:ResourceURI", e.data))
 227                   {
 228                       if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
 229                           return -1;
 230           
 231                       classname = strrchr(e.data, '/');
 232 mike  1.1             /* skip '/' */
 233                       if (classname) 
 234                           classname++;
 235           
 236                       if (XML_Expect(xml, &e, XML_END, "w:ResourceURI") != 0)
 237                           return -1;
 238           
 239                       continue;
 240                   }
 241           
 242                   if (0 == strcmp("w:SelectorSet", e.data))
 243                   {
 244                       /* Allocate an instance */
 245                       if (!*dynamicInstanceParams)
 246                       {
 247                           MI_Result r;
 248                           const MI_Char* cn;
 249           
 250                           if (!classname)
 251                           {
 252                               XML_Raise(xml, "ResourceURI tag expected");
 253 mike  1.1                     return -1;
 254                           }
 255           
 256                           cn = Batch_Strdup2(dynamicBatch, classname);
 257           
 258                           r = Instance_NewDynamic(dynamicInstanceParams, cn, MI_FLAG_CLASS, dynamicBatch);
 259                           if (MI_RESULT_OK != r)
 260                               return -1;
 261                       }
 262           
 263                       /* iterate through all selector tags */
 264                       for (;;)
 265                       {
 266                           const char* ns = NULL;
 267           
 268                           if (_GetSelector(
 269                               xml, 
 270                               &e, 
 271                               &ns, 
 272                               classname, 
 273                               dynamicInstanceParams, 
 274 mike  1.1                     &dynamicBatch) != 0)
 275                           {
 276                               return -1;
 277                           }
 278           
 279                           if (ns)
 280                           {
 281                               nameSpace = ns;
 282                           }
 283           
 284                           /**/
 285                           if (XML_Next(xml, &e) != 0)
 286                               return -1;
 287           
 288                           if (XML_END == e.type)
 289                               break;
 290           
 291                       }
 292                       continue;
 293                   }
 294               }
 295 mike  1.1 
 296               if (nameSpace)
 297                   (*dynamicInstanceParams)->nameSpace = nameSpace;
 298           
 299               return 0;
 300           }
 301           
 302           static int _GetReference(
 303               XML* xml, 
 304               XML_Elem *start,
 305               Batch*  dynamicBatch,
 306               MI_Instance** dynamicInstanceParams)
 307           {
 308               XML_Elem e;
 309           
 310               e = *start;
 311           
 312               /* extract all parameters */
 313               for (;;)
 314               {
 315                   if (0 != strcmp("a:ReferenceParameters", e.data))
 316 mike  1.1         {
 317                       if (XML_Skip(xml) != 0)
 318                           return -1;
 319           
 320                       if (XML_Next(xml, &e) != 0)
 321                           return -1;
 322           
 323                       if (e.type == XML_END)
 324                           break;
 325           
 326                       continue;
 327                   }
 328           
 329                   if (0 != _GetReferenceParameters(xml, dynamicBatch, dynamicInstanceParams))
 330                       return -1;
 331           
 332                   if (XML_Next(xml, &e) != 0)
 333                       return -1;
 334           
 335                   if (e.type == XML_END)
 336                       break;
 337 mike  1.1     }
 338           
 339               return 0;
 340           }
 341           
 342           static int _GetSingleProperty(
 343               XML* xml,
 344               Batch*  dynamicBatch,
 345               const char* propNameChar,
 346               MI_Value* value,
 347               MI_Type* type)
 348           {
 349               XML_Elem e;
 350           
 351               if (XML_Next(xml, &e) != 0)
 352                   return -1;
 353           
 354               if (e.type == XML_CHARS)
 355               {
 356                   /* Plain string property */
 357                   value->string = Batch_Strdup2(dynamicBatch, e.data);
 358 mike  1.1         *type = MI_STRING;
 359           
 360                   if (XML_Expect(xml, &e, XML_END, propNameChar) != 0)
 361                       return -1;
 362               }
 363               else if ('a' == e.data[0])
 364               {
 365                   /* Reference as </adddress></ReferenceParameters>*/
 366                   value->instance = 0;
 367                   if (0 != _GetReference(xml, &e, dynamicBatch, &value->instance))
 368                       return -1;
 369           
 370                   *type = MI_REFERENCE;
 371               }
 372               else
 373               {
 374                   /* Embedded instance */
 375                   value->instance = 0;
 376                   if (0 != _GetInstance(xml, &e, dynamicBatch, &value->instance))
 377                       return -1;
 378           
 379 mike  1.1         *type = MI_INSTANCE;
 380           
 381                   if (XML_Expect(xml, &e, XML_END, propNameChar) != 0)
 382                       return -1;
 383               }
 384           
 385           
 386               return 0;
 387           }
 388           
 389           static int _AddValueToArray(
 390               Batch*  dynamicBatch,
 391               MI_Value* valueA,
 392               MI_Type typeA,
 393               const MI_Value* value,
 394               MI_Type type)
 395           {
 396               /* does type match? */
 397               if ((type | MI_ARRAY_BIT) != typeA)
 398                   return -1;
 399           
 400 mike  1.1     /* do we need to realloc array? */
 401               if ((valueA->array.size % 16) == 0)
 402               {
 403                   void* newData = Batch_Get(dynamicBatch, (valueA->array.size + 16) * sizeof(void*));
 404           
 405                   if (!newData)
 406                       return -1;
 407           
 408                   if (valueA->array.size)
 409                       memcpy(newData, valueA->array.data, valueA->array.size * sizeof(void*));
 410           
 411                   valueA->array.data = newData;
 412               }
 413           
 414               if (type == MI_STRING)
 415                   valueA->stringa.data[valueA->stringa.size] = value->string;
 416               else
 417                   valueA->instancea.data[valueA->instancea.size] = value->instance;
 418           
 419               valueA->array.size++;
 420               return 0;
 421 mike  1.1 }
 422           
 423           static int _GetInstance(
 424               XML* xml, 
 425               XML_Elem *start,
 426               Batch*  dynamicBatch,
 427               MI_Instance** dynamicInstanceParams)
 428           {
 429               XML_Elem e;
 430               const MI_Char* propNameA = 0;
 431               MI_Value valueA;
 432               MI_Type typeA = MI_BOOLEAN;
 433               const MI_Char* propNamePrev = 0;
 434               MI_Value valuePrev;
 435               MI_Type typePrev = MI_BOOLEAN;
 436           
 437               memset(&valueA, 0, sizeof(valueA));
 438           
 439               /* extract all parameters */
 440               for (;;)
 441               {
 442 mike  1.1         if (XML_Next(xml, &e) != 0)
 443                       return -1;
 444           
 445                   if (e.type == XML_END)
 446                       break;
 447           
 448                   /* skip possible comments */
 449                   if (e.type != XML_START)
 450                       continue;
 451           
 452                   /* allocate new instance if needed */
 453                   if (!*dynamicInstanceParams)
 454                   {
 455                       MI_Result r;
 456                       const MI_Char* cn = Batch_Strdup2(dynamicBatch, start->data + 2);
 457           
 458                       r = Instance_NewDynamic(dynamicInstanceParams, cn, MI_FLAG_CLASS, dynamicBatch);
 459                       if (MI_RESULT_OK != r)
 460                           return -1;
 461                   }
 462           
 463 mike  1.1         /* add next property to the instance */
 464                   if (e.size > 2) /* ?:<name> */
 465                   {
 466                       MI_Result r;
 467                       MI_Value value;
 468                       MI_Type type = MI_BOOLEAN;
 469                       const char* propNameChar;
 470                       const MI_Char* propName;
 471           
 472                       propNameChar = e.data;
 473                       propName = Batch_Strdup2(dynamicBatch, propNameChar + 2);
 474           
 475                       type = MI_BOOLEAN;
 476           
 477                       if (0 != _GetSingleProperty(xml, dynamicBatch, propNameChar, &value, &type))
 478                           return -1;
 479           
 480                       /* Did we collect array's items? */
 481                       if (propNameA)
 482                       {
 483                           /* if we have array and new property matches array - add new item to the array */
 484 mike  1.1                 if (0 == Zcmp(propNameA, propName))
 485                           {
 486                               if (0 != _AddValueToArray(dynamicBatch, &valueA, typeA, &value, type))
 487                                   return -1;
 488                           }
 489                           else
 490                           {
 491                               r = MI_Instance_AddElement(*dynamicInstanceParams, propNameA, &valueA, 
 492                                   typeA, MI_FLAG_BORROW);
 493           
 494                               if (MI_RESULT_OK != r)
 495                                   return -1;
 496           
 497                               /* Clear array prop name */
 498                               propNameA = 0;
 499           
 500                               propNamePrev = propName;
 501                               valuePrev = value;
 502                               typePrev = type;
 503                           }
 504                       }
 505 mike  1.1             else if (propNamePrev)
 506                       {
 507                           /* Check if name is the same and we need to create an array */
 508                           if (0 == Zcmp(propNamePrev, propName))
 509                           {
 510                               /* create array */
 511                               valueA.array.size = 0;
 512                               valueA.array.data = 0;
 513           
 514                               typeA = type | MI_ARRAY_BIT;
 515                               propNameA = propName;
 516           
 517                               if (0 != _AddValueToArray(dynamicBatch, &valueA, typeA, &valuePrev, typePrev))
 518                                   return -1;
 519           
 520                               if (0 != _AddValueToArray(dynamicBatch, &valueA, typeA, &value, type))
 521                                   return -1;
 522           
 523                           }
 524                           else
 525                           {
 526 mike  1.1                     r = MI_Instance_AddElement(*dynamicInstanceParams, propNamePrev, &valuePrev, 
 527                                   typePrev, MI_FLAG_BORROW);
 528           
 529                               if (MI_RESULT_OK != r)
 530                                   return -1;
 531           
 532           
 533                               propNamePrev = propName;
 534                               valuePrev = value;
 535                               typePrev = type;
 536                          }
 537           
 538                       }
 539                       else
 540                       {
 541                           /* collecting first item */
 542                           propNamePrev = propName;
 543                           valuePrev = value;
 544                           typePrev = type;
 545                       }
 546                   }
 547 mike  1.1     }
 548           
 549               /* if last property was array - add it */
 550               if (propNameA)
 551               {
 552                   MI_Result r;
 553           
 554                   r = MI_Instance_AddElement(*dynamicInstanceParams, propNameA, &valueA, 
 555                       typeA, MI_FLAG_BORROW);
 556           
 557                   if (MI_RESULT_OK != r)
 558                       return -1;
 559               }
 560               else if (propNamePrev)
 561               {
 562                   MI_Result r;
 563           
 564                   r = MI_Instance_AddElement(*dynamicInstanceParams, propNamePrev, &valuePrev, 
 565                       typePrev, MI_FLAG_BORROW);
 566           
 567                   if (MI_RESULT_OK != r)
 568 mike  1.1             return -1;
 569               }
 570           
 571               /* check closing tag */
 572               if (strcmp(e.data, start->data) != 0)
 573                   return -1;
 574           
 575               return 0;
 576           }
 577           
 578           int WS_ParseWSHeader(
 579               XML* xml,
 580               WSMAN_WSHeader* wsheader)
 581           {
 582               XML_Elem e;
 583           
 584               memset(wsheader, 0, sizeof(WSMAN_WSHeader));
 585           
 586               /* Expect <s:Header> */
 587               if (XML_Expect(xml, &e, XML_START, "s:Header") != 0)
 588                   return -1;
 589 mike  1.1 
 590               for (;;)
 591               {
 592                   if (XML_Next(xml, &e) != 0)
 593                       return -1;
 594           
 595                   if (e.type == XML_END)// && strcmp(e.data, "s:Header") == 0)
 596                   {
 597                       int tag = HashStr(e.data, e.size);
 598           
 599                       if (WSMANTAG_HEADER != tag)
 600                       {
 601                           LOGW_CHAR(("wsman: unexpected close tag [%s] in incoming xml", e.data ));
 602                           return -1;
 603                       }
 604                       //printf("DONE\n");
 605                       break;
 606                   }
 607           
 608                   /* skip possible comments */
 609                   if (e.type != XML_START)
 610 mike  1.1             continue;
 611           
 612                   switch (HashStr(e.data, e.size))
 613                   {
 614                       case WSMANTAG_TO:
 615                       {
 616                           if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
 617                               return -1;
 618           
 619                           PRINTF(("a:To{%s}\n", e.data));
 620           
 621                           if (XML_Expect(xml, &e, XML_END, "a:To") != 0)
 622                               return -1;
 623                       }
 624                       break;
 625           
 626                       case WSMANTAG_RESOURCE_URI:
 627                       {
 628                           if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
 629                               return -1;
 630           
 631 mike  1.1                 PRINTF(("w:ResourceURI{%s}\n", e.data));
 632                           wsheader->rqtClassname = strrchr(e.data, '/');
 633                           /* skip '/' */
 634                           if (wsheader->rqtClassname) 
 635                               wsheader->rqtClassname++;
 636           
 637                           if (XML_Expect(xml, &e, XML_END, "w:ResourceURI") != 0)
 638                               return -1;
 639                       }
 640                       break;
 641           
 642                       case WSMANTAG_REPLY_TO:
 643                       {
 644                           if (XML_Expect(xml, &e, XML_START, "a:Address") != 0)
 645                               return -1;
 646           
 647                           if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
 648                               return -1;
 649           
 650                           if (XML_Expect(xml, &e, XML_END, "a:Address") != 0)
 651                               return -1;
 652 mike  1.1 
 653                           if (XML_Expect(xml, &e, XML_END, "a:ReplyTo") != 0)
 654                               return -1;
 655                       }
 656                       break;
 657           
 658                       case WSMANTAG_ACTION:
 659                       {
 660                           wsheader->foundAction = MI_TRUE;
 661           
 662                           if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
 663                               return -1;
 664           
 665                           wsheader->rqtAction = HashStr(e.data, e.size);
 666           
 667                           if (0 == wsheader->rqtAction)
 668                           {
 669                               char* s;
 670                               /* DSP0226; 9: Custom Actions (Methods) just need to have unique URI.
 671                                   We are assuming it has format like http://<server>/wbem/wscim/1/cim-schema/2/<class-name>/<method-name> */
 672           
 673 mike  1.1                     if (0 != strncmp(e.data, "http://", 7))
 674                                   return -1;
 675           
 676                               wsheader->rqtServer = e.data + 7;
 677           
 678                               s = strchr(wsheader->rqtServer, '/');
 679           
 680                               if (!s)
 681                                   return -1;
 682           
 683                               *s = 0;
 684                               s++;
 685           
 686                               if (0 != strncmp(s, "wbem/wscim/1/cim-schema/2/", 26))
 687                                   return -1;
 688           
 689                               s += 26;
 690           
 691                               wsheader->rqtClassname = s;
 692                               s = strchr(s, '/');
 693           
 694 mike  1.1                     if (!s)
 695                                   return -1;
 696           
 697                               *s = 0;
 698                               s++;
 699                               wsheader->rqtMethod = s;
 700                           }
 701           
 702                           if (XML_Expect(xml, &e, XML_END, "a:Action") != 0)
 703                               return -1;
 704                       }
 705                       break;
 706           
 707                       case WSMANTAG_SELECTOR_SET:
 708                       {
 709                           if (_GetSelectorSet(xml, wsheader) != 0)
 710                               return -1;
 711                       }
 712                       break;
 713           
 714                       case WSMANTAG_MESSAGE_ID:
 715 mike  1.1             {
 716                           if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
 717                               return -1;
 718           
 719                           wsheader->rqtMessageID = e.data;
 720           
 721                           if (XML_Expect(xml, &e, XML_END, "a:MessageID") != 0)
 722                               return -1;
 723                       }
 724                       break;
 725           
 726                       case WSMANTAG_MAX_ENVELOPE_SIZE:
 727                       {
 728                           if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
 729                               return -1;
 730           
 731                           wsheader->maxEnvelopeSize = (MI_Uint32)Strtoull(e.data, NULL, 10);
 732                           PRINTF(("maxEnvelopeSize{%d}\n", wsheader->maxEnvelopeSize));
 733           
 734                           if (XML_Expect(xml, &e, XML_END, "w:MaxEnvelopeSize") != 0)
 735                               return -1;
 736 mike  1.1             }
 737                       break;
 738           
 739                       default:
 740                       {
 741                           if (_MustUnderstandCanBeIgnored(&e) != 0)
 742                           {
 743                               wsheader->unknownMandatoryTag = e.data;
 744                               LOGW_CHAR(("wsman: unknown mandatory tag [%s]; aborted", 
 745                                   e.data ));
 746                               /* validate header will send correct repsonse to the client */
 747                           }
 748           
 749                           if (XML_Skip(xml) != 0)
 750                               return -1;
 751                       }
 752                       break;
 753           
 754                   }
 755               }
 756               return 0;
 757 mike  1.1 }
 758           
 759           int WS_ParseSoapEnvelope(XML* xml)
 760           {
 761               XML_Elem e;
 762           
 763               /* Ignore the processing instruction (if any) */
 764               {
 765                   if (XML_Next(xml, &e) != 0)
 766                   {
 767                       XML_Raise(xml, "missing root element");
 768                       return -1;
 769                   }
 770           
 771                   if (e.type != XML_INSTRUCTION)
 772                   {
 773                       if (XML_PutBack(xml, &e) != 0)
 774                           return -1;
 775                   }
 776               }
 777           
 778 mike  1.1     /* Expect <s:Envelope> */
 779               if (XML_Expect(xml, &e, XML_START, "s:Envelope") != 0)
 780                   return -1;
 781           
 782               return 0;
 783           }
 784           
 785           static const char* _ExpectCharsAndEnd(
 786               XML* xml,
 787               const char* name)
 788           {
 789               XML_Elem e;
 790               const char* chars;
 791           
 792               if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
 793                   return NULL;
 794           
 795               chars = e.data;
 796           
 797               if (XML_Expect(xml, &e, XML_END, name) != 0)
 798                   return NULL;
 799 mike  1.1 
 800               return chars;
 801           }
 802           
 803           /*
 804           **==============================================================================
 805           **
 806           ** _ParseAssociationFilterObject()
 807           **
 808           ** Example:
 809           **   <b:Object>
 810           **     <a:Address>
 811           **       http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
 812           **     </a:Address>
 813           **     <a:ReferenceParameters>
 814           **       <w:ResourceURI>
 815           **         http://schemas.microsoft.com/wbem/wscim/1/cim-schema/2/ABC_Widget
 816           **       </w:ResourceURI>
 817           **       <w:SelectorSet>
 818           **         <w:Selector Name="__cimnamespace">
 819           **           root/cimv2
 820 mike  1.1 **         </w:Selector>
 821           **         <w:Selector Name="Key">
 822           **           1001
 823           **         </w:Selector>
 824           **       </w:SelectorSet>
 825           **     </a:ReferenceParameters>
 826           **   </b:Object>
 827           *
 828           **==============================================================================
 829           */
 830           
 831           static int _ParseAssociationFilterObject(
 832               XML* xml, 
 833               Batch* batch,
 834               WSMAN_AssociationFilter* filter)
 835           {
 836               XML_Elem e;
 837           
 838               /* Parse child elements */
 839           
 840               for (;;)
 841 mike  1.1     {
 842                   /* Get next element */
 843           
 844                   if (XML_Next(xml, &e) != 0)
 845                       return -1;
 846           
 847                   /* Put it back and break out if not a start tag */
 848           
 849                   if (e.type != XML_START)
 850                   {
 851                       if (XML_PutBack(xml, &e) != 0)
 852                           return -1;
 853           
 854                       break;
 855                   }
 856           
 857                   /* Handle "Object" tag */
 858           
 859                   if (strcmp(e.data, "a:ReferenceParameters") == 0)
 860                   {
 861                       if (_GetReferenceParameters(
 862 mike  1.1                 xml, 
 863                           batch, 
 864                           &filter->referenceParameters) != 0)
 865                       {
 866                           return -1;
 867                       }
 868                   }
 869                   else if (strcmp(e.data, "a:Address") == 0)
 870                   {
 871                       filter->address = _ExpectCharsAndEnd(xml, "a:Address");
 872           
 873                       if (!filter->address)
 874                           return -1;
 875                   }
 876                   else
 877                   {
 878                       if (XML_Skip(xml) != 0)
 879                           return -1;
 880                   }
 881               }
 882           
 883 mike  1.1     /* Expect </Object> */
 884           
 885               if (XML_Expect(xml, &e, XML_END, "b:Object") != 0)
 886                   return -1;
 887           
 888               return 0;
 889           }
 890           
 891           /*
 892           **==============================================================================
 893           **
 894           ** _ParseAssociationFilter()
 895           **
 896           ** Example:
 897           **   <b:AssociatedInstances>
 898           **     <b:Object>
 899           **       <a:Address>
 900           **         http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
 901           **       </a:Address>
 902           **       <a:ReferenceParameters>
 903           **         <w:ResourceURI>
 904 mike  1.1 **           http://schemas.microsoft.com/wbem/wscim/1/cim-schema/2/ABC_Widget
 905           **         </w:ResourceURI>
 906           **         <w:SelectorSet>
 907           **           <w:Selector Name="__cimnamespace">
 908           **             root/cimv2
 909           **           </w:Selector>
 910           **           <w:Selector Name="Key">
 911           **             1001
 912           **           </w:Selector>
 913           **         </w:SelectorSet>
 914           **       </a:ReferenceParameters>
 915           **       </b:Object>
 916           **       <b:AssociationClassName>
 917           **           ABC_Connector
 918           **       </b:AssociationClassName>
 919           **       <b:Role>
 920           **           Component
 921           **       </b:Role>
 922           **     <b:ResultClassName>
 923           **       ABC_Gadget
 924           **     </b:ResultClassName>
 925 mike  1.1 **     <b:ResultRole>
 926           **       Part
 927           **     </b:ResultRole>
 928           **   </b:AssociatedInstances>
 929           **
 930           **==============================================================================
 931           */
 932           
 933           static int _ParseAssociationFilter(
 934               XML* xml, 
 935               Batch* batch,
 936               WSMAN_AssociationFilter* filter)
 937           {
 938               XML_Elem e;
 939           
 940               /* Expect <AssociatedInstances> */
 941           
 942               if (XML_Expect(xml, &e, XML_START, "b:AssociatedInstances") != 0)
 943                   return -1;
 944           
 945               /* Parse child elements */
 946 mike  1.1 
 947               for (;;)
 948               {
 949                   /* Get next element */
 950           
 951                   if (XML_Next(xml, &e) != 0)
 952                       return -1;
 953           
 954                   /* Put it back and break out if not a start tag */
 955           
 956                   if (e.type != XML_START)
 957                   {
 958                       if (XML_PutBack(xml, &e) != 0)
 959                           return -1;
 960           
 961                       break;
 962                   }
 963           
 964                   /* Handle "Object" tag */
 965           
 966                   if (strcmp(e.data, "b:Object") == 0)
 967 mike  1.1         {
 968                       if (_ParseAssociationFilterObject(xml, batch, filter) != 0)
 969                           return -1;
 970                   }
 971                   else if (strcmp(e.data, "b:AssociationClassName") == 0)
 972                   {
 973                       filter->associationClassName = _ExpectCharsAndEnd(
 974                           xml, "b:AssociationClassName");
 975           
 976                       if (!filter->associationClassName)
 977                           return -1;
 978                   }
 979                   else if (strcmp(e.data, "b:Role") == 0)
 980                   {
 981                       filter->role = _ExpectCharsAndEnd(xml, "b:Role");
 982           
 983                       if (!filter->role)
 984                           return -1;
 985                   }
 986                   else if (strcmp(e.data, "b:ResultClassName") == 0)
 987                   {
 988 mike  1.1             filter->resultClassName = _ExpectCharsAndEnd(
 989                           xml, 
 990                           "b:ResultClassName");
 991           
 992                       if (!filter->resultClassName)
 993                           return -1;
 994                   }
 995                   else if (strcmp(e.data, "b:ResultRole") == 0)
 996                   {
 997                       filter->resultRole = _ExpectCharsAndEnd(
 998                           xml, 
 999                           "b:ResultRole");
1000           
1001                       if (!filter->resultRole)
1002                           return -1;
1003                   }
1004                   else
1005                   {
1006                       if (XML_Skip(xml) != 0)
1007                           return -1;
1008                   }
1009 mike  1.1     }
1010           
1011           #if 0
1012               printf("AssociationFilter\n");
1013               printf("{\n");
1014               Instance_Print(filter->referenceParameters, stdout, 1, MI_TRUE);
1015               printf("    nameSpace{%s}\n", filter->referenceParameters->nameSpace);
1016               printf("    address{%s}\n", filter->address);
1017               printf("    associationClassName{%s}\n", filter->associationClassName);
1018               printf("    resultClassName{%s}\n", filter->resultClassName);
1019               printf("    role{%s}\n", filter->role);
1020               printf("    resultRole{%s}\n", filter->resultRole);
1021               printf("}\n");
1022           #endif
1023           
1024               /* Expect </AssociatedInstances> */
1025           
1026               if (XML_Expect(xml, &e, XML_END, "b:AssociatedInstances") != 0)
1027                   return -1;
1028           
1029               return 0;
1030 mike  1.1 }
1031           
1032           int WS_ParseEnumerateBody(
1033               XML* xml, 
1034               Batch** batch,
1035               WSMAN_WSEnumeratePullBody* wsenumbody)
1036           {
1037               XML_Elem e;
1038           
1039               memset(wsenumbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
1040           
1041               /* Allocate batch (owned by WSMAN_ConnectionData object */
1042           
1043               if (*batch == NULL)
1044               {
1045                   *batch = Batch_New(BATCH_MAX_PAGES);
1046           
1047                   if (!*batch)
1048                       return -1;
1049               }
1050           
1051 mike  1.1     /* Expect <s:Body> */
1052               if (XML_Expect(xml, &e, XML_START, "s:Body") != 0)
1053                   return -1;
1054           
1055               /* Expect <n:Enumerate> */
1056               if (XML_Expect(xml, &e, XML_START, "n:Enumerate") != 0)
1057                   return -1;
1058           
1059               for (;;)
1060               {
1061                   if (XML_Next(xml, &e) != 0)
1062                       return -1;
1063           
1064                   if (e.type == XML_END)
1065                   {
1066                       int tag = HashStr(e.data, e.size);
1067           
1068                       if (WSMANTAG_ENUM_ENUMERATE != tag)
1069                       {
1070                           LOGW_CHAR(("wsman: unexpected close tag [%s] in incoming xml", e.data ));
1071                           return -1;
1072 mike  1.1             }
1073                       break;
1074                   }
1075           
1076                   /* skip possible comments */
1077                   if (e.type != XML_START)
1078                       continue;
1079           
1080                   switch (HashStr(e.data, e.size))
1081                   {
1082                   case WSMANTAG_ENUM_MAX_ELEMENTS:
1083                       {
1084                           if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
1085                               return -1;
1086           
1087                           wsenumbody->maxElements = (MI_Uint32)Strtoull(e.data, NULL, 10);
1088                           PRINTF(("maxElements{%d}\n", wsenumbody->maxElements));
1089           
1090                           if (XML_Expect(xml, &e, XML_END, "w:MaxElements") != 0)
1091                               return -1;
1092                       }
1093 mike  1.1             break;
1094           
1095                   case WSMANTAG_ENUM_OPTIMIZE_ENUMERATION:
1096                       {
1097                           wsenumbody->allowOptimization = MI_TRUE;
1098           
1099                           if (XML_Skip(xml) != 0)
1100                               return -1;
1101                       }
1102                       break;
1103           
1104                   case WSMANTAG_ENUM_POLYMORPHISM_MODE:
1105                       {
1106                           if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
1107                               return -1;
1108           
1109                           wsenumbody->polymorphismMode = HashStr(e.data, e.size);
1110           
1111                           if (XML_Expect(xml, &e, XML_END, "b:PolymorphismMode") != 0)
1112                               return -1;
1113                       }
1114 mike  1.1             break;
1115           
1116                   case WSMANTAG_ENUM_MODE:
1117                       {
1118                           if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
1119                               return -1;
1120           
1121                           wsenumbody->enumerationMode = HashStr(e.data, e.size);
1122           
1123                           if (XML_Expect(xml, &e, XML_END, "w:EnumerationMode") != 0)
1124                               return -1;
1125                       }
1126                       break;
1127           
1128                   /* 
1129                    * Examples:
1130                    *   <w:Filter Dialect="http://microsoft.com/wbem/wsman/1/WQL">
1131                    *     SELECT Weight FROM Widget WHERE Key = 1001
1132                    *   </w:Filter>
1133                    *
1134                    *   <w:Filter Dialect="http://microsoft.com/wbem/wsman/1/WQL">
1135 mike  1.1          *     <b:AssociatedInstances>
1136                    *       ...
1137                    *     </b:AssociatedInstances>
1138                    *   </w:Filter>
1139                    */
1140                   case WSMANTAG_ENUM_FILTER:
1141                       {
1142                           const char* dialect;
1143                           const char* p;
1144           
1145                           /* Get 'Dialect' attribute? */
1146                           dialect = XML_Elem_GetAttr(&e, "Dialect");
1147                           if (!dialect)
1148                           {
1149                               LOGW_CHAR(("wsman: Filter tag missing Dialect attribute"));
1150                               return -1;
1151                           }
1152           
1153           
1154                           /* Reduce long dialect name to final component of path */
1155                           p = strrchr(dialect, '/');
1156 mike  1.1                 if (p)
1157                               wsenumbody->dialect = p + 1;
1158                           else
1159                               wsenumbody->dialect = dialect;
1160           
1161                           /* Parse the association filter */
1162                           if (strcmp(dialect, URI_CIMBINDING "/associationFilter") == 0)
1163                           {
1164                               wsenumbody->foundAssociationFilter = MI_TRUE;
1165           
1166                               if (_ParseAssociationFilter(xml, *batch,
1167                                   &wsenumbody->associationFilter) != 0)
1168                               {
1169                                   return -1;
1170                               }
1171                           }
1172                           else
1173                           {
1174                               /* Get the filter text */
1175                               if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
1176                                   return -1;
1177 mike  1.1 
1178                               wsenumbody->filter = e.data;
1179                           }
1180           
1181                           /* Check for closing </w:Filter> tag */
1182                           if (XML_Expect(xml, &e, XML_END, "w:Filter") != 0)
1183                               return -1;
1184                       }
1185                       break;
1186           
1187                   default:
1188                       {
1189                           if (_MustUnderstandCanBeIgnored(&e) != 0)
1190                           {
1191                               LOGW_CHAR(("wsman: unknown mandatory tag [%s]; aborted", e.data ));
1192                               return -1;
1193                           }
1194           
1195                           if (XML_Skip(xml) != 0)
1196                               return -1;
1197                       }
1198 mike  1.1             break;
1199           
1200                   }
1201               }
1202           
1203               /* Expect <s:Body> */
1204               if (XML_Expect(xml, &e, XML_END, "s:Body") != 0)
1205                   return -1;
1206           
1207               /* Expect </s:Envelope> */
1208               if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0)
1209                   return -1;
1210           
1211               return 0;
1212           }
1213           
1214           int WS_ParseInvokeBody(
1215               XML* xml, 
1216               Batch*  dynamicBatch,
1217               MI_Instance** dynamicInstanceParams)
1218           {
1219 mike  1.1     XML_Elem e;
1220           
1221               *dynamicInstanceParams = 0;
1222           
1223               /* Expect <s:Body> */
1224               if (XML_Expect(xml, &e, XML_START, "s:Body") != 0)
1225                   return -1;
1226           
1227               /* Expect <?:?> parameter's tag */
1228               for (;;)
1229               {
1230                   if (XML_Next(xml, &e) != 0)
1231                       return -1;
1232           
1233                   /* empty body? can be valid for methods without parameters */
1234                   if (e.type == XML_END)
1235                       return 0;
1236           
1237                   if (e.type == XML_START)
1238                       break;
1239               }
1240 mike  1.1 
1241               if (0 != _GetInstance(xml, &e, dynamicBatch, dynamicInstanceParams))
1242                   return -1;
1243           
1244           
1245               /* Expect <s:Body> */
1246               if (XML_Expect(xml, &e, XML_END, "s:Body") != 0)
1247                   return -1;
1248           
1249               /* Expect </s:Envelope> */
1250               if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0)
1251                   return -1;
1252           
1253               return 0;
1254           }
1255           
1256           int WS_ParseCreateBody(
1257               XML* xml, 
1258               Batch*  dynamicBatch,
1259               MI_Instance** dynamicInstanceParams)
1260           {
1261 mike  1.1     XML_Elem e;
1262           
1263               /* Expect <s:Body> */
1264               if (XML_Expect(xml, &e, XML_START, "s:Body") != 0)
1265                   return -1;
1266           
1267               /* Expect <?:?> parameter's tag */
1268               if (XML_Next(xml, &e) != 0)
1269                   return -1;
1270           
1271               if (0 != _GetInstance(xml, &e, dynamicBatch, dynamicInstanceParams))
1272                   return -1;
1273           
1274               /* Expect <s:Body> */
1275               if (XML_Expect(xml, &e, XML_END, "s:Body") != 0)
1276                   return -1;
1277           
1278               /* Expect </s:Envelope> */
1279               if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0)
1280                   return -1;
1281           
1282 mike  1.1     return 0;
1283           }
1284           
1285           int WS_ParsePullBody(
1286               XML* xml, 
1287               WSMAN_WSEnumeratePullBody* wsenumpullbody)
1288           {
1289               XML_Elem e;
1290           
1291               memset(wsenumpullbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
1292           
1293               /* Expect <s:Body> */
1294               if (XML_Expect(xml, &e, XML_START, "s:Body") != 0)
1295                   return -1;
1296           
1297               /* Expect <n:Enumerate> */
1298               if (XML_Expect(xml, &e, XML_START, "n:Pull") != 0)
1299                   return -1;
1300           
1301               for (;;)
1302               {
1303 mike  1.1         if (XML_Next(xml, &e) != 0)
1304                       return -1;
1305           
1306                   if (e.type == XML_END)
1307                   {
1308                       int tag = HashStr(e.data, e.size);
1309           
1310                       if (WSMANTAG_ENUM_PULL != tag)
1311                       {
1312                           LOGW_CHAR(("wsman: unexpected close tag [%s] in incoming xml", e.data ));
1313                           return -1;
1314                       }
1315                       break;
1316                   }
1317           
1318                   /* skip possible comments */
1319                   if (e.type != XML_START)
1320                       continue;
1321           
1322                   switch (HashStr(e.data, e.size))
1323                   {
1324 mike  1.1         case WSMANTAG_PULL_MAX_ELEMENTS:
1325                       {
1326                           if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
1327                               return -1;
1328           
1329                           wsenumpullbody->maxElements = (MI_Uint32)Strtoull(e.data, NULL, 10);
1330                           PRINTF(("maxElements{%d}\n", wsenumpullbody->maxElements));
1331           
1332                           if (XML_Expect(xml, &e, XML_END, "n:MaxElements") != 0)
1333                               return -1;
1334                       }
1335                       break;
1336           
1337                   case WSMANTAG_PULL_ENUMERATION_CONTEXT:
1338                       {
1339                           if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
1340                               return -1;
1341           
1342                           wsenumpullbody->enumerationContextID = (MI_Uint32)Strtoull(e.data, NULL, 10);
1343           
1344                           if (XML_Expect(xml, &e, XML_END, "n:EnumerationContext") != 0)
1345 mike  1.1                     return -1;
1346                       }
1347                       break;
1348           
1349                   default:
1350                       {
1351                           if (_MustUnderstandCanBeIgnored(&e) != 0)
1352                           {
1353                               LOGW_CHAR(("wsman: unknown mandatory tag [%s]; aborted", e.data ));
1354                               return -1;
1355                           }
1356           
1357                           if (XML_Skip(xml) != 0)
1358                               return -1;
1359                       }
1360                       break;
1361           
1362                   }
1363               }
1364           
1365               /* Expect <s:Body> */
1366 mike  1.1     if (XML_Expect(xml, &e, XML_END, "s:Body") != 0)
1367                   return -1;
1368           
1369               /* Expect </s:Envelope> */
1370               if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0)
1371                   return -1;
1372           
1373               return 0;
1374           }
1375           
1376           int WS_ParseReleaseBody(
1377               XML* xml, 
1378               WSMAN_WSEnumeratePullBody* wsenumpullbody)
1379           {
1380               XML_Elem e;
1381           
1382               memset(wsenumpullbody, 0, sizeof(WSMAN_WSEnumeratePullBody));
1383           
1384               /* Expect <s:Body> */
1385               if (XML_Expect(xml, &e, XML_START, "s:Body") != 0)
1386                   return -1;
1387 mike  1.1 
1388               /* Expect <n:Release> */
1389               if (XML_Expect(xml, &e, XML_START, "n:Release") != 0)
1390                   return -1;
1391           
1392               for (;;)
1393               {
1394                   if (XML_Next(xml, &e) != 0)
1395                       return -1;
1396           
1397                   if (e.type == XML_END)
1398                   {
1399                       int tag = HashStr(e.data, e.size);
1400           
1401                       if (WSMANTAG_ENUM_RELEASE != tag)
1402                       {
1403                           LOGW_CHAR(("wsman: unexpected close tag [%s] in incoming xml", e.data ));
1404                           return -1;
1405                       }
1406                       break;
1407                   }
1408 mike  1.1 
1409                   /* skip possible comments */
1410                   if (e.type != XML_START)
1411                       continue;
1412           
1413                   switch (HashStr(e.data, e.size))
1414                   {
1415                   case WSMANTAG_PULL_ENUMERATION_CONTEXT:
1416                       {
1417                           if (XML_Expect(xml, &e, XML_CHARS, NULL) != 0)
1418                               return -1;
1419           
1420                           wsenumpullbody->enumerationContextID = (MI_Uint32)Strtoull(e.data, NULL, 10);
1421           
1422                           if (XML_Expect(xml, &e, XML_END, "n:EnumerationContext") != 0)
1423                               return -1;
1424                       }
1425                       break;
1426           
1427                   default:
1428                       {
1429 mike  1.1                 if (_MustUnderstandCanBeIgnored(&e) != 0)
1430                           {
1431                               LOGW_CHAR(("wsman: unknown mandatory tag [%s]; aborted", e.data ));
1432                               return -1;
1433                           }
1434           
1435                           if (XML_Skip(xml) != 0)
1436                               return -1;
1437                       }
1438                       break;
1439           
1440                   }
1441               }
1442           
1443               /* Expect <s:Body> */
1444               if (XML_Expect(xml, &e, XML_END, "s:Body") != 0)
1445                   return -1;
1446           
1447               /* Expect </s:Envelope> */
1448               if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0)
1449                   return -1;
1450 mike  1.1 
1451               return 0;
1452           }
1453           
1454           int WS_ParseIdentifyBody(
1455               XML* xml)
1456           {
1457               XML_Elem e;
1458           
1459               if (XML_Expect(xml, &e, XML_START, "s:Body") != 0)
1460                   return -1;
1461           
1462               if (XML_Expect(xml, &e, XML_START, "i:Identify") != 0)
1463                   return -1;
1464           
1465               if (XML_Expect(xml, &e, XML_END, "i:Identify") != 0)
1466                   return -1;
1467           
1468               if (XML_Expect(xml, &e, XML_END, "s:Body") != 0)
1469                   return -1;
1470           
1471 mike  1.1     if (XML_Expect(xml, &e, XML_END, "s:Envelope") != 0)
1472                   return -1;
1473           
1474               return 0;
1475           }

ViewCVS 0.9.2