campo-sirio/server/soap.cpp

446 lines
8.8 KiB
C++
Raw Normal View History

#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 </SOAP-ENV>
{
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)
{
TXmlItem& xmlVar = AddChild(name);
xmlVar.SetAttr("xsi:type", "xsd:string");
xmlVar.AddChild("").SetText(value);
return xmlVar;
}
TXmlItem& TXmlItem::AddSoapInt(const wxChar* name, int value)
{
TXmlItem& xmlVar = AddChild(name);
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;
}
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 << "</" << GetTag() << ">";
}
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);
// outf << "<?xml Version=\"1.0\" ?>"; // Non dovrebbe servire a nulla
Write(outf);
str.UngetWriteBuf();
if (buf[nSize-1] == '\0')
break;
}
return str;
}
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, "<SOAP-ENV:");
if (soapstart != NULL)
{
const int soaplen = len - (soapstart - buf);
wxMemoryInputStream input(soapstart, soaplen);
TXmlItem query;
if (query.Read(input))
{
const TXmlItem* pxmlBody = query.FindFirst("SOAP-ENV:Body");
if (pxmlBody != NULL) for (int m = 0; ; m++)
{
const TXmlItem* pxmlMethod = pxmlBody->GetChild(m);
if (pxmlMethod == NULL)
break;
if (pxmlMethod->GetTag().StartsWith("m:"))
{
wxString str;
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;
}