📄 cimexportrequestdecoder.cpp
字号:
//%2006//////////////////////////////////////////////////////////////////////////// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;// IBM Corp.; EMC Corporation, The Open Group.// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;// EMC Corporation; VERITAS Software Corporation; The Open Group.// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;// EMC Corporation; Symantec Corporation; The Open Group.//// Permission is hereby granted, free of charge, to any person obtaining a copy// of this software and associated documentation files (the "Software"), to// deal in the Software without restriction, including without limitation the// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or// sell copies of the Software, and to permit persons to whom the Software is// furnished to do so, subject to the following conditions://// THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN// ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.////==============================================================================////%/////////////////////////////////////////////////////////////////////////////#include <Pegasus/Common/Config.h>#include <Pegasus/Common/Tracer.h>#include <cctype>#include <cstdio>#include <Pegasus/Common/Constants.h>#include <Pegasus/Common/XmlParser.h>#include <Pegasus/Common/XmlReader.h>#include <Pegasus/Common/XmlWriter.h>#include <Pegasus/Common/System.h>#include <Pegasus/Common/Logger.h>#include "CIMExportRequestDecoder.h"#include <Pegasus/Common/CommonUTF.h>#include <Pegasus/Common/MessageLoader.h>#include <Pegasus/Common/LanguageParser.h>PEGASUS_USING_STD;PEGASUS_NAMESPACE_BEGINCIMExportRequestDecoder::CIMExportRequestDecoder( MessageQueueService* outputQueue, Uint32 returnQueueId) : Base(PEGASUS_QUEUENAME_EXPORTREQDECODER), _outputQueue(outputQueue), _returnQueueId(returnQueueId), _serverTerminating(false){}CIMExportRequestDecoder::~CIMExportRequestDecoder(){}void CIMExportRequestDecoder::sendResponse( Uint32 queueId, Buffer& message, Boolean closeConnect){ MessageQueue* queue = MessageQueue::lookup(queueId); if (queue) { HTTPMessage* httpMessage = new HTTPMessage(message); httpMessage->setCloseConnect(closeConnect); queue->enqueue(httpMessage); }}void CIMExportRequestDecoder::sendEMethodError( Uint32 queueId, HttpMethod httpMethod, const String& messageId, const String& eMethodName, const CIMException& cimException, Boolean closeConnect){ Buffer message; message = XmlWriter::formatSimpleEMethodErrorRspMessage( eMethodName, messageId, httpMethod, cimException); sendResponse(queueId, message,closeConnect);}void CIMExportRequestDecoder::sendHttpError( Uint32 queueId, const String& status, const String& cimError, const String& messageBody, Boolean closeConnect){ Buffer message; message = XmlWriter::formatHttpErrorRspMessage( status, cimError, messageBody); sendResponse(queueId, message,closeConnect);}void CIMExportRequestDecoder::handleEnqueue(Message *message){ PEGASUS_ASSERT(message != 0); switch (message->getType()) { case HTTP_MESSAGE: handleHTTPMessage((HTTPMessage*)message); break; default: PEGASUS_ASSERT(0); break; } delete message;}void CIMExportRequestDecoder::handleEnqueue(){ Message* message = dequeue(); if(message) handleEnqueue(message);}//------------------------------------------------------------------------------//// From the HTTP/1.1 Specification (RFC 2626)://// Both types of message consist of a start-line, zero or more header fields// (also known as "headers"), an empty line (i.e., a line with nothing// preceding the CRLF) indicating the end of the header fields, and possibly// a message-body.//// Example CIM request://// M-POST /cimom HTTP/1.1// HOST: www.erewhon.com// Content-Type: application/xml; charset="utf-8"// Content-Length: xxxx// Man: http://www.dmtf.org/cim/operation ; ns=73// 73-CIMExport: MethodRequest// 73-CIMExportMethod: ExportIndication// 73-CIMObject: root/cimv2////------------------------------------------------------------------------------void CIMExportRequestDecoder::handleHTTPMessage(HTTPMessage* httpMessage){ // Save queueId: Uint32 queueId = httpMessage->queueId; // Save userName: String userName; // Bug #351: if ( httpMessage->message.size() == 0 ) { // The message is empty; just drop it. The connection has // probably closed. return; } // </bug> if ( httpMessage->authInfo->isAuthenticated() ) { userName = httpMessage->authInfo->getAuthenticatedUser(); } Boolean closeConnect = httpMessage->getCloseConnect(); Tracer::trace( TRC_HTTP, Tracer::LEVEL3, "CIMOperationRequestDecoder::handleHTTPMessage()- httpMessage->getCloseConnect() returned %d",httpMessage->getCloseConnect()); // Parse the HTTP message: String startLine; Array<HTTPHeader> headers; char* content; Uint32 contentLength; httpMessage->parse(startLine, headers, contentLength); // Parse the request line: String methodName; String requestUri; String httpVersion; HttpMethod httpMethod = HTTP_METHOD__POST; Tracer::trace(TRC_XML_IO, Tracer::LEVEL2, "%s", httpMessage->message.getData()); // ATTN-RK-P3-20020404: The requestUri may need to be pruned of the host // name. All we care about at this point is the path. HTTPMessage::parseRequestLine( startLine, methodName, requestUri, httpVersion); // // Set HTTP method for the request // if (methodName == "M-POST") { httpMethod = HTTP_METHOD_M_POST; } // Unsupported methods are caught in the HTTPAuthenticatorDelegator //<Bug #351> //PEGASUS_ASSERT(methodName == "M-POST" || methodName == "POST"); if( methodName != "M-POST" && methodName != "POST" ) { sendHttpError( queueId, HTTP_STATUS_NOTIMPLEMENTED, "Only POST and M-POST are implemented", String::EMPTY, closeConnect); return; } //</bug> // // Not true: "Mismatch of method and version is caught in HTTPAuthenticatorDelegator", bug #351 fixes this: // //PEGASUS_ASSERT (!((httpMethod == HTTP_METHOD_M_POST) && // (httpVersion == "HTTP/1.0"))); if( (httpMethod == HTTP_METHOD_M_POST) && (httpVersion == "HTTP/1.0") ) { sendHttpError( queueId, HTTP_STATUS_BADREQUEST, "M-POST method is not valid with version 1.0", String::EMPTY, closeConnect); return; } //</bug> // Process M-POST and POST messages: String cimContentType; String cimExport; String cimExportBatch; Boolean cimExportBatchFlag; String cimProtocolVersion; String cimExportMethod; if (httpVersion == "HTTP/1.1") { // Validate the presence of a "Host" header. The HTTP/1.1 specification // says this in section 14.23 regarding the Host header field: // // All Internet-based HTTP/1.1 servers MUST respond with a 400 (Bad // Request) status code to any HTTP/1.1 request message which lacks // a Host header field. // // Note: The Host header value is not validated. String hostHeader; Boolean hostHeaderFound = HTTPMessage::lookupHeader( headers, "Host", hostHeader, false); if (!hostHeaderFound) { MessageLoaderParms parms( "ExportServer.CIMExportRequestDecoder.MISSING_HOST_HEADER", "HTTP request message lacks a Host header field."); String msg(MessageLoader::getMessage(parms)); sendHttpError( queueId, HTTP_STATUS_BADREQUEST, "", msg, closeConnect); return; } } // Validate the "CIMExport" header: Boolean exportHeaderFound = HTTPMessage::lookupHeader( headers, "CIMExport", cimExport, true); // If the CIMExport header was missing, the HTTPAuthenticatorDelegator // would not have passed the message to us. // <bug #351> // PEGASUS_ASSERT(exportHeaderFound); if (!exportHeaderFound) { sendHttpError( queueId, HTTP_STATUS_BADREQUEST, "Export header not found", String::EMPTY, closeConnect); return; } // </bug> if (!String::equalNoCase(cimExport, "MethodRequest")) { // The Specification for CIM Operations over HTTP reads: // 3.3.5. CIMExport // If a CIM Listener receives CIM Export request with this // header, but with a missing value or a value that is not // "MethodRequest", then it MUST fail the request with // status "400 Bad Request". The CIM Server MUST include a // CIMError header in the response with a value of // unsupported-operation. sendHttpError( queueId, HTTP_STATUS_BADREQUEST, "unsupported-operation", String::EMPTY, closeConnect); return; } // Validate the "CIMExportBatch" header: cimExportBatchFlag = HTTPMessage::lookupHeader( headers, "CIMExportBatch", cimExportBatch, true); if (cimExportBatchFlag) { // The Specification for CIM Operations over HTTP reads: // 3.3.10. CIMExportBatch // If a CIM Listener receives CIM Export Request for which the // CIMExportBatch header is present, but the Listener does not // support Multiple Exports, then it MUST fail the request and // return a status of "501 Not Implemented". sendHttpError( queueId, HTTP_STATUS_NOTIMPLEMENTED, "multiple-requests-unsupported", String::EMPTY, closeConnect); return; } // Save these headers for later checking if (!HTTPMessage::lookupHeader( headers, "CIMProtocolVersion", cimProtocolVersion, true)) { // Mandated by the Specification for CIM Operations over HTTP cimProtocolVersion.assign("1.0"); } if (HTTPMessage::lookupHeader( headers, "CIMExportMethod", cimExportMethod, true)) { if (cimExportMethod == String::EMPTY) { // This is not a valid value, and we use EMPTY to mean "absent" sendHttpError( queueId, HTTP_STATUS_BADREQUEST, "header-mismatch", String::EMPTY, closeConnect); return; } }// l10n start AcceptLanguageList acceptLanguages; ContentLanguageList contentLanguages; try { if(httpMessage->acceptLanguagesDecoded){ acceptLanguages = httpMessage->acceptLanguages; }else{ // Get and validate the Accept-Language header, if set String acceptLanguageHeader; if (HTTPMessage::lookupHeader( headers, "Accept-Language", acceptLanguageHeader, false) == true) { acceptLanguages = LanguageParser::parseAcceptLanguageHeader( acceptLanguageHeader); } } if(httpMessage->contentLanguagesDecoded){ contentLanguages = httpMessage->contentLanguages; }else{ // Get and validate the Content-Language header, if set String contentLanguageHeader; if (HTTPMessage::lookupHeader( headers, "Content-Language", contentLanguageHeader, false) == true) { contentLanguages = LanguageParser::parseContentLanguageHeader( contentLanguageHeader); } } } catch (Exception &e) { Thread::clearLanguages(); MessageLoaderParms msgParms("ExportServer.CIMExportRequestDecoder.REQUEST_NOT_VALID","request-not-valid"); String msg(MessageLoader::getMessage(msgParms)); sendHttpError( queueId, HTTP_STATUS_BADREQUEST, msg, e.getMessage(), closeConnect); return; }// l10n end // Zero-terminate the message: httpMessage->message.append('\0'); // Calculate the beginning of the content from the message size and // the content length. Subtract 1 to take into account the null // character we just added to the end of the message. content = (char *) httpMessage->message.getData() + httpMessage->message.size() - contentLength - 1; // Validate the "Content-Type" header: Boolean contentTypeHeaderFound = HTTPMessage::lookupHeader(headers, "Content-Type", cimContentType, true); // ATTN: Bug 5928: Need to validate that the content type is text/xml or // application/xml, and the encoding is utf-8 (or compatible) if (!contentTypeHeaderFound) { sendHttpError( queueId, HTTP_STATUS_BADREQUEST, "", "HTTP Content-Type header error.", closeConnect); return; } else { // Validating content falls within UTF8 (required to be complaint // with section C12 of Unicode 4.0 spec, chapter 3.) Uint32 count = 0; while(count<contentLength)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -