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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2