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
|