/*************************************************************************** soapmessage.cpp - description ------------------- begin : Sun Jul 24 2005 copyright : (C) 2005 by Diederik van der Boor email : vdboor --at-- codingdomain.com ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "soapmessage.h" #include "xmlfunctions.h" #include "../../kmessdebug.h" #include <kdebug.h> #include <qtextstream.h> #ifdef KMESSDEBUG_SOAPMESSAGE #define KMESSDEBUG_SOAPMESSAGE_GENERAL #endif // The soap message constructor SoapMessage::SoapMessage() : errorCode_(0) { } // The constructor for action SoapMessages SoapMessage::SoapMessage(const QString &message) : errorCode_(0) { parseMessage(message); } // The destructor SoapMessage::~SoapMessage() { } // Add a field to the message void SoapMessage::addField(const QString& field, const QString& value) { fields_ << field; values_ << value; } // Change a field, or add it void SoapMessage::setField(const QString& field, const QString& value) { int index = fields_.findIndex(field); if(index == -1) { addField(field, value); } else { values_[index]= value; } } // Return the message action const QString& SoapMessage::getAction() const { return action_; } // Return the message action namespace prefix const QString& SoapMessage::getActionPrefix() const { return actionPrefix_; } // Return the message action namespace const QString& SoapMessage::getActionNamespace() const { return actionNs_; } // Return the error code int SoapMessage::getErrorCode() const { return errorCode_; } // Return the error description const QString& SoapMessage::getErrorDescription() const { return errorDescription_; } // Return the entire message as string QString SoapMessage::getMessage() const { // Create the data message QString soapMessage = "<s:Envelope" " xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"" " s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"" "><s:Body>"; // Add the body tag if(actionPrefix_.isEmpty()) { soapMessage += "<" + action_; if(! actionNs_.isEmpty()) { soapMessage += " xmlns=\"" + actionNs_ + "\""; } soapMessage += ">"; } else { // Create a <m:Tag xmlns:m="fdfd"> tag soapMessage += "<" + actionPrefix_ + ":" + action_; if(! actionNs_.isEmpty()) { soapMessage += " xmlns:" + actionPrefix_ + "=\"" + actionNs_ + "\""; } soapMessage += ">"; } // If we received a tree of result nodes, include that if(! responseBody_.isNull()) { QString str; QTextStream ts( &str, IO_WriteOnly ); ts << responseBody_; soapMessage += str; } else { // Otherwise, add the parsed field/value pairs // Add the fields and values for ( uint i = 0; i < fields_.count(); i++ ) { soapMessage += "<" + fields_[i] + ">" + values_[i] + "</" + fields_[i] + ">"; } } // Add the body closing tag if(actionPrefix_.isEmpty()) { soapMessage += "</" + action_ + ">"; } else { soapMessage += "</" + actionPrefix_ + ":" + action_ + ">"; } // Add the remaining tags soapMessage += "</s:Body></s:Envelope>"; // Return the message return soapMessage; } // The total number of fields uint SoapMessage::getNoFields() const { return fields_.count(); } // Get a value given a field const QString& SoapMessage::getValue(const QString& field ) const { int index = fields_.findIndex( field ); // Warn if not found if(index == -1) { kdWarning() << "SoapMessage: This message does not have a field named '" << field << "'." << endl; return QString::null; } return values_[index]; } // Return the response xml tree const QDomNode& SoapMessage::getResponseBody() const { return responseBody_; } // Test whether a given field exists in the message header bool SoapMessage::hasField(const QString& field) const { return (fields_.findIndex( field ) == -1); } // Return whether this was an error response bool SoapMessage::isErrorMessage() const { return (errorCode_ != 0); } // Parse the incoming message void SoapMessage::parseMessage(const QString &message) { QDomDocument xml; // Parse the XML QString errorMessage; bool error = ! xml.setContent(message, true, &errorMessage); // Handle errors first if(error) { kdWarning() << "SoapMessage::parseMessage - XML Parsing failed: '" << errorMessage << "'." << endl; // Create a dummy the error message errorCode_ = 1; errorDescription_ = errorMessage; return; } // Get the body child node QDomNode resultNode = XmlFunctions::getNode(xml, "/Envelope/Body").firstChild(); QString resultNodeName = resultNode.toElement().nodeName(); if(resultNode.isNull()) { kdWarning() << "SoapMessage::parseMessage - XML Parsing failed: result node is null." << endl; // Create a dummy the error message errorCode_ = 1; errorDescription_ = "result node is null"; return; } // See if it's a soap error message if(resultNodeName == "Fault") { QString faultString = XmlFunctions::getNodeValue(resultNode, "/faultstring"); errorCode_ = XmlFunctions::getNodeValue(resultNode, "/detail/" + faultString + "/errorCode").toInt(); errorDescription_ = XmlFunctions::getNodeValue(resultNode, "/detail/" + faultString + "/errorDescription"); return; } // TODO: test this parsing code action_ = resultNodeName; actionPrefix_ = resultNode.prefix(); actionNs_ = resultNode.namespaceURI(); // Try to parse the result node if(resultNodeName.endsWith("Response")) { responseBody_ = resultNode.firstChild(); } else { // Parse all parameters // It's possible to pass the entire QDomNode object to the gotActionResponse() // function, but this is somewhat nicer, and reduces code boat in the subclasses QDomNodeList children = resultNode.childNodes(); for(uint i = 0; i < children.count(); i++) { fields_.append( children.item(i).nodeName() ); values_.append( children.item(i).toElement().text() ); } } } // Set the message type void SoapMessage::setAction(const QString &action, const QString &prefix, const QString &xmlns) { action_ = action; actionPrefix_ = prefix; actionNs_ = xmlns; }