#include "baseserv.h" #include "xml.h" #include #include #include #ifdef WIN32 #include #endif #define LF_TABGEN 3 #define LF_TABCOM 4 #define LF_TAB 5 ////////////////////////////////////////////////////////// // Date utilities /////////////////////////////////////////////////////////// static const byte _days_in_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int last_day(int month, int year) // parse_filastrok( // "trenta giorni ha novembre // con april, giugno e settembre // son ventotto case uno // per default ce n'ha trentuno"); { int d = _days_in_month[month-1]; if (month == 2 && (year % 4) == 0) d++; return d; } bool isdate(const wxChar * s) { const int len = strlen(s); if (len != 8 && len != 10) return false; int d = 0, m = 0, y = 0, i; if (len == 8) { for (i = 0; i < 8; i++) if (!isdigit(s[i])) break; if (i == 8) { wxString str(s); d = atoi(((const char *)str)+6); str[6] = '\0'; m = atoi(((const char *)str)+4); str[4] = '\0'; y = atoi(((const char *)str)+0); } } else if (len == 10) { if (s[2] == s[5] && !isdigit(s[2])) { d = atoi(s); m = atoi(&s[3]); y = atoi(&s[6]); } } if (d < 1 || d > 31 || m < 1 || m > 12 || y < 0) return false; return d <= last_day(m,y); } long date2ansi(const wxChar * s) { long val = 0L; const int len = (s && *s >= '0') ? strlen(s) : 0; if (len != 8 && len != 10) // Chi si azzarda ad aggiungere len != 6 ? return 0L; if (len == 8) { int i; for (i = 0; i < 8; i++) if (!isdigit(s[i])) break; if (i == 8) val = atol(s); } else { if (s[2] == s[5] && !isdigit(s[2])) { const int d = atoi(s); const int m = atoi(&s[3]); const int y = atoi(&s[6]); val = d + m + 100 + y * 10000; } } return val; } /////////////////////////////////////////////////////////// // TPostmanServer /////////////////////////////////////////////////////////// class TPostmanServer : public TBaseServerApp { wxArrayString m_Editors; wxArrayString m_FirmEditors; int m_Logicnum; int m_Firm; int m_LastFirm; wxArrayString m_TableName; int m_Err; wxString m_DataPath; protected: virtual void ProcessHttpGet(wxString cmd, wxSocketBase& outs); bool IsMagicName(wxString& strFilename) const; virtual const wxChar* GetAppName() const; void AbsoluteNameName(wxString & name); const wxString Table2Editor(const wxString & table); bool LoadEditors(const wxChar * filename, wxArrayString & editors); void SaveXml2IniParagraph(wxFileConfig & ini, TXmlItem& xmlItem); void SaveTransaction(const TXmlItem& xmlMethod, wxString & filename); void AdjustTransaction(wxString & filename); const wxString EditorCommand(); void ExecuteTransaction(wxString & filename); void LoadXmlParagraph(TXmlItem & xmlItem, wxString & paragraph, wxString & filename); void LoadTransaction(wxString & filename, TXmlItem & xmlAnswer); void Log(TXmlItem& xmlItem, wxString & filename); virtual void SoapProcessMethod(const TXmlItem& xmlMethod, TXmlItem& xmlAnswer); virtual int GetDefaultPort() const; public: virtual bool Initialization(); TPostmanServer() : m_Logicnum(0), m_Err(0), m_Firm(0), m_LastFirm(0) {} }; void TPostmanServer::ProcessHttpGet(wxString cmd, wxSocketBase& outs) { const int stop = cmd.Find(" HTTP"); wxString str = cmd.Mid(4, stop-4).Trim(); if (str == "/") str += "index.htm"; wxString strFilename = GetDocumentRoot() + str; IsMagicName(strFilename); SendFile(strFilename, outs); } bool TPostmanServer::IsMagicName(wxString& strFilename) const { wxFileName fnName(strFilename); wxString strName(fnName.GetName().Lower()); if (strName == "index" || strName == "log") { strFilename = GetLogFileName(); return true; } return false; } const wxString TPostmanServer::Table2Editor(const wxString & table) { wxString row; wxString module; wxString editor; wxString name; { name << "../recdesc/d" << table << ".des"; name.Lower(); wxFileName f(name); f.MakeAbsolute(); name = f.GetFullPath(); wxTextFile file(name); if (file.Open()) { for (row = file.GetFirstLine(); !file.Eof(); row = file.GetNextLine()) { row.Trim(false); if (row.StartsWith("Module")) { const int pos = row.Find("="); if (pos >= 0) module = row.Mid(pos + 1); module.Trim(); module.Trim(false); break; } } } } if (module.IsEmpty()) { module = "ba"; name = "../??tb"; name << table << ".msk"; name.Lower(); wxFileName f(name); f.MakeAbsolute(); name = f.GetFullPath(); wxString foundfile = ::wxFindFirstFile(name, wxFILE); while (!foundfile.IsEmpty()) { f = foundfile; wxString str(f.GetName().Left(2)); if (str != "ba") { module = str; break; } foundfile = ::wxFindNextFile(); } } wxFileName f("../install.ini"); f.MakeAbsolute(); name = f.GetFullPath(); wxTextFile file(name); wxString wmodule; if (file.Open()) { for (row = file.GetFirstLine(); !file.Eof(); row = file.GetNextLine()) { row.Trim(false); if (row.StartsWith("[")) wmodule = row.Mid(1, 2); else if (row.StartsWith("Edit_")) { const int pos = row.Find("="); if (pos >= 0) { const wxString table(row.Mid(5, pos - 4)); const int logicnum = atoi(table); if ((logicnum <= LF_TAB && module == wmodule) || table == m_TableName[m_Logicnum]) { editor = row.Mid(pos + 1); editor.Trim(false); editor << " "; if (m_Logicnum == LF_TABGEN) editor << '#'; else if (m_Logicnum == LF_TABCOM) editor << '%'; editor << m_TableName[m_Logicnum]; if (table == m_TableName[m_Logicnum]) break; } } } } } return editor; } bool TPostmanServer::LoadEditors(const wxChar * filename, wxArrayString & editors) { wxFileName f(filename); f.MakeAbsolute(); wxString name(f.GetFullPath()); wxTextFile file(name); wxString row; wxString module; if (file.Open()) { for (row = file.GetFirstLine(); !file.Eof(); row = file.GetNextLine()) { wxString editor; row.Trim(false); if (row.StartsWith("[")) module = row.Mid(1, 2); else if (row.StartsWith("Edit_")) { const int pos = row.Find("="); if (pos < 0) continue; const int logicnum = atoi(row.Mid(5, pos - 4)); if (logicnum < 7 && module != "ba") continue; editor = row.Mid(pos + 1); editor.Trim(false); int nrows2add = logicnum - editors.GetCount() + 1; if (nrows2add > 0) editors.Add(wxEmptyString, nrows2add); editors[logicnum] = editor; } } } return editors.GetCount() > 0; } int TPostmanServer::GetDefaultPort() const { return GetConfigInt("Port", 8080); } void TPostmanServer::SaveXml2IniParagraph(wxFileConfig& ini, TXmlItem& xmlItem) { int items = xmlItem.GetChildren(); for (int i = 0; i < items; i++) { TXmlItem * child = xmlItem.GetChild(i); wxString key(child->GetAttr("Name")); wxString val(child->GetEnclosedText()); if (key == "Firm") m_Firm = atoi(val); ini.Write(key, val); } } void TPostmanServer::SaveTransaction(const TXmlItem& xmlMethod, wxString & filename) { wxString paragraph; int items = xmlMethod.GetChildren(); if (wxFileName::FileExists(filename)) wxRemoveFile(filename); for (int i = 0; i < items; i++) { TXmlItem * child = xmlMethod.GetChild(i); const int logicnum = atoi(child->GetAttr("LogicNumber")); paragraph = "/"; if (logicnum > 0) { if (m_Logicnum == 0) m_Logicnum = logicnum; paragraph << logicnum; const int rownum = atoi(child->GetAttr("RowNumber")); if (rownum > 0) paragraph << ',' << rownum; int nrows2add = logicnum - m_TableName.GetCount() + 1; if (nrows2add > 0) m_TableName.Add(wxEmptyString, nrows2add); m_TableName[logicnum] = child->GetAttr("TableName"); } else paragraph << child->GetTag(); wxFileConfig ini("", "", filename, "", wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH); ini.SetPath(paragraph); SaveXml2IniParagraph(ini, *child); } } void TPostmanServer::AdjustTransaction(wxString & filename) { wxTextFile file(filename); bool changed = false; if (file.Open()) { for (wxString & row = file.GetFirstLine(); !file.Eof(); row = file.GetNextLine()) { const int pos = row.Find("\\,"); if (pos > 0) { row.Remove(pos, 1); changed = true; size_t rowno = file.GetCurrentLine(); file.InsertLine(row, rowno); file.RemoveLine(rowno + 1); } } if (changed) file.Write(); } else WriteLog("Can't create Transaction file"); } const wxString TPostmanServer::EditorCommand() { const bool firmchanged = m_Firm != m_LastFirm; m_LastFirm = m_Firm; if (firmchanged) { m_FirmEditors.empty(); wxString name(m_DataPath); wxChar l = name[name.Len() - 1]; if (l != '/' && l != '\\') name << '/'; wxString str; str << m_Firm; while(str.Len() < 5) str.insert(0, "0"); name << str << "a/ditta.ini"; LoadEditors(name.c_str(), m_FirmEditors); } wxString table(m_TableName[m_Logicnum]); if (m_Logicnum <= LF_TAB && !table.IsEmpty()) { wxString editor(Table2Editor(table)); if (!editor.IsEmpty()) return editor; } if (m_Logicnum < (int) m_FirmEditors.GetCount() && !m_FirmEditors[m_Logicnum].IsEmpty()) return m_FirmEditors[m_Logicnum].c_str(); if (m_Logicnum < (int) m_Editors.GetCount() && !m_Editors[m_Logicnum].IsEmpty()) return m_Editors[m_Logicnum].c_str(); return wxEmptyString; } void TPostmanServer::ExecuteTransaction(wxString & filename) { wxString editor(EditorCommand()); if (!editor.IsEmpty()) { wxFileName cmdname(editor); if (cmdname.IsRelative()) { cmdname.MakeAbsolute(); cmdname.RemoveLastDir(); } wxString command(cmdname.GetFullPath()); const wxString currdir(wxGetCwd()); wxSetWorkingDirectory(cmdname.GetPath()); command << " -i" < 0 ? "Field" : "Attr"; int rownum = 0 ; if (logicnum > 0 && tok.HasMoreTokens()) rownum = atoi(tok.GetNextToken()); if (logicnum > 0) tag = "Record"; TXmlItem & child =xmlItem.AddChild(tag); if (logicnum > 0) { child.SetAttr("LogicNumber", logicnum); if (logicnum < m_TableName.GetCount()) child.SetAttr("TableName", m_TableName[logicnum]); if (rownum > 0) child.SetAttr("RowNumber", rownum); } wxString s; wxString key; long index = 0; for (bool ok = ini.GetFirstEntry(key, index); ok; ok = ini.GetNextEntry (key, index)) { wxString val(ini.Read(key)); if (val.StartsWith("\"") && val.EndsWith("\"")) { val = val.Mid(1); val[val.Len()] = '\0'; } else { val.Trim(); val.Trim(false); } if (isdate(val)) child.AddSoapInt(attr, date2ansi(val)).SetAttr("Name", key); else { if (val.IsNumber()) { if (key == "Error" && m_Err != 0) child.AddSoapInt(attr, m_Err).SetAttr("Name", key); else child.AddSoapInt(attr, atoi(val)).SetAttr("Name", key); } else { if (key == "Result" && m_Err != 0) child.AddSoapString(attr, "ERROR").SetAttr("Name", key); else child.AddSoapString(attr, val).SetAttr("Name", key); } } } } void TPostmanServer::LoadTransaction(wxString & filename, TXmlItem& xmlAnswer) { wxString paragraph; long index = 0; wxFileConfig ini("", "", filename, "", wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH); for (bool ok = ini.GetFirstGroup(paragraph, index); ok; ok = ini.GetNextGroup(paragraph, index)) LoadXmlParagraph(xmlAnswer, paragraph, filename); } void TPostmanServer::Log(TXmlItem& WXUNUSED(xmlItem), wxString & filename) { wxFileConfig ini("", "", filename, "", wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_RELATIVE_PATH); wxString str; wxString key; long index = 0; ini.SetPath("/Transaction"); str << "Transaction : Command " << m_Editors[m_Logicnum]; WriteLog(str); for (bool ok = ini.GetFirstEntry(key, index); ok; ok = ini.GetNextEntry (key, index)) { wxString val(ini.Read(key)); str = " ", str << key << " = " << val; WriteLog(str); } } void TPostmanServer::SoapProcessMethod(const TXmlItem& xmlMethod, TXmlItem& xmlAnswer) { const wxString& strMethod = xmlMethod.GetTag(); if (strMethod == "m:CampoTransaction") { m_Logicnum = 0; wxFileName filename(GetTempFilename("ini")); wxString name(filename.GetFullPath()); SaveTransaction(xmlMethod, name); AdjustTransaction(name); ExecuteTransaction(name); LoadTransaction(name, xmlAnswer); Log(xmlAnswer, name); } } // Implementazione delle due funzioni pure virtuali const wxChar* TPostmanServer::GetAppName() const { return "Postman"; } bool TPostmanServer::Initialization() { wxFileName f("../campo.ini"); f.MakeAbsolute(); wxString name(f.GetFullPath()); wxTextFile file(name); wxString row; if (file.Open()) { for (row = file.GetFirstLine(); !file.Eof(); row = file.GetNextLine()) { if (row.StartsWith("Study")) { const int pos = row.Find('='); if (pos >= 0) { m_DataPath = row.Mid(pos + 1); m_DataPath.Trim(false); } break; } } } if (m_DataPath.IsEmpty()) { WriteLog("No data path"); return false; } if (!LoadEditors("../install.ini", m_Editors)) { WriteLog("No editors found"); return false; } return true; } // Istanziare l'applicazione principale IMPLEMENT_APP(TPostmanServer)