version 1.101, 2004/01/16 00:44:36
|
version 1.111, 2004/08/05 12:51:55
|
|
|
// Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com) | // Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com) |
// Carol Ann Krug Graves, Hewlett-Packard Company | // Carol Ann Krug Graves, Hewlett-Packard Company |
// (carolann_graves@hp.com) | // (carolann_graves@hp.com) |
|
// Amit K Arora, IBM (amita@in.ibm.com) for PEP#101 |
|
// Brian G. Campbell, EMC (campbell_brian@emc.com) - PEP140/phase1 |
|
// Willis White (whiwill@us.ibm.com) PEP 127 and 128 |
// | // |
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
|
|
#include <cstdlib> | #include <cstdlib> |
#include <cstdio> | #include <cstdio> |
#include "Constants.h" | #include "Constants.h" |
#include "Destroyer.h" |
|
#include "CIMClass.h" | #include "CIMClass.h" |
#include "CIMClassRep.h" | #include "CIMClassRep.h" |
#include "CIMInstance.h" | #include "CIMInstance.h" |
|
|
| |
PEGASUS_NAMESPACE_BEGIN | PEGASUS_NAMESPACE_BEGIN |
| |
|
// This is a shortcut macro for outputing content length. This |
|
// pads the output number to the max characters representing a Uint32 number |
|
// so that it can be overwritten easily with a transfer encoding line later |
|
// on in HTTPConnection if required. This is strictly for performance since |
|
// messages can be very large. This overwriting shortcut allows us to NOT have |
|
// to repackage a large message later. |
|
|
|
#define OUTPUT_CONTENTLENGTH \ |
|
{ \ |
|
char contentLengthP[11]; \ |
|
sprintf(contentLengthP,"%.10u", contentLength); \ |
|
out << "content-length: " << contentLengthP << "\r\n"; \ |
|
} |
|
|
Array<Sint8>& operator<<(Array<Sint8>& out, const char* x) | Array<Sint8>& operator<<(Array<Sint8>& out, const char* x) |
{ | { |
XmlWriter::append(out, x); | XmlWriter::append(out, x); |
|
|
&strtgt, | &strtgt, |
endtgt); | endtgt); |
| |
out.append((Sint8 *)str,trailingBytesForUTF8[Uint32(str[0])]+1); |
out.append((Sint8 *)str, UTF_8_COUNT_TRAIL_BYTES(str[0]) + 1); |
} | } |
| |
inline void _xmlWritter_appendSpecialChar(Array<Sint8>& out, const Char16& c) | inline void _xmlWritter_appendSpecialChar(Array<Sint8>& out, const Char16& c) |
|
|
&strtgt, | &strtgt, |
endtgt); | endtgt); |
| |
Uint32 number1 = trailingBytesForUTF8[Uint32(str[0])]+1; |
Uint32 number1 = UTF_8_COUNT_TRAIL_BYTES(str[0]) + 1; |
| |
out.append((Sint8 *)str,number1); | out.append((Sint8 *)str,number1); |
} | } |
|
|
&strtgt, | &strtgt, |
endtgt); | endtgt); |
| |
Uint32 number1 = trailingBytesForUTF8[Uint32(str[0])]+1; |
Uint32 number1 = UTF_8_COUNT_TRAIL_BYTES(str[0]) + 1; |
out.append((Sint8 *)str,number1); | out.append((Sint8 *)str,number1); |
} | } |
| |
|
|
append(out, buffer); | append(out, buffer); |
} | } |
| |
|
void XmlWriter::append(Array<Sint8>& out, Real32 x) |
|
{ |
|
char buffer[128]; |
|
// %.7e gives '[-]m.ddddddde+/-xx', which seems compatible with the format |
|
// given in the CIM/XML spec, and the precision required by the CIM 2.2 spec |
|
// (4 byte IEEE floating point) |
|
sprintf(buffer, "%.7e", x); |
|
append(out, buffer); |
|
} |
|
|
void XmlWriter::append(Array<Sint8>& out, Real64 x) | void XmlWriter::append(Array<Sint8>& out, Real64 x) |
{ | { |
char buffer[128]; | char buffer[128]; |
// %e gives '[-]m.dddddde+/-xx', which seems compatible with CIM/XML spec |
// %.16e gives '[-]m.dddddddddddddddde+/-xx', which seems compatible with the format |
sprintf(buffer, "%e", x); |
// given in the CIM/XML spec, and the precision required by the CIM 2.2 spec |
|
// (8 byte IEEE floating point) |
|
sprintf(buffer, "%.16e", x); |
append(out, buffer); | append(out, buffer); |
} | } |
| |
void XmlWriter::append(Array<Sint8>& out, const char* str) | void XmlWriter::append(Array<Sint8>& out, const char* str) |
{ | { |
while (*str) | while (*str) |
_xmlWritter_appendChar(out, *str++); |
XmlWriter::append(out, *str++); |
} | } |
| |
void XmlWriter::append(Array<Sint8>& out, const String& str) | void XmlWriter::append(Array<Sint8>& out, const String& str) |
|
|
} | } |
} | } |
| |
// chuck start |
|
|
|
// See http://www.ietf.org/rfc/rfc2396.txt section 2 | // See http://www.ietf.org/rfc/rfc2396.txt section 2 |
// Reserved characters = ';' '/' '?' ':' '@' '&' '=' '+' '$' ',' | // Reserved characters = ';' '/' '?' ':' '@' '&' '=' '+' '$' ',' |
// Excluded characters: | // Excluded characters: |
|
|
Uint8 c = (Uint8)char8; | Uint8 c = (Uint8)char8; |
| |
#ifndef PEGASUS_DO_NOT_IMPLEMENT_URI_ENCODING | #ifndef PEGASUS_DO_NOT_IMPLEMENT_URI_ENCODING |
if ( ((c <= 0x20) && (c >= 0x00)) || // Control characters + space char |
if ( (c <= 0x20) || // Control characters + space char |
( (c >= 0x22) && (c <= 0x26) ) || // '"' '#' '$' '%' '&' | ( (c >= 0x22) && (c <= 0x26) ) || // '"' '#' '$' '%' '&' |
(c == 0x2b) || // '+' | (c == 0x2b) || // '+' |
(c == 0x2c) || // ',' | (c == 0x2c) || // ',' |
|
|
( (c >= 0x5b) && (c <= 0x5e) ) || // '[' '\\' ']' '^' | ( (c >= 0x5b) && (c <= 0x5e) ) || // '[' '\\' ']' '^' |
(c == 0x60) || // '`' | (c == 0x60) || // '`' |
( (c >= 0x7b) && (c <= 0x7d) ) || // '{' '|' '}' | ( (c >= 0x7b) && (c <= 0x7d) ) || // '{' '|' '}' |
// (c == 0x7f) ) // Control character |
|
(c >= 0x7f) ) // Control character or non US-ASCII (UTF-8) | (c >= 0x7f) ) // Control character or non US-ASCII (UTF-8) |
{ | { |
char hexencoding[4]; | char hexencoding[4]; |
|
|
{ | { |
out << "<LOCALNAMESPACEPATH>\n"; | out << "<LOCALNAMESPACEPATH>\n"; |
| |
char* nameSpaceCopy = strdup(nameSpace.getString().getCStringUTF8()); |
char* nameSpaceCopy = strdup(nameSpace.getString().getCString()); |
|
|
#if defined(PEGASUS_PLATFORM_SOLARIS_SPARC_CC) || \ | #if defined(PEGASUS_PLATFORM_SOLARIS_SPARC_CC) || \ |
defined(PEGASUS_OS_HPUX) || \ | defined(PEGASUS_OS_HPUX) || \ |
defined(PEGASUS_OS_LINUX) | defined(PEGASUS_OS_LINUX) |
|
|
| |
inline void _xmlWritter_appendValue(Array<Sint8>& out, Real32 x) | inline void _xmlWritter_appendValue(Array<Sint8>& out, Real32 x) |
{ | { |
XmlWriter::append(out, Real64(x)); |
XmlWriter::append(out, x); |
} | } |
| |
inline void _xmlWritter_appendValue(Array<Sint8>& out, Real64 x) | inline void _xmlWritter_appendValue(Array<Sint8>& out, Real64 x) |
|
|
} | } |
out << "HOST: " << host << "\r\n"; | out << "HOST: " << host << "\r\n"; |
out << "Content-Type: application/xml; charset=\"utf-8\"\r\n"; | out << "Content-Type: application/xml; charset=\"utf-8\"\r\n"; |
out << "Content-Length: " << contentLength << "\r\n"; |
OUTPUT_CONTENTLENGTH; |
if (acceptLanguages.size() > 0) | if (acceptLanguages.size() > 0) |
{ | { |
out << "Accept-Language: " << acceptLanguages << "\r\n"; | out << "Accept-Language: " << acceptLanguages << "\r\n"; |
|
|
{ | { |
out << "Content-Language: " << contentLanguages << "\r\n"; | out << "Content-Language: " << contentLanguages << "\r\n"; |
} | } |
|
|
|
// backdoor environment variable to turn OFF client requesting transfer |
|
// encoding. The default is on. to turn off, set this variable to zero. |
|
// This should be removed when stable. This should only be turned off in |
|
// a debugging/testing environment. |
|
#ifdef PEGASUS_DEBUG |
|
static const char *clientTransferEncodingOff = |
|
getenv("PEGASUS_HTTP_TRANSFER_ENCODING_REQUEST"); |
|
if (!clientTransferEncodingOff || *clientTransferEncodingOff != '0') |
|
#endif |
|
out << "TE: chunked, trailers" << "\r\n"; |
|
|
if (httpMethod == HTTP_METHOD_M_POST) | if (httpMethod == HTTP_METHOD_M_POST) |
{ | { |
out << "Man: http://www.dmtf.org/cim/mapping/http/v1.0; ns="; | out << "Man: http://www.dmtf.org/cim/mapping/http/v1.0; ns="; |
|
|
{ | { |
out << authenticationHeader << "\r\n"; | out << authenticationHeader << "\r\n"; |
} | } |
|
|
out << "\r\n"; | out << "\r\n"; |
} | } |
| |
|
|
char nn[] = { '0' + (rand() % 10), '0' + (rand() % 10), '\0' }; | char nn[] = { '0' + (rand() % 10), '0' + (rand() % 10), '\0' }; |
| |
out << "HTTP/1.1 " HTTP_STATUS_OK "\r\n"; | out << "HTTP/1.1 " HTTP_STATUS_OK "\r\n"; |
|
out << "Content-Type: application/xml; charset=\"utf-8\"\r\n"; |
|
OUTPUT_CONTENTLENGTH; |
|
|
|
if (contentLanguages.size() > 0) |
|
{ |
|
out << "Content-Language: " << contentLanguages << "\r\n"; |
|
} |
|
if (httpMethod == HTTP_METHOD_M_POST) |
|
{ |
|
out << "Ext:\r\n"; |
|
out << "Cache-Control: no-cache\r\n"; |
|
out << "Man: http://www.dmtf.org/cim/mapping/http/v1.0; ns="; |
|
out << nn <<"\r\n"; |
|
out << nn << "-CIMOperation: MethodResponse\r\n\r\n"; |
|
} |
|
else |
|
{ |
|
out << "CIMOperation: MethodResponse\r\n\r\n"; |
|
} |
|
} |
|
|
|
|
|
void XmlWriter::appendMethodResponseHeader( |
|
Array<Sint8>& out, |
|
HttpMethod httpMethod, |
|
const ContentLanguages & contentLanguages, |
|
Uint32 contentLength, |
|
Uint64 serverResponseTime) |
|
{ |
|
char nn[] = { '0' + (rand() % 10), '0' + (rand() % 10), '\0' }; |
|
|
|
out << "HTTP/1.1 " HTTP_STATUS_OK "\r\n"; |
STAT_SERVERTIME | STAT_SERVERTIME |
out << "Content-Type: application/xml; charset=\"utf-8\"\r\n"; | out << "Content-Type: application/xml; charset=\"utf-8\"\r\n"; |
out << "Content-Length: " << contentLength << "\r\n"; |
OUTPUT_CONTENTLENGTH; |
|
|
if (contentLanguages.size() > 0) | if (contentLanguages.size() > 0) |
{ | { |
out << "Content-Language: " << contentLanguages << "\r\n"; | out << "Content-Language: " << contentLanguages << "\r\n"; |
|
|
} | } |
} | } |
| |
|
|
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ |
// | // |
// appendHttpErrorResponseHeader() | // appendHttpErrorResponseHeader() |
|
|
// is usually intended to have content. But, for Kerberos this | // is usually intended to have content. But, for Kerberos this |
// may not always be the case so we need to indicate that there | // may not always be the case so we need to indicate that there |
// is no content | // is no content |
out << "Content-Length: 0" << "\r\n"; |
Uint32 contentLength = 0; |
|
OUTPUT_CONTENTLENGTH; |
out << content << "\r\n"; | out << content << "\r\n"; |
out << "\r\n"; | out << "\r\n"; |
| |
|
|
const String& messageId, | const String& messageId, |
HttpMethod httpMethod, | HttpMethod httpMethod, |
const ContentLanguages & httpContentLanguages, | const ContentLanguages & httpContentLanguages, |
const Array<Sint8>& body) |
const Array<Sint8>& body, |
|
Boolean isFirst, |
|
Boolean isLast) |
{ | { |
Array<Sint8> out; | Array<Sint8> out; |
Array<Sint8> tmp; |
|
| |
|
if (isFirst == true) |
|
{ |
|
// NOTE: temporarily put zero for content length. the http code |
|
// will later decide to fill in the length or remove it altogether |
|
appendMethodResponseHeader(out, httpMethod, httpContentLanguages, 0); |
_appendMessageElementBegin(out, messageId); | _appendMessageElementBegin(out, messageId); |
_appendSimpleRspElementBegin(out); | _appendSimpleRspElementBegin(out); |
_appendMethodResponseElementBegin(out, methodName); | _appendMethodResponseElementBegin(out, methodName); |
|
} |
|
|
|
if (body.size() != 0) |
|
{ |
out << body; | out << body; |
|
} |
|
|
|
if (isLast == true) |
|
{ |
_appendMethodResponseElementEnd(out); | _appendMethodResponseElementEnd(out); |
_appendSimpleRspElementEnd(out); | _appendSimpleRspElementEnd(out); |
_appendMessageElementEnd(out); | _appendMessageElementEnd(out); |
|
} |
| |
appendMethodResponseHeader(tmp, |
return out; |
httpMethod, |
} |
httpContentLanguages, |
|
out.size()); |
|
tmp << out; |
|
| |
return tmp; |
|
|
//PEP 128 adding serverRsponseTime to header |
|
Array<Sint8> XmlWriter::formatSimpleMethodRspMessage( |
|
const CIMName& methodName, |
|
const String& messageId, |
|
HttpMethod httpMethod, |
|
const ContentLanguages & httpContentLanguages, |
|
const Array<Sint8>& body, |
|
Uint64 serverResponseTime, |
|
Boolean isFirst, |
|
Boolean isLast) |
|
{ |
|
Array<Sint8> out; |
|
|
|
if (isFirst == true) |
|
{ |
|
// NOTE: temporarily put zero for content length. the http code |
|
// will later decide to fill in the length or remove it altogether |
|
appendMethodResponseHeader(out, httpMethod, httpContentLanguages, 0, serverResponseTime); |
|
_appendMessageElementBegin(out, messageId); |
|
_appendSimpleRspElementBegin(out); |
|
_appendMethodResponseElementBegin(out, methodName); |
|
} |
|
|
|
if (body.size() != 0) |
|
{ |
|
out << body; |
|
} |
|
|
|
if (isLast == true) |
|
{ |
|
_appendMethodResponseElementEnd(out); |
|
_appendSimpleRspElementEnd(out); |
|
_appendMessageElementEnd(out); |
} | } |
| |
|
return out; |
|
} |
|
|
|
|
|
|
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ |
// | // |
// XmlWriter::formatSimpleMethodErrorRspMessage() | // XmlWriter::formatSimpleMethodErrorRspMessage() |
|
|
const String& messageId, | const String& messageId, |
HttpMethod httpMethod, | HttpMethod httpMethod, |
const ContentLanguages & httpContentLanguages, | const ContentLanguages & httpContentLanguages, |
const Array<Sint8>& body) |
const Array<Sint8>& body, |
|
Boolean isFirst, |
|
Boolean isLast) |
{ | { |
Array<Sint8> out; | Array<Sint8> out; |
Array<Sint8> tmp; |
|
| |
|
if (isFirst == true) |
|
{ |
|
// NOTE: temporarily put zero for content length. the http code |
|
// will later decide to fill in the length or remove it altogether |
|
appendMethodResponseHeader(out, httpMethod, httpContentLanguages, 0); |
_appendMessageElementBegin(out, messageId); | _appendMessageElementBegin(out, messageId); |
_appendSimpleRspElementBegin(out); | _appendSimpleRspElementBegin(out); |
_appendIMethodResponseElementBegin(out, iMethodName); | _appendIMethodResponseElementBegin(out, iMethodName); |
if (body.size() != 0) | if (body.size() != 0) |
{ |
|
_appendIReturnValueElementBegin(out); | _appendIReturnValueElementBegin(out); |
|
} |
|
|
|
if (body.size() != 0) |
|
{ |
out << body; | out << body; |
_appendIReturnValueElementEnd(out); |
|
} | } |
|
|
|
if (isLast == true) |
|
{ |
|
if (body.size() != 0) |
|
_appendIReturnValueElementEnd(out); |
_appendIMethodResponseElementEnd(out); | _appendIMethodResponseElementEnd(out); |
_appendSimpleRspElementEnd(out); | _appendSimpleRspElementEnd(out); |
_appendMessageElementEnd(out); | _appendMessageElementEnd(out); |
|
} |
| |
appendMethodResponseHeader(tmp, |
return out; |
httpMethod, |
} |
httpContentLanguages, |
|
out.size()); |
|
tmp << out; |
|
| |
return tmp; |
|
|
|
|
Array<Sint8> XmlWriter::formatSimpleIMethodRspMessage( |
|
const CIMName& iMethodName, |
|
const String& messageId, |
|
HttpMethod httpMethod, |
|
const ContentLanguages & httpContentLanguages, |
|
const Array<Sint8>& body, |
|
Uint64 serverResponseTime, |
|
Boolean isFirst, |
|
Boolean isLast) |
|
{ |
|
Array<Sint8> out; |
|
|
|
if (isFirst == true) |
|
{ |
|
// NOTE: temporarily put zero for content length. the http code |
|
// will later decide to fill in the length or remove it altogether |
|
appendMethodResponseHeader(out, httpMethod, httpContentLanguages, 0, serverResponseTime); |
|
_appendMessageElementBegin(out, messageId); |
|
_appendSimpleRspElementBegin(out); |
|
_appendIMethodResponseElementBegin(out, iMethodName); |
|
if (body.size() != 0) |
|
_appendIReturnValueElementBegin(out); |
|
} |
|
|
|
if (body.size() != 0) |
|
{ |
|
out << body; |
} | } |
| |
|
if (isLast == true) |
|
{ |
|
if (body.size() != 0) |
|
_appendIReturnValueElementEnd(out); |
|
_appendIMethodResponseElementEnd(out); |
|
_appendSimpleRspElementEnd(out); |
|
_appendMessageElementEnd(out); |
|
} |
|
|
|
return out; |
|
} |
|
|
|
|
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ |
// | // |
// XmlWriter::formatSimpleIMethodErrorRspMessage() | // XmlWriter::formatSimpleIMethodErrorRspMessage() |
|
|
} | } |
out << "HOST: " << host << "\r\n"; | out << "HOST: " << host << "\r\n"; |
out << "Content-Type: application/xml; charset=\"utf-8\"\r\n"; | out << "Content-Type: application/xml; charset=\"utf-8\"\r\n"; |
out << "Content-Length: " << contentLength << "\r\n"; |
OUTPUT_CONTENTLENGTH; |
|
|
if (acceptLanguages.size() > 0) | if (acceptLanguages.size() > 0) |
{ | { |
out << "Accept-Language: " << acceptLanguages << "\r\n"; | out << "Accept-Language: " << acceptLanguages << "\r\n"; |
|
|
{ | { |
out << "Content-Language: " << contentLanguages << "\r\n"; | out << "Content-Language: " << contentLanguages << "\r\n"; |
} | } |
|
|
|
// backdoor environment variable to turn OFF client requesting transfer |
|
// encoding. The default is on. to turn off, set this variable to zero. |
|
// This should be removed when stable. This should only be turned off in |
|
// a debugging/testing environment. |
|
#ifdef PEGASUS_DEBUG |
|
static const char *clientTransferEncodingOff = |
|
getenv("PEGASUS_HTTP_TRANSFER_ENCODING_REQUEST"); |
|
if (!clientTransferEncodingOff || *clientTransferEncodingOff != '0') |
|
#endif |
|
out << "TE: chunked, trailers" << "\r\n"; |
|
|
if (httpMethod == HTTP_METHOD_M_POST) | if (httpMethod == HTTP_METHOD_M_POST) |
{ | { |
out << "Man: http://www.hp.com; ns="; |
out << "Man: http://www.dmtf.org/cim/mapping/http/v1.0; ns="; |
out << nn <<"\r\n"; | out << nn <<"\r\n"; |
out << nn << "-CIMExport: MethodRequest\r\n"; | out << nn << "-CIMExport: MethodRequest\r\n"; |
out << nn << "-CIMExportMethod: " << cimMethod << "\r\n"; | out << nn << "-CIMExportMethod: " << cimMethod << "\r\n"; |
|
|
{ | { |
out << authenticationHeader << "\r\n"; | out << authenticationHeader << "\r\n"; |
} | } |
|
|
out << "\r\n"; | out << "\r\n"; |
} | } |
| |
|
|
| |
out << "HTTP/1.1 " HTTP_STATUS_OK "\r\n"; | out << "HTTP/1.1 " HTTP_STATUS_OK "\r\n"; |
out << "Content-Type: application/xml; charset=\"utf-8\"\r\n"; | out << "Content-Type: application/xml; charset=\"utf-8\"\r\n"; |
out << "Content-Length: " << contentLength << "\r\n"; |
OUTPUT_CONTENTLENGTH; |
|
|
if (contentLanguages.size() > 0) | if (contentLanguages.size() > 0) |
{ | { |
out << "Content-Language: " << contentLanguages << "\r\n"; | out << "Content-Language: " << contentLanguages << "\r\n"; |
|
|
const char* text, | const char* text, |
Uint32 indentChars) | Uint32 indentChars) |
{ | { |
char* tmp = strcpy(new char[strlen(text) + 1], text); |
AutoArrayPtr<char> tmp(strcpy(new char[strlen(text) + 1], text)); |
| |
XmlParser parser(tmp); |
XmlParser parser(tmp.get()); |
XmlEntry entry; | XmlEntry entry; |
Stack<const char*> stack; | Stack<const char*> stack; |
| |
|
|
os << PEGASUS_STD(endl); | os << PEGASUS_STD(endl); |
} | } |
| |
delete [] tmp; |
|
} | } |
| |
//------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ |
|
|
| |
PEGASUS_NAMESPACE_END | PEGASUS_NAMESPACE_END |
| |
|
|