diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-04-20 19:28:50 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-04-20 19:28:50 (GMT) |
commit | c1ebae519210cd4d09eb63bde593d48e769ad7ca (patch) | |
tree | 488cfd8056c2e727a7b49882c2f3d46240d00998 /src | |
parent | 26609f8b8097b21e952835e7064bc938c8542d93 (diff) | |
download | uscxml-c1ebae519210cd4d09eb63bde593d48e769ad7ca.zip uscxml-c1ebae519210cd4d09eb63bde593d48e769ad7ca.tar.gz uscxml-c1ebae519210cd4d09eb63bde593d48e769ad7ca.tar.bz2 |
Support for event.raw and more XPath datamodel refactorings
Diffstat (limited to 'src')
20 files changed, 395 insertions, 147 deletions
diff --git a/src/uscxml/Factory.h b/src/uscxml/Factory.h index e21fe72..59835b3 100644 --- a/src/uscxml/Factory.h +++ b/src/uscxml/Factory.h @@ -237,6 +237,10 @@ public: // foreach virtual uint32_t getLength(const std::string& expr) = 0; + virtual void setForeach(const std::string& item, + const std::string& array, + const std::string& index, + uint32_t iteration) = 0; virtual void pushContext() = 0; virtual void popContext() = 0; @@ -313,6 +317,12 @@ public: virtual uint32_t getLength(const std::string& expr) { return _impl->getLength(expr); } + virtual void setForeach(const std::string& item, + const std::string& array, + const std::string& index, + uint32_t iteration) { + return _impl->setForeach(item, array, index, iteration); + } virtual void assign(const Arabica::DOM::Element<std::string>& assignElem, const Arabica::DOM::Document<std::string>& doc, diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp index bec2a2a..21f64cb 100644 --- a/src/uscxml/Interpreter.cpp +++ b/src/uscxml/Interpreter.cpp @@ -1033,22 +1033,11 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node<std::string>& cont CATCH_AND_DISTRIBUTE("Syntax error in array attribute of foreach element:") try { _dataModel.pushContext(); // copy old and enter new context - if (!_dataModel.isDeclared(item)) { - _dataModel.init(item, Data()); - } +// if (!_dataModel.isDeclared(item)) { +// _dataModel.init(item, Data()); +// } for (uint32_t iteration = 0; iteration < iterations; iteration++) { - { - // assign array element to item - std::stringstream ss; - ss << array << "[" << iteration << "]"; - _dataModel.assign(item, ss.str()); - } - if (index.length() > 0) { - // assign iteration element to index - std::stringstream ss; - ss << iteration; - _dataModel.assign(index, ss.str()); - } + _dataModel.setForeach(item, array, index, iteration); if (content.hasChildNodes()) // execute content and have exception rethrown to break foreach executeContent(content.getChildNodes(), true); @@ -1166,7 +1155,7 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node<std::string>& cont execContent = Factory::createExecutableContent(content.getLocalName(), content.getNamespaceURI(), this); if (!execContent) { LOG(ERROR) << "No custom executable content known for element '" - << content.getLocalName() << "' in namespace '" << content.getNamespaceURI() << "'"; + << content.getLocalName() << "' in namespace '" << content.getNamespaceURI() << "'"; return; } _executableContent[content] = execContent; diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h index 3d41f70..27bd071 100644 --- a/src/uscxml/Message.h +++ b/src/uscxml/Message.h @@ -140,6 +140,13 @@ public: this->dom = dom; } + std::string getRaw() { + return raw; + } + void setRaw(const std::string& raw) { + this->raw = raw; + } + std::string getContent() { return content; } @@ -227,6 +234,7 @@ public: protected: #endif + std::string raw; std::string name; Type type; std::string origin; diff --git a/src/uscxml/URL.cpp b/src/uscxml/URL.cpp index 83d3dcb..45aba88 100644 --- a/src/uscxml/URL.cpp +++ b/src/uscxml/URL.cpp @@ -266,11 +266,11 @@ URL URL::asBaseURL(const URL& uri) { return URL(baseUriStr); } - + const bool URLImpl::toAbsolute(const std::string& baseUrl) { if (_uri.is_absolute()) return true; - + std::string uriStr = _uri.as_string(); #ifdef _WIN32 if (baseUrl.find("file://") == 0) { @@ -281,7 +281,7 @@ const bool URLImpl::toAbsolute(const std::string& baseUrl) { #else _uri = Arabica::io::URI(baseUrl, _uri.as_string()); #endif - + if (!_uri.is_absolute()) return false; return true; diff --git a/src/uscxml/URL.h b/src/uscxml/URL.h index 37b0614..402666f 100644 --- a/src/uscxml/URL.h +++ b/src/uscxml/URL.h @@ -177,7 +177,7 @@ public: const std::string asLocalFile(const std::string& suffix, bool reload = false) { return _impl->asLocalFile(suffix, reload); } - + static URL asBaseURL(const URL& url); static void toBaseURL(URL& uri); diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp index 22777fa..34dd524 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp @@ -339,11 +339,30 @@ uint32_t V8DataModel::getLength(const std::string& expr) { Event exceptionEvent; exceptionEvent.name = "error.execution"; - exceptionEvent.data.compound["exception"] = Data("'" + expr + "' does not evaluate to an array.", Data::VERBATIM);; + exceptionEvent.data.compound["exception"] = Data("'" + expr + "' does not evaluate to an array.", Data::VERBATIM); throw(exceptionEvent); } +void V8DataModel::setForeach(const std::string& item, + const std::string& array, + const std::string& index, + uint32_t iteration) { + if (!isDeclared(item)) { + assign(item, Data()); + } + // assign array element to item + std::stringstream ss; + ss << array << "[" << iteration << "]"; + assign(item, ss.str()); + if (index.length() > 0) { + // assign iteration element to index + std::stringstream ss; + ss << iteration; + assign(index, ss.str()); + } +} + void V8DataModel::eval(const std::string& expr) { v8::Locker locker; v8::HandleScope handleScope; diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h index 7c4f2b3..548cf20 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h @@ -36,6 +36,10 @@ public: virtual bool validate(const std::string& location, const std::string& schema); virtual uint32_t getLength(const std::string& expr); + virtual void setForeach(const std::string& item, + const std::string& array, + const std::string& index, + uint32_t iteration); virtual void pushContext(); virtual void popContext(); diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEvent.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEvent.cpp index 86fcfef..9679d74 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEvent.cpp +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEvent.cpp @@ -32,6 +32,15 @@ v8::Handle<v8::Value> V8SCXMLEvent::origintypeAttrGetter(v8::Local<v8::String> p return v8::String::New(privData->nativeObj->origintype.c_str()); } +v8::Handle<v8::Value> V8SCXMLEvent::rawAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { + v8::Local<v8::Object> self = info.Holder(); + struct V8SCXMLEventPrivate* privData = V8DOM::toClassPtr<V8SCXMLEventPrivate >(self->GetInternalField(0)); + + if (privData->nativeObj->raw.length() == 0) + return v8::Undefined(); + return v8::String::New(privData->nativeObj->raw.c_str()); +} + v8::Handle<v8::Value> V8SCXMLEvent::domAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info) { v8::Local<v8::Object> self = info.Holder(); struct V8SCXMLEventPrivate* privData = V8DOM::toClassPtr<V8SCXMLEventPrivate >(self->GetInternalField(0)); diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEvent.h b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEvent.h index e7dbacc..670d818 100644 --- a/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEvent.h +++ b/src/uscxml/plugins/datamodel/ecmascript/v8/dom/V8SCXMLEvent.h @@ -45,6 +45,7 @@ public: static v8::Handle<v8::Value> nameAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info); static v8::Handle<v8::Value> originAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info); static v8::Handle<v8::Value> origintypeAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info); + static v8::Handle<v8::Value> rawAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info); static v8::Handle<v8::Value> domAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info); static v8::Handle<v8::Value> sendidCustomAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info); static v8::Handle<v8::Value> invokeidAttrGetter(v8::Local<v8::String> property, const v8::AccessorInfo& info); @@ -70,6 +71,8 @@ public: v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None)); instance->SetAccessor(v8::String::NewSymbol("origintype"), V8SCXMLEvent::origintypeAttrGetter, 0, v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None)); + instance->SetAccessor(v8::String::NewSymbol("raw"), V8SCXMLEvent::rawAttrGetter, 0, + v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None)); instance->SetAccessor(v8::String::NewSymbol("dom"), V8SCXMLEvent::domAttrGetter, 0, v8::External::New(0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None)); instance->SetAccessor(v8::String::NewSymbol("sendid"), V8SCXMLEvent::sendidCustomAttrGetter, 0, diff --git a/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp b/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp index 6911480..dac3386 100644 --- a/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp +++ b/src/uscxml/plugins/datamodel/null/NULLDataModel.cpp @@ -55,6 +55,12 @@ uint32_t NULLDataModel::getLength(const std::string& expr) { return 0; } +void NULLDataModel::setForeach(const std::string& item, + const std::string& array, + const std::string& index, + uint32_t iteration) { +} + void NULLDataModel::eval(const std::string& expr) { } diff --git a/src/uscxml/plugins/datamodel/null/NULLDataModel.h b/src/uscxml/plugins/datamodel/null/NULLDataModel.h index 423c5ff..3d86bf2 100644 --- a/src/uscxml/plugins/datamodel/null/NULLDataModel.h +++ b/src/uscxml/plugins/datamodel/null/NULLDataModel.h @@ -33,6 +33,11 @@ public: virtual bool validate(const std::string& location, const std::string& schema); virtual uint32_t getLength(const std::string& expr); + virtual void setForeach(const std::string& item, + const std::string& array, + const std::string& index, + uint32_t iteration); + virtual void pushContext(); virtual void popContext(); diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp index cc1fb39..db91869 100644 --- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp +++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp @@ -96,6 +96,13 @@ uint32_t SWIDataModel::getLength(const std::string& expr) { return 0; } +void SWIDataModel::setForeach(const std::string& item, + const std::string& array, + const std::string& index, + uint32_t iteration) { + // std::cout << "SWIDataModel::setForeach" << std::endl; +} + void SWIDataModel::eval(const std::string& expr) { URL localPLFile = URL::toLocalFile(expr, ".pl"); PlCall("user", "load_files", PlTermv(localPLFile.asLocalFile(".pl").c_str())) || LOG(ERROR) << "Could not execute prolog from file"; diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h index a278db8..19dc712 100644 --- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h +++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.h @@ -33,6 +33,11 @@ public: virtual bool validate(const std::string& location, const std::string& schema); virtual uint32_t getLength(const std::string& expr); + virtual void setForeach(const std::string& item, + const std::string& array, + const std::string& index, + uint32_t iteration); + virtual void pushContext(); virtual void popContext(); diff --git a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp index 179fded..39616f8 100644 --- a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp +++ b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.cpp @@ -59,7 +59,11 @@ boost::shared_ptr<DataModelImpl> XPathDataModel::create(InterpreterImpl* interpr dm->_datamodel.appendChild(ioProcElem); NodeSet<std::string> ioProcNodeSet; - ioProcNodeSet.push_back(ioProcElem); + Node<std::string> node = ioProcElem.getFirstChild(); + while(node) { + ioProcNodeSet.push_back(node); + node = node.getNextSibling(); + } dm->_varResolver.setVariable("_ioprocessors", ioProcNodeSet); Element<std::string> sessIdElem = dm->_doc.createElement("data"); @@ -69,7 +73,7 @@ boost::shared_ptr<DataModelImpl> XPathDataModel::create(InterpreterImpl* interpr dm->_datamodel.appendChild(sessIdElem); NodeSet<std::string> sessIdNodeSet; - sessIdNodeSet.push_back(sessIdElem); + sessIdNodeSet.push_back(sessIdText); dm->_varResolver.setVariable("_sessionid", sessIdNodeSet); @@ -80,7 +84,7 @@ boost::shared_ptr<DataModelImpl> XPathDataModel::create(InterpreterImpl* interpr dm->_datamodel.appendChild(nameElem); NodeSet<std::string> nameNodeSet; - nameNodeSet.push_back(nameElem); + nameNodeSet.push_back(nameText); dm->_varResolver.setVariable("_name", nameNodeSet); return dm; @@ -129,6 +133,13 @@ void XPathDataModel::setEvent(const Event& event) { namelistIter++; } } + if (event.raw.size() > 0) { + Element<std::string> eventRawElem = _doc.createElement("raw"); + Text<std::string> textNode = _doc.createTextNode(event.raw.c_str()); + eventRawElem.appendChild(textNode); + eventDataElem.appendChild(eventRawElem); + } + if (event.content.size() > 0) { Text<std::string> textNode = _doc.createTextNode(Interpreter::spaceNormalize(event.content).c_str()); eventDataElem.appendChild(textNode); @@ -139,7 +150,7 @@ void XPathDataModel::setEvent(const Event& event) { } eventElem.appendChild(eventDataElem); - eventNodeSet.push_back(eventElem); + eventNodeSet.push_back(eventDataElem); // do we need to replace an existing event? Node<std::string> oldEventElem = _datamodel.getFirstChild(); @@ -169,28 +180,103 @@ bool XPathDataModel::validate(const std::string& location, const std::string& sc } uint32_t XPathDataModel::getLength(const std::string& expr) { - std::cout << _datamodel << std::endl; +// std::cout << _datamodel << std::endl; XPathValue<std::string> result = _xpath.evaluate_expr(expr, _doc); switch(result.type()) { - case NUMBER: - return result.asNumber(); - break; - case NODE_SET: - return result.asNodeSet().size(); - break; - default: - throw Event("error.execution", Event::PLATFORM); + case NUMBER: + return result.asNumber(); + break; + case NODE_SET: + return result.asNodeSet().size(); + break; + default: + Event exceptionEvent("error.execution", Event::PLATFORM); + exceptionEvent.data.compound["exception"] = Data("'" + expr + "' does not evaluate to an array.", Data::VERBATIM); + throw(exceptionEvent); } return 0; } +void XPathDataModel::setForeach(const std::string& item, + const std::string& array, + const std::string& index, + uint32_t iteration) { + + XPathValue<std::string> arrayResult = _xpath.evaluate_expr(array, _doc); + assert(arrayResult.type() == NODE_SET); + +#if 0 + std::cout << "Array Size: " << arrayResult.asNodeSet().size() << std::endl; + for (int i = 0; i < arrayResult.asNodeSet().size(); i++) { + std::cout << arrayResult.asNodeSet()[i] << std::endl; + } +#endif + + assert(arrayResult.asNodeSet().size() >= iteration); + + + NodeSet<std::string> arrayNodeSet; + arrayNodeSet.push_back(arrayResult.asNodeSet()[iteration]); + + if (!isDeclared(item)) { + if (!isValidIdentifier(item)) + throw Event("error.execution", Event::PLATFORM); + Element<std::string> container = _doc.createElement("data"); + container.setAttribute("id", item); + container.appendChild(arrayResult.asNodeSet()[iteration].cloneNode(true)); + _datamodel.appendChild(container); + _varResolver.setVariable(item, arrayNodeSet); + } + XPathValue<std::string> itemResult = _varResolver.resolveVariable("", item); + assign(itemResult, arrayNodeSet, Element<std::string>()); + + if (index.length() > 0) { + NodeSet<std::string> indexNodeSet; + Text<std::string> indexElem = _doc.createTextNode(toStr(iteration)); + indexNodeSet.push_back(indexElem); + + if (!isDeclared(index)) { + Element<std::string> container = _doc.createElement("data"); + container.setAttribute("id", index); + container.appendChild(indexElem); + _datamodel.appendChild(container); + + NodeSet<std::string> indexVarNodeSet; + indexVarNodeSet.push_back(container); + _varResolver.setVariable(index, indexVarNodeSet); + } + XPathValue<std::string> indexResult = _varResolver.resolveVariable("", index); + assign(indexResult, indexNodeSet, Element<std::string>()); + } + + +#if 0 + std::cout << _datamodel << std::endl << std::endl; + std::cout << "Index: " << indexResult.asNodeSet().size() << std::endl; + for (int i = 0; i < indexResult.asNodeSet().size(); i++) { + std::cout << indexResult.asNodeSet()[i] << std::endl; + } + std::cout << std::endl; +#endif + + +} + +bool XPathDataModel::isValidIdentifier(const std::string& identifier) { + if(boost::starts_with(identifier, ".")) + return false; + + return true; +} + + void XPathDataModel::eval(const std::string& expr) { XPathValue<std::string> result = _xpath.evaluate_expr(expr, _doc); } bool XPathDataModel::isDeclared(const std::string& expr) { try { - return evalAsBool(expr); + return _varResolver.isDeclared(expr) || evalAsBool(expr); } catch(...) { return false; } @@ -247,7 +333,22 @@ void XPathDataModel::assign(const Element<std::string>& assignElem, XPathValue<std::string> key = _xpath.evaluate_expr(location, _doc); NodeSet<std::string> nodeSet; if (doc) { - nodeSet.push_back(doc.getDocumentElement()); + if (doc.getDocumentElement()) { + Node<std::string> data = doc.getDocumentElement().getFirstChild(); + while (data) { + // do not add empty text as a node + if (data.getNodeType() == Node_base::TEXT_NODE) { + std::string trimmed = data.getNodeValue(); + boost::trim(trimmed); + if (trimmed.length() == 0) { + data = data.getNextSibling(); + continue; + } + } + nodeSet.push_back(data); + data = data.getNextSibling(); + } + } assign(key, nodeSet, assignElem); } else if (content.length() > 0) { Text<std::string> textNode = _doc.createTextNode(Interpreter::spaceNormalize(content)); @@ -292,11 +393,26 @@ void XPathDataModel::init(const Element<std::string>& dataElem, Text<std::string> textNode = _doc.createTextNode(Interpreter::spaceNormalize(content)); container.appendChild(textNode); } else if (HAS_ATTR(dataElem, "expr")) { - XPathValue<std::string> expr = _xpath.evaluate_expr(ATTR(dataElem, "expr"), _doc); - XPathValue<std::string> key = _xpath.evaluate_expr(location, _doc); - assign(key, expr, dataElem); - for (int i = 0; expr.asNodeSet().size(); i++) - container.appendChild(expr.asNodeSet()[i]); + try { + XPathValue<std::string> expr = _xpath.evaluate_expr(ATTR(dataElem, "expr"), _doc); + switch (expr.type()) { + case NODE_SET: + for (int i = 0; expr.asNodeSet().size(); i++) + container.appendChild(expr.asNodeSet()[i]); + break; + case STRING: + container.appendChild(_doc.createTextNode(expr.asString())); + break; + case NUMBER: + container.appendChild(_doc.createTextNode(toStr(expr.asNumber()))); + break; + case BOOL: + case ANY: + throw Event("error.execution", Event::PLATFORM); + } + } catch (SyntaxException e) { + throw Event("error.execution", Event::PLATFORM); + } } else { LOG(ERROR) << "data element has no content"; } @@ -307,7 +423,7 @@ void XPathDataModel::init(const Element<std::string>& dataElem, nodeSet.push_back(container); _varResolver.setVariable(location, nodeSet); - std::cout << _datamodel << std::endl; +// std::cout << _datamodel << std::endl; } void XPathDataModel::init(const std::string& location, const Data& data) { @@ -320,46 +436,49 @@ void XPathDataModel::assign(const XPathValue<std::string>& key, const XPathValue<std::string>& value, const Element<std::string>& assignElem) { switch (key.type()) { - case NODE_SET: { - switch (value.type()) { - case STRING: - assign(key.asNodeSet(), value.asString(), assignElem); - break; - case BOOL: - assign(key.asNodeSet(), value.asBool(), assignElem); - break; - case NUMBER: - assign(key.asNodeSet(), value.asNumber(), assignElem); - break; - case NODE_SET: - assign(key.asNodeSet(), value.asNodeSet(), assignElem); - break; - case ANY: - throw Event("error.execution", Event::PLATFORM); - } - break; + case NODE_SET: { + if (key.asNodeSet().size() == 0) { + throw Event("error.execution", Event::PLATFORM); } + switch (value.type()) { case STRING: + assign(key.asNodeSet(), value.asString(), assignElem); + break; case BOOL: + assign(key.asNodeSet(), value.asBool(), assignElem); + break; case NUMBER: + assign(key.asNodeSet(), value.asNumber(), assignElem); + break; + case NODE_SET: + assign(key.asNodeSet(), value.asNodeSet(), assignElem); + break; case ANY: throw Event("error.execution", Event::PLATFORM); + } + break; + } + case STRING: + case BOOL: + case NUMBER: + case ANY: + throw Event("error.execution", Event::PLATFORM); } } void XPathDataModel::assign(const XPathValue<std::string>& key, - const NodeSet<std::string>& value, - const Element<std::string>& assignElem) { + const NodeSet<std::string>& value, + const Element<std::string>& assignElem) { switch (key.type()) { - case NODE_SET: { - assign(key.asNodeSet(), value, assignElem); - break; - } - case STRING: - case BOOL: - case NUMBER: - case ANY: - throw Event("error.execution", Event::PLATFORM); + case NODE_SET: { + assign(key.asNodeSet(), value, assignElem); + break; + } + case STRING: + case BOOL: + case NUMBER: + case ANY: + throw Event("error.execution", Event::PLATFORM); } } @@ -404,7 +523,7 @@ void XPathDataModel::assign(const NodeSet<std::string>& key, } } } - + void XPathDataModel::assign(const NodeSet<std::string>& key, const double value, const Element<std::string>& assignElem) { @@ -429,6 +548,7 @@ void XPathDataModel::assign(const NodeSet<std::string>& key, break; } default: +// std::cout << key[i].getNodeType() << std::endl; throw Event("error.execution", Event::PLATFORM); break; } @@ -436,23 +556,23 @@ void XPathDataModel::assign(const NodeSet<std::string>& key, } void XPathDataModel::assign(const Element<std::string>& key, - const NodeSet<std::string>& value, - const Element<std::string>& assignElem) { + const NodeSet<std::string>& value, + const Element<std::string>& assignElem) { Element<std::string> element(key); if (false) { - } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "firstchild")) { + } else if (assignElem && HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "firstchild")) { // firstchild: Insert the value specified by 'expr' before all of the children at 'location'. for (int i = value.size(); i; i--) { Node<std::string> importedNode = _doc.importNode(value[i-1], true); element.insertBefore(importedNode, element.getFirstChild()); } - } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "lastchild")) { + } else if (assignElem && HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "lastchild")) { // lastchild: Insert the value specified by 'expr' after all of the children at 'location'. for (int i = 0; i < value.size(); i++) { Node<std::string> importedNode = _doc.importNode(value[i], true); element.appendChild(importedNode); } - } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "previoussibling")) { + } else if (assignElem && HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "previoussibling")) { // previoussibling: Insert the value specified by 'expr' before the // node specified by 'location', keeping the same parent. Node<std::string> parent = element.getParentNode(); @@ -462,7 +582,7 @@ void XPathDataModel::assign(const Element<std::string>& key, Node<std::string> importedNode = _doc.importNode(value[i], true); parent.insertBefore(importedNode, element); } - } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "nextsibling")) { + } else if (assignElem && HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "nextsibling")) { // nextsibling: Insert the value specified by 'expr' after the node // specified by 'location', keeping the same parent. Node<std::string> parent = element.getParentNode(); @@ -477,7 +597,7 @@ void XPathDataModel::assign(const Element<std::string>& key, parent.appendChild(importedNode); } } - } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "replace")) { + } else if (assignElem && HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "replace")) { // replace: Replace the node specified by 'location' by the value specified by 'expr'. Node<std::string> parent = element.getParentNode(); if (!parent) @@ -486,7 +606,7 @@ void XPathDataModel::assign(const Element<std::string>& key, throw Event("error.execution", Event::PLATFORM); Node<std::string> importedNode = _doc.importNode(value[0], true); parent.replaceChild(importedNode, element); - } else if (HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "delete")) { + } else if (assignElem && HAS_ATTR(assignElem, "type") && boost::iequals(ATTR(assignElem, "type"), "delete")) { // delete: Delete the node specified by 'location'. ('expr' is ignored.). Node<std::string> parent = element.getParentNode(); if (!parent) @@ -510,6 +630,13 @@ NodeSetVariableResolver::resolveVariable(const std::string& namepaceUri, if(n == _variables.end()) { throw Event("error.execution"); } +#if 0 + std::cout << std::endl << name << ":" << std::endl; + for (int i = 0; i < n->second.size(); i++) { + std::cout << n->second[i].getNodeType() << " | " << n->second[i] << std::endl; + } + std::cout << std::endl; +#endif return XPathValue<std::string>(new NodeSetValue<std::string>(n->second)); } diff --git a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h index 391af0b..7140b2f 100644 --- a/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h +++ b/src/uscxml/plugins/datamodel/xpath/XPathDataModel.h @@ -58,7 +58,7 @@ public: bool isDeclared(const std::string& name) { return _variables.find(name) != _variables.end(); } - + private: std::map<std::string, Arabica::XPath::NodeSet<std::string> > _variables; friend class XPathDataModel; @@ -82,6 +82,11 @@ public: virtual bool validate(const std::string& location, const std::string& schema); virtual uint32_t getLength(const std::string& expr); + virtual void setForeach(const std::string& item, + const std::string& array, + const std::string& index, + uint32_t iteration); + virtual void pushContext(); virtual void popContext(); @@ -109,6 +114,8 @@ protected: Arabica::DOM::Element<std::string> _datamodel; Arabica::DOM::Document<std::string> _doc; + bool isValidIdentifier(const std::string& identifier); + // resolve value to its type void assign(const Arabica::XPath::XPathValue<std::string>& key, const Arabica::XPath::XPathValue<std::string>& value, @@ -116,7 +123,7 @@ protected: void assign(const Arabica::XPath::XPathValue<std::string>& key, const Arabica::XPath::NodeSet<std::string>& value, const Arabica::DOM::Element<std::string>& assignElem); - + // assign value to a nodeset key void assign(const Arabica::XPath::NodeSet<std::string>& key, const std::string& value, @@ -130,12 +137,19 @@ protected: void assign(const Arabica::XPath::NodeSet<std::string>& key, const Arabica::XPath::NodeSet<std::string>& value, const Arabica::DOM::Element<std::string>& assignElem); - + // assign value to an element key (from nodeset) void assign(const Arabica::DOM::Element<std::string>& key, const Arabica::XPath::NodeSet<std::string>& value, const Arabica::DOM::Element<std::string>& assignElem); + + // assign value to a text node key (from nodeset) + void assign(const Arabica::DOM::Text<std::string>& key, + const Arabica::XPath::NodeSet<std::string>& value, + const Arabica::DOM::Element<std::string>& assignElem); + + NodeSetVariableResolver _varResolver; XPathFunctionResolver _funcResolver; diff --git a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp index 09195bf..1d6394e 100644 --- a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp +++ b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp @@ -73,15 +73,32 @@ void BasicHTTPIOProcessor::httpRecvRequest(const HTTPServer::Request& req) { reqEvent.type = Event::EXTERNAL; bool scxmlStructFound = false; - if (reqEvent.data.compound["header"].compound.find("_scxmleventstruct") != reqEvent.data.compound["header"].compound.end()) { - // TODO: this looses all other information - reqEvent = Event::fromXML(evhttp_decode_uri(reqEvent.data.compound["header"].compound["_scxmleventstruct"].atom.c_str())); - scxmlStructFound = true; - } - if (reqEvent.data.compound["header"].compound.find("_scxmleventname") != reqEvent.data.compound["header"].compound.end()) { - reqEvent.name = evhttp_decode_uri(reqEvent.data.compound["header"].compound["_scxmleventname"].atom.c_str()); + if (reqEvent.data.compound["header"].compound.find("Content-Type") != reqEvent.data.compound["header"].compound.end() && + boost::iequals(reqEvent.data.compound["header"].compound["Content-Type"].atom, "application/x-www-form-urlencoded")) { + std::stringstream ss(reqEvent.data.compound["content"].atom); + std::string term; + while(std::getline(ss, term, '&')) { + size_t split = term.find_first_of("="); + if (split != std::string::npos) { + std::string key = evhttp_decode_uri(term.substr(0, split).c_str()); + std::string value = evhttp_decode_uri(term.substr(split + 1).c_str()); + if (boost::iequals(key, "_scxmleventname")) { + reqEvent.name = value; + } else { + reqEvent.data.compound[key] = value; + } + } + } + } else { + if (reqEvent.data.compound["header"].compound.find("_scxmleventstruct") != reqEvent.data.compound["header"].compound.end()) { + // TODO: this looses all other information + reqEvent = Event::fromXML(evhttp_decode_uri(reqEvent.data.compound["header"].compound["_scxmleventstruct"].atom.c_str())); + scxmlStructFound = true; + } + if (reqEvent.data.compound["header"].compound.find("_scxmleventname") != reqEvent.data.compound["header"].compound.end()) { + reqEvent.name = evhttp_decode_uri(reqEvent.data.compound["header"].compound["_scxmleventname"].atom.c_str()); + } } - std::map<std::string, Data>::iterator headerIter = reqEvent.data.compound["header"].compound.begin(); while(headerIter != reqEvent.data.compound["header"].compound.end()) { reqEvent.data.compound[headerIter->first] = Data(evhttp_decode_uri(headerIter->second.atom.c_str()), Data::VERBATIM); @@ -118,12 +135,12 @@ void BasicHTTPIOProcessor::httpRecvRequest(const HTTPServer::Request& req) { } void BasicHTTPIOProcessor::send(const SendRequest& req) { - + if (req.target.length() == 0) { _interpreter->receiveInternal(Event("error.communication", Event::PLATFORM)); return; } - + bool isLocal = false; std::string target; if (!boost::equals(req.target, _url)) { @@ -133,17 +150,23 @@ void BasicHTTPIOProcessor::send(const SendRequest& req) { target = _url; } URL targetURL(target); + std::stringstream kvps; + std::string kvpSeperator; // event name if (req.name.size() > 0) { - targetURL.addOutHeader("_scxmleventname", evhttp_encode_uri(req.name.c_str())); + kvps << kvpSeperator << evhttp_encode_uri("_scxmleventname") << "=" << evhttp_encode_uri(req.name.c_str()); + kvpSeperator = "&"; +// targetURL.addOutHeader("_scxmleventname", evhttp_encode_uri(req.name.c_str())); } // event namelist if (req.namelist.size() > 0) { std::map<std::string, std::string>::const_iterator namelistIter = req.namelist.begin(); while (namelistIter != req.namelist.end()) { - targetURL.addOutHeader(namelistIter->first, namelistIter->second); + kvps << kvpSeperator << evhttp_encode_uri(namelistIter->first.c_str()) << "=" << evhttp_encode_uri(namelistIter->second.c_str()); + kvpSeperator = "&"; +// targetURL.addOutHeader(namelistIter->first, namelistIter->second); namelistIter++; } } @@ -152,15 +175,19 @@ void BasicHTTPIOProcessor::send(const SendRequest& req) { if (req.params.size() > 0) { std::multimap<std::string, std::string>::const_iterator paramIter = req.params.begin(); while (paramIter != req.params.end()) { - targetURL.addOutHeader(paramIter->first, paramIter->second); + kvps << kvpSeperator << evhttp_encode_uri(paramIter->first.c_str()) << "=" << evhttp_encode_uri(paramIter->second.c_str()); + kvpSeperator = "&"; +// targetURL.addOutHeader(paramIter->first, paramIter->second); paramIter++; } } // content - if (req.content.size() > 0) + if (kvps.str().size() > 0) { + targetURL.setOutContent(kvps.str()); + } else if (req.content.size() > 0) { targetURL.setOutContent(req.content); - + } targetURL.setRequestType("post"); targetURL.addMonitor(this); diff --git a/src/uscxml/plugins/ioprocessor/modality/MMIComponent.h b/src/uscxml/plugins/ioprocessor/modality/MMIComponent.h index bee568b..ba3f2c8 100644 --- a/src/uscxml/plugins/ioprocessor/modality/MMIComponent.h +++ b/src/uscxml/plugins/ioprocessor/modality/MMIComponent.h @@ -19,7 +19,7 @@ public: virtual std::set<std::string> getNames() { return std::set<std::string>(); }; - + virtual Data getDataModelVariables(); virtual void send(const SendRequest& req); @@ -37,7 +37,7 @@ public: virtual NewContextResponse newContext(const NewContextRequest&); virtual DoneNotification done(const DoneNotification&); // virtual ExtensionNotification extension(const ExtensionNotification&); - + }; diff --git a/src/uscxml/plugins/ioprocessor/modality/MMIMessages.cpp b/src/uscxml/plugins/ioprocessor/modality/MMIMessages.cpp index ed92fac..717e174 100644 --- a/src/uscxml/plugins/ioprocessor/modality/MMIMessages.cpp +++ b/src/uscxml/plugins/ioprocessor/modality/MMIMessages.cpp @@ -24,14 +24,14 @@ Arabica::DOM::Document<std::string> MMIMessage::toXML() { if (data.size() > 0) { Element<std::string> dataElem = doc.createElementNS(nameSpace, "data"); - + // try to parse content std::stringstream* ss = new std::stringstream(); (*ss) << data; std::auto_ptr<std::istream> ssPtr(ss); Arabica::SAX::InputSource<std::string> inputSource; inputSource.setByteStream(ssPtr); - + Arabica::SAX2DOM::Parser<std::string> parser; if(parser.parse(inputSource)) { Node<std::string> importedNode = doc.importNode(parser.getDocument().getDocumentElement(), true); @@ -40,9 +40,9 @@ Arabica::DOM::Document<std::string> MMIMessage::toXML() { Text<std::string> textElem = doc.createTextNode(data); dataElem.appendChild(textElem); } - msgElem.appendChild(dataElem); + msgElem.appendChild(dataElem); } - + mmiElem.appendChild(msgElem); doc.appendChild(mmiElem); std::cout << doc; @@ -67,7 +67,7 @@ Arabica::DOM::Document<std::string> ContentRequest::toXML() { contentURLElem.setAttributeNS(nameSpace, "max-age", contentURL.maxAge); msgElem.appendChild(contentURLElem); } - + if (content.size() > 0) { Element<std::string> contentElem = doc.createElementNS(nameSpace, "content"); @@ -77,7 +77,7 @@ Arabica::DOM::Document<std::string> ContentRequest::toXML() { std::auto_ptr<std::istream> ssPtr(ss); Arabica::SAX::InputSource<std::string> inputSource; inputSource.setByteStream(ssPtr); - + Arabica::SAX2DOM::Parser<std::string> parser; if(parser.parse(inputSource)) { Node<std::string> importedNode = doc.importNode(parser.getDocument().getDocumentElement(), true); @@ -117,12 +117,12 @@ Arabica::DOM::Document<std::string> StatusResponse::toXML() { Arabica::DOM::Document<std::string> StatusInfoResponse::toXML() { Document<std::string> doc = StatusResponse::toXML(); Element<std::string> msgElem = Element<std::string>(doc.getDocumentElement().getFirstChild()); - + Element<std::string> statusInfoElem = doc.createElementNS(nameSpace, "StatusInfo"); Text<std::string> statusInfoText = doc.createTextNode(statusInfo); statusInfoElem.appendChild(statusInfoText); msgElem.appendChild(statusInfoElem); - + return doc; } @@ -135,7 +135,7 @@ Arabica::DOM::Document<std::string> StatusRequest::toXML() { } else { msgElem.setAttributeNS(nameSpace, "RequestAutomaticUpdate", "false"); } - + return doc; } @@ -153,14 +153,14 @@ MMIMessage MMIMessage::fromXML(const Arabica::DOM::Document<std::string>& doc) { // msg.data = msgElem.getAttributeNS("http://www.w3.org/2008/04/mmi-arch", "Data"); msg.requestId = msgElem.getAttributeNS("http://www.w3.org/2008/04/mmi-arch", "RequestID"); msg.tagName = msgElem.getLocalName(); - + Element<std::string> dataElem; node = msgElem.getFirstChild(); while (node) { if (node.getNodeType() == Node_base::ELEMENT_NODE) dataElem = Element<std::string>(node); - if (dataElem && boost::iequals(dataElem.getLocalName(), "data")) - break; + if (dataElem && boost::iequals(dataElem.getLocalName(), "data")) + break; node = node.getNextSibling(); } @@ -176,7 +176,7 @@ MMIMessage MMIMessage::fromXML(const Arabica::DOM::Document<std::string>& doc) { } msg.data = ss.str(); } - + return msg; } @@ -203,13 +203,13 @@ ContentRequest ContentRequest::fromXML(const Arabica::DOM::Document<std::string> } Element<std::string> msgElem(node); Element<std::string> contentElem; - + node = msgElem.getFirstChild(); while (node) { if (node.getNodeType() == Node_base::ELEMENT_NODE) { contentElem = Element<std::string>(node); if (boost::iequals(contentElem.getLocalName(), "content") || - boost::iequals(contentElem.getLocalName(), "contentURL")) + boost::iequals(contentElem.getLocalName(), "contentURL")) break; } node = node.getNextSibling(); @@ -233,7 +233,7 @@ ContentRequest ContentRequest::fromXML(const Arabica::DOM::Document<std::string> msg.contentURL.fetchTimeout = contentElem.getAttributeNS("http://www.w3.org/2008/04/mmi-arch", "fetchtimeout"); } } - + //msg.content = msgElem.getAttributeNS("http://www.w3.org/2008/04/mmi-arch", "Context"); return msg; } @@ -294,7 +294,7 @@ StatusInfoResponse StatusInfoResponse::fromXML(const Arabica::DOM::Document<std: } node = node.getNextSibling(); } - + if (statusInfoElem && boost::iequals(statusInfoElem.getLocalName(), "statusInfo")) { node = statusInfoElem.getFirstChild(); while (node) { @@ -305,11 +305,11 @@ StatusInfoResponse StatusInfoResponse::fromXML(const Arabica::DOM::Document<std: node = node.getNextSibling(); } } - + return msg; } - + StatusRequest StatusRequest::fromXML(const Arabica::DOM::Document<std::string>& doc) { StatusRequest msg(ContextualizedRequest::fromXML(doc)); Node<std::string> node = doc.getDocumentElement().getFirstChild(); @@ -320,7 +320,7 @@ StatusRequest StatusRequest::fromXML(const Arabica::DOM::Document<std::string>& } Element<std::string> msgElem(node); std::string autoUpdate = msgElem.getAttributeNS("http://www.w3.org/2008/04/mmi-arch", "RequestAutomaticUpdate"); - + if (boost::iequals(autoUpdate, "true")) { msg.automaticUpdate = true; } else if(boost::iequals(autoUpdate, "on")) { diff --git a/src/uscxml/plugins/ioprocessor/modality/MMIMessages.h b/src/uscxml/plugins/ioprocessor/modality/MMIMessages.h index af31efe..a5328ac 100644 --- a/src/uscxml/plugins/ioprocessor/modality/MMIMessages.h +++ b/src/uscxml/plugins/ioprocessor/modality/MMIMessages.h @@ -18,11 +18,11 @@ public: std::string tagName; static std::string nameSpace; - + protected: MMIMessage() {} }; - + class NewContextRequest : public MMIMessage { public: NewContextRequest() { @@ -56,7 +56,7 @@ public: return ContextualizedRequest::fromXML(doc); } }; -class ResumeRequest : public ContextualizedRequest { +class ResumeRequest : public ContextualizedRequest { public: ResumeRequest() { tagName = "ResumeRequest"; @@ -67,7 +67,7 @@ public: } }; -class CancelRequest : public ContextualizedRequest { +class CancelRequest : public ContextualizedRequest { public: CancelRequest() { tagName = "CancelRequest"; @@ -78,7 +78,7 @@ public: } }; -class ClearContextRequest : public ContextualizedRequest { +class ClearContextRequest : public ContextualizedRequest { public: ClearContextRequest() { tagName = "ClearContextRequest"; @@ -89,7 +89,7 @@ public: } }; -class StatusRequest : public ContextualizedRequest { +class StatusRequest : public ContextualizedRequest { public: StatusRequest() { tagName = "StatusRequest"; @@ -109,7 +109,7 @@ public: std::string maxAge; std::string fetchTimeout; }; - + virtual Arabica::DOM::Document<std::string> toXML(); static ContentRequest fromXML(const Arabica::DOM::Document<std::string>& doc); std::string content; @@ -119,7 +119,7 @@ protected: ContentRequest(const ContextualizedRequest& father) : ContextualizedRequest(father) {} }; -class PrepareRequest : public ContentRequest { +class PrepareRequest : public ContentRequest { public: PrepareRequest() { tagName = "PrepareRequest"; @@ -130,7 +130,7 @@ public: } }; -class StartRequest : public ContentRequest { +class StartRequest : public ContentRequest { public: StartRequest() { tagName = "StartRequest"; @@ -159,10 +159,10 @@ protected: class StatusResponse : public ContextualizedRequest { public: enum Status { - ALIVE = 0, - DEAD = 1, - SUCCESS = 2, - FAILURE = 3 + ALIVE = 0, + DEAD = 1, + SUCCESS = 2, + FAILURE = 3 }; StatusResponse() { @@ -196,7 +196,7 @@ public: return StatusInfoResponse::fromXML(doc); } }; - + class StartResponse : public StatusInfoResponse { public: StartResponse() { @@ -207,7 +207,7 @@ public: return StatusInfoResponse::fromXML(doc); } }; - + class CancelResponse : public StatusInfoResponse { public: CancelResponse() { @@ -218,7 +218,7 @@ public: return StatusInfoResponse::fromXML(doc); } }; - + class PauseResponse : public StatusInfoResponse { public: PauseResponse() { @@ -229,7 +229,7 @@ public: return StatusInfoResponse::fromXML(doc); } }; - + class ResumeResponse : public StatusInfoResponse { public: ResumeResponse() { @@ -240,7 +240,7 @@ public: return StatusInfoResponse::fromXML(doc); } }; - + class ClearContextResponse : public StatusInfoResponse { public: ClearContextResponse() { @@ -251,7 +251,7 @@ public: return StatusInfoResponse::fromXML(doc); } }; - + class NewContextResponse : public StatusInfoResponse { public: NewContextResponse() { @@ -263,7 +263,7 @@ public: } }; - + class DoneNotification : public StatusInfoResponse { public: DoneNotification() { diff --git a/src/uscxml/server/HTTPServer.cpp b/src/uscxml/server/HTTPServer.cpp index 0d5feee..70b272f 100644 --- a/src/uscxml/server/HTTPServer.cpp +++ b/src/uscxml/server/HTTPServer.cpp @@ -114,10 +114,14 @@ void HTTPServer::httpRecvReqCallback(struct evhttp_request *req, void *callbackD // evhttp_send_error(req, 404, NULL); // return; + std::stringstream raw; + evhttp_request_own(req); Request request; request.curlReq = req; + + switch (evhttp_request_get_command(req)) { case EVHTTP_REQ_GET: request.data.compound["type"] = Data("get", Data::VERBATIM); @@ -150,6 +154,18 @@ void HTTPServer::httpRecvReqCallback(struct evhttp_request *req, void *callbackD request.data.compound["type"] = Data("unknown", Data::VERBATIM); break; } + raw << boost::to_upper_copy(request.data.compound["type"].atom); + + request.data.compound["remoteHost"] = Data(req->remote_host, Data::VERBATIM); + request.data.compound["remotePort"] = Data(toStr(req->remote_port), Data::VERBATIM); + request.data.compound["httpMajor"] = Data(toStr((unsigned short)req->major), Data::VERBATIM); + request.data.compound["httpMinor"] = Data(toStr((unsigned short)req->minor), Data::VERBATIM); + request.data.compound["uri"] = Data(HTTPServer::getBaseURL() + req->uri, Data::VERBATIM); + request.data.compound["path"] = Data(evhttp_uri_get_path(evhttp_request_get_evhttp_uri(req)), Data::VERBATIM); + + raw << " " << request.data.compound["path"].atom; + raw << " HTTP/" << request.data.compound["httpMajor"].atom << "." << request.data.compound["httpMinor"].atom; + raw << std::endl; struct evkeyvalq *headers; struct evkeyval *header; @@ -159,14 +175,9 @@ void HTTPServer::httpRecvReqCallback(struct evhttp_request *req, void *callbackD headers = evhttp_request_get_input_headers(req); for (header = headers->tqh_first; header; header = header->next.tqe_next) { request.data.compound["header"].compound[header->key] = Data(header->value, Data::VERBATIM); + raw << header->key << ": " << header->value << std::endl; } - - request.data.compound["remoteHost"] = Data(req->remote_host, Data::VERBATIM); - request.data.compound["remotePort"] = Data(toStr(req->remote_port), Data::VERBATIM); - request.data.compound["httpMajor"] = Data(toStr((unsigned short)req->major), Data::VERBATIM); - request.data.compound["httpMinor"] = Data(toStr((unsigned short)req->minor), Data::VERBATIM); - request.data.compound["uri"] = Data(HTTPServer::getBaseURL() + req->uri, Data::VERBATIM); - request.data.compound["path"] = Data(evhttp_uri_get_path(evhttp_request_get_evhttp_uri(req)), Data::VERBATIM); + raw << std::endl; // This was used for debugging // if (boost::ends_with(request.data.compound["path"].atom, ".png")) { @@ -207,6 +218,8 @@ void HTTPServer::httpRecvReqCallback(struct evhttp_request *req, void *callbackD } } + raw << request.data.compound["content"].atom; + // decode content if (request.data.compound.find("content") != request.data.compound.end() && request.data.compound["header"].compound.find("Content-Type") != request.data.compound["header"].compound.end()) { @@ -219,6 +232,8 @@ void HTTPServer::httpRecvReqCallback(struct evhttp_request *req, void *callbackD } } + request.raw = raw.str(); + if (callbackData == NULL) { HTTPServer::getInstance()->processByMatchingServlet(request); } else { |