#include "wx/wx.h" #include "wx/time.h" #include "soap.h" /////////////////////////////////////////////////////////// // Utility /////////////////////////////////////////////////////////// wxOutputStream& operator<<(wxOutputStream& outf, const wxChar* str) { if (str && *str) outf.Write(str, wxStrlen(str)); return outf; } wxOutputStream& operator<<(wxOutputStream& outf, const wxString str) { if (!str.IsEmpty()) outf.Write(str, str.Length()); return outf; } void Spaces(wxOutputStream& outf, int nSpaces) { outf << "\n"; if (nSpaces > 0) { wxString str; str.Append(' ', nSpaces); outf << str; } } /////////////////////////////////////////////////////////// // TXmlAttr /////////////////////////////////////////////////////////// class TXmlAttr : public wxObject { public: wxString m_str; void Write(wxOutputStream& outf) const; TXmlAttr(const wxChar* str) : m_str(str) { } }; void TXmlAttr::Write(wxOutputStream& outf) const { if (m_str.IsNumber()) outf << m_str; else outf << "\"" << m_str << "\""; } /////////////////////////////////////////////////////////// // TXmlItem /////////////////////////////////////////////////////////// void TXmlItem::SetAttr(const wxChar* strAttr, const wxChar* strVal) { if (m_Attributes == NULL) { m_Attributes = new wxHashTable(wxKEY_STRING, 17); m_Attributes->DeleteContents(true); } m_Attributes->Delete(strAttr); m_Attributes->Put(strAttr, new TXmlAttr(strVal)); } wxString TXmlItem::GetAttr(const wxChar* strAttr) const { wxString strResult; if (m_Attributes != NULL) { const TXmlAttr* str = (const TXmlAttr*)m_Attributes->Get(strAttr); if (str != NULL) strResult = str->m_str; } return strResult; } int TXmlItem::GetChildren() const { int n = 0; if (m_Children != NULL) n = m_Children->GetCount(); return n; } TXmlItem* TXmlItem::GetChild(size_t n) const { TXmlItem* i = NULL; if (m_Children != NULL && n < m_Children->GetCount()) { wxNode* pNode = m_Children->Item(n); if (pNode != NULL) i = (TXmlItem*)pNode->GetData(); } return i; } wxString TXmlItem::GetWord(wxInputStream& inf) const { wxString str; int cFirstChar = EOF; while (!inf.Eof()) { cFirstChar = inf.GetC(); if (cFirstChar <= 0 || cFirstChar > ' ') break; } if (cFirstChar == EOF) return str; const bool bIsString = cFirstChar == '"' || cFirstChar == '\''; if (bIsString) str = ""; else { str = char(cFirstChar); if (strchr("<=/>", cFirstChar)) return str; // Simboli terminali } while (!inf.Eof()) { int c = inf.GetC(); if (bIsString) { if (c == cFirstChar) break; if (c >= '\0' && c <= ' ') c = ' '; str += char(c); } else { if (c >= '\0' && c <= ' ') break; if (strchr("<=/>", c)) { inf.Ungetch(char(c)); break; } str += char(c); } } return str; } int TXmlItem::ReadTag(wxInputStream& inf) { wxString str = GetWord(inf); if (str.IsEmpty()) return -1; if (str[0] != '<') // No tag = sequence of words { bool bFirstChar = true; while (!inf.Eof()) { const wxChar c = inf.GetC(); if (c == '<') { inf.Ungetch(c); break; } if (bFirstChar) { str << ' '; bFirstChar = false; } str << c; } SetTag(""); SetText(str); return 0; } bool bChildrenFollow = true; m_strTag = GetWord(inf); if (m_strTag == "/") // Sto leggendo un tag di chiusura del tipo { bChildrenFollow = false; m_strTag += GetWord(inf); } wxString name = GetWord(inf); while (!name.IsEmpty()) { if (name[0] == '>') return bChildrenFollow ? +1 : 0; if (name[0] == '/') { bChildrenFollow = false; continue; } // Ho letto un nome di attributo wxString str = GetWord(inf); if (str.IsEmpty() || str[0] != '=') break; // Leggo il valore dell'attributo str = GetWord(inf); SetAttr(name, str); name = GetWord(inf); } return -1; } TXmlItem& TXmlItem::AddChild(TXmlItem* pItem) { if (m_Children == NULL) { m_Children = new wxList; m_Children->DeleteContents(true); } if (pItem == NULL) pItem = new TXmlItem; m_Children->Append(pItem); return *pItem; } TXmlItem& TXmlItem::AddChild(const wxChar* strTagName) { TXmlItem& i = AddChild((TXmlItem*)NULL); i.SetTag(strTagName); return i; } TXmlItem& TXmlItem::AddSoapString(const wxChar* name, const wxChar* value, bool typized) { TXmlItem& xmlVar = AddChild(name); if (typized) xmlVar.SetAttr("xsi:type", "xsd:string"); xmlVar.AddChild("").SetText(value); return xmlVar; } TXmlItem& TXmlItem::AddSoapInt(const wxChar* name, int value, bool typized) { TXmlItem& xmlVar = AddChild(name); if (typized) xmlVar.SetAttr("xsi:type", "xsd:int"); wxString str; str += value; xmlVar.AddChild("").SetText(str); return xmlVar; } void TXmlItem::RemoveLastChild() { if (m_Children != NULL) { wxNode* n = m_Children->GetLast(); if (n != NULL) m_Children->DeleteNode(n); } } bool TXmlItem::Read(wxInputStream& inf) { const int res = ReadTag(inf); if (res > 0) // There are children ahead { while (!inf.Eof()) { TXmlItem& item = AddChild("/"); // Add dummy child if (item.Read(inf)) { if (item.m_strTag[0] == '/') break; } else break; } RemoveLastChild(); // Remove dummy child } return res >= 0; } TXmlItem* TXmlItem::ForEach(XmlItemCallback cb, long jolly) { if (cb(*this, jolly)) return this; for (int n = 0; ; n++) { TXmlItem* c = GetChild(n); if (c == NULL) break; c = c->ForEach(cb, jolly); if (c) return c; } return NULL; } static bool GetEnclosedTextCallback(TXmlItem& item, long jolly) { wxString* strText = (wxString*)jolly; const wxString& str = item.GetText(); if (!str.IsEmpty()) { if (!strText->IsEmpty()) *strText << " "; *strText << str; } return false; } wxString TXmlItem::GetEnclosedText() const { wxString text; ((TXmlItem*)this)->ForEach(GetEnclosedTextCallback, (long)&text); return text; } void TXmlItem::Write(wxOutputStream& outf, int tab) const { if (!GetTag().IsEmpty()) { Spaces(outf, tab); outf << "<" << GetTag(); if (m_Attributes != NULL) { m_Attributes->BeginFind(); for (wxNode* pNode = m_Attributes->Next(); pNode; pNode = m_Attributes->Next()) { outf << " " << pNode->GetKeyString() << "="; const TXmlAttr* attr = (const TXmlAttr*)pNode->GetData(); attr->Write(outf); } } if (GetChildren() > 0) { outf << ">"; for (int n = 0; ; n++) { TXmlItem* c = GetChild(n); if (c == NULL) break; c->Write(outf, tab+1); } if (GetChild(n-1)->GetText().IsEmpty()) Spaces(outf, tab); outf << ""; } else outf << " />"; } else outf << GetText(); } wxString TXmlItem::AsString() const { wxString str; for (size_t nSize = 8192; ; nSize *= 2) { char* buf = str.GetWriteBuf(nSize); memset(buf, 0, nSize); wxMemoryOutputStream outf(buf, nSize); Write(outf); str.UngetWriteBuf(); if (buf[nSize-1] == '\0') break; } return str; } static bool FindFirstCallback(TXmlItem& item, long jolly) { const wxChar* strTag = (const wxChar*)jolly; return item.GetTag() == strTag; } TXmlItem* TXmlItem::FindFirst(const wxChar* strTag) const { return ((TXmlItem*)this)->ForEach(FindFirstCallback, (long)strTag); } TXmlItem::TXmlItem() : m_Attributes(NULL), m_Children(NULL) { } TXmlItem::~TXmlItem() { if (m_Attributes) delete m_Attributes; if (m_Children) delete m_Children; } /////////////////////////////////////////////////////////// // SoapProcess* /////////////////////////////////////////////////////////// #include "Diction.h" bool SoapProcessMethod(const TXmlItem& xmlMethod, TXmlItem& xmlAnswer) { const wxString& strMethod = xmlMethod.GetTag(); if (strMethod == "m:Translate") return DoTranslate(xmlMethod, xmlAnswer); return false; } wxString SoapProcessMessage(const char* buf, unsigned int len) { TXmlItem xmlEnvelope; xmlEnvelope.SetTag("SOAP-ENV:Envelope"); TXmlItem& xmlBody = xmlEnvelope.AddChild("SOAP-ENV:Body"); const char* soapstart = strstr(buf, "GetChild(m); if (pxmlMethod == NULL) break; if (pxmlMethod->GetTag().StartsWith("m:")) { wxString str = pxmlMethod->GetTag(); str += "Result"; TXmlItem& xmlAnswer = xmlBody.AddChild(str); SoapProcessMethod(*pxmlMethod, xmlAnswer); } } } } const wxString strResult = xmlEnvelope.AsString(); wxChar strLength[16]; sprintf(strLength, "%d", strResult.Length()); wxString strAnswer; strAnswer += "HTTP/1.1 200 OK\n"; strAnswer += "Connection: close\n"; strAnswer += "Content-Length: "; strAnswer += strLength; strAnswer += "\nContent-Type: text/xml; charset=utf-8\n"; strAnswer += "Date: "; strAnswer += wxDateTime::Now().Format("%#c"); strAnswer += "\nServer: "; strAnswer += wxGetHostName(); strAnswer += "\r\n\r\n"; strAnswer += strResult; return strAnswer; }