//OpenSCADA module UI.WebCfg file: web_cfg.cpp /*************************************************************************** * Copyright (C) 2004-2024 by Roman Savochenko, * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; version 2 of the License. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include "web_cfg.h" //************************************************* //* Modul info! * #define MOD_ID "WebCfg" #define MOD_NAME trS("Program configurator (WEB)") #define MOD_TYPE SUI_ID #define VER_TYPE SUI_VER #define SUB_TYPE "WWW" #define MOD_VER "2.0.4" #define AUTHORS trS("Roman Savochenko") #define DESCRIPTION trS("Provides the WEB-based configurator of the OpenSCADA.") #define LICENSE "GPL2" //************************************************* WebCfg::TWEB *WebCfg::mod; extern "C" { #ifdef MOD_INCL TModule::SAt ui_WebCfg_module( int n_mod ) #else TModule::SAt module( int n_mod ) #endif { if(n_mod == 0) return TModule::SAt(MOD_ID,MOD_TYPE,VER_TYPE); return TModule::SAt(""); } #ifdef MOD_INCL TModule *ui_WebCfg_attach( const TModule::SAt &AtMod, const string &source ) #else TModule *attach( const TModule::SAt &AtMod, const string &source ) #endif { if(AtMod == TModule::SAt(MOD_ID,MOD_TYPE,VER_TYPE)) return new WebCfg::TWEB(source); return NULL; } } using namespace WebCfg; //************************************************* //* TWEB * //************************************************* TWEB::TWEB( string name ) : TUI(MOD_ID) { mod = this; modInfoMainSet(MOD_NAME, MOD_TYPE, MOD_VER, AUTHORS, DESCRIPTION, LICENSE, name); //Reg export functions modFuncReg(new ExpFunc("void HTTP_GET(const string&,string&,vector&,const string&,TProtocolIn*);", "GET command processing from HTTP protocol!",(void(TModule::*)( )) &TWEB::HTTP_GET)); modFuncReg(new ExpFunc("void HTTP_POST(const string&,string&,vector&,const string&,TProtocolIn*);", "POST command processing from HTTP protocol!",(void(TModule::*)( )) &TWEB::HTTP_POST)); //Default CSS init mCSStables = "hr { width: 100%; }\n" "body { background-color: #818181; }\n" "h1.head { text-align:center; color:#ffff00; }\n" "h2.title { text-align:center; font-style:italic; margin: 0px; padding: 0px; border-width: 0px; }\n" "table.work { background-color: #9999ff; border: 3px ridge #a9a9a9; padding: 2px; }\n" "table.work td { background-color:#cccccc; text-align: left; }\n" "table.work td.content { padding: 5px; padding-bottom: 20px; }\n" "table.work ul { margin: 0px; padding: 0px; padding-left: 20px; }\n" "table.page_head { background-color: #cccccc; border: 3px ridge blue; width: 100%; }\n" "table.page_head td.tool { text-align: center; border: 1px solid blue; width:120px; white-space: nowrap; }\n" "table.page_head td.tool img { height: 32px; border: 0px; vertical-align: middle; }\n" "table.page_head td.user { text-align: left; border: 1px solid blue; width: 120px; white-space: nowrap; }\n" "table.page_area { background-color: #9999ff; border:3px ridge #a9a9a9; width:100%; padding:2px; }\n" "table.page_area tr.content { background-color: #cccccc; border:5px ridge #9999ff; padding:5px; }\n"; } TWEB::~TWEB() { } void TWEB::load_( ) { //Load parameters from command line //Load parameters from config-file } void TWEB::modStart( ) { runSt = true; } void TWEB::modStop( ) { runSt = false; } string TWEB::httpHead( const string &rcode, int cln, const string &cnt_tp, const string &addattr ) { return "HTTP/1.1 "+rcode+"\x0D\x0A" "Server: "+PACKAGE_STRING+"\x0D\x0A" "Accept-Ranges: bytes\x0D\x0A" "Content-Length: "+i2s(cln)+"\x0D\x0A" "Content-Type: "+cnt_tp+";charset="+Mess->charset()+"\x0D\x0A"+addattr+"\x0D\x0A"; } string TWEB::pgHead( string head_els ) { return "\n" "\n" "\n" "\n" " \n" " \n"+ head_els+ " \n" // " \n" " " PACKAGE_NAME ". " + _(mod->modInfo("Name")) + "\n" " \n" "\n" "\n" "

" PACKAGE_NAME ". " + _(mod->modInfo("Name")) + "

\n" "

\n"; } string TWEB::pgTail( ) { return "
\n\n"; } void TWEB::HTTP_GET( const string &urli, string &page, vector &vars, const string &user, TProtocolIn *iprt ) { map::iterator prmEl; SSess ses(TSYS::strDecode(urli,TSYS::HttpURL), TSYS::strLine(iprt->srcAddr(),0), user, vars, ""); TrCtxAlloc trCtx; if(Mess->translDyn()) trCtx.hold(ses.user+"\n"+ses.lang); ses.page = pgHead(); try { string zero_lev = TSYS::pathLev(ses.url, 0); //Get about module page if(zero_lev == "about") getAbout(ses); //Get module icon and global image else if(zero_lev == "ico" || zero_lev.find("img_") == 0) { string itp; ses.page = TUIS::icoGet((zero_lev=="ico")?"UI." MOD_ID:zero_lev.substr(4), &itp); page = httpHead("200 OK",ses.page.size(),string("image/")+itp)+ses.page; return; } else { ses.pg_info.setName("info"); ses.pg_info.setAttr("path", ses.url)->setAttr("user", ses.user); if(cntrIfCmd(ses.pg_info)) throw TError(ses.pg_info.attr("mcat"), ses.pg_info.text()); ses.root = ses.pg_info.childGet(0); if(ses.root->name()=="img") { // Transfer page image XMLNode req("get"); req.setAttr("path", ses.url)->setAttr("user", ses.user); if(cntrIfCmd(req)) throw TError(req.attr("mcat"), req.text()); ses.page=TSYS::strDecode(req.text(),TSYS::base64); page = httpHead("200 OK",ses.page.size(),string("image/")+req.attr("tp"))+ses.page; return; } else { prmEl = ses.prm.find("com"); string wp_com = (prmEl!=ses.prm.end()) ? prmEl->second : ""; if(wp_com == "load") { XMLNode reqc("load"); reqc.setAttr("path", ses.url+"/%2fobj")->setAttr("user", ses.user); cntrIfCmd(reqc); } else if(wp_com == "save") { XMLNode reqc("save"); reqc.setAttr("path", ses.url+"/%2fobj")->setAttr("user", ses.user); cntrIfCmd(reqc); } // Get area getHead(ses); getArea(ses, *ses.root, "/"); } } } catch(TError &err) { ses.page = "Page '"+ses.url+"' error: "+TSYS::strEncode(err.mess,TSYS::Html); //postMess(ses.page,err.cat,err.mess,TWEB::Error); page = httpHead("404 Not Found",ses.page.size())+ses.page; return; } colontDown( ses ); ses.page += pgTail(); page = httpHead("200 OK",ses.page.size()) + ses.page; } void TWEB::getAbout( SSess &ses ) { string mess = string("
\n")+ "\n" "\n" "\n
"+MOD_ID+" v"+MOD_VER+"
\n" "\n" "\n" "\n" "\n" "\n" "
"+_("Name: ")+""+_(mod->modInfo("Name"))+"
"+_("Description: ")+""+_(mod->modInfo("Description"))+"
"+_("License: ")+""+mod->modInfo("License")+"
"+_("Author: ")+""+_(mod->modInfo("Author"))+"
\n" "

\n" "\n" "\n" "
"+PACKAGE+" v"+VERSION+"
\n" "\n" "\n" "\n" "\n" "\n" "
"+_("Name: ")+"%s
"+_("License: ")+"%s
"+_("Author: ")+"%s
"+_("Web site: ")+"%s
\n" "

\n" "
\n"; #undef _ #define _(mess) Mess->I18N(mess).c_str() ses.page += TSYS::strMess(mess.c_str(),_(PACKAGE_DESCR),PACKAGE_LICENSE,_(PACKAGE_AUTHOR),PACKAGE_SITE); #undef _ #define _(mess) mod->I18N(mess).c_str() } void TWEB::getHead( SSess &ses ) { string path = string("/")+MOD_ID+ses.url; ses.page += "\n" "\n" "\n" "
\n" "" + _("Load") + "\n" "" + _("Save") + "\n" "\n" "" + _("Root page") + "\n" "" +_("Curent page") + "\n" "" + _("Previous page") + "\n" "\n" "" + _("About") + "\n" ""; if(ses.root->childGet("id","ico",true)) ses.page += ""; ses.page += "

"+TSYS::strEncode(ses.root->attr("dscr"),TSYS::Html)+"

"+ _("user:")+" "+ses.user+"
"+_("from:")+" "+ses.sender+"
\n" "("+_("Change")+", "+_("Exit")+")\n" "

\n"; } void TWEB::getArea( SSess &ses, XMLNode &node, string a_path ) { unsigned i_cf,c_cfg; bool wr; string area_path; string path = string("/")+MOD_ID+ses.url; for(i_cf = 0; i_cf < node.childSize(); i_cf++) { XMLNode *t_s = node.childGet(i_cf); if(t_s->name() == "area") { wr = false; area_path = a_path+t_s->attr("id")+'/'; if(a_path == "/") ses.page = ses.page+"\n" "\n" "
"+TSYS::strEncode(t_s->attr("dscr"),TSYS::Html)+ "
"; else ses.page = ses.page+"
"+TSYS::strEncode(t_s->attr("dscr"),TSYS::Html)+"\n"; //ses.page = ses.page+"
"; //Get area's fields c_cfg = 0; bool f_open = false; for(unsigned i_el = 0; i_el < t_s->childSize(); i_el++) { XMLNode *t_c = t_s->childGet(i_el); if(t_c->name() == "fld") { // First element if((c_cfg++) == 0) ses.page += "
\n\n"; // Start full element if(t_c->attr("dscr").size()) { if(f_open) ses.page += ""; ses.page += ""; if(c_cfg > 0) { ses.page += "
"+TSYS::strEncode(t_c->attr("dscr"),TSYS::Html)+":"; f_open = true; } wr |= getVal(ses,*t_c,area_path+t_c->attr("id")); } } if(f_open) ses.page += "

\n"; if(wr) ses.page += "\n"; // Submit button ses.page += "
\n
\n"; } //Get area's lists c_cfg = 0; for(unsigned i_el = 0; i_el < t_s->childSize(); i_el++) { XMLNode *t_c = t_s->childGet(i_el); if(t_c->name() == "list" || t_c->name() == "table" || t_c->name() == "img") { c_cfg++; ses.page += TSYS::strEncode(t_c->attr("dscr"),TSYS::Html)+":
"; getVal(ses,*t_c,area_path+t_c->attr("id")); } } //if(c_cfg > 0) ses.page = ses.page+"
\n"; //Get area's tables - /*c_cfg = 0; for( unsigned i_el = 0; i_el < t_s->childSize(); i_el++) { XMLNode *t_c = t_s->childGet(i_el); if(t_c->name() == "table") { c_cfg++; ses.page = ses.page+t_c->attr("dscr")+":
"; getVal(ses,*t_c,area_path+t_c->attr("id")); } }*/ if(c_cfg > 0) ses.page += "
\n"; //Get area's commands for(unsigned i_el = 0; i_el < t_s->childSize(); i_el++) { // First element XMLNode *t_c = t_s->childGet(i_el); if(t_c->name() == "comm") getCmd(ses,*t_c,area_path+t_c->attr("id")); } getArea(ses, *t_s, area_path); if(a_path == "/") ses.page += "
\n"; else ses.page += "\n"; } } } void TWEB::getCmd( SSess &ses, XMLNode &node, string a_path ) { string path = string("/")+MOD_ID+ses.url; ses.page += "
\n" "\n"; int f_cfg=0; for(unsigned i_el=0; i_el < node.childSize(); i_el++) { XMLNode *t_c = node.childGet(i_el); if(t_c->name() == "fld") { if((f_cfg++) > 0) ses.page += ", "; else ses.page += "
("; ses.page += TSYS::strEncode(t_c->attr("dscr"),TSYS::Html)+":"; getVal(ses,*t_c,a_path,false); } } if(f_cfg > 0) ses.page += ")
\n"; ses.page += "
\n"; } bool TWEB::getVal( SSess &ses, XMLNode &node, string a_path, bool rd ) { string path = string("/")+MOD_ID+ses.url; bool wr = s2i(node.attr("acs"))&SEC_WR; if(node.name() == "fld") { XMLNode dt_req("get"); if(rd) { dt_req.setAttr("path",ses.url+"/"+TSYS::strEncode(a_path,TSYS::PathEl))->setAttr("user",ses.user); if(cntrIfCmd(dt_req)) { ses.mess.push_back(dt_req.text().c_str()); dt_req.setText(""); } } if((node.attr("dest") == "select" || node.attr("dest") == "sel_ed") && wr) { bool sel_ok = false; ses.page += "\n"; } else { if(node.attr("tp") == "bool") { ses.page += "\n"; } else if(node.attr("tp") == "time") { struct tm tm_tm; time_t tm_t = dt_req.text().size() ? s2i(dt_req.text()) : time(NULL); localtime_r(&tm_t, &tm_tm); if(!wr) ses.page += ""+atm2s(tm_t,"%d-%m-%Y %H:%M:%S")+""; else { string s_id = node.attr("id"); ses.page += "\n"; ses.page += "\n"; ses.page += "\n"; ses.page += " , "; ses.page += "\n"; ses.page += "\n"; ses.page += "\n"; } } else { //Other fields if(!wr) ses.page += ""+dt_req.text()+""; else { ses.page = ses.page+" 0) ses.page += " maxlength='"+i2s(val_n)+"' size='"+i2s((val_n>50)?50:val_n)+"'"; else { if(node.attr("tp") == "dec" || node.attr("tp") == "hex" || node.attr("tp") == "oct" || node.attr("tp") == "real") ses.page += " size='5'"; else ses.page += " size='50'"; } ses.page += "/>\n"; } } } } } else if(node.name() == "list") { if(node.attr("tp") == "br" || wr) ses.page += "
\n"; XMLNode req("get"); req.setAttr("path",ses.url+"/"+TSYS::strEncode(a_path, TSYS::PathEl))->setAttr("user",ses.user); if(cntrIfCmd(req)) ses.mess.push_back(req.text().c_str()); bool ind_m = s2i(node.attr("idm")); int p_size = vmin(20,vmax(4,req.childSize())); ses.page += "
\n"; if(node.attr("tp") == "br") ses.page += "
\n"; //Go branch command if(wr && node.attr("s_com").size()) { bool p_edit = false; //ses.page = ses.page+"
\n"; if(node.attr("s_com").find("add") != string::npos) { ses.page += "\n"; //Add element to list p_edit = true; } if(node.attr("s_com").find("ins") != string::npos) { ses.page += "\n"; //Insert element to list p_edit = true; } if(node.attr("s_com").find("edit") != string::npos) { ses.page += "\n"; //Edit list element p_edit = true; } if(p_edit) { if(ind_m) ses.page += "\n"; node.setName("fld"); node.setAttr("id","ener_f"); getVal(ses, node, node.attr("id"), false); ses.page += "
\n"; } if(node.attr("s_com").find("move") != string::npos) ses.page += "\n" "\n"; if(node.attr("s_com").find("del") != string::npos) ses.page += "\n"; //Del element from list } if(node.attr("tp") == "br" || wr) ses.page += "
\n"; } else if(node.name() == "table") { if(wr) ses.page += "
\n"; XMLNode req("get"); req.setAttr("path",ses.url+"/"+TSYS::strEncode(a_path, TSYS::PathEl))->setAttr("user",ses.user); if(cntrIfCmd(req)) ses.mess.push_back(req.text().c_str()); ses.page += "\n"; int clm_sz[req.childSize()]; //Draw head ses.page += ""; for(unsigned i_cl = 0; i_cl < req.childSize(); i_cl++) { XMLNode *t_lsel = req.childGet(i_cl); XMLNode *t_linf = node.childGet("id",t_lsel->attr("id"),true); if(!t_linf) { t_linf = node.childIns(i_cl); *t_linf = *t_lsel; } ses.page += ""; // Calc column sizes clm_sz[i_cl] = t_linf->attr("dscr").size(); for(unsigned i_rw = 0; i_rw < t_lsel->childSize(); i_rw++) { XMLNode *x_el = t_lsel->childGet(i_rw); if((int)x_el->text().size() > clm_sz[i_cl]) clm_sz[i_cl] = x_el->text().size(); } clm_sz[i_cl] = vmin(40,vmax(5,clm_sz[i_cl])); } if(wr) ses.page += ""; ses.page += "\n"; for(unsigned i_rw = 0; req.childSize() && i_rw < req.childGet(0)->childSize(); i_rw++) { ses.page += ""; for(unsigned i_cl = 0; i_cl < req.childSize(); i_cl++) { XMLNode *t_lsel = req.childGet(i_cl); XMLNode *t_linf = node.childGet("id",t_lsel->attr("id"),true); if(!t_linf) continue; bool c_wr = wr && (s2i(t_linf->attr("acs"))&SEC_WR); XMLNode *x_el = t_lsel->childGet(i_rw); if(t_linf->attr("tp") == "time") ses.page += ""; else if((t_linf->attr("dest") == "select" || t_linf->attr("dest") == "sel_ed") && c_wr) { ses.page += "\n"; } else if(t_linf->attr("tp") == "bool") { ses.page += "\n"; } else { if(!c_wr) ses.page += ""; else ses.page += ""; } } // Add modify buttons if(wr) ses.page += ""; ses.page += "\n"; } ses.page += "
"+TSYS::strEncode(t_linf->attr("dscr"),TSYS::Html)+"*
"+atm2s(s2i(x_el->text()),"%d-%m-%Y %H:%M:%S")+"text())) ses.page += " checked='checked'"; if(!c_wr) ses.page += " disabled='disabled'"; ses.page += "/>"+TSYS::strEncode(x_el->text(),TSYS::Html)+"
\n"; if(wr) { ses.page += "
"; if(node.attr("s_com").find("add") != string::npos) ses.page += ""; if(node.attr("s_com").find("ins") != string::npos) ses.page += ""; if(node.attr("s_com").find("del") != string::npos) ses.page += ""; if(node.attr("s_com").find("move") != string::npos) { ses.page += ""; ses.page += ""; } ses.page += "
\n"; } } else if(node.name() == "img") ses.page += string("
\n"; return wr; } void TWEB::HTTP_POST( const string &url, string &page, vector &vars, const string &user, TProtocolIn *iprt ) { map::iterator cntEl; SSess ses(TSYS::strDecode(url,TSYS::HttpURL), TSYS::strLine(iprt->srcAddr(),0), user, vars, page); TrCtxAlloc trCtx; if(Mess->translDyn()) trCtx.hold(ses.user+"\n"+ses.lang); //Commands process ses.page = pgHead(); try { ses.pg_info.setName("info"); ses.pg_info.setAttr("path", ses.url)->setAttr("user", ses.user); if(cntrIfCmd(ses.pg_info)) throw TError(ses.pg_info.attr("mcat"), ses.pg_info.text()); ses.root = ses.pg_info.childGet(0); // Parse post category and path to area string prs_cat, prs_path, prs_comm; for(cntEl = ses.cnt.begin(); cntEl != ses.cnt.end(); cntEl++) { prs_comm = cntEl->first; string comm_t = TSYS::strSepParse(prs_comm,0,':'); if(comm_t == "apply" || comm_t == "comm" || comm_t == "list" || comm_t == "tbl") break; } if(cntEl != ses.cnt.end()) { ses.cnt.erase(cntEl); int kz = postArea(ses, *ses.root, prs_comm); if(!(kz&0x01)) messPost(ses.page,nodePath(),_("The post request is broken!"),TWEB::Error); else if(!(kz&0x02)) { ses.pg_info.setName("info"); ses.pg_info.setAttr("path", ses.url)->setAttr("user", ses.user); if(cntrIfCmd(ses.pg_info)) throw TError(ses.pg_info.attr("mcat"), ses.pg_info.text()); ses.root = ses.pg_info.childGet(0); getHead(ses); getArea(ses, *ses.root, "/"); } } } catch(TError &err) { messPost(ses.page,err.cat,err.mess,TWEB::Error); } colontDown(ses); ses.page += pgTail(); page = httpHead("200 OK",ses.page.size(),"text/html") + ses.page; } int TWEB::postArea( SSess &ses, XMLNode &node, const string &prs_comm, int level ) { string prs_cat = TSYS::strSepParse(prs_comm,0,':'); string prs_path = TSYS::strSepParse(prs_comm,1,':'); if(!TSYS::pathLev(prs_path,level).size()) return 0x00; try { XMLNode *t_nd = TCntrNode::ctrId(&node, TSYS::pathLev(prs_path,level)); if(prs_cat == "apply" && !TSYS::pathLev(prs_path,level+1).size()) return postVal(ses,*t_nd,prs_path); else if(prs_cat == "comm" && !TSYS::pathLev(prs_path,level+1).size()) return postCmd(ses,*t_nd,prs_path); else if(prs_cat == "list" && t_nd->name() == "list") return postList(ses,*t_nd,prs_path); else if(prs_cat == "tbl" && t_nd->name() == "table") return postTable(ses,*t_nd,prs_path); return postArea(ses, *t_nd, prs_comm, ++level); } catch(TError &err) { messPost(ses.page,err.cat,err.mess,TWEB::Error); return 0x01|0x02; } } int TWEB::postVal( SSess &ses, XMLNode &node, string prs_path) { //Free no changed elements (polimorfic problem fix) for(unsigned i_cf = 0; i_cf < node.childSize(); i_cf++) { XMLNode *t_c = node.childGet(i_cf); if((t_c->name() == "fld") && (s2i(t_c->attr("acs"))&SEC_WR) && t_c->attr("tp") != "bool" && !valPrepare(ses,*t_c,prs_path,true)) ses.cnt.erase(t_c->attr("id")); } //Check and modify for(unsigned i_cf = 0; i_cf < node.childSize(); i_cf++) { XMLNode *t_c = node.childGet(i_cf); if(t_c->name() == "fld" && (s2i(t_c->attr("acs"))&SEC_WR)) { if(!valPrepare(ses,*t_c,prs_path,true)) continue; mess_info(nodePath().c_str(),_("%s| Changed for <%s:%s> to %s"), ses.user.c_str(), t_c->attr("id").c_str(), t_c->attr("dscr").c_str(), t_c->text().c_str()); XMLNode req("set"); req.setAttr("path",ses.url+"/"+TSYS::strEncode(prs_path+t_c->attr("id"), TSYS::PathEl))-> setAttr("user",ses.user)->setText(t_c->text()); if(cntrIfCmd(req)) { ses.mess.push_back(req.text().c_str()); return 0x01; } continue; } } return 0x01; } int TWEB::postCmd( SSess &ses, XMLNode &node, string prs_path ) { //Prepare command options try { // Check for link if(node.attr("tp") == "lnk") { XMLNode req("get"); req.setAttr("path",ses.url+"/"+TSYS::strEncode(prs_path,TSYS::PathEl))->setAttr("user",ses.user); if(cntrIfCmd(req)) ses.mess.push_back(req.text().c_str()); string url = string("/")+MOD_ID+"/"+TSYS::strEncode(req.text(),TSYS::HttpURL); mess_info(nodePath().c_str(),_("%s| Went to the link '%s'"),ses.user.c_str(),url.c_str()); ses.page += "\n"; messPost(ses.page, nodePath(), TSYS::strMess(_("Went to '%s'."),url.c_str()), TWEB::Info); return 0x01|0x02; //No error. That no draw current page } for(unsigned i_prm = 0; i_prm < node.childSize(); i_prm++) { XMLNode *t_c = node.childGet(i_prm); if(t_c->name() == "fld") valPrepare(ses, *t_c, "", false); } mess_info(nodePath().c_str(),_("%s| Put the command <%s:%s>"), ses.user.c_str(), node.attr("id").c_str(), node.attr("dscr").c_str()); XMLNode req("set"); req.setAttr("path",ses.url+"/"+TSYS::strEncode(prs_path,TSYS::PathEl))->setAttr("user",ses.user); // Copy command parameters for(unsigned i_ch = 0; i_ch < node.childSize(); i_ch++) *req.childAdd() = *node.childGet(i_ch); if(cntrIfCmd(req)) ses.mess.push_back(req.text().c_str()); //return 0x01; } catch(TError &err) { ses.mess.push_back( err.mess ); } //{ //postMess(ses.page,err.mess,TWEB::Error); //return 0x01|0x02; //} return 0x01; } int TWEB::postList( SSess &ses, XMLNode &node, string prs_path ) { string path = string("/")+MOD_ID+ses.url; string f_path, l_path, nd_nm, l_com, ener_f, ener_id; bool ind_m = s2i(node.attr("idm")); //Get command name and path int c_pos = 1; while(true) { size_t t_pos = prs_path.find("/",c_pos); if(t_pos == string::npos) { l_com = prs_path.substr(c_pos,t_pos-c_pos); break; } l_path += "/" + prs_path.substr(c_pos,t_pos-c_pos);//+"/"; c_pos = t_pos+1; } f_path = ses.url+"/"+TSYS::strEncode(l_path,TSYS::PathEl); //Get new element value map::iterator cntEl; if((cntEl=ses.cnt.find("ener_id")) != ses.cnt.end())ener_id = cntEl->second; if((cntEl=ses.cnt.find("ener_f")) != ses.cnt.end()) ener_f = cntEl->second; string i_pos, i_el, l_el; //Check selected item if(l_com == "go" || l_com == "ins" || l_com == "edit" || l_com == "del" || l_com == "up" || l_com == "down") { if((cntEl=ses.cnt.find(node.attr("id"))) != ses.cnt.end()) l_el = cntEl->second; else { ses.mess.push_back("No select list element of <"+TSYS::strEncode(node.attr("dscr"),TSYS::Html)+">!"); return 0x01; //postMess(ses.page,"No select list element for list <"+node.attr("dscr")+">!",TWEB::Warning); //return( 0x01|0x02 ); } i_pos= TSYS::strSepParse(l_el,0,':'); i_el = TSYS::strSepParse(l_el,1,':'); l_el = TSYS::strSepParse(l_el,2,':'); } if(l_com == "go") { // Get branch prefix string br_pref = node.attr("br_pref"); //if( node.attr("br_pref").size() ) br_pref = node.attr("br_pref"); //else br_pref = l_path; // Check branch type string url = path+"/"; // Check Index-list mode if(i_el.size()) url.append(TSYS::strEncode(TSYS::strEncode(br_pref+i_el,TSYS::PathEl),TSYS::HttpURL)); else url.append(TSYS::strEncode(TSYS::strEncode(br_pref+l_el,TSYS::PathEl),TSYS::HttpURL)); //printf("GO URL: %s\n",url.c_str()); ses.page += "\n"; messPost(ses.page, nodePath(), TSYS::strMess(_("Went to '%s'."),url.c_str()), TWEB::Info); return 0x01|0x02; //No error. That no draw current page } XMLNode n_el1; n_el1.setAttr("path",f_path)->setAttr("user",ses.user); if(l_com == "del") { n_el1.setName("del"); n_el1.setAttr("pos",i_pos); if(ind_m) n_el1.setAttr("id",i_el); else n_el1.setText(l_el); mess_info(nodePath().c_str(), _("%s| Deleted '%s' for the element <%s:%s>."), ses.user.c_str(), f_path.c_str(), i_el.c_str(), l_el.c_str()); } else if(l_com == "ins") { n_el1.setName("ins"); n_el1.setAttr("pos",i_pos); n_el1.setAttr("p_id",(ind_m)?i_el:l_el); if(ind_m) n_el1.setAttr("id",ener_id); n_el1.setText(ener_f); mess_info(nodePath().c_str(), _("%s| Inserted '%s' for the element <%s:%s> to %s."), ses.user.c_str(), f_path.c_str(), ener_id.c_str(), ener_f.c_str(), i_pos.c_str()); } else if(l_com == "add") { n_el1.setName("add"); if(ind_m) n_el1.setAttr("id",ener_id); n_el1.setText(ener_f); mess_info(nodePath().c_str(), _("%s| Added '%s' for the element <%s:%s>."), ses.user.c_str(), f_path.c_str(), ener_id.c_str(), ener_f.c_str()); } else if(l_com == "edit") { n_el1.setName("edit"); n_el1.setAttr("pos",i_pos); n_el1.setAttr("p_id",(ind_m)?i_el:l_el); if(ind_m) n_el1.setAttr("id",ener_id); n_el1.setText(ener_f); mess_info(nodePath().c_str(), _("%s| Set '%s' for the element %s to <%s:%s>."), ses.user.c_str(), f_path.c_str(), i_pos.c_str(), ener_id.c_str(), ener_f.c_str()); } else if(l_com == "up" || l_com == "down") { string i_pos_to; if(l_com == "down") i_pos_to = i2s(s2i(i_pos)-1); else i_pos_to = i2s(s2i(i_pos)+1); n_el1.setName("move"); n_el1.setAttr("pos",i_pos); n_el1.setAttr("to",i_pos_to); mess_info(nodePath().c_str(), _("%s| Moved '%s' from %s to %s."), ses.user.c_str(), f_path.c_str(), i_pos.c_str(), i_pos_to.c_str()); } if(cntrIfCmd(n_el1)) ses.mess.push_back(n_el1.text().c_str()); return 0x01; } int TWEB::postTable( SSess &ses, XMLNode &node, string prs_path ) { XMLNode n_el1; string path = string("/")+MOD_ID+ses.url; string f_path, l_path, l_com; int op_cnt = 0; bool wr = s2i(node.attr("acs"))&SEC_WR; if(!wr) return 0x01; //Get command name and path int c_pos = 1; while(true) { size_t t_pos = prs_path.find("/",c_pos); if(t_pos == string::npos) { l_com = prs_path.substr(c_pos,t_pos-c_pos); break; } l_path += "/" + prs_path.substr(c_pos,t_pos-c_pos);//+"/"; c_pos = t_pos+1; } f_path = ses.url+"/"+TSYS::strEncode(l_path,TSYS::PathEl); XMLNode dt_tbl("get"); dt_tbl.setAttr("path",f_path)->setAttr("user",ses.user); if(cntrIfCmd(dt_tbl)) ses.mess.push_back(dt_tbl.text().c_str()); n_el1.setAttr("path",f_path)->setAttr("user",ses.user); if(l_com == "apply") { for(unsigned i_cl = 0; i_cl < dt_tbl.childSize(); i_cl++) { XMLNode *t_lsel = dt_tbl.childGet(i_cl); XMLNode *t_linf = node.childGet("id",t_lsel->attr("id"),true); if(!t_linf) continue; if(wr && (s2i(t_linf->attr("acs"))&SEC_WR) ) for(unsigned i_rw = 0; i_rw < t_lsel->childSize(); i_rw++) { XMLNode *w_el = t_lsel->childGet(i_rw); string new_val = cntGet(ses,i2s(i_rw)+":"+t_linf->attr("id")); if(t_linf->attr("tp") == "bool") new_val = (new_val!="")?"1":"0"; if(new_val != "" && new_val != w_el->text()) { n_el1.setName("set"); n_el1.setText(new_val); string row_addr; if(!node.attr("key").size()) { row_addr = i2s(i_rw); n_el1.setAttr("row",row_addr)->setAttr("col",i2s(i_cl)); } else { // Get Key columns string key; for(int i_off = 0; (key=TSYS::strSepParse(node.attr("key"),0,',',&i_off)).size(); ) for(unsigned i_el = 0; i_el < dt_tbl.childSize(); i_el++) if(dt_tbl.childGet(i_el)->attr("id") == key) { n_el1.setAttr("key_"+key,dt_tbl.childGet(i_el)->childGet(i_rw)->text()); row_addr += "key_"+key+"="+dt_tbl.childGet(i_el)->childGet(i_rw)->text()+","; break; } // Get current column id n_el1.setAttr("col",t_linf->attr("id")); } mess_info(nodePath().c_str(), _("%s| Set '%s' for the cell <%s:%s> to %s."), ses.user.c_str(), f_path.c_str(), row_addr.c_str(), t_linf->attr("id").c_str(), new_val.c_str()); if(cntrIfCmd(n_el1)) ses.mess.push_back(n_el1.text().c_str()); } } } } else if(l_com == "add") { n_el1.setName("add"); mess_info(nodePath().c_str(), _("%s| Added '%s' for a record."), ses.user.c_str(), f_path.c_str() ); if(cntrIfCmd(n_el1)) ses.mess.push_back(n_el1.text().c_str()); } else if(l_com == "ins" && dt_tbl.childSize() > 0) { for(unsigned i_rw = 0; i_rw < dt_tbl.childGet(0)->childSize(); i_rw++) if(cntGet(ses,"row:"+i2s(i_rw)) != "") { n_el1.setName("ins"); n_el1.setAttr("row",i2s(i_rw+op_cnt)); mess_info(nodePath().c_str(), _("%s| Inserted '%s' for the record %d."), ses.user.c_str(), f_path.c_str(), i_rw+op_cnt); if(cntrIfCmd(n_el1)) ses.mess.push_back(n_el1.text().c_str()); op_cnt++; } } else if(l_com == "del" && dt_tbl.childSize() > 0) { for(unsigned i_rw = 0; i_rw < dt_tbl.childGet(0)->childSize(); i_rw++) if(cntGet(ses,"row:"+i2s(i_rw)) != "") { n_el1.setName("del"); if(!node.attr("key").size()) n_el1.setAttr("row",i2s(i_rw-op_cnt)); else { // Get Key columns string key; for(int i_off = 0; (key=TSYS::strSepParse(node.attr("key"),0,',',&i_off)).size(); ) for(unsigned i_el = 0; i_el < dt_tbl.childSize(); i_el++) if(dt_tbl.childGet(i_el)->attr("id") == key) { n_el1.setAttr("key_"+key,dt_tbl.childGet(i_el)->childGet(i_rw)->text()); break; } } mess_info(nodePath().c_str(), _("%s| Deleted '%s' for the record %d."), ses.user.c_str(), f_path.c_str(), i_rw-op_cnt); if(cntrIfCmd(n_el1)) ses.mess.push_back(n_el1.text().c_str()); op_cnt++; } } else if((l_com == "up" || l_com == "down") && dt_tbl.childSize() > 0) { for(unsigned i_rw = 0; i_rw < dt_tbl.childGet(0)->childSize(); i_rw++) if(cntGet(ses,"row:"+i2s(i_rw)) != "") { int r_new = i_rw-1; if(l_com == "down") r_new = i_rw+1; n_el1.setName("move"); n_el1.setAttr("row",i2s(i_rw))->setAttr("to",i2s(r_new)); mess_info(nodePath().c_str(),_("%s| Moved '%s' for a record from %d to %d."), ses.user.c_str(), f_path.c_str(), i_rw, r_new); if(cntrIfCmd(n_el1)) ses.mess.push_back(n_el1.text().c_str()); } } return 0x01; } void TWEB::messPost( string &page, const string &cat, const string &mess, MessLev type ) { //Put system message. message(cat.c_str(), (type==Error) ? TMess::Error : (type==Warning) ? TMess::Warning : TMess::Info,"%s",mess.c_str()); //Prepare HTML messages page += "\n"; if(type == Warning) page += "\n"; else if(type == Error) page += "\n"; else page += "\n"; page += "\n"; page += "
Warning!
Error!
Message!
"+TSYS::strEncode(mess,TSYS::Html)+"
\n"; } bool TWEB::valPrepare( SSess &ses, XMLNode &node, string prs_path, bool compare ) { string val; map::iterator cntEl; XMLNode req("get"); req.setAttr("path",ses.url+"/"+TSYS::strEncode(prs_path+node.attr("id"),TSYS::PathEl))->setAttr("user",ses.user); if(node.attr("tp") == "bool") { val = (ses.cnt.find(node.attr("id")) != ses.cnt.end()) ? "1" : "0"; if(compare) { if(cntrIfCmd(req)) ses.mess.push_back(req.text().c_str()); if(req.text() == val) return false; //No change fld } } else if(node.attr("tp") == "time") { struct tm tm_tm; string s_id = node.attr("id"); tm_tm.tm_isdst = -1; if((cntEl=ses.cnt.find(s_id+"_d")) != ses.cnt.end()) tm_tm.tm_mday = s2i(cntEl->second); if((cntEl=ses.cnt.find(s_id+"_ms")) != ses.cnt.end()) tm_tm.tm_mon = s2i(cntEl->second)-1; if((cntEl=ses.cnt.find(s_id+"_y")) != ses.cnt.end()) tm_tm.tm_year = s2i(cntEl->second)-1900; if((cntEl=ses.cnt.find(s_id+"_h")) != ses.cnt.end()) tm_tm.tm_hour = s2i(cntEl->second); if((cntEl=ses.cnt.find(s_id+"_m")) != ses.cnt.end()) tm_tm.tm_min = s2i(cntEl->second); if((cntEl=ses.cnt.find(s_id+"_s")) != ses.cnt.end()) tm_tm.tm_sec = s2i(cntEl->second); val = i2s(mktime(&tm_tm)); if(compare) { if(cntrIfCmd(req)) ses.mess.push_back(req.text().c_str()); if(req.text() == val) return false; //No change time } } else { if((cntEl=ses.cnt.find(node.attr("id"))) != ses.cnt.end()) { val = cntEl->second; if(compare) { if(cntrIfCmd(req)) ses.mess.push_back(req.text().c_str()); if(req.text() == val) return false; //No change fld } } else return false; } node.setText(val); return true; } int TWEB::cntrIfCmd( XMLNode &node ) { SYS->cntrCmd(&node); return s2i(node.attr("rez")); } string TWEB::getCookie( string name, vector &vars ) { for(unsigned i_var = 0; i_var < vars.size(); i_var++) if(vars[i_var].substr(0, vars[i_var].find(":",0)) == "Cookie") { size_t i_beg = vars[i_var].find(name+"=",0); if(i_beg == string::npos) return ""; i_beg += name.size()+1; return vars[i_var].substr(i_beg,vars[i_var].find(";",i_beg)-i_beg); } return ""; } void TWEB::colontDown( SSess &ses ) { //Draw path ses.page += "
"+ses.url+"
\n"; //Make warning messages if(ses.mess.size()) { ses.page += "\n"; } } string TWEB::cntGet( SSess &ses, const string &nm ) { map::iterator prmEl = ses.cnt.find(nm); if(prmEl != ses.cnt.end()) return prmEl->second; return ""; } //************************************************* //* SSess * //************************************************* SSess::SSess( const string &iurl, const string &isender, const string &iuser, vector &ivars, const string &icontent ) : url(iurl), sender(isender), user(TSYS::strLine(iuser,0)), content(icontent), vars(ivars) { //URL parameters parse size_t prmSep = iurl.find("?"); if(prmSep != string::npos) { url = iurl.substr(0,prmSep); string prms = iurl.substr(prmSep+1); string sprm; for(int iprm = 0; (sprm=TSYS::strSepParse(prms,0,'&',&iprm)).size(); ) if((prmSep=sprm.find("=")) == string::npos) prm[sprm] = "true"; else { prm[sprm.substr(0,prmSep)] = sprm.substr(prmSep+1); if(sprm.substr(0,prmSep) == "lang") gPrms += (gPrms.size()?"&":"") + sprm; } } if(gPrms.size()) gPrms = "?" + gPrms; //Get language for(size_t iVr = 0; iVr < vars.size(); iVr++) if(TSYS::strParse(vars[iVr],0,":") == "oscd_lang") { lang = sTrm(TSYS::strParse(vars[iVr],1,":")); break; } //Content parse string boundary; const char *c_bound = "boundary="; const char *c_term = "\x0D\x0A"; const char *c_end = "--"; const char *c_fd = "Content-Disposition"; const char *c_name = "name=\""; for(size_t i_vr = 0, pos = 0; i_vr < vars.size() && boundary.empty(); i_vr++) if(vars[i_vr].compare(0,vars[i_vr].find(":",0),"Content-Type") == 0 && (pos=vars[i_vr].find(c_bound,0)) != string::npos) { pos += strlen(c_bound); boundary = vars[i_vr].substr(pos,vars[i_vr].size()-pos); } if(boundary.empty()) return; for(size_t pos = 0, spos = 0, i_bnd = 0; true; ) { pos = content.find(boundary,pos); if(pos == string::npos || content.compare(pos+boundary.size(),2,c_end) == 0) break; pos += boundary.size()+strlen(c_term); // Process properties and get name string p_name; while(pos < content.size()) { string c_head = content.substr(pos, content.find(c_term,pos)-pos); pos += c_head.size()+strlen(c_term); if(c_head.empty()) break; if((spos=c_head.find(":")) == string::npos) return; if(c_head.compare(0,spos,c_fd) == 0 && (i_bnd=c_head.find(c_name,spos)) != string::npos) { i_bnd += strlen(c_name); p_name = c_head.substr(i_bnd,c_head.find("\"",i_bnd)-i_bnd); } } if(pos >= content.size()) return; if(!p_name.empty()) cnt[p_name] = content.substr(pos,content.find(string(c_term)+c_end+boundary,pos)-pos); } } void TWEB::modInfo( vector &list ) { TModule::modInfo(list); list.push_back("SubType"); list.push_back("Auth"); } string TWEB::modInfo( const string &name ) { if(name == "SubType") return SUB_TYPE; if(name == "Auth") return "1"; return TModule::modInfo(name); }