(file) Return to CIMExportRequestDecoder.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / ExportServer

  1 karl  1.61 //%2006////////////////////////////////////////////////////////////////////////
  2 mike  1.2  //
  3 karl  1.49 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
  4            // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
  5            // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
  6 karl  1.38 // IBM Corp.; EMC Corporation, The Open Group.
  7 karl  1.49 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  8            // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
  9 karl  1.52 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10            // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11 karl  1.61 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 12            // EMC Corporation; Symantec Corporation; The Open Group.
 13 mike  1.2  //
 14            // Permission is hereby granted, free of charge, to any person obtaining a copy
 15 kumpf 1.20 // of this software and associated documentation files (the "Software"), to
 16            // deal in the Software without restriction, including without limitation the
 17            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 18 mike  1.2  // sell copies of the Software, and to permit persons to whom the Software is
 19            // furnished to do so, subject to the following conditions:
 20 ms.aruran 1.68 //
 21 kumpf     1.20 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 22 mike      1.2  // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 23                // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 24 kumpf     1.20 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 25                // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 26                // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 27 mike      1.2  // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 28                // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 29                //
 30                //==============================================================================
 31                //
 32                //%/////////////////////////////////////////////////////////////////////////////
 33                
 34                #include <Pegasus/Common/Config.h>
 35 david     1.30 #include <Pegasus/Common/Tracer.h>
 36 mike      1.2  #include <cctype>
 37                #include <cstdio>
 38 kumpf     1.15 #include <Pegasus/Common/Constants.h>
 39 mike      1.2  #include <Pegasus/Common/XmlParser.h>
 40                #include <Pegasus/Common/XmlReader.h>
 41                #include <Pegasus/Common/XmlWriter.h>
 42 kumpf     1.21 #include <Pegasus/Common/System.h>
 43 mike      1.2  #include <Pegasus/Common/Logger.h>
 44                #include "CIMExportRequestDecoder.h"
 45 david     1.30 #include <Pegasus/Common/CommonUTF.h>
 46 humberto  1.43 #include <Pegasus/Common/MessageLoader.h>
 47 kumpf     1.59 #include <Pegasus/Common/LanguageParser.h>
 48 mike      1.2  
 49                PEGASUS_USING_STD;
 50                
 51                PEGASUS_NAMESPACE_BEGIN
 52                
 53                CIMExportRequestDecoder::CIMExportRequestDecoder(
 54 kumpf     1.77     MessageQueueService* outputQueue,
 55                    Uint32 returnQueueId)
 56                    : Base(PEGASUS_QUEUENAME_EXPORTREQDECODER),
 57                      _outputQueue(outputQueue),
 58                      _returnQueueId(returnQueueId),
 59                      _serverTerminating(false)
 60 mike      1.2  {
 61                }
 62                
 63                CIMExportRequestDecoder::~CIMExportRequestDecoder()
 64                {
 65                }
 66                
 67                void CIMExportRequestDecoder::sendResponse(
 68 ms.aruran 1.68     Uint32 queueId,
 69 mike      1.58     Buffer& message,
 70 j.alex    1.57     Boolean closeConnect)
 71 mike      1.2  {
 72 kumpf     1.77     MessageQueue* queue = MessageQueue::lookup(queueId);
 73 mike      1.2  
 74 kumpf     1.77     if (queue)
 75                    {
 76                        HTTPMessage* httpMessage = new HTTPMessage(message);
 77                        httpMessage->setCloseConnect(closeConnect);
 78                        queue->enqueue(httpMessage);
 79                    }
 80 mike      1.2  }
 81                
 82 kumpf     1.7  void CIMExportRequestDecoder::sendEMethodError(
 83 kumpf     1.77     Uint32 queueId,
 84                    HttpMethod httpMethod,
 85                    const String& messageId,
 86                    const String& eMethodName,
 87                    const CIMException& cimException,
 88                    Boolean closeConnect)
 89 mike      1.2  {
 90 mike      1.58     Buffer message;
 91 kumpf     1.8      message = XmlWriter::formatSimpleEMethodErrorRspMessage(
 92                        eMethodName,
 93                        messageId,
 94 kumpf     1.22         httpMethod,
 95 kumpf     1.14         cimException);
 96 kumpf     1.7  
 97 j.alex    1.57     sendResponse(queueId, message,closeConnect);
 98 mike      1.2  }
 99                
100 kumpf     1.12 void CIMExportRequestDecoder::sendHttpError(
101 kumpf     1.77     Uint32 queueId,
102                    const String& status,
103                    const String& cimError,
104                    const String& messageBody,
105                    Boolean closeConnect)
106 kumpf     1.9  {
107 mike      1.58     Buffer message;
108 kumpf     1.12     message = XmlWriter::formatHttpErrorRspMessage(
109                        status,
110                        cimError,
111                        messageBody);
112 kumpf     1.9  
113 j.alex    1.57     sendResponse(queueId, message,closeConnect);
114 kumpf     1.9  }
115 mday      1.5  
116 kumpf     1.77 void CIMExportRequestDecoder::handleEnqueue(Message* message)
117 mike      1.2  {
118 kumpf     1.77     PEGASUS_ASSERT(message != 0);
119 mike      1.2  
120 kumpf     1.77     switch (message->getType())
121                    {
122 karl      1.73         case HTTP_MESSAGE:
123                            handleHTTPMessage((HTTPMessage*)message);
124                            break;
125 carolann.graves 1.62 
126                              default:
127                                  PEGASUS_ASSERT(0);
128                                  break;
129 kumpf           1.77     }
130 mday            1.5  
131 kumpf           1.77     delete message;
132 mday            1.5  }
133 mike            1.2  
134                      
135 mday            1.5  void CIMExportRequestDecoder::handleEnqueue()
136                      {
137 kumpf           1.77     Message* message = dequeue();
138                          if (message)
139                              handleEnqueue(message);
140 mike            1.2  }
141                      
142                      //------------------------------------------------------------------------------
143                      //
144                      // From the HTTP/1.1 Specification (RFC 2626):
145                      //
146 ms.aruran       1.68 // Both types of message consist of a start-line, zero or more header fields
147                      // (also known as "headers"), an empty line (i.e., a line with nothing
148                      // preceding the CRLF) indicating the end of the header fields, and possibly
149 mike            1.2  // a message-body.
150                      //
151                      // Example CIM request:
152                      //
153 ms.aruran       1.68 //     M-POST /cimom HTTP/1.1
154                      //     HOST: www.erewhon.com
155                      //     Content-Type: application/xml; charset="utf-8"
156                      //     Content-Length: xxxx
157                      //     Man: http://www.dmtf.org/cim/operation ; ns=73
158 mike            1.2  //     73-CIMExport: MethodRequest
159                      //     73-CIMExportMethod: ExportIndication
160 ms.aruran       1.68 //     73-CIMObject: root/cimv2
161                      //
162 mike            1.2  //------------------------------------------------------------------------------
163                      
164                      void CIMExportRequestDecoder::handleHTTPMessage(HTTPMessage* httpMessage)
165                      {
166 kumpf           1.78     PEGASUS_ASSERT(httpMessage->message.size() != 0);
167                      
168                          // Save queueId and userName
169 mike            1.2  
170 kumpf           1.77     Uint32 queueId = httpMessage->queueId;
171 kumpf           1.78     String userName = httpMessage->authInfo->getAuthenticatedUser();
172 kumpf           1.55 
173 kumpf           1.77     Boolean closeConnect = httpMessage->getCloseConnect();
174                          PEG_TRACE((
175                              TRC_HTTP,
176                              Tracer::LEVEL3,
177                              "CIMOperationRequestDecoder::handleHTTPMessage() -"
178                                   " httpMessage->getCloseConnect() returned %d",
179                              httpMessage->getCloseConnect()));
180                      
181                          // Parse the HTTP message:
182                      
183                          String startLine;
184                          Array<HTTPHeader> headers;
185                          char* content;
186                          Uint32 contentLength;
187                      
188                          httpMessage->parse(startLine, headers, contentLength);
189                      
190                          // Parse the request line:
191                      
192                          String methodName;
193                          String requestUri;
194 kumpf           1.77     String httpVersion;
195                          HttpMethod httpMethod = HTTP_METHOD__POST;
196                      
197                          // ATTN-RK-P3-20020404: The requestUri may need to be pruned of the host
198                          // name.  All we care about at this point is the path.
199                          HTTPMessage::parseRequestLine(
200                              startLine, methodName, requestUri, httpVersion);
201                      
202                          //
203                          //  Set HTTP method for the request
204                          //
205                          if (methodName == "M-POST")
206                          {
207                              httpMethod = HTTP_METHOD_M_POST;
208                          }
209 kumpf           1.13 
210 kumpf           1.77     // Unsupported methods are caught in the HTTPAuthenticatorDelegator
211                          //<Bug #351>
212                          //PEGASUS_ASSERT(methodName == "M-POST" || methodName == "POST");
213                          if (methodName != "M-POST" && methodName != "POST")
214                          {
215                              sendHttpError(
216                                  queueId,
217                                  HTTP_STATUS_NOTIMPLEMENTED,
218                                  "Only POST and M-POST are implemented",
219                                  String::EMPTY,
220                                  closeConnect);
221                              return;
222                          }
223                          //</bug>
224                          //
225                          // Not true: "Mismatch of method and version is caught in
226                          // HTTPAuthenticatorDelegator", bug #351 fixes this:
227                          //
228                          //PEGASUS_ASSERT (!((httpMethod == HTTP_METHOD_M_POST) &&
229                          //                  (httpVersion == "HTTP/1.0")));
230                          if ((httpMethod == HTTP_METHOD_M_POST) &&
231 kumpf           1.77          (httpVersion == "HTTP/1.0"))
232                          {
233                              sendHttpError(
234 j.alex          1.57             queueId,
235                                  HTTP_STATUS_BADREQUEST,
236 kumpf           1.77             "M-POST method is not valid with version 1.0",
237 j.alex          1.57             String::EMPTY,
238                                  closeConnect);
239 kumpf           1.55         return;
240 kumpf           1.77     }
241                          //</bug>
242                      
243                          // Process M-POST and POST messages:
244                          String cimContentType;
245                          String cimExport;
246                          String cimExportBatch;
247                          Boolean cimExportBatchFlag;
248                          String cimProtocolVersion;
249                          String cimExportMethod;
250                      
251                          if (httpVersion == "HTTP/1.1")
252                          {
253                              // Validate the presence of a "Host" header.  The HTTP/1.1 specification
254                              // says this in section 14.23 regarding the Host header field:
255                              //
256                              //     All Internet-based HTTP/1.1 servers MUST respond with a 400 (Bad
257                              //     Request) status code to any HTTP/1.1 request message which lacks
258                              //     a Host header field.
259                              //
260                              // Note:  The Host header value is not validated.
261 kumpf           1.77 
262                              String hostHeader;
263                              Boolean hostHeaderFound = HTTPMessage::lookupHeader(
264                                  headers, "Host", hostHeader, false);
265                      
266                              if (!hostHeaderFound)
267                              {
268                                  MessageLoaderParms parms(
269                                      "ExportServer.CIMExportRequestDecoder.MISSING_HOST_HEADER",
270                                      "HTTP request message lacks a Host header field.");
271                                  String msg(MessageLoader::getMessage(parms));
272                                  sendHttpError(
273                                      queueId,
274                                      HTTP_STATUS_BADREQUEST,
275                                      "",
276                                      msg,
277                                      closeConnect);
278                                  return;
279                              }
280                          }
281                      
282 kumpf           1.77     // Validate the "CIMExport" header:
283                      
284                          Boolean exportHeaderFound = HTTPMessage::lookupHeader(
285                              headers, "CIMExport", cimExport, true);
286                          // If the CIMExport header was missing, the HTTPAuthenticatorDelegator
287                          // would not have passed the message to us.
288                      
289                          // <bug #351>
290                          // PEGASUS_ASSERT(exportHeaderFound);
291                          if (!exportHeaderFound)
292                          {
293                              sendHttpError(
294 ms.aruran       1.68              queueId,
295                                   HTTP_STATUS_BADREQUEST,
296 kumpf           1.77              "Export header not found",
297 j.alex          1.57              String::EMPTY,
298                                   closeConnect);
299 kumpf           1.13          return;
300 kumpf           1.77     }
301                          // </bug>
302                      
303                          if (!String::equalNoCase(cimExport, "MethodRequest"))
304                          {
305                              // The Specification for CIM Operations over HTTP reads:
306                              //     3.3.5. CIMExport
307                              //     If a CIM Listener receives CIM Export request with this
308                              //     header, but with a missing value or a value that is not
309                              //     "MethodRequest", then it MUST fail the request with
310                              //     status "400 Bad Request". The CIM Server MUST include a
311                              //     CIMError header in the response with a value of
312                              //     unsupported-operation.
313                              sendHttpError(
314                                  queueId,
315                                  HTTP_STATUS_BADREQUEST,
316                                  "unsupported-operation",
317                                  String::EMPTY,
318                                  closeConnect);
319                              return;
320                          }
321 kumpf           1.10 
322 kumpf           1.77     // Validate the "CIMExportBatch" header:
323                      
324                          cimExportBatchFlag = HTTPMessage::lookupHeader(
325                              headers, "CIMExportBatch", cimExportBatch, true);
326                          if (cimExportBatchFlag)
327                          {
328                              // The Specification for CIM Operations over HTTP reads:
329                              //     3.3.10. CIMExportBatch
330                              //     If a CIM Listener receives CIM Export Request for which the
331                              //     CIMExportBatch header is present, but the Listener does not
332                              //     support Multiple Exports, then it MUST fail the request and
333                              //     return a status of "501 Not Implemented".
334                              sendHttpError(
335                                  queueId,
336                                  HTTP_STATUS_NOTIMPLEMENTED,
337                                  "multiple-requests-unsupported",
338                                  String::EMPTY,
339                                  closeConnect);
340                              return;
341                          }
342                      
343 kumpf           1.77     // Save these headers for later checking
344                      
345                          if (!HTTPMessage::lookupHeader(
346                                  headers, "CIMProtocolVersion", cimProtocolVersion, true))
347                          {
348                              // Mandated by the Specification for CIM Operations over HTTP
349                              cimProtocolVersion.assign("1.0");
350                          }
351                      
352                          if (HTTPMessage::lookupHeader(
353                                  headers, "CIMExportMethod", cimExportMethod, true))
354                          {
355                              if (cimExportMethod == String::EMPTY)
356                              {
357                                  // This is not a valid value, and we use EMPTY to mean "absent"
358                                  sendHttpError(
359                                      queueId,
360                                      HTTP_STATUS_BADREQUEST,
361                                      "header-mismatch",
362                                      String::EMPTY,
363                                      closeConnect);
364 kumpf           1.77             return;
365 karl            1.73         }
366                          }
367                      
368 kumpf           1.77     AcceptLanguageList acceptLanguages;
369                          ContentLanguageList contentLanguages;
370                          try
371                          {
372                              if (httpMessage->acceptLanguagesDecoded)
373                              {
374                                  acceptLanguages = httpMessage->acceptLanguages;
375                              }
376                              else
377                              {
378                                  // Get and validate the Accept-Language header, if set
379                                  String acceptLanguageHeader;
380                                  if (HTTPMessage::lookupHeader(
381                                          headers,
382                                          "Accept-Language",
383                                          acceptLanguageHeader,
384                                          false))
385                                  {
386                                      acceptLanguages = LanguageParser::parseAcceptLanguageHeader(
387                                          acceptLanguageHeader);
388                                  }
389 kumpf           1.77         }
390                      
391                              if (httpMessage->contentLanguagesDecoded)
392                              {
393                                  contentLanguages = httpMessage->contentLanguages;
394                              }
395                              else
396                              {
397                                  // Get and validate the Content-Language header, if set
398                                  String contentLanguageHeader;
399                                  if (HTTPMessage::lookupHeader(
400                                          headers,
401                                          "Content-Language",
402                                          contentLanguageHeader,
403                                          false))
404                                  {
405                                      contentLanguages = LanguageParser::parseContentLanguageHeader(
406                                          contentLanguageHeader);
407                                  }
408 karl            1.73         }
409                          }
410 kumpf           1.77     catch (Exception& e)
411                          {
412                              Thread::clearLanguages();
413                              MessageLoaderParms msgParms(
414                                  "ExportServer.CIMExportRequestDecoder.REQUEST_NOT_VALID",
415 karl            1.73             "request-not-valid");
416 kumpf           1.77         String msg(MessageLoader::getMessage(msgParms));
417                              sendHttpError(
418 ms.aruran       1.68             queueId,
419                                  HTTP_STATUS_BADREQUEST,
420 j.alex          1.57             msg,
421                                  e.getMessage(),
422 ms.aruran       1.68             closeConnect);
423 karl            1.73         return;
424 kumpf           1.77     }
425 chuck           1.27 
426 kumpf           1.77     // Calculate the beginning of the content from the message size and
427                          // the content length.
428 mike            1.2  
429 kumpf           1.77     content = (char *) httpMessage->message.getData() +
430                              httpMessage->message.size() - contentLength;
431 chuck           1.40 
432 kumpf           1.77     // Validate the "Content-Type" header:
433 chuck           1.40 
434 kumpf           1.77     Boolean contentTypeHeaderFound = HTTPMessage::lookupHeader(
435                              headers, "Content-Type", cimContentType, true);
436                      
437 venkat.puvvada  1.79     if (!contentTypeHeaderFound ||
438                              !HTTPMessage::isSupportedContentType (cimContentType))
439 kumpf           1.77     {
440                              sendHttpError(
441                                  queueId,
442                                  HTTP_STATUS_BADREQUEST,
443                                  "",
444                                  "HTTP Content-Type header error.",
445                                  closeConnect);
446                              return;
447                          }
448                          else
449                          {
450                              // Validating content falls within UTF8 (required to be complaint
451                              // with section C12 of Unicode 4.0 spec, chapter 3.)
452                              Uint32 count = 0;
453                              while(count<contentLength)
454                              {
455                                  if (!(isUTF8((char *)&content[count])))
456                                  {
457                                      sendHttpError(
458                                          queueId,
459                                          HTTP_STATUS_BADREQUEST,
460 kumpf           1.77                     "request-not-valid",
461                                          "Invalid UTF-8 character detected.",
462                                          closeConnect);
463                                      return;
464                                  }
465                                  UTF8_NEXT(content,count);
466                              }
467                          }
468                      
469                          // If it is a method call, then dispatch it to be handled:
470                      
471                          handleMethodRequest(
472                              queueId,
473                              httpMethod,
474                              content,
475                              requestUri,
476                              cimProtocolVersion,
477                              cimExportMethod,
478                              userName,
479                              httpMessage->ipAddress,
480                              acceptLanguages,
481 kumpf           1.77         contentLanguages,
482                              closeConnect);
483 mike            1.2  }
484                      
485                      void CIMExportRequestDecoder::handleMethodRequest(
486 j.alex          1.57     Uint32 queueId,
487                          HttpMethod httpMethod,
488                          char* content,
489                          const String& requestUri,
490                          const String& cimProtocolVersionInHeader,
491                          const String& cimExportMethodInHeader,
492                          const String& userName,
493 kumpf           1.65     const String& ipAddress,
494 kumpf           1.60     const AcceptLanguageList& httpAcceptLanguages,
495                          const ContentLanguageList& httpContentLanguages,
496 ms.aruran       1.68     Boolean closeConnect)
497 mday            1.5  {
498 karl            1.73     // Set the Accept-Language into the thread for this service.
499                          // This will allow all code in this thread to get
500                          // the languages for the messages returned to the client.
501                          Thread::setLanguages(new AcceptLanguageList(httpAcceptLanguages));
502 chuck           1.28 
503 kumpf           1.77     //
504                          // If CIM Listener is shutting down, return error response
505                          //
506                          if (_serverTerminating)
507                          {
508                              sendHttpError(
509                                  queueId,
510                                  HTTP_STATUS_SERVICEUNAVAILABLE,
511                                  String::EMPTY,
512                                  "CIM Listener is shutting down.",
513                                  closeConnect);
514                              return;
515                          }
516                      
517                          // Create a parser:
518                      
519                          XmlParser parser(content);
520                          XmlEntry entry;
521                          String messageId;
522                          const char* cimExportMethodName = "";
523                          AutoPtr<CIMExportIndicationRequestMessage> request;
524 kumpf           1.77 
525                          try
526                          {
527                              //
528                              // Process <?xml ... >
529                              //
530                      
531                              // These values are currently unused
532                              const char* xmlVersion = 0;
533                              const char* xmlEncoding = 0;
534                      
535                              XmlReader::getXmlDeclaration(parser, xmlVersion, xmlEncoding);
536                      
537                              // Expect <CIM ...>
538                      
539                              const char* cimVersion = 0;
540                              const char* dtdVersion = 0;
541                      
542                              XmlReader::getCimStartTag(parser, cimVersion, dtdVersion);
543                      
544                              if (!XmlReader::isSupportedCIMVersion(cimVersion))
545 kumpf           1.77         {
546                                  sendHttpError(
547                                      queueId,
548                                      HTTP_STATUS_NOTIMPLEMENTED,
549                                      "unsupported-cim-version",
550                                      String::EMPTY,
551                                      closeConnect);
552                                  return;
553                              }
554                      
555                              if (!XmlReader::isSupportedDTDVersion(dtdVersion))
556                              {
557                                  sendHttpError(
558                                      queueId,
559                                      HTTP_STATUS_NOTIMPLEMENTED,
560                                      "unsupported-dtd-version",
561                                      String::EMPTY,
562                                      closeConnect);
563                                  return;
564                              }
565                      
566 kumpf           1.77         // Expect <MESSAGE ...>
567                      
568                              String protocolVersion;
569                              if (!XmlReader::getMessageStartTag(
570                                      parser, messageId, protocolVersion))
571                              {
572                                  MessageLoaderParms mlParms(
573                                      "ExportServer.CIMExportRequestDecoder.EXPECTED_MESSAGE_ELEMENT",
574                                      "expected MESSAGE element");
575                      
576                                  throw XmlValidationError(parser.getLine(), mlParms);
577                              }
578                      
579                              // Validate that the protocol version in the header matches the XML
580                      
581                              if (!String::equalNoCase(protocolVersion, cimProtocolVersionInHeader))
582                              {
583                                  sendHttpError(
584                                      queueId,
585                                      HTTP_STATUS_BADREQUEST,
586                                      "header-mismatch",
587 kumpf           1.77                 String::EMPTY,
588                                      closeConnect);
589                                  return;
590                              }
591                      
592                              // We accept protocol version 1.x (see Bugzilla 1556)
593                      
594                              Boolean protocolVersionAccepted = false;
595                      
596                              if ((protocolVersion.size() >= 3) &&
597                                  (protocolVersion[0] == '1') &&
598                                  (protocolVersion[1] == '.'))
599                              {
600                                  // Verify that all characters after the '.' are digits
601                                  Uint32 index = 2;
602                                  while ((index < protocolVersion.size()) &&
603                                         (protocolVersion[index] >= '0') &&
604                                         (protocolVersion[index] <= '9'))
605                                  {
606                                      index++;
607                                  }
608 kumpf           1.77 
609                                  if (index == protocolVersion.size())
610                                  {
611                                      protocolVersionAccepted = true;
612                                  }
613                              }
614                      
615                              if (!protocolVersionAccepted)
616                              {
617                                  // See Specification for CIM Operations over HTTP section 4.3
618                                  sendHttpError(
619                                      queueId,
620                                      HTTP_STATUS_NOTIMPLEMENTED,
621                                      "unsupported-protocol-version",
622                                      String::EMPTY,
623                                      closeConnect);
624                                  return;
625                              }
626                      
627                              if (XmlReader::testStartTag(parser, entry, "MULTIEXPREQ"))
628                              {
629 kumpf           1.77             // We wouldn't have gotten here if CIMExportBatch header was
630                                  // specified, so this must be indicative of a header mismatch
631                                  sendHttpError(
632                                      queueId,
633                                      HTTP_STATUS_BADREQUEST,
634                                      "header-mismatch",
635                                      String::EMPTY,
636                                      closeConnect);
637                                  return;
638                                  // Future: When MULTIEXPREQ is supported, must ensure
639                                  // CIMExportMethod header is absent, and CIMExportBatch header
640                                  // is present.
641                              }
642 kumpf           1.10 
643 kumpf           1.77         // Expect <SIMPLEEXPREQ ...>
644 mday            1.5  
645 kumpf           1.77         XmlReader::expectStartTag(parser, entry, "SIMPLEEXPREQ");
646 mday            1.5  
647 kumpf           1.77         // Expect <EXPMETHODCALL ...>
648 humberto        1.32 
649 kumpf           1.77         if (!XmlReader::getEMethodCallStartTag(parser, cimExportMethodName))
650                              {
651                                  MessageLoaderParms mlParms(
652                                      "ExportServer.CIMExportRequestDecoder."
653                                          "EXPECTED_EXPMETHODCALL_ELEMENT",
654                                      "expected EXPMETHODCALL element");
655 humberto        1.32 
656 kumpf           1.77             throw XmlValidationError(parser.getLine(), mlParms);
657                              }
658 humberto        1.32 
659 kumpf           1.77         // The Specification for CIM Operations over HTTP reads:
660                              //     3.3.9. CIMExportMethod
661                              //
662                              //     This header MUST be present in any CIM Export Request
663                              //     message that contains a Simple Export Request.
664                              //
665                              //     It MUST NOT be present in any CIM Export Response message,
666                              //     nor in any CIM Export Request message that is not a
667                              //     Simple Export Request. It MUST NOT be present in any CIM
668                              //     Operation Request or Response message.
669                              //
670                              //     The name of the CIM export method within a Simple Export
671                              //     Request is defined to be the value of the NAME attribute
672                              //     of the <EXPMETHODCALL> element.
673                              //
674                              //     If a CIM Listener receives a CIM Export Request for which
675                              //     either:
676                              //
677                              //     - The CIMExportMethod header is present but has an invalid
678                              //       value, or;
679                              //     - The CIMExportMethod header is not present but the Export
680 kumpf           1.77         //       Request Message is a Simple Export Request, or;
681                              //     - The CIMExportMethod header is present but the Export
682                              //       Request Message is not a Simple Export Request, or;
683                              //     - The CIMExportMethod header is present, the Export Request
684                              //       Message is a Simple Export Request, but the CIMIdentifier
685                              //       value (when unencoded) does not match the unique method
686                              //       name within the Simple Export Request,
687                              //
688                              //     then it MUST fail the request and return a status of
689                              //     "400 Bad Request" (and MUST include a CIMError header in the
690                              //     response with a value of header-mismatch), subject to the
691                              //     considerations specified in Errors.
692                              if (!String::equalNoCase(cimExportMethodName, cimExportMethodInHeader))
693                              {
694                                  // ATTN-RK-P3-20020404: How to decode cimExportMethodInHeader?
695                                  sendHttpError(
696                                      queueId,
697                                      HTTP_STATUS_BADREQUEST,
698                                      "header-mismatch",
699                                      String::EMPTY,
700                                      closeConnect);
701 kumpf           1.77             return;
702                              }
703 mday            1.5  
704 kumpf           1.77         // This try block only catches CIMExceptions, because they must be
705                              // responded to with a proper EMETHODRESPONSE.  Other exceptions are
706                              // caught in the outer try block.
707                              try
708                              {
709                                  // Delegate to appropriate method to handle:
710 kumpf           1.10 
711 kumpf           1.77             if (System::strcasecmp(
712                                          cimExportMethodName, "ExportIndication") == 0)
713                                  {
714                                     request.reset(decodeExportIndicationRequest(
715                                         queueId, parser, messageId, requestUri));
716                                  }
717                                  else
718                                  {
719                                      throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_NOT_SUPPORTED,
720                                          MessageLoaderParms(
721                                              "ExportServer.CIMExportRequestDecoder."
722                                                  "UNRECOGNIZED_EXPORT_METHOD",
723                                              "Unrecognized export method: $0",
724                                              cimExportMethodName));
725                                  }
726                              }
727                              catch (CIMException& e)
728                              {
729                                  sendEMethodError(
730                                      queueId,
731                                      httpMethod,
732 kumpf           1.77                 messageId,
733                                      cimExportMethodName,
734                                      e,
735                                      closeConnect);
736 kumpf           1.10 
737 kumpf           1.77             return;
738                              }
739 kumpf           1.47 
740 kumpf           1.77         // Expect </EXPMETHODCALL>
741 kumpf           1.47 
742 kumpf           1.77         XmlReader::expectEndTag(parser, "EXPMETHODCALL");
743 ms.aruran       1.68 
744 kumpf           1.77         // Expect </SIMPLEEXPREQ>
745 mday            1.5  
746 kumpf           1.77         XmlReader::expectEndTag(parser, "SIMPLEEXPREQ");
747 ms.aruran       1.68 
748 kumpf           1.77         // Expect </MESSAGE>
749 mike            1.2  
750 kumpf           1.77         XmlReader::expectEndTag(parser, "MESSAGE");
751 mike            1.2  
752 kumpf           1.77         // Expect </CIM>
753 mike            1.2  
754 kumpf           1.77         XmlReader::expectEndTag(parser, "CIM");
755                          }
756                          catch (XmlValidationError& e)
757                          {
758                              Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::TRACE,
759                                  "CIMExportRequestDecoder::handleMethodRequest - "
760                                  "XmlValidationError exception has occurred. Message: $0",
761                                  e.getMessage());
762 mike            1.2  
763 kumpf           1.77         sendHttpError(
764                                  queueId,
765                                  HTTP_STATUS_BADREQUEST,
766                                  "request-not-valid",
767                                  e.getMessage(),
768                                  closeConnect);
769                              return;
770                          }
771                          catch (XmlSemanticError& e)
772                          {
773                              Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::TRACE,
774                                  "CIMExportRequestDecoder::handleMethodRequest - "
775                                  "XmlSemanticError exception has occurred. Message: $0",
776                                  e.getMessage());
777                              // ATTN-RK-P2-20020404: Is this the correct response for these errors?
778                              sendHttpError(
779                                  queueId,
780                                  HTTP_STATUS_BADREQUEST,
781                                  "request-not-valid",
782                                  e.getMessage(),
783                                  closeConnect);
784 kumpf           1.77         return;
785                          }
786                          catch (XmlException& e)
787                          {
788                              Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::TRACE,
789                                  "CIMExportRequestDecoder::handleMethodRequest - "
790                                  "XmlException has occurred. Message: $0",e.getMessage());
791 mike            1.2  
792 kumpf           1.77         sendHttpError(
793                                  queueId,
794                                  HTTP_STATUS_BADREQUEST,
795                                  "request-not-well-formed",
796                                  e.getMessage(),
797                                  closeConnect);
798                              return;
799                          }
800                          catch (Exception& e)
801                          {
802                              // Don't know why I got this exception.  Seems like a bad thing.
803                              // Any exceptions we're expecting should be caught separately and
804                              // dealt with appropriately.  This is a last resort.
805                              sendHttpError(
806                                  queueId,
807                                  HTTP_STATUS_INTERNALSERVERERROR,
808                                  String::EMPTY,
809                                  e.getMessage(),
810                                  closeConnect);
811                              return;
812                          }
813 kumpf           1.77     catch (...)
814                          {
815                              // Don't know why I got whatever this is.  Seems like a bad thing.
816                              // Any exceptions we're expecting should be caught separately and
817                              // dealt with appropriately.  This is a last resort.
818                              sendHttpError(
819                                  queueId,
820                                  HTTP_STATUS_INTERNALSERVERERROR,
821                                  String::EMPTY,
822                                  String::EMPTY,
823                                  closeConnect);
824                              return;
825                          }
826 chuck           1.27 
827                      // l10n TODO - might want to move A-L and C-L to Message
828                      // to make this more maintainable
829 karl            1.73     // Add the language headers to the request.
830                          // Note: Since the text of an export error response will be ignored
831                          // by the export client, ignore Accept-Language in the export request.
832                          // This will cause any export error response message to be sent in the
833                          // default language.
834                          request->operationContext.insert(IdentityContainer(userName));
835                          request->operationContext.set(
836 kumpf           1.77         ContentLanguageListContainer(httpContentLanguages));
837 karl            1.73     request->operationContext.set(
838 kumpf           1.77         AcceptLanguageListContainer(AcceptLanguageList()));
839 mike            1.2  
840 kumpf           1.77     request->ipAddress = ipAddress;
841 kumpf           1.65 
842 kumpf           1.77     request->setCloseConnect(closeConnect);
843 j.alex          1.57 
844 kumpf           1.77     _outputQueue->enqueue(request.release());
845 mike            1.2  }
846                      
847 kumpf           1.77 CIMExportIndicationRequestMessage*
848 karl            1.73 CIMExportRequestDecoder::decodeExportIndicationRequest(
849 kumpf           1.77     Uint32 queueId,
850                          XmlParser& parser,
851                          const String& messageId,
852                          const String& requestUri)
853                      {
854                          CIMInstance instanceName;
855                      
856                          String destStr = requestUri.subString(
857                              requestUri.find("/CIMListener") + 12, PEG_NOT_FOUND);
858                      
859                          for (const char* name; XmlReader::getEParamValueTag(parser, name);)
860                          {
861                              if (System::strcasecmp(name, "NewIndication") == 0)
862                              {
863                                  XmlReader::getInstanceElement(parser, instanceName);
864                              }
865                              else
866                              {
867                                  MessageLoaderParms mlParms(
868                                      "ExportServer.CIMExportRequestDecoder."
869                                          "UNRECOGNIZED_EXPPARAMVALUE_NAME",
870 kumpf           1.77                 "Unrecognized EXPPARAMVALUE Name $0", name);
871                                  throw PEGASUS_CIM_EXCEPTION(CIM_ERR_NOT_SUPPORTED, mlParms);
872                              }
873                      
874                              XmlReader::expectEndTag(parser, "EXPPARAMVALUE");
875                          }
876                      
877                          CIMExportIndicationRequestMessage* request =
878                              new CIMExportIndicationRequestMessage(
879                                  messageId,
880                                  destStr,
881                                  instanceName,
882                                  QueueIdStack(queueId, _returnQueueId));
883 ms.aruran       1.68 
884 kumpf           1.77     return request;
885 mike            1.2  }
886                      
887                      void CIMExportRequestDecoder::setServerTerminating(Boolean flag)
888                      {
889 kumpf           1.77     _serverTerminating = flag;
890 mike            1.2  }
891                      
892                      PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2