#include #include "baseserv.h" #include #include #include wxString GetSoapParam(const TXmlItem &xmlMethod, const char* strParam) { wxString val; const TXmlItem* xml = xmlMethod.FindFirst(strParam); if (xml != NULL) val = xml->GetEnclosedText(); return val; } /////////////////////////////////////////////////////////// // TRecord // Tabella di database con 1 o piu' viste in base alla chiave /////////////////////////////////////////////////////////// class TRecord : public wxObject { private: wxArrayString m_Fields; wxString m_strLocker; // User locking the record bool m_bDeleted; public: bool Locked() const { return !m_strLocker.IsEmpty(); } const wxString& LockedBy() const { return m_strLocker; } bool Deleted() const { return m_bDeleted; } void MarkAsDeleted() { m_bDeleted = true; } void MarkAsUndeleted() { m_bDeleted = false; } void Add(const wxString& strValue) { m_Fields.Add(strValue); } const wxString& operator[] (size_t i) const { return m_Fields[i]; } wxString& operator[] (size_t i) { return m_Fields[i]; } }; /////////////////////////////////////////////////////////// // TArrayObject /////////////////////////////////////////////////////////// WX_DEFINE_ARRAY(wxObject*, TArrayObject); /////////////////////////////////////////////////////////// // TIndexEntry /////////////////////////////////////////////////////////// struct TIndexEntry : public wxObject { wxString m_strkey; long m_nRecno; }; /////////////////////////////////////////////////////////// // TIndex /////////////////////////////////////////////////////////// class TIndex : public wxObject { enum { MAX_KEY_ENTRIES = 8 }; int m_nField[MAX_KEY_ENTRIES]; int m_nSize[MAX_KEY_ENTRIES]; bool m_bUpper[MAX_KEY_ENTRIES]; int m_nKeyFields; TArrayObject m_ndx; protected: void AddRecord(const TRecord& rec, long recno); long FindPosition(long recno) const; public: void AddKeyField(int nPos, int nSize, bool upper); long FindPosition(const wxString& key) const; long SkipTo(long recno, long offset) const; void Update(const TArrayObject& records); bool Ok() const { return m_nKeyFields > 0; } long GetCount() const { return m_ndx.GetCount(); } TIndex(); }; void TIndex::AddKeyField(int nPos, int nSize, bool upper) { if (m_nKeyFields < MAX_KEY_ENTRIES) { m_nField[m_nKeyFields] = nPos; m_nSize[m_nKeyFields] = nPos; m_bUpper[m_nKeyFields] = upper; m_nKeyFields++; } } long TIndex::FindPosition(const wxString& key) const { int nFirst = 0; int nLast = m_ndx.GetCount()-1; while (nFirst <= nLast) { const int nCurr = (nFirst + nLast) / 2; const int nCmp = ((TIndexEntry*)m_ndx[nCurr])->m_strkey.Cmp(key); if (nCmp == 0) return nCurr; if (nCmp > 0) nLast = nCurr-1; if (nCmp < 0) nFirst = nCurr+1; } return nFirst; } long TIndex::FindPosition(long recno) const { long i; for (i = m_ndx.GetCount()-1; i >= 0; i--) if (((TIndexEntry*)m_ndx[i])->m_nRecno == recno) break; return i; } long TIndex::SkipTo(long recno, long offset) const { const long tot = m_ndx.GetCount(); long i = 0; if (tot > 0) { if (recno == 0) // Goto first i = ((TIndexEntry*)m_ndx[0])->m_nRecno; else if (recno < 0) // Goto last i = ((TIndexEntry*)m_ndx[tot-1])->m_nRecno; else { const long p = FindPosition(recno) + offset; if (p >= 0 && p < tot) i = ((TIndexEntry*)m_ndx[p])->m_nRecno; } } return i; } void TIndex::AddRecord(const TRecord& rec, long recno) { TIndexEntry* e = new TIndexEntry; e->m_nRecno = recno; for (int i = 0; i < m_nKeyFields; i++) { const char* val = rec[m_nField[i]]; if (m_bUpper[i]) { e->m_strkey.Printf("%*s", -m_nSize[i], val); e->m_strkey.Upper(); } else e->m_strkey.Printf("%*s", m_nSize[i], val); } const int nPos = FindPosition(e->m_strkey); m_ndx.Insert(e, nPos); } void TIndex::Update(const TArrayObject& records) { WX_CLEAR_ARRAY(m_ndx); for (size_t i = 0; i < records.GetCount(); i++) AddRecord(*((TRecord*)records[i]), i+1); } TIndex::TIndex() : m_nKeyFields(0) { } /////////////////////////////////////////////////////////// // TTable // Tabella di database con 1 o piu' viste in base alla chiave /////////////////////////////////////////////////////////// class TTable : public wxObject { wxDbColInf* m_ci; wxDbTable* m_table; UWORD m_nColumns; char* m_field[128]; TArrayObject m_Records, m_Indexes; long m_nCurrent; protected: void KillRecordSet(); bool FillRecordSet(); bool GoTo(long& recno); int FindColumn(const char* name) const; public: long Rows(int index) const; void GetRecord(long recno, wxOutputStream& out); void GetRecordLength(wxOutputStream& out); bool CreateIndex(int index, const TXmlItem& fields); TIndex& Index(int n); bool ok() const { return m_nColumns > 0; } TTable(wxDb* db, const wxString& strName); virtual ~TTable(); }; long TTable::Rows(int index) const { const TIndex& idx = ((TTable*)this)->Index(index); return idx.Ok() ? idx.GetCount() : m_Records.GetCount(); } bool TTable::GoTo(long& rec) { const long tot = m_Records.GetCount(); bool ok = false; if (rec < 0) // -1 = last record rec = tot + rec + 1; if (rec > 0 && rec <= tot) { m_nCurrent = rec; ok = true; } return ok; } void TTable::GetRecord(long recno, wxOutputStream& out) { if (GoTo(recno)) { const TRecord& record = *((TRecord*)m_Records[m_nCurrent-1]); TXmlItem rec; rec.SetTag("Record"); rec.SetAttr("RecNo", recno); for (UWORD c = 0; c < m_nColumns; c++) { const wxString& str = record[c]; if (!str.IsEmpty() && str != "1899-12-30") rec.AddSoapString("Field", str).SetAttr("Name", m_ci[c].colName); } rec.Write(out, 2); } } void TTable::GetRecordLength(wxOutputStream& out) { int len = 0; for (UWORD i = 0; i < m_nColumns; i++) { const wxDbColInf& ci = m_ci[i]; switch (ci.sqlDataType) { case SQL_C_DATE: len += 8; break; default: if (ci.bufferSize > 128) // It's a MEMO! len += 10; else len += ci.bufferSize; break; } } out << wxString::Format("%d", len); } int TTable::FindColumn(const char* name) const { int i = m_nColumns-1; for ( ; i >= 0; i--) { if (wxStricmp(m_ci[i].colName, name) == 0) break; } return i; } TIndex& TTable::Index(int index) { if (index < 0 || index > 8) index = 0; for (int i = m_Indexes.GetCount(); i <= index; i++) m_Indexes.Add(new TIndex); return *((TIndex*)m_Indexes[index]); } bool TTable::CreateIndex(int index, const TXmlItem& fields) { TIndex& ndx = Index(index); if (!ndx.Ok()) { for (int c = 0; c < fields.GetChildren(); c++) { const TXmlItem& field = *fields.GetChild(c); if (field.GetTag() == "Field") { const int i = FindColumn(field.GetAttr("Name")); if (i >= 0) { const bool upper = !field.GetAttr("Upper").IsEmpty(); ndx.AddKeyField(i, m_ci[i].bufferSize, upper); } } } ndx.Update(m_Records); } return ndx.Ok(); } void TTable::KillRecordSet() { WX_CLEAR_ARRAY(m_Records); m_Records.Clear(); } bool TTable::FillRecordSet() { KillRecordSet(); const bool ok = m_table->Query(); if (ok) { while (m_table->GetNext()) { TRecord* rec = new TRecord; for (UWORD i = 0; i < m_nColumns; i++) { char* spc = NULL; for (char* c = m_field[i]; *c; c++) { if (*c == ' ') { if (spc == NULL) spc = c; } else spc = NULL; } if (spc != NULL) *spc = '\0'; rec->Add(m_field[i]); } m_Records.Add(rec); } } for (size_t i = 1; i < m_Indexes.GetCount(); i++) { TIndex& ndx = Index(i); if (ndx.Ok()) ndx.Update(m_Records); } return ok; } TTable::TTable(wxDb* db, const wxString& strName) { m_ci = db->GetColumns(strName, &m_nColumns); m_table = new wxDbTable(db, strName, m_nColumns, strName, false); // Bind columns for (UWORD i = 0; i < m_nColumns; i++) { const wxDbColInf& ci = m_ci[i]; const int length = ci.bufferSize+1; m_field[i] = new char[length]; memset(m_field[i], 0, length); int nSqlType = ci.sqlDataType; if (nSqlType <= 0 || nSqlType == 2) nSqlType = SQL_C_CHAR; m_table->SetColDefs(i, ci.colName, DB_DATA_TYPE_VARCHAR, m_field[i], nSqlType, length); } if (m_table->Open(false, false)) { if (!FillRecordSet()) GetServerApp().WriteLog(wxString::Format("Can't query table %s", strName.c_str())); } else GetServerApp().WriteLog(wxString::Format("Can't open table %s", strName.c_str())); m_nCurrent = 0; // Before the first } TTable::~TTable() { KillRecordSet(); delete m_table; for (UWORD i = 0; m_field[i] != NULL; i++) delete m_field[i]; delete m_ci; } /////////////////////////////////////////////////////////// // TDataBase // Database di dati comuni (COM) o di DITTA (00001A, ecc...) /////////////////////////////////////////////////////////// class TDataBase : public wxHashTable { wxDbConnectInf m_ci; wxDb* m_db; public: bool Open(const wxString& dsn, const wxString& user, const wxString& password); bool IsOpen() const; void Close(); wxDb& DataBase() { return *m_db; } TTable* Table(const wxString& strName); TDataBase(); virtual ~TDataBase(); }; bool TDataBase::Open(const wxString& dsn, const wxString& user, const wxString& password) { Close(); m_ci.SetDsn(dsn); m_ci.SetUserID(user); m_ci.SetPassword(password); if (m_ci.AllocHenv()) { m_db = ::wxDbGetConnection(&m_ci, false); // Forward only? if (m_db == NULL) m_ci.FreeHenv(); else { const wxString strLog = GetServerApp().GetLogFileName(); if (!strLog.IsEmpty()) m_db->SetSqlLogging(sqlLogON, strLog, TRUE); } } return IsOpen(); } void TDataBase::Close() { if (m_db) { m_db->SetSqlLogging(sqlLogOFF); ::wxDbFreeConnection(m_db); m_db = NULL; m_ci.FreeHenv(); } } bool TDataBase::IsOpen() const { return m_db != NULL; } TTable* TDataBase::Table(const wxString& strName) { TTable* s = (TTable*)Get(strName); if (s == NULL) { s = new TTable(m_db, strName); if (s->ok()) Put(strName, s); } return s; } TDataBase::TDataBase() : wxHashTable(wxKEY_STRING), m_db(NULL) { m_ci.Henv = 0; DeleteContents(true); } TDataBase::~TDataBase() { Close(); } /////////////////////////////////////////////////////////// // TStudy // Elenco di Databases: COM, 00001A, 00002A, ecc... /////////////////////////////////////////////////////////// class TStudy : public wxHashTable { wxString m_strUser, m_strPass; wxString m_strName; public: TDataBase& DB(long firm); // 0 = COM TStudy(const char* strName, const char* strUser, const char* strPass); }; TDataBase& TStudy::DB(long firm) { TDataBase* db = (TDataBase*)Get(firm); if (db == NULL) { wxString strDsn, strPath; if (firm > 0) strDsn.sprintf("%s_%05lda", m_strName.c_str(), firm); else strDsn.sprintf("%s_COM", m_strName.c_str()); db = new TDataBase; db->Open(strDsn, m_strUser, m_strPass); Put(firm, db); } return *db; } TStudy::TStudy(const char* strName, const char* strUser, const char* strPass) : wxHashTable(wxKEY_INTEGER), m_strUser(strUser), m_strPass(strPass), m_strName(strName) { DeleteContents(true); } /////////////////////////////////////////////////////////// // TCommercialist /////////////////////////////////////////////////////////// class TCommercialist : public wxHashTable { wxString m_strUser, m_strPass; // User impersonated by the TCommenrcialist public: const wxString& User() const { return m_strUser; } const wxString& Password() const { return m_strPass; } TStudy& Study(const wxString& strStudy); TTable* Table(const TXmlItem& item); TCommercialist(); }; TStudy& TCommercialist::Study(const wxString& strStudy) { TStudy* s = (TStudy*)Get(strStudy); if (s == NULL) { if (m_strUser.IsEmpty()) { TBaseServerApp& a = GetServerApp(); m_strUser = a.GetConfigString("User", "ADMIN"); m_strPass = a.GetConfigString("Password", "AD.MIN"); } s = new TStudy(strStudy, m_strUser, m_strPass); Put(strStudy, s); } return *s; } TTable* TCommercialist::Table(const TXmlItem& xmlMethod) { TTable* tab = NULL; const wxString strStudy = GetSoapParam(xmlMethod, "Study"); const long nFirm = atol(GetSoapParam(xmlMethod, "Firm")); TStudy& study = Study(strStudy); TDataBase& firm = study.DB(nFirm); if (firm.IsOpen()) { const wxString strTable = GetSoapParam(xmlMethod, "Table"); tab = firm.Table(strTable); } return tab; } TCommercialist::TCommercialist() { DeleteContents(true); } /////////////////////////////////////////////////////////// // TDataBaseServer /////////////////////////////////////////////////////////// class TDataBaseServer : public TBaseServerApp { TCommercialist m_caminetti; protected: virtual const wxChar* GetAppName() const; virtual void ProcessCommand(wxString cmd, wxSocketBase& outs); virtual bool Initialization(); virtual bool Deinitialization(); protected: void AddAsterisk(const wxString& strField, const wxString& strQuery, TDataBase& db, wxArrayString& arr); wxString ParseQuery(const wxString& strOriginalQuery, TDataBase& db, wxArrayString& arr); void WriteTable(wxString strDsn, wxString strUser, wxString strPass, wxString strOriginalQuery, wxOutputStream& out); void SoapProcessMethod(const TXmlItem& xmlMethod, wxOutputStream& out); void SoapProcessQuery(const TXmlItem &xmlMethod, wxOutputStream& out); void SoapProcessTableRows(const TXmlItem &xmlMethod, wxOutputStream& out); void SoapProcessGetRecord(const TXmlItem &xmlMethod, wxOutputStream& out); void SoapProcessGetRecordLength(const TXmlItem &xmlMethod, wxOutputStream& out); void SoapProcessCreateIndex(const TXmlItem &xmlMethod, wxOutputStream& out); void SoapProcessSkipRecord(const TXmlItem &xmlMethod, wxOutputStream& out); public: bool IsMagicName(wxString& strFilename) const; void ProcessFormQuery(const wxString& strFileName, THashTable& hashArgs); void ProcessFormCommand(wxString cmd, wxSocketBase& outs); void ProcessSoapCommand(wxString cmd, wxSocketBase& outs); void GenerateIndex(wxString& strFilename); void GenerateSql(wxString& strFilename); void GenerateFile(wxString& strFilename); }; // Implementare almeno queste due funzioni pure virtuali const wxChar* TDataBaseServer::GetAppName() const { return "DataBase"; } bool TDataBaseServer::IsMagicName(wxString& strFilename) const { wxString strName; wxSplitPath(strFilename, NULL, &strName, NULL); strName.MakeLower(); const int q = strName.Find('?'); if (q > 0) strName.Truncate(q); if (strName == "index" || strName == "sql") { strFilename = strName; return true; } if (strName == "log") { strFilename = GetLogFileName(); } return false; } void TDataBaseServer::GenerateIndex(wxString& strFilename) { TXmlItem html; TXmlItem& body = CreatePageBody(html).AddChild("center"); TXmlItem& table = body.AddChild("table"); table.SetAttr("border", "1"); table.SetAttr("width", "70%"); TXmlItem& tr0 = body.AddChild("tr"); TXmlItem& aq = tr0.AddChild("td").AddChild("a"); aq.SetAttr("href", "sql.htm"); aq << "SQL query"; tr0.AddChild("td") << "Perform any SQL query on the selected Data Source"; TXmlItem& tr1 = body.AddChild("tr"); TXmlItem& al = tr1.AddChild("td").AddChild("a"); al.SetAttr("href", "Log"); al << "Log File"; tr1.AddChild("td") << "Display current server log"; TXmlItem& tr2 = body.AddChild("tr"); TXmlItem& as = tr2.AddChild("td").AddChild("a"); as.SetAttr("href", "stop.cgi"); as << "Stop"; tr2.AddChild("td") << "Stop this database server"; strFilename = GetTempFilename(); html.Save(strFilename); } void TDataBaseServer::GenerateSql(wxString& strFilename) { TXmlItem html; TXmlItem& body = CreatePageBody(html).AddChild("center"); TXmlItem& form = body.AddChild("form"); form.SetAttr("method", "post"); form.SetAttr("action", "Query.cgi"); TXmlItem& table = form.AddChild("table").SetAttr("width", "70%"); TXmlItem& tr0 = table.AddChild("tr"); tr0.AddChild("td") << "Data Source Name"; TXmlItem& dsn = tr0.AddChild("td").AddChild("input"); dsn.SetAttr("type", "string"); dsn.SetAttr("name", "Dsn"); dsn.SetAttr("value", GetConfigString("Dsn")); TXmlItem& tr1 = table.AddChild("tr"); tr1.AddChild("td") << "User"; TXmlItem& user = tr1.AddChild("td").AddChild("input"); user.SetAttr("type", "string"); user.SetAttr("name", "User"); user.SetAttr("value", GetConfigString("User")); TXmlItem& tr2 = table.AddChild("tr"); tr2.AddChild("td") << "Password"; TXmlItem& pass = tr2.AddChild("td").AddChild("input"); pass.SetAttr("type", "password"); pass.SetAttr("name", "User"); form.AddChild("br"); form.AddChild("h3") << "SQL query:"; TXmlItem& q = form.AddChild("textarea"); q.SetAttr("name", "Sql"); q.SetAttr("cols", "80"); q.SetAttr("rows", "10"); wxString query = GetConfigString("Sql"); q << query; form.AddChild("br"); form.AddChild("br"); TXmlItem& sub = form.AddChild("input"); sub.SetAttr("type", "submit"); sub.SetAttr("value", "Execute"); AddLinkButton(body, "Return to main page", "/"); strFilename = GetTempFilename(); html.Save(strFilename); } void TDataBaseServer::GenerateFile(wxString& strFilename) { wxString strName, strArgs; wxSplitPath(strFilename, NULL, &strName, NULL); strName.MakeLower(); const int q = strFilename.Find('?'); if (q > 0) strArgs = strFilename.Mid(q+1); if (strName == "index") GenerateIndex(strFilename); else if (strName == "sql") GenerateSql(strFilename); else if (strName == "log") strFilename = GetLogFileName(); } void TDataBaseServer::AddAsterisk(const wxString& strField, const wxString& strQuery, TDataBase& db, wxArrayString& arr) { wxString strTable; const int nDot = strField.Find(".*"); if (nDot < 0) { const int nFrom = strQuery.Find("FROM "); if (nFrom > 0) strTable = strQuery.Mid(nFrom+5); const int nComma = strTable.Find(','); const int nSpace = strTable.Find(' '); int nTrunc = strTable.Length(); if (nComma > 0) nTrunc = nComma; if (nSpace > 0 && nSpace < nTrunc) nTrunc = nSpace; strTable.Truncate(nTrunc); } else strTable = strField.Left(nDot); strTable.Trim(false); strTable.Trim(true); UWORD numCols; wxDbColInf* dci = db.DataBase().GetColumns(strTable, &numCols); wxString strFieldName; for (UWORD i = 0; i < numCols; i++) { if (strField == "*") strFieldName = dci[i].colName; else { strFieldName = strTable; strFieldName += "."; strFieldName += dci[i].colName; } arr.Add(strFieldName); } delete dci; } wxString TDataBaseServer::ParseQuery(const wxString& strOriginalQuery, TDataBase& db, wxArrayString& arr) { wxString strQuery; const int nSelect = strOriginalQuery.Find("SELECT "); const int nFrom = strOriginalQuery.Find("FROM "); if (nSelect >= 0 && nFrom > nSelect) { wxString strFields = strOriginalQuery.Mid(nSelect+7, nFrom-nSelect-7); strFields.Trim(false); strFields.Trim(true); while(!strFields.IsEmpty()) { const int nComma = strFields.Find(','); wxString strField = nComma < 0 ? strFields : strFields.Mid(0, nComma); strField.Trim(); strField.Trim(false); if (strField.Find("*") >= 0) AddAsterisk(strField, strOriginalQuery, db, arr); else arr.Add(strField); if (nComma > 0) strFields = strFields.Mid(nComma+1); else break; } strQuery = "SELECT "; for (size_t i = 0; i < arr.GetCount(); i++) { if (i > 0) strQuery << ","; strQuery << arr[i]; } strQuery << strOriginalQuery.Mid(nFrom-1); } else strQuery = strOriginalQuery; return strQuery; } void TDataBaseServer::WriteTable(wxString strDsn, wxString strUser, wxString strPass, wxString strOriginalQuery, wxOutputStream& out) { const clock_t tTotalStart = clock(); clock_t tQueryTime = 0; clock_t tRetrieveTime = 0; clock_t tTotalTime = 0; size_t nRecords = 0; out << "\n"; if (strDsn.IsEmpty()) strDsn = GetConfigString("DataPath"); if (strUser.IsEmpty()) strUser = GetConfigString("User"); if (strPass.IsEmpty()) strPass = GetConfigString("Password"); TStudy s(strDsn, strUser, strPass); TDataBase& d = s.DB(0); // Ditta/COM if (d.IsOpen()) { wxArrayString arr; const wxString strQuery = ParseQuery(strOriginalQuery, d, arr); wxDb& db = d.DataBase(); const clock_t tQueryStart = clock(); db.ExecSql(strQuery); tQueryTime = clock() - tQueryStart; const int nColumns = arr.GetCount(); if (nColumns > 0) { out << " \n"; for (int i = 0; i < nColumns; i++) out << " \n"; out << " \n"; const int bufsize = 33000; wxChar* buffer = new wxChar[bufsize]; const clock_t tRetrieveStart = clock(); for (nRecords = 0; db.GetNext(); nRecords++) { out << " \n"; for (int c = 1; c <= nColumns; c++) { SDWORD cb; if (db.GetData(c, SQL_C_CHAR, buffer, bufsize, &cb)) { if (strcmp(buffer, "1899-12-30") == 0) *buffer = '\0'; out << " \n"; } else break; } out << " \n"; } delete buffer; tRetrieveTime = clock() - tRetrieveStart; } } out << "
" << arr[i] << "
" << buffer << "
\n"; tTotalTime = clock() - tTotalStart; WriteLog(wxString::Format("--- %u Records. Query:%u Retrieve:%u Total:%u", nRecords, (unsigned int) tQueryTime, (unsigned int) tRetrieveTime, (unsigned int) tTotalTime)); } void TDataBaseServer::ProcessFormQuery(const wxString& strFileName, THashTable& hashArgs) { const wxString strDsn = hashArgs.Get("DSN"); const wxString strUser = hashArgs.Get("User"); const wxString strPass = hashArgs.Get("Password"); const wxString strOriginalQuery = hashArgs.Get("SQL"); SetConfigString("DSN", strDsn); SetConfigString("User", strUser); wxString strQuery = strOriginalQuery; strQuery.Replace("\r\n", " "); SetConfigString("SQL", strQuery); wxFileOutputStream out(strFileName); out << "\n"; out << "\n"; WriteTable(strDsn, strUser, strPass, strOriginalQuery, out); out << "\n"; out << "\n"; } void TDataBaseServer::ProcessFormCommand(wxString cmd, wxSocketBase& outs) { const int stop = cmd.Find(" HTTP"); wxString strFileName = cmd.Mid(5, stop-5).Trim(); wxString strName, args; wxSplitPath(strFileName, NULL, &strName, NULL); const int pos = cmd.Find("\r\n\r\n"); if (pos > 0) args = cmd.Mid(pos+4); THashTable hashArgs(13); ParseArguments(args, hashArgs); strFileName = GetTempFilename(); if (strName == "Query") ProcessFormQuery(strFileName, hashArgs); SendFile(strFileName, outs); } void TDataBaseServer::SoapProcessQuery(const TXmlItem &xmlMethod, wxOutputStream& out) { const wxString dsn = GetSoapParam(xmlMethod, "DSN"); const wxString usr = GetSoapParam(xmlMethod, "User"); const wxString pwd = GetSoapParam(xmlMethod, "Password"); const wxString sql = GetSoapParam(xmlMethod, "SQL"); WriteTable(dsn, usr, pwd, sql, out); } void TDataBaseServer::SoapProcessTableRows(const TXmlItem &xmlMethod, wxOutputStream& out) { TTable* tab = m_caminetti.Table(xmlMethod); if (tab != NULL) { const int index = atoi(GetSoapParam(xmlMethod, "Index")); out << wxString::Format("%ld", tab->Rows(index)); } } void TDataBaseServer::SoapProcessGetRecord(const TXmlItem &xmlMethod, wxOutputStream& out) { TTable* tab = m_caminetti.Table(xmlMethod); if (tab != NULL) { const long recno = atol(GetSoapParam(xmlMethod, "RecNo")); tab->GetRecord(recno, out); } } void TDataBaseServer::SoapProcessSkipRecord(const TXmlItem &xmlMethod, wxOutputStream& out) { TTable* tab = m_caminetti.Table(xmlMethod); if (tab != NULL) { const int index = atoi(GetSoapParam(xmlMethod, "Index")); const long recno = atol(GetSoapParam(xmlMethod, "RecNo")); const long offset = atol(GetSoapParam(xmlMethod, "Offset")); const long newrecno = tab->Index(index).SkipTo(recno, offset); tab->GetRecord(newrecno, out); } } void TDataBaseServer::SoapProcessGetRecordLength(const TXmlItem &xmlMethod, wxOutputStream& out) { TTable* tab = m_caminetti.Table(xmlMethod); if (tab != NULL) tab->GetRecordLength(out); } void TDataBaseServer::SoapProcessCreateIndex(const TXmlItem &xmlMethod, wxOutputStream& out) { TTable* tab = m_caminetti.Table(xmlMethod); if (tab != NULL) { const int index = atoi(GetSoapParam(xmlMethod, "Index")); const bool ok = index > 0 && tab->CreateIndex(index, xmlMethod); out << (ok ? "1" : "0"); } } void TDataBaseServer::SoapProcessMethod(const TXmlItem &xmlMethod, wxOutputStream& out) { const wxString strTag = xmlMethod.GetTag(); wxString str = strTag; str << "Result"; out << "<" << str << ">\n"; if (strTag == "m:GetRecord") SoapProcessGetRecord(xmlMethod, out); else if (strTag == "m:SkipRecord") SoapProcessSkipRecord(xmlMethod, out); else if (strTag == "m:GetRecordLength") SoapProcessGetRecordLength(xmlMethod, out); else if (strTag == "m:TableRows") SoapProcessTableRows(xmlMethod, out); else if (strTag == "m:CreateIndex") SoapProcessCreateIndex(xmlMethod, out); else if (strTag == "m:Query") SoapProcessQuery(xmlMethod, out); out << "\n"; } void TDataBaseServer::ProcessSoapCommand(wxString cmd, wxSocketBase& sock) { wxMemoryOutputStream outf; outf << "\n\n"; const int soapstart = cmd.Find(" 0) { const size_t soaplen = cmd.length() - soapstart; const char* buff = (const char*)cmd; buff += soapstart; wxMemoryInputStream input(buff, 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:")) { SoapProcessMethod(*pxmlMethod, outf); } } } } outf << "\n\n"; const size_t nSize = outf.GetSize(); char* mem = new char[nSize]; outf.CopyTo(mem, nSize); sock << "HTTP/1.1 200 OK\n"; sock << "Server: " << GetAppName() << "\n"; sock << "Host: " << wxGetFullHostName() << "\n"; sock << "Connection: keep-alive\n"; sock << "Content-Type: text/xml; charset=utf-8\n"; sock << "Content-Length: " << nSize << "\n"; sock << "Date: " << wxDateTime::Now().Format("%#c") << "\n"; sock << "\n" << mem; delete mem; } void TDataBaseServer::ProcessCommand(wxString cmd, wxSocketBase& outs) { if (cmd.StartsWith("GET ")) { const int stop = cmd.Find(" HTTP"); wxString str = cmd.Mid(4, stop-4).Trim(); if (str == "/") str += "index.htm"; wxString strFilename = GetDocumentRoot() + str; if (IsMagicName(strFilename)) GenerateFile(strFilename); else { const int ims = cmd.Find("If-Modified-Since: "); if (ims > 0) { const wxString strDate = cmd.Mid(ims+19, 24); wxDateTime tIms; if (tIms.ParseDateTime(strDate)) { const wxDateTime tFile = ::wxFileModificationTime(strFilename); if (tFile <= tIms) { SendNotModifiedFile(outs); return; } } } } SendFile(strFilename, outs); } else if (cmd.StartsWith("POST ")) { if (cmd.Find("SOAPAction") > 0) ProcessSoapCommand(cmd, outs); else ProcessFormCommand(cmd, outs); } } bool TDataBaseServer::Initialization() { return true; } bool TDataBaseServer::Deinitialization() { wxDbCloseConnections(); return true; } // Istanziare l'applicazione principale IMPLEMENT_APP(TDataBaseServer)