From: konrad Date: Tue, 18 Aug 2009 17:02:23 +0000 (+0000) Subject: *auditing (used to log money transfers) X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=ee8a7bcd26ef69f58d6785ce026e5033e71bd575;p=web%2Fkonrad%2Fsmoke.git *auditing (used to log money transfers) *brought woc table generation up to snuff *allow calls in mappings git-svn-id: https://silmor.de/svn/softmagic/smoke/trunk@335 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33 --- diff --git a/wob/audit.wolf b/wob/audit.wolf index af255b3..1a8443e 100644 --- a/wob/audit.wolf +++ b/wob/audit.wolf @@ -7,20 +7,6 @@ - see COPYING.AGPL for details --> - - - - - - - - - - - - -
- diff --git a/wob/event.wolf b/wob/event.wolf index dd11253..777b778 100644 --- a/wob/event.wolf +++ b/wob/event.wolf @@ -73,6 +73,13 @@ + + + + + + + @@ -102,7 +109,9 @@ - + + + diff --git a/wob/magicsmoke.wolf b/wob/magicsmoke.wolf index f6ac072..e898b9b 100644 --- a/wob/magicsmoke.wolf +++ b/wob/magicsmoke.wolf @@ -10,7 +10,19 @@ - + + + + + + + + + + + + + @@ -18,7 +30,7 @@ diff --git a/wob/order.wolf b/wob/order.wolf index 6921415..6507c4a 100644 --- a/wob/order.wolf +++ b/wob/order.wolf @@ -13,7 +13,12 @@
- +
+ + + +
+ @@ -43,12 +48,19 @@ + + + + +
- +
- + + + @@ -70,9 +82,11 @@
- +
- + + + @@ -94,7 +108,7 @@
- +
diff --git a/woc/phpout.cpp b/woc/phpout.cpp index 8f256fb..676bb26 100644 --- a/woc/phpout.cpp +++ b/woc/phpout.cpp @@ -169,7 +169,7 @@ void WocPHPServerOut::newTable(const WocTable&tbl) for(int i=0;iescapeColumn(\""+foreign[0]+"\",\""+foreign[1]+"\",$this->"+cols[i]+"));\n}\n\n"; } @@ -214,6 +214,31 @@ void WocPHPServerOut::newTable(const WocTable&tbl) code+="const "+ens[i].first+"="+QString::number(ens[i].second)+";\n"; } + //hasproperty function + code+="public function hasProperty($p){switch($p){\n"; + for(int i=0;idata,false,\""+tbl.name()+"_audit\");\n"; + code+="\treturn $ad->insert();\n}\n"; + } + + //create newKey function + code+="public function newKey(){\n\tparent::newKey();\n"; + for(int i=0;i >map=cls.mapping(k[i]); - for(int j=0;j"+map[j].first+";\n"; + QMapmap=cls.mapping(k[i]); + QStringList mapk=map.keys(); + for(int j=0;j"+map[mapk[j]]+";\n"; } code+="\treturn $data;\n}\n"; code+="static public function fromTableArray"+k[i]+"(array $table){\n\t$ret=array();\n"; @@ -792,6 +820,8 @@ void WocPHPServerOut::newTransaction(const WocTransaction&trn) //getters/setters tf.write(trnGetSet(trn).toAscii()); + //direct execution + tf.write(trnExecute(trn).toAscii()); //end code="\n//end of class\n}\n"; @@ -991,3 +1021,22 @@ QString WocPHPServerOut::trnGetSet(const WocTransaction&trn) return code; } + +QString WocPHPServerOut::trnExecute(const WocTransaction&trn) +{ + QStringList in=trn.inputNames(); + QString code="static public function execute("; + for(int i=0;i >map; + QListmap; QDomNodeList nl2=el.elementsByTagName("Map"); for(int j=0;j(col,prp)); + QDomNodeList nl3=el2.elementsByTagName("Call"); + for(int k=0;k WocClass::mapping(QString m)const +{ + if(!m_maps.contains(m))return QMap(); + QList sml=m_maps[m]; + QMapret; + for(int i=0;i sml=m_maps[table]; + for(int i=0;i cl=parseColumn(el,m_name); + if(!cl.first)return; + if(hasColumn(cl.second.name)){ + qDebug("Error: double definition of column %s in table %s.",cl.second.name.toAscii().data(),m_name.toAscii().data()); m_valid=false; return; } - if(hasColumn(cl.name)){ - qDebug("Error: double definition of column %s in table %s.",cl.name.toAscii().data(),m_name.toAscii().data()); - m_valid=false; - return; - } - cl.isprime=str2bool(el.attribute("primarykey","0")); - cl.isunique=str2bool(el.attribute("unique","0")); - cl.isindex=str2bool(el.attribute("index","0")); - if(el.hasAttribute("null")) - cl.isnull=str2bool(el.attribute("null")); - else - cl.isnull=!str2bool(el.attribute("notnull","0")); - cl.type=el.attribute("type"); - //TODO: validate type - cl.foreign=el.attribute("foreignkey"); - //check foreign key exists - if(cl.foreign!=""){ - QStringList fgn=cl.foreign.split(":"); - if(fgn.size()!=2){ - qDebug("Error: table %s column %s: foreign key definition must use syntax 'table:column'",m_name.toAscii().data(),cl.name.toAscii().data()); - m_valid=false; - return; - } - if(!woc->hasTable(fgn[0])){ - qDebug("Error: table %s column %s: foreign key target table %s does not exist",m_name.toAscii().data(),cl.name.toAscii().data(),fgn[0].toAscii().data()); - m_valid=false; - return; - } - if(!woc->table(fgn[0]).hasColumn(fgn[1])){ - qDebug("Error: table %s column %s: foreign key target table/column %s does not exist",m_name.toAscii().data(),cl.name.toAscii().data(),cl.foreign.toAscii().data()); - m_valid=false; - return; - } - } - cl.defaultval=el.attribute("default"); - //TODO: validate default against type - QDomNodeList nl2=el.elementsByTagName("Value"); - int nxval=0; - //enum values - for(int j=0;j(n,nxval)); - nxval++; - } - m_columns.append(cl); + m_columns.append(cl.second); + } + //Audit Columns + nl=tbl.elementsByTagName("AuditColumn"); + for(int i=0;i cl=parseColumn(el,m_name); + if(!cl.first)return; + m_auditcolumns.append(cl.second); } //Foreign getter methods @@ -675,6 +673,74 @@ WocTable::WocTable(const QDomElement&tbl) } } + +QPair WocTable::parseColumn(const QDomElement&el,QString m_name) +{ + s_col cl; + QRegExp good("[a-z][a-z0-9_]*",Qt::CaseInsensitive); + cl.name=el.attribute("name"); + //check name syntax, check it is not doubled + if(!good.exactMatch(cl.name)){ + qDebug("Error: table %s column %s does not have a regular name.",m_name.toAscii().data(),cl.name.toAscii().data()); + return QPair(false,s_col()); + } + cl.isprime=str2bool(el.attribute("primarykey","0")); + cl.isunique=str2bool(el.attribute("unique","0")); + cl.isindex=str2bool(el.attribute("index","0")); + if(el.hasAttribute("null")) + cl.isnull=str2bool(el.attribute("null")); + else + cl.isnull=!str2bool(el.attribute("notnull","0")); + cl.type=el.attribute("type"); + //TODO: validate type + cl.foreign=el.attribute("foreignkey"); + WocProcessor*woc=WocProcessor::instance(); + //check foreign key exists + if(cl.foreign!=""){ + QStringList fgn=cl.foreign.split(":"); + if(fgn.size()!=2){ + qDebug("Error: table %s column %s: foreign key definition must use syntax 'table:column'",m_name.toAscii().data(),cl.name.toAscii().data()); + return QPair(false,s_col()); + } + if(!woc->hasTable(fgn[0])){ + qDebug("Error: table %s column %s: foreign key target table %s does not exist",m_name.toAscii().data(),cl.name.toAscii().data(),fgn[0].toAscii().data()); + return QPair(false,s_col()); + } + if(!woc->table(fgn[0]).hasColumn(fgn[1])){ + qDebug("Error: table %s column %s: foreign key target table/column %s does not exist",m_name.toAscii().data(),cl.name.toAscii().data(),cl.foreign.toAscii().data()); + return QPair(false,s_col()); + } + } + cl.defaultval=el.attribute("default"); + //TODO: validate default against type + QDomNodeList nl2=el.elementsByTagName("Value"); + int nxval=0; + //enum values + for(int j=0;j(n,nxval)); + nxval++; + } + //default calls + nl2=el.elementsByTagName("Call"); + for(int j=0;j(true,cl); +} + QStringList WocTable::columns()const { QStringList r; @@ -683,6 +749,16 @@ QStringList WocTable::columns()const return r; } +QStringList WocTable::auditColumns()const +{ + QStringList r; + for(int i=0;iWocTable::m_staticauditcolumns; +void WocTable::parseAuditStatic(const QDomElement&el) +{ + QDomNodeList nl=el.elementsByTagName("Column"); + for(int i=0;icl=parseColumn(el2,"(global audit settings)"); + if(!cl.first){ + WocProcessor::instance()->errorFound(); + return; + } + m_staticauditcolumns.append(cl.second); + } +} + +WocTable WocTable::auditTable()const +{ + WocTable adt; + adt.m_valid=m_valid; + adt.m_backup=m_backup; + adt.m_audit=false; + adt.m_name=m_name+"_audit";//enhance the name + adt.m_base="WobTable";//revert to default + adt.m_foreign=m_foreign; + //these stay empty: m_presets, m_auditcolumns + + //now for the complicated stuff + //create primary key + s_col cl; + cl.name="auditid";cl.type="seq64"; + cl.isindex=cl.isunique=cl.isnull=false;cl.isprime=true; + adt.m_columns.append(cl); + //copy common columns + adt.m_columns.append(m_staticauditcolumns); + //copy normal columns + for(int i=0;i >mapping(QString m)const{return m_maps[m];} + /**returns the specific mapping; map key=property, map value=column*/ + QMap mapping(QString m)const; + /**returns the method for a specific mapping or an empty string if it does not exist in the specified language*/ + QString mapMethod(QString table,QString property,QString lang)const; private: //valid: parsing the WOLF succeeded @@ -111,7 +113,11 @@ class WocClass }; QList m_props; //mappings: "table-name" => List of ("column-name","property-name") - QMap > >m_maps; + struct s_map{ + QString column,property; + QMapmethod;//lang->method + }; + QMap >m_maps; //enum types: "type-name" => List of ("constant-name",int-constant-value) QMap > >m_enumvals; //serializers: "name" => List of properties (syntax Objects: "propertyname/Serializer" @@ -166,6 +172,8 @@ class WocTable bool columnIsUnique(QString)const; /**returns enum definitions of the column - each pair contains the symbolic name in first and the assigned integer value in second*/ QList > columnEnums(QString)const; + /**returns the insert call of a column for a specific language; empty string if there is none*/ + QString columnCall(QString col,QString lang)const; /**returns all enum definitions of the table; see also columnEnums */ QList > getEnums()const; @@ -180,17 +188,31 @@ class WocTable /**returns a list of all preset values (to be generated when the DB is created); each entry in the list is a dictionary with the column name as key and the intended preset value as value - each entry of the list is one DB row, each key-value-pair in the map is one preset value in that row*/ QList > presets()const{return m_presets;} + + /**parses the static part of auditing*/ + static void parseAuditStatic(const QDomElement&); + /**returns whether the table is auditable*/ + bool isAuditable()const{return m_audit;} + /**creates and returns the table instance that represents the audit table*/ + WocTable auditTable()const; + /**returns the names of audit columns (except auditid)*/ + QStringList auditColumns()const; private: - bool m_valid,m_backup; + bool m_valid,m_backup,m_audit; QString m_name,m_base; struct s_col { QString name,type,foreign,defaultval; bool isnull,isprime,isindex,isunique; QList >enumvals; + QMapmethodcalls; }; - QListm_columns; + QListm_columns,m_auditcolumns; + static QListm_staticauditcolumns; QList >m_foreign; QList >m_presets; + + //helper method: parses a single column element + static QPair parseColumn(const QDomElement&,QString); }; /**internal representation of a transaction*/ @@ -349,7 +371,7 @@ class WocProcessor:public QObject void newClass(const WocClass&); void newTable(const WocTable&); void newTransaction(const WocTransaction&); - private slots: + public slots: void errorFound(); private: QString m_baseDir,m_wobDir,m_verComm,m_verNeedComm,m_verHR,m_projname; diff --git a/www/inc/db/autoload.php b/www/inc/db/autoload.php index 741b725..f33f429 100644 --- a/www/inc/db/autoload.php +++ b/www/inc/db/autoload.php @@ -12,6 +12,7 @@ // $AUTOCLASS["DbEngine"]='./inc/db/db.php'; $AUTOCLASS["MysqlEngine"]='./inc/db/db_mysql.php'; +$AUTOCLASS["BarcodeTable"]='./inc/db/barcodetable.php'; include('./inc/db/db_scheme.php'); ?> \ No newline at end of file diff --git a/www/inc/db/barcodetable.php b/www/inc/db/barcodetable.php new file mode 100644 index 0000000..57527be --- /dev/null +++ b/www/inc/db/barcodetable.php @@ -0,0 +1,44 @@ +, (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +class BarcodeTable extends WobTable +{ + private static $NumTicketChars=false; + private static function init() + { + if(self::$NumTicketChars===false){ + self::$NumTicketChars=$db->getConfig("TicketIDChars")+0; + if(self::$NumTicketChars<=5)self::$NumTicketChars=10; + } + } + public static function getNewTicketId() + { + self::init(); + do{ + $tid=getCode39ID(self::$NumTicketChars,RND_TICKET); + $res=$db->select("ticket","ticketid","ticketid=".$db->escapeString($tid)); + if(count($res)==0)return $tid; + }while(true); + } + public static function getNewVoucherId() + { + self::init(); + do{ + $tid=getCode39ID(self::$NumTicketChars,RND_VOUCHER); + $res=$db->select("voucher","voucherid","voucherid=".$db->escapeString($tid)); + if(count($res)==0)return $tid; + }while(true); + } +}; + +?> \ No newline at end of file diff --git a/www/inc/db/db.php b/www/inc/db/db.php index 00a7656..555b3f5 100644 --- a/www/inc/db/db.php +++ b/www/inc/db/db.php @@ -195,6 +195,8 @@ abstract class DbEngine $cm=""; $val=") VALUES ("; while(list($k,$v)=each($values)){ + //make sure the column exists, ignore the riff-raff + if(!$dbScheme->tableHasColumn($table,$k))continue; $ret.=$cm;$val.=$cm;$cm=","; //append column name $ret.=$k; @@ -230,6 +232,8 @@ abstract class DbEngine reset($values); $cm=""; while(list($k,$v)=each($values)){ + //make sure the column exists, ignore the riff-raff + if(!$dbScheme->tableHasColumn($table,$k))continue; $ret.=$cm;$cm=","; //append column name $ret.=$k."="; diff --git a/www/inc/machine/session.php b/www/inc/machine/session.php index 218cae2..9e89db6 100644 --- a/www/inc/machine/session.php +++ b/www/inc/machine/session.php @@ -19,10 +19,10 @@ $db->deleteRows("session","timeout<=".time()); /**The session class*/ class Session { - private $sessid=""; - private $user=""; - private $roles; - private $rights; + protected $sessid=""; + protected $user=""; + protected $roles; + protected $rights; /**construct the session object, check validity*/ public function __construct($trans) @@ -48,6 +48,21 @@ class Session return $session; } + /**return the name of the currently logged in user*/ + public static function currentUserName() + { + global $session; + if(isset($session))return $session->getUser(); + else return "(unknown)"; + } + + /**initialize system in web session mode (ie. some user called the web page in a browser)*/ + public static function setWebSession() + { + global $session; + $session=new DummyWebSession; + } + /**internal: retrieve and remember the rights of this user*/ protected function initRights() { @@ -67,7 +82,7 @@ class Session /**returns all roles of this user*/ public function getRoles(){return $this->roles;} - /**creates a new session*/ + /**creates a new session, called from the Login transaction*/ static public function login($trans) { global $db,$ClientSessionTimeout; @@ -79,39 +94,39 @@ class Session $hosts[]=$hst["host"]; //logic check 1: abort if host is unknown if(count($hres)==0){ - $trans->abortWithError(translate("php::","Unknown Host"),"auth"); + $trans->abortWithError(translate("Session","Unknown Host"),"auth"); } //logic check: login is allowed if // a) $hosts contains _any and the host is known, or // b) $hosts contains the transmitted host name $hostname=$trans->gethostname(); if( !in_array($hostname,$hosts) && !in_array("_any",$hosts)){ - $trans->abortWithError(translate("php::","Host/User combination not allowed"),"auth"); + $trans->abortWithError(translate("Session","Host/User combination not allowed"),"auth"); } //validate host $splt=explode(" ",$hres[0]["hostkey"]); if(count($splt)!=2){ - $trans->abortWithError(translate("php::","Host authentication failed"),"auth"); + $trans->abortWithError(translate("Session","Host authentication failed"),"auth"); } $cmp=strtolower(sha1($splt[0].$trans->gethostkey())); if($cmp != strtolower($splt[1])){ - $trans->abortWithError(translate("php::","Host authentication failed"),"auth"); + $trans->abortWithError(translate("Session","Host authentication failed"),"auth"); } //get user data $ures=$db->select("user","*","uname=".$db->escapeString($trans->getusername())); if(count($ures)<1){ - $trans->abortWithError(translate("php::","User Authentication failed"),"auth"); + $trans->abortWithError(translate("Session","User Authentication failed"),"auth"); } //validate user $splt=explode(" ",$ures[0]["passwd"]); if(count($splt)!=2){ - $trans->abortWithError(translate("php::","User Authentication failed"),"auth"); + $trans->abortWithError(translate("Session","User Authentication failed"),"auth"); } $cmp=strtolower(sha1($splt[0].$trans->getpassword())); if($cmp!=strtolower($splt[1])){ - $trans->abortWithError(translate("php::","User Authentication failed"),"auth"); + $trans->abortWithError(translate("Session","User Authentication failed"),"auth"); } //create session and return @@ -161,16 +176,7 @@ class Session return $this->user!=""; } - /**helper function for authenticate*/ - protected function xdie($str) - { - //debug version: -// print($str); - //all versions - exit(); - } - - /**set my own password*/ + /**set my own password; called from SetMyPasswd transaction*/ public function setMyPasswd($trans) { $old=$trans->getoldpassword(); @@ -214,333 +220,17 @@ class Session } }; -//return all users to client -function getAllUsersXml() -{ - global $db; - header("X-MagicSmoke-Status: Ok"); - $res=$db->select("users","uname,description",""); - $dom=new DomDocument; - $root=$dom->createElement("Users"); - for($i=0;$icreateElement("User",xq($res[$i]["description"])); - $usr->setAttributeNode(new DOMAttr("name",$res[$i]["uname"])); - $root->appendChild($usr); - } - $dom->appendChild($root); - print($dom->saveXML()); -} - -//return the roles of a specific user -function getUserAclXml($user) +/**dummy class used by browsed pages to represent the virtual web user*/ +class DummyWebSession extends Session { - //sanity check - $user=trim($user); - if(ereg("^[A-Za-z0-9_\\.,:-]+$",$user)===false){ - header("X-MagicSmoke-Status: SyntaxError"); - die(tr("invalid user name")); - } - //go on... - global $db,$ALLOWEDREQUESTS,$SPECIALROLES; - header("X-MagicSmoke-Status: Ok"); - //create list of roles - $roles=$ALLOWEDREQUESTS; - foreach($SPECIALROLES as $rl) - $roles[]=$rl; - //get roles from DB - $res=$db->select("userrole","role","uname=".$db->escapeString($user)); - $acl=array(); - foreach($res as $rl)$acl[]=$rl["role"]; - $dom=new DOMDocument; - $root=$dom->createElement("ACL"); - $root->setAttributeNode(new DOMAttr("user",$user)); - foreach($roles as $rl){ - $re=$dom->createElement("Role"); - $re->setAttributeNode(new DOMAttr("name",$rl)); - if(array_search($rl,$acl)===false)$re->setAttributeNode(new DOMAttr("set","0")); - else $re->setAttributeNode(new DOMAttr("set","1")); - $root->appendChild($re); - } - $dom->appendChild($root); - print($dom->saveXML()); -} - -//set the ACL of a user -function setUserAclXml($txt) -{ - //DOM - $xml=new DOMDocument; - if(!$xml->loadXML($txt)){ - header("X-MagicSmoke-Status: SyntaxError"); - die(tr("unable to parse XML data")); - } - //get user name - $acl=$xml->getElementsByTagName("ACL"); - if($acl->length != 1){ - header("X-MagicSmoke-Status: SyntaxError"); - die(tr("expected exactly 1 ACL element")); - } - global $db,$ALLOWEDREQUESTS,$SPECIALROLES; - $roles=$ALLOWEDREQUESTS; - foreach($SPECIALROLES as $rl) - $roles[]=$rl; - $usr=$acl->item(0)->getAttribute("user"); - //check user name - $db->beginTransaction(); - $res=$db->select("users","count(uname)","uname=".$db->escapeString($usr)); - if($res[0][0]!=1){ - header("X-MagicSmoke-Status: SyntaxError"); - $db->rollbackTransaction(); - die(tr("unknown user name")); - } - //update roles - $acl=$xml->getElementsByTagName("Role"); - for($i=0;$i<$acl->length;$i++){ - //does role exist? - $name=$acl->item($i)->getAttribute("name"); - if(array_search($name,$roles)===false)continue; - $isset=$acl->item($i)->getAttribute("set")+0; - if($isset){ - $res=$db->select("userrole","count(role)","uname=".$db->escapeString($usr)." AND role=".$db->escapeString($name)); - if($res[0][0]!=0)continue; - $db->insert("userrole",array("uname"=>$usr,"role"=>$name)); - }else{ - $db->deleteRows("userrole","uname=".$db->escapeString($usr)." AND role=".$db->escapeString($name)); - } - } - $db->commitTransaction(); - header("X-MagicSmoke-Status: Ok"); -} - -//return the hosts of a specific user -function getUserHostsXml($user) -{ - //sanity check - $user=trim($user); - if(ereg("^[A-Za-z0-9_\\.,:-]+$",$user)===false){ - header("X-MagicSmoke-Status: SyntaxError"); - die(tr("invalid user name")); - } - //go on... - global $db; - header("X-MagicSmoke-Status: Ok"); - //create list of hosts - $hosts=array(); - $res=$db->select("host","hostname",""); - for($i=0;$iselect("userhosts","host","uname=".$db->escapeString($user)); - $acl=array(); - foreach($res as $rl)$acl[]=$rl["host"]; - $dom=new DOMDocument; - $root=$dom->createElement("Hosts"); - $root->setAttributeNode(new DOMAttr("user",$user)); - foreach($hosts as $hs){ - $re=$dom->createElement("Host"); - $re->setAttributeNode(new DOMAttr("name",$hs)); - if(array_search($hs,$acl)===false)$re->setAttributeNode(new DOMAttr("set","0")); - else $re->setAttributeNode(new DOMAttr("set","1")); - $root->appendChild($re); - } - $dom->appendChild($root); - print($dom->saveXML()); -} - -//set the Hosts of a user -function setUserHostsXml($txt) -{ - //DOM - $xml=new DOMDocument; - if(!$xml->loadXML($txt)){ - header("X-MagicSmoke-Status: SyntaxError"); - die(tr("unable to parse XML data")); - } - //get user name - $acl=$xml->getElementsByTagName("Hosts"); - if($acl->length != 1){ - header("X-MagicSmoke-Status: SyntaxError"); - die(tr("expected exactly 1 Hosts element")); - } - global $db; - //create list of hosts - $hosts=array(); - $res=$db->select("host","hostname",""); - for($i=0;$iitem(0)->getAttribute("user"); - //check user name - $db->beginTransaction(); - $res=$db->select("users","count(uname)","uname=".$db->escapeString($usr)); - if($res[0][0]!=1){ - header("X-MagicSmoke-Status: SyntaxError"); - $db->rollbackTransaction(); - die(tr("unknown user name")); - } - //update roles - $acl=$xml->getElementsByTagName("Host"); - for($i=0;$i<$acl->length;$i++){ - //does role exist? - $name=$acl->item($i)->getAttribute("name"); - if(array_search($name,$hosts)===false)continue; - $isset=$acl->item($i)->getAttribute("set")+0; - if($isset){ - $res=$db->select("userhosts","count(host)","uname=".$db->escapeString($usr)." AND host=".$db->escapeString($name)); - if($res[0][0]!=0)continue; - $db->insert("userhosts",array("uname"=>$usr,"host"=>$name)); - }else{ - $db->deleteRows("userhosts","uname=".$db->escapeString($usr)." AND host=".$db->escapeString($name)); - } - } - $db->commitTransaction(); - header("X-MagicSmoke-Status: Ok"); -} - -//helper function: parse User-XML-structure -function parseUserXml($txt) -{ - $xml=new DOMDocument; - if(!$xml->loadXML($txt)){ - header("X-MagicSmoke-Status: SyntaxError"); - die(tr("unable to parse XML data")); - } - $ret=array(); - foreach($xml->getElementsByTagName("User") as $el){ - $usr["name"]=$el->getAttribute("name"); - $usr["descr"]=""; - $usr["passwd"]=$el->getAttribute("passwd"); - foreach($el->childNodes as $cn) - if($cn->nodeType==XML_TEXT_NODE) - $usr["descr"]=$cn->wholeText; - $ret[]=$usr; - } - return $ret; -} - -//set new description for user -function setUserDescrXml($txt) -{ - global $db; - $usr=parseUserXml($txt); - for($i=0;$iupdate("users",array("description"=>$usr[$i]["descr"]),"uname=".$db->escapeString($usr[$i]["name"])); - } - header("X-MagicSmoke-Status: Ok"); -} - -//add a new user -function addUserXml($txt) -{ - global $db; - $usr=parseUserXml($txt); - $dom=new DOMDocument; - $root=$dom->createElement("Users"); - for($i=0;$ibeginTransaction(); - $res=$db->select("users","uname","uname='".$usr[$i]["name"]."'"); - if(count($res)==0){ - //create new - $db->insert("users",array("uname"=>$usr[$i]["name"],"description"=>$usr[$i]["descr"],"passwd"=>$usr[$i]["passwd"])); - //print data - $udm=$dom->createElement("User",xq($usr[$i]["descr"])); - $udm->setAttributeNode(new DOMAttr("name",$usr[$i]["name"])); - $root->appendChild($udm); - } - $db->commitTransaction(); - } - $dom->appendChild($root); - print($dom->saveXML()); - header("X-MagicSmoke-Status: Ok"); -} - -//delete a user -function deleteUserXml($txt) -{ - global $db; - $lst=explode("\n",trim($txt)); - if($lst===false || count($lst)<1){ - header("X-MagicSmoke-Status: SyntaxError"); - echo tr("Syntax Error"); - return; - } - $usr=trim($lst[0]); - if(count($lst)>1)$nusr=trim($lst[1]); - else $nusr=false; - //start transaction - $db->beginTransaction(); - $b=true; - //delete ACL - $b &= $db->deleteRows("userrole","uname=".$db->escapeString($usr)) !== false; - //delete Hosts - $b &= $db->deleteRows("userhosts","uname=".$db->escapeString($usr)) !== false; - //delete open sessions - $b &= $db->deleteRows("session","user=".$db->escapeString($usr)) !== false; - //check for success so far - if(!$b){ - $db->rollbackTransaction(); - echo tr("Cannot remove user: DB error while deleting ACL."); - return; - } - //re-assign DB objects - $b &= $db->update("order",array("soldby"=>$nusr),"soldby=".$db->escapeString($usr)) !== false; - $b &= $db->update("order",array("depositat"=>$nusr),"depositat=".$db->escapeString($usr)) !== false; - $b &= $db->update("ticket",array("reservedby"=>$nusr),"reservedby=".$db->escapeString($usr)) !== false; - if(!$b){ - header("X-MagicSmoke-Status: Error"); - echo tr("Cannot remove user: unable to replace user."); - //end transaction - $db->rollbackTransaction(); - return; - } - //attempt to delete User itself - $b=$db->deleteRows("users","uname=".$db->escapeString($usr)) !== false; - //say OK or not OK now - if($b){ - header("X-MagicSmoke-Status: Ok"); - //end transaction - $db->commitTransaction(); - }else{ - header("X-MagicSmoke-Status: Error"); - echo tr("Cannot remove user: DB error while deleting user."); - //end transaction - $db->rollbackTransaction(); - } -} - -//set another users passwd -function setPasswdXml($txt) -{ - global $db; - //parse XML - $dom=new DOMDocument; - if(!$dom->loadXML($txt)){ - header("X-MagicSmoke-Status: SyntaxError"); - die(tr("unable to parse XML data")); - } - $nl=$dom->getElementsByTagName("SetPasswd"); - if($nl->length!=1){ - header("X-MagicSmoke-Status: SyntaxError"); - die(tr("expected exactly one passwd element")); - } - $spw=$nl->item(0); - $usr=$spw->getAttribute("user"); - $nwp=$spw->getAttribute("newpwd"); - //sanity check - if($nwp==""){ - header("X-MagicSmoke-Status: SyntaxError"); - die(tr("cannot set an empty password")); + public function __construct() + { + $this->user="(web)"; + //fake admin, because web pages do their own checks + //TODO: do something more sensible (eg. _web role) + $this->roles=array("_admin"); + $this->rights=array(); } - //set new password - if($db->update("users",array("passwd"=>$nwp),"uname=".$db->escapeString($usr))===false){ - header("X-MagicSmoke-Status: Error"); - die(tr("Unable to change this password.")); - }else - header("X-MagicSmoke-Status: Ok"); } ?> \ No newline at end of file diff --git a/www/inc/wbase/table.php b/www/inc/wbase/table.php index 79070d2..7d103f2 100644 --- a/www/inc/wbase/table.php +++ b/www/inc/wbase/table.php @@ -11,6 +11,7 @@ // // +/**thrown by WobTable if a property change is out of range*/ class ValueOutOfRange extends Exception { public function __construct($tab,$col,$val) @@ -19,38 +20,76 @@ class ValueOutOfRange extends Exception } }; -class WobTable +/**parent class of all tables*/ +abstract class WobTable { private $data; + private $cdata; private $isfromdb; private $table; + /**constructs a basic table*/ protected function __construct(array $data,$isfromdb,$table) { $this->data=$data; $this->isfromdb=$isfromdb; $this->table=$table; + $this->cdata=array(); } + /**set properties*/ public function __set($name,$value) { - global $db,$dbScheme; - //verify name against scheme - if(!$dbScheme->tableHasColumn($this->table,$name))return; - //verify enum vals + //check for property + if(!$this->hasProperty($name)){ + $trace=debug_backtrace(); + trigger_error("Trying to set undefined property ".$name." in ".$trace[0]['file']." on line ".$trace[0]['line'],E_USER_NOTICE); + } + //verify value (TODO: what about NULL?) $vm="verifyValue".$name; if(method_exists($this,$vm)) - if(!$t->$vm($value)) + if(!$this->$vm($value)) throw ValueOutOfRange($this->table,$name,$value); - //DB update (if from DB) - $succ=true; - if($this->isfromdb){ - $succ=$db->update($this->table,array($name => $value),$this->where()); + //set + $this->cdata[$name]=$value; + } + + /**reverts changes to the property*/ + public function revert($name) + { + if(!$this->hasProperty($name)){ + $trace=debug_backtrace(); + trigger_error("Trying to revert undefined property ".$name." in ".$trace[0]['file']." on line ".$trace[0]['line'],E_USER_NOTICE); } - //if successful: store - if($succ)$this->data[$name]=$value; + if(array_key_exists($name,$this->cdata))unset($this->cdata[$name]); } + /**reverts all changes to properties*/ + public function revertAll() + { + $this->cdata=array(); + } + + /**returns the name of the table*/ + public function tableName(){return $this->table;} + + /**returns whether the table contains a specific column*/ + public function hasColumn($c) + { + global $dbScheme; + return $dbScheme->tableHasColumn($this->table,$name); + } + + /**overridden by woc, returns true if the property exists*/ + abstract public function hasProperty($c); + + /**returns whether this is an auditable table*/ + public function isAuditable(){return false;} + + /**overridden by woc, if this an auditable table; used in insert and update*/ + protected function createAudit(){} + + /**returns the where clause to find this instance (via primary key columns)*/ public function where() { global $dbScheme,$db; @@ -63,11 +102,17 @@ class WobTable return $r; } + /**returns the property*/ public function __get($name) { //verify name + if(!$this->hasProperty($name)){ + $trace=debug_backtrace(); + trigger_error("Accessing undefined property ".$name." in ".$trace[0]['file']." on line ".$trace[0]['line'],E_USER_NOTICE); + } //return value or null - if(isset($this->data[$name]))return $this->data[$name]; + if(array_key_exists($name,$this->cdata))return $this->cdata[$name]; + if(array_key_exists($name,$this->data))return $this->data[$name]; else return null; } @@ -75,7 +120,8 @@ class WobTable { global $db; //verify name and return true on existence AND notnull - if(isset($this->data[$name]))return !$db->isNull($this->data[$name]); + if(array_key_exists($name,$this->cdata))return isset($this->cdata[$name]); + if(array_key_exists($name,$this->data))return isset($this->data[$name]); else return false; } @@ -83,30 +129,80 @@ class WobTable { global $dbScheme; //reset to null - if($dbScheme->tableHasColumn($name))$this->data[$name]=null; + if($this->hasProperty($name))$this->cdata[$name]=null; } /**insert the object under a new primary key value into the DB (implicitly calls newKey); returns true on success*/ public function insert() { - //remove PK from object (so it is set to default) global $dbScheme; $this->isfromdb=false; - $pk=$dbScheme->primaryKeyColumns($this->table); - foreach($pk as $c)unset($this->data[$c]); - //optionally create new key + //create new key $this->newKey(); //now insert - $r=$db->insert($this->table,$this->data); + $data=array(); + foreach($this->data as $k=>$d)$data[$k]=$d; + foreach($this->cdata as $k=>$d)$data[$k]=$d; + $r=$db->insert($this->table,$data); if($r===false)return false; - //TODO: make this a bit more safe: - if($r!==true)$this->data[$pk[0]]=$r; + $this->isfromdb=true; + $this->data=$data; + $this->cdata=array(); + createAudit(); + //assign primary key if sequence (otherwise newKey has done it) + $seq=$dbScheme->hasSequence($this->table); + if($seq!==false) + $this->data[$seq]=$r; + //return success return true; } - /**generate a new primary key value for insert and marks the object as not yet in the DB; the default sets the primary key to NULL; call the original first if you overwrite it*/ + /**generate a new primary key value for insert and marks the object as not yet in the DB; the default sets the primary key to NULL if it is a sequence; call the original first if you overwrite it*/ public function newKey() { + $this->isfromdb=false; + $pk=$dbScheme->hasSequence($this->table); + if($pk!==false){ + if(array_key_exists($pk,$this->data))unset($this->data[$pk]); + if(array_key_exists($pk,$this->cdata))unset($this->cdata[$pk]); + } + } + + /**updates the object in the database; returns true on success; fails if it did not come from the DB - use insertOrUpdate in this case; succeeds without asking the database if nothing has changed*/ + public function update() + { + if(!$this->isfromdb)return false; + if(count($this->cdata)==0)return true; + global $db; + $succ=$db->update($this->table,$this->cdata,$this->where())!==false; + if($succ){ + foreach($this->cdata as $k=>$d)$this->data[$k]=$d; + $this->cdata=array(); + createAudit(); + } + return $succ; + } + + /**updates existing object in the database or inserts it if it does not exist in the DB yet*/ + public function insertOrUpdate() + { + if($this->isfromdb)return $this->update(); + else return $this->insert(); + } + + /**deletes this instance from the database; returns true if it actually executed*/ + public function deleteFromDb() + { + if(!$this->isfromdb)return false; + global $db; + //obliterate audit data + if($this->isAuditable()) + $db->deleteRows($this->table."_audit",$this->where()); + //delete data + $db->deleteRows($this->table,$this->where()); + //mark as outsider + $this->isfromdb=false; + return true; } }; diff --git a/www/inc/wbase/transaction.php b/www/inc/wbase/transaction.php index 8c34a1f..7d3de02 100644 --- a/www/inc/wbase/transaction.php +++ b/www/inc/wbase/transaction.php @@ -18,6 +18,10 @@ class WobTransactionBase { protected $aoutput; protected $toutput; + protected static $running=""; + + static public function getExecutingName(){return self::$running;} + /**called to determine the correct transaction, aborts the script if there is none.*/ static public function getTransactionName(){ global $_SERVER; @@ -31,7 +35,8 @@ class WobTransactionBase { print("Request is not a Wob Request, Aborting.\n"); exit(); } - return $_SERVER["HTTP_X_WOBREQUEST"]; + self::$running=$_SERVER["HTTP_X_WOBREQUEST"]; + return self::$running; } /**called to determine the session id*/ static public function getHeader($hd) diff --git a/www/index.php b/www/index.php index d8ffbe5..3dfaff2 100644 --- a/www/index.php +++ b/www/index.php @@ -21,6 +21,8 @@ if(isset($_GET["mode"])){ $lang->setLanguage("de"); +Session::setWebSession(); + //get page template and process it switch($mode){ case "eventDetails":