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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2