1 carolann.graves 1.1 //%2006////////////////////////////////////////////////////////////////////////
2 //
3 // 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 // IBM Corp.; EMC Corporation, The Open Group.
7 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
11 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // 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 // 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 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 carolann.graves 1.1 // 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 // 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 // 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 #include <Pegasus/Common/Constants.h>
36 #include <Pegasus/Common/XmlReader.h>
37 #include <Pegasus/Common/System.h>
38 #include <Pegasus/Common/CIMMessage.h>
39 #include <Pegasus/Common/MessageLoader.h>
40 #include <Pegasus/Common/Tracer.h>
41 #include <Pegasus/Client/CIMClientException.h>
42 #include "HTTPExportResponseDecoder.h"
43 carolann.graves 1.1
44 PEGASUS_USING_STD;
45 PEGASUS_NAMESPACE_BEGIN
46
47 void HTTPExportResponseDecoder::parseHTTPHeaders(
48 HTTPMessage* httpMessage,
49 ClientExceptionMessage*& exceptionMessage,
50 Array<HTTPHeader>& headers,
51 Uint32& contentLength,
52 Uint32& statusCode,
53 String& reasonPhrase,
54 Boolean& cimReconnect,
55 Boolean& valid)
56 {
57 PEG_METHOD_ENTER(TRC_EXPORT_CLIENT,
58 "HTTPExportResponseDecoder::parseHTTPHeaders()");
59
60 exceptionMessage = 0;
61 headers.clear();
62 contentLength = 0;
63 statusCode = 0;
64 carolann.graves 1.1 reasonPhrase = String::EMPTY;
65 cimReconnect = false;
66 valid = true;
67
68 String startLine;
69 String connectClose;
70
71 //
72 // Check for empty HTTP response message
73 //
74 if (httpMessage->message.size() == 0)
75 {
76 MessageLoaderParms mlParms(
77 "ExportClient.CIMExportResponseDecoder.EMPTY_RESPONSE",
|
78 dave.sudlik 1.1.18.4 "Connection closed by CIM Server.");
|
79 carolann.graves 1.1 String mlString(MessageLoader::getMessage(mlParms));
80 AutoPtr<CIMClientMalformedHTTPException> malformedHTTPException(
81 new CIMClientMalformedHTTPException(mlString));
82 AutoPtr<ClientExceptionMessage> response(
83 new ClientExceptionMessage(malformedHTTPException.get()));
84 malformedHTTPException.release();
85 exceptionMessage = response.release();
86 valid = false;
87
88 PEG_METHOD_EXIT();
89 return;
90 }
91
92 //
93 // Parse the HTTP message headers and get content length
94 //
95 httpMessage->parse(startLine, headers, contentLength);
96
97 //
98 // Check for Connection: Close
99 //
100 carolann.graves 1.1 if (HTTPMessage::lookupHeader(headers, "Connection", connectClose, false))
101 {
102 if (String::equalNoCase(connectClose, "Close"))
103 {
104 // reconnect and then resend next request.
105 cimReconnect=true;
106 }
107 }
108
|
109 marek 1.1.18.3 PEG_TRACE_CSTRING(TRC_XML_IO, Tracer::LEVEL2,
110 httpMessage->message.getData());
|
111 kumpf 1.1.18.1
|
112 carolann.graves 1.1 //
113 // Parse HTTP message status line
114 //
115 String httpVersion;
116
117 Boolean parsableMessage = HTTPMessage::parseStatusLine(
118 startLine, httpVersion, statusCode, reasonPhrase);
119 if (!parsableMessage)
120 {
121 MessageLoaderParms mlParms(
122 "ExportClient.CIMExportResponseDecoder.MALFORMED_RESPONSE",
123 "Malformed HTTP response message.");
124 String mlString(MessageLoader::getMessage(mlParms));
125 AutoPtr<CIMClientMalformedHTTPException> malformedHTTPException(
126 new CIMClientMalformedHTTPException(mlString));
127 AutoPtr<ClientExceptionMessage> response(
128 new ClientExceptionMessage(malformedHTTPException.get()));
129 malformedHTTPException.release();
130 response->setCloseConnect(cimReconnect);
131 exceptionMessage = response.release();
132 valid = false;
133 carolann.graves 1.1
134 PEG_METHOD_EXIT();
135 return;
136 }
137
138 PEG_METHOD_EXIT();
139 }
140
141 void HTTPExportResponseDecoder::validateHTTPHeaders(
142 HTTPMessage* httpMessage,
143 Array<HTTPHeader>& headers,
144 Uint32 contentLength,
145 Uint32 statusCode,
146 Boolean cimReconnect,
147 const String& reasonPhrase,
148 char*& content,
149 ClientExceptionMessage*& exceptionMessage,
150 Boolean& valid)
151 {
152 PEG_METHOD_ENTER(TRC_EXPORT_CLIENT,
153 "HTTPExportResponseDecoder::validateHTTPHeaders()");
154 carolann.graves 1.1
155 content = 0;
156 exceptionMessage = 0;
157 valid = true;
158
159 //
160 // If authentication failed, a CIMClientHTTPErrorException will be
161 // generated with the "401 Unauthorized" status in the (re-challenge)
162 // response
163 //
164 // Check for a non-success (200 OK) response
165 //
166 if (statusCode != HTTP_STATUSCODE_OK)
167 {
168 String cimError;
169 String pegasusError;
170
171 HTTPMessage::lookupHeader(headers, "CIMError", cimError);
172 HTTPMessage::lookupHeader(headers, PEGASUS_HTTPHEADERTAG_ERRORDETAIL,
173 pegasusError);
174 try
175 carolann.graves 1.1 {
176 pegasusError = XmlReader::decodeURICharacters(pegasusError);
177 }
178 catch (const ParseError&)
179 {
180 // Ignore this exception. We're more interested in having the
181 // message in encoded form than knowing that the format is invalid.
182 }
183
184 AutoPtr<CIMClientHTTPErrorException> httpError(
185 new CIMClientHTTPErrorException(statusCode, reasonPhrase, cimError,
186 pegasusError));
187 AutoPtr<ClientExceptionMessage> response(
188 new ClientExceptionMessage(httpError.get()));
189
190 httpError.release();
191 response->setCloseConnect(cimReconnect);
192 exceptionMessage = response.release();
193 valid = false;
194
195 PEG_METHOD_EXIT();
196 carolann.graves 1.1 return;
197 }
198
199 //
200 // Check for missing "CIMExport" header
201 //
202 String cimExport;
203 if (!HTTPMessage::lookupHeader(headers, "CIMExport", cimExport, true))
204 {
205 MessageLoaderParms mlParms(
206 "ExportClient.CIMExportResponseDecoder.MISSING_CIMEXP_HEADER",
207 "Missing CIMExport HTTP header");
208 String mlString(MessageLoader::getMessage(mlParms));
209
210 AutoPtr<CIMClientMalformedHTTPException> malformedHTTPException(new
211 CIMClientMalformedHTTPException(mlString));
212
213 AutoPtr<ClientExceptionMessage> response(
214 new ClientExceptionMessage(malformedHTTPException.get()));
215
216 malformedHTTPException.release();
217 carolann.graves 1.1 response->setCloseConnect(cimReconnect);
218 exceptionMessage = response.release();
219 valid = false;
220
221 PEG_METHOD_EXIT();
222 return;
223 }
224
225 //
226 // Check for missing "Content-Type" header
227 //
228 String cimContentType;
229 if (!HTTPMessage::lookupHeader(
230 headers, "Content-Type", cimContentType, true))
231 {
232 AutoPtr<CIMClientMalformedHTTPException> malformedHTTPException(new
233 CIMClientMalformedHTTPException(
234 "Missing CIMContentType HTTP header"));
235 AutoPtr<ClientExceptionMessage> response(
236 new ClientExceptionMessage(malformedHTTPException.get()));
237
238 carolann.graves 1.1 malformedHTTPException.release();
239 response->setCloseConnect(cimReconnect);
240 exceptionMessage = response.release();
241 valid = false;
242
243 PEG_METHOD_EXIT();
244 return;
245 }
246
247 //
248 // Calculate the beginning of the content from the message size and
249 // the content length
250 //
251 content = (char *) httpMessage->message.getData() +
252 httpMessage->message.size() - contentLength;
253
254 //
255 // Expect CIMExport HTTP header value MethodResponse
256 //
257 if (!String::equalNoCase(cimExport, "MethodResponse"))
258 {
259 carolann.graves 1.1 MessageLoaderParms mlParms(
260 "ExportClient.CIMExportResponseDecoder.EXPECTED_METHODRESPONSE",
261 "Received CIMExport HTTP header value \"$0\", "
262 "expected \"MethodResponse\"", cimExport);
263 String mlString(MessageLoader::getMessage(mlParms));
264
265 AutoPtr<CIMClientMalformedHTTPException> malformedHTTPException(
266 new CIMClientMalformedHTTPException(mlString));
267
268 AutoPtr<ClientExceptionMessage> response(
269 new ClientExceptionMessage(malformedHTTPException.get()));
270
271 malformedHTTPException.release();
272 response->setCloseConnect(cimReconnect);
273 exceptionMessage = response.release();
274 valid = false;
275
276 PEG_METHOD_EXIT();
277 return;
278 }
279
280 carolann.graves 1.1 PEG_METHOD_EXIT();
281 }
282
283 void HTTPExportResponseDecoder::decodeExportResponse(
284 char* content,
285 Boolean cimReconnect,
286 Message*& responseMessage)
287 {
288 PEG_METHOD_ENTER (TRC_EXPORT_CLIENT,
289 "HTTPExportResponseDecoder::decodeExportResponse()");
290
291 AutoPtr<Message> response;
292
293 //
294 // Create and initialize XML parser:
295 //
296 XmlParser parser((char*)content);
297 XmlEntry entry;
298
299 try
300 {
301 carolann.graves 1.1 //
302 // Process <?xml ... >
303 //
304 const char* xmlVersion = 0;
305 const char* xmlEncoding = 0;
306 XmlReader::getXmlDeclaration(parser, xmlVersion, xmlEncoding);
307
308 //
309 // Process <CIM ... >
310 //
311 const char* cimVersion = 0;
312 const char* dtdVersion = 0;
313 XmlReader::getCimStartTag(parser, cimVersion, dtdVersion);
314
315 //
316 // Expect <MESSAGE ... >
317 //
318 String messageId;
319 String protocolVersion;
320 if (!XmlReader::getMessageStartTag(parser, messageId, protocolVersion))
321 {
322 carolann.graves 1.1 MessageLoaderParms mlParms(
323 "ExportClient.CIMExportResponseDecoder."
324 "EXPECTED_MESSAGE_ELEMENT",
325 "expected MESSAGE element");
326 String mlString(MessageLoader::getMessage(mlParms));
327
328 PEG_METHOD_EXIT();
329 throw XmlValidationError(parser.getLine(), mlString);
330 }
331
332 //
333 // Check for unsupported protocol version
334 //
|
335 karl 1.1.18.2 if (!XmlReader::isSupportedProtocolVersion(protocolVersion))
|
336 carolann.graves 1.1 {
337 MessageLoaderParms mlParms(
338 "ExportClient.CIMExportResponseDecoder.UNSUPPORTED_PROTOCOL",
339 "Received unsupported protocol version \"$0\", expected \"$1\"",
340 protocolVersion, "1.0");
341 String mlString(MessageLoader::getMessage(mlParms));
342
343 AutoPtr<CIMClientResponseException> responseException(
344 new CIMClientResponseException(mlString));
345
346 AutoPtr<ClientExceptionMessage> response(
347 new ClientExceptionMessage(responseException.get()));
348
349 responseException.release();
350 response->setCloseConnect(cimReconnect);
351 responseMessage = response.release();
352
353 PEG_METHOD_EXIT();
354 return;
355 }
356
357 carolann.graves 1.1 //
358 // Expect <SIMPLEEXPRSP ... >
359 //
360 XmlReader::expectStartTag(parser, entry, "SIMPLEEXPRSP");
361
362 //
363 // Expect <EXPMETHODRESPONSE ... >
364 //
365 const char* expMethodResponseName = 0;
366 Boolean isEmptyTag = false;
367
368 if (XmlReader::getEMethodResponseStartTag(
369 parser, expMethodResponseName, isEmptyTag))
370 {
371 if (System::strcasecmp(expMethodResponseName, "ExportIndication")
372 == 0)
373 {
374 response.reset(_decodeExportIndicationResponse(
375 parser, messageId, isEmptyTag));
376 }
377 else
378 carolann.graves 1.1 {
379 //
380 // Unrecognized ExpMethodResponse name attribute
381 //
382 MessageLoaderParms mlParms(
383 "ExportClient.CIMExportResponseDecoder."
384 "UNRECOGNIZED_EXPMETHRSP",
385 "Unrecognized ExpMethodResponse name \"$0\"",
386 expMethodResponseName);
387 String mlString(MessageLoader::getMessage(mlParms));
388
389 PEG_METHOD_EXIT();
390 throw XmlValidationError(parser.getLine(), mlString);
391 }
392
393 //
394 // Handle end tag:
395 //
396 if (!isEmptyTag)
397 {
398 XmlReader::expectEndTag(parser, "EXPMETHODRESPONSE");
399 carolann.graves 1.1 }
400 }
401 else
402 {
403 //
404 // Expected ExpMethodResponse element
405 //
406 MessageLoaderParms mlParms(
407 "ExportClient.CIMExportResponseDecoder."
408 "EXPECTED_EXPMETHODRESPONSE_ELEMENT",
409 "expected EXPMETHODRESPONSE element");
410 String mlString(MessageLoader::getMessage(mlParms));
411
412 PEG_METHOD_EXIT();
413 throw XmlValidationError(parser.getLine(), mlString);
414 }
415
416 //
417 // Handle end tags:
418 //
419 XmlReader::expectEndTag(parser, "SIMPLEEXPRSP");
420 carolann.graves 1.1 XmlReader::expectEndTag(parser, "MESSAGE");
421 XmlReader::expectEndTag(parser, "CIM");
422 }
423 catch (XmlException& x)
424 {
425 response.reset(new ClientExceptionMessage(
426 new CIMClientXmlException(x.getMessage())));
427 }
428 catch (Exception& x)
429 {
430 response.reset(new ClientExceptionMessage(
431 new CIMClientResponseException(x.getMessage())));
432 }
433
434 //
435 // Note: Ignore any ContentLanguage set in the export response
436 //
437
438 response->setCloseConnect(cimReconnect);
439 responseMessage = response.release();
440
441 carolann.graves 1.1 PEG_METHOD_EXIT();
442 }
443
444 CIMExportIndicationResponseMessage*
445 HTTPExportResponseDecoder::_decodeExportIndicationResponse(
446 XmlParser& parser,
447 const String& messageId,
448 Boolean isEmptyExpMethodResponseTag)
449 {
450 PEG_METHOD_ENTER (TRC_EXPORT_CLIENT,
451 "HTTPExportResponseDecoder::_decodeExportIndicationResponse()");
452 XmlEntry entry;
453 CIMException cimException;
454
455 if (!isEmptyExpMethodResponseTag)
456 {
457 if (XmlReader::getErrorElement(parser, cimException))
458 {
459 PEG_METHOD_EXIT();
460 return(new CIMExportIndicationResponseMessage(
461 messageId,
462 carolann.graves 1.1 cimException,
463 QueueIdStack()));
464 }
465
466 if (XmlReader::testStartTagOrEmptyTag(parser, entry, "IRETURNVALUE"))
467 {
468 if (entry.type != XmlEntry::EMPTY_TAG)
469 {
470 XmlReader::expectEndTag(parser, "IRETURNVALUE");
471 }
472 }
473 }
474
475 PEG_METHOD_EXIT();
476 return(new CIMExportIndicationResponseMessage(
477 messageId,
478 cimException,
479 QueueIdStack()));
480 }
481
482 PEGASUS_NAMESPACE_END
|