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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2