From 0a5a4768a95c8927fe8c959d5bd6adfef3f7c4f3 Mon Sep 17 00:00:00 2001 From: konrad Date: Sat, 14 Mar 2009 18:22:57 +0000 Subject: [PATCH] PHP side of transactions git-svn-id: https://silmor.de/svn/softmagic/smoke/trunk@277 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33 --- wob/magicsmoke.wolf | 6 +- wob/user.wolf | 5 +- woc/phpout.cpp | 267 +++++++++++++++++++++++++++++++++++++++- woc/phpout.h | 16 ++- woc/processor.cpp | 38 ++---- woc/processor.h | 36 ++++++- www/inc/classes/autoload.php | 26 ++++ www/inc/db/autoload.php | 17 +++ www/inc/loader.php | 4 +- www/inc/loader_nonadmin.php | 17 +--- www/inc/machine/autoload.php | 21 ++++ www/inc/machine/session.php | 1 + www/inc/wbase/autoload.php | 1 + www/inc/wbase/transaction.php | 91 ++++++++++++++ www/wob.php | 20 +++ 15 files changed, 509 insertions(+), 57 deletions(-) create mode 100644 www/inc/classes/autoload.php create mode 100644 www/inc/db/autoload.php create mode 100644 www/inc/machine/autoload.php create mode 100644 www/inc/wbase/transaction.php create mode 100644 www/wob.php diff --git a/wob/magicsmoke.wolf b/wob/magicsmoke.wolf index 389cf08..895aa5e 100644 --- a/wob/magicsmoke.wolf +++ b/wob/magicsmoke.wolf @@ -14,8 +14,10 @@ - - + + + + diff --git a/wob/user.wolf b/wob/user.wolf index 348ffe2..2c25549 100644 --- a/wob/user.wolf +++ b/wob/user.wolf @@ -46,9 +46,8 @@ - - - + + diff --git a/woc/phpout.cpp b/woc/phpout.cpp index 716ebf6..8fbda4a 100644 --- a/woc/phpout.cpp +++ b/woc/phpout.cpp @@ -13,6 +13,7 @@ #include "phpout.h" #include +#include static const QByteArray PHPSTART(""); @@ -20,15 +21,29 @@ static const QByteArray PHPEND("\n//END OF AUTOGENERATED FILE\n?>"); static const QByteArray SCHEMASTART("class WobSchema extends WobSchemaBase\n{\nfunction __construct(){\n"); static const QByteArray SCHEMAEND("}};\n"); -WocPHPServerOut::WocPHPServerOut(QString srcDir,QString subDir,QString ext,bool clean) +static const QByteArray TRANSACTSTART("class WobTransaction extends WobTransactionBase\n{\nstatic public function handle(){switch(WobTransactionBase::getTransactionName()){\n"); +static const QByteArray TRANSACTEND("\tdefault:WobTransactionBase::noSuchTransaction();break;\n}}\n};\n"); + +WocPHPServerOut::WocPHPServerOut(const QDomElement&el) { qDebug("Info: creating PHP Server Output Generator."); - m_basedir=WocProcessor::instance()->baseDir()+"/"+srcDir; - m_subdir=subDir; - m_fileext=ext; + m_basedir=WocProcessor::instance()->baseDir()+"/"+el.attribute("sourceDir","."); + m_subdir=el.attribute("subDir","phpwob"); + m_fileext=el.attribute("extension",".inc"); + QDomNodeList nl=el.elementsByTagName("Authenticator"); + if(nl.size()){ + QDomElement el2=nl.at(0).toElement(); + m_isauth=el2.attribute("isAuthenticated","false"); + m_hasrole=el2.attribute("hasRole","false"); + m_username=el2.attribute("userName","\"\""); + }else{ + m_isauth="false"; + m_hasrole="false"; + m_username="\"\""; + } //cleanup directory (remove normal files, assume remainder is harmless) QDir d(m_basedir+"/"+m_subdir); - if(d.exists() && clean){ + if(d.exists() && str2bool(el.attribute("clean","0"))){ QStringList ent=d.entryList(QDir::Files); for(int i=0;isversion=\""+WocProcessor::instance()->dbVersion()+"\";\n").toAscii()); addLoad("WobSchema","schema"); + //create Transaction file + m_transact.setFileName(m_basedir+"/"+m_subdir+"/transaction"+m_fileext); + if(!m_transact.open(QIODevice::ReadWrite|QIODevice::Truncate)){ + qDebug("Error: PHP Server Generator - cannot create transaction processor file."); + emit errorFound(); + return; + } + m_transact.write(PHPSTART); + m_transact.write(TRANSACTSTART); + addLoad("WobTransaction","transaction"); } void WocPHPServerOut::finalize() @@ -67,6 +92,11 @@ void WocPHPServerOut::finalize() m_schema.write(PHPEND); m_schema.close(); } + if(m_transact.isOpen()){ + m_transact.write(TRANSACTEND); + m_transact.write(PHPEND); + m_transact.close(); + } } void WocPHPServerOut::newTable(const WocTable&tbl) @@ -602,7 +632,230 @@ QString WocPHPServerOut::propertyToXml(const WocClass&cls,QString pt) return "//internal generator error!\n"; } -void WocPHPServerOut::newTransaction(const WocTransaction&) +void WocPHPServerOut::newTransaction(const WocTransaction&trn) +{ + //create file + QString cn="WTr"+trn.name(); + QString fn="wtr_"+trn.name(); + addLoad(cn,fn); + fn=m_subdir+"/"+fn+m_fileext; + QFile tf(m_basedir+"/"+fn); + if(!tf.open(QIODevice::ReadWrite|QIODevice::Truncate)){ + qDebug("Error: cannot create PHP object file %s.",fn.toAscii().data()); + emit errorFound(); + return; + } + tf.write(PHPSTART); + + //// + //generate code + QString code="class "+cn+" extends WobTransaction{\n"; + //constructor + code+=trnConstruct(trn); + tf.write(code.toAscii()); + + //request handler: + code="public function handleRequest(){\n"; + + //security handling + switch(trn.authMode()){ + case WocTransaction::Checked: + code+="\tif(!"+m_isauth+"||!"+QString(m_hasrole).replace("%",trn.name())+")notAuthenticated();\n"; + break; + case WocTransaction::Auth: + code+="\tif(!"+m_isauth+")notAuthenticated();\n"; + break; + default: break;//none + } + + //parse inputs + code+=trnInput(trn); + + //call + if(trn.hasCall("php")){ + code+="\ttry{"+trn.callFunction("php")+"}catch(Exception $e){handleException($e);}\n"; + }else + qDebug("Warning: transaction %s does not have a PHP call!",trn.name().toAscii().data()); + + //encode outputs/handle errors + code+=trnOutput(trn); + + code+="}\n"; + tf.write(code.toAscii()); + + //getters/setters + tf.write(trnGetSet(trn).toAscii()); + + tf.write(PHPEND); + tf.close(); + + //// + //generate loader code + code="\tcase \""+trn.name()+"\":$trn=new "+cn+";$trn->handleRequest();break;\n"; + m_transact.write(code.toAscii()); +} + +QString WocPHPServerOut::trnConstruct(const WocTransaction&trn) +{ + QString code="public function __construct(){\n\t$this->ainput=array("; + QStringList sl=trn.inputNames(); + for(int i=0;i"; + if(trn.isListType(trn.inputType(sl[i])))code+="array()"; + else code+="false"; + } + code+=");\n"; + code+="\t$this->tinput=array("; + for(int i=0;i\""; + code+=trn.inputType(sl[i]); + code+="\""; + } + code+=");\n"; + + + code+="\t$this->aoutput=array("; + sl=trn.outputNames(); + for(int i=0;i"; + if(trn.isListType(trn.outputType(sl[i])))code+="array()"; + else code+="false"; + } + code+=");\n"; + code+="\t$this->toutput=array("; + for(int i=0;i\""; + code+=trn.outputType(sl[i]); + code+="\""; + } + code+=");\n}\n"; + return code; +} + +QString WocPHPServerOut::trnInput(const WocTransaction&trn) +{ + QString code="\tglobal $HTTP_RAW_POST_DATA;\n\tif(isset($HTTP_RAW_POST_DATA))$txt=$HTTP_RAW_POST_DATA;else $txt=\"\";\n"; + code+="\t$xml=new DOMDocument;\n\tif(!$xml->loadXML($txt))xmlParserError();\n"; + code+="\t$root=$xml->documentElement;\n\ttry{\n"; + QStringList sl=trn.inputNames(); + for(int i=0;igetAttribute(\""+sl[i]+"\")"; + if(trn.isIntType(t))code+="+0"; + code+=";\n"; + }else{ + if(trn.isListType(t)){ + QString pt=trn.plainType(t); + code+="\t\tforeach($root->getElementsByTagName(\""+sl[i]+"\") as $el){\n"; + if(trn.isObjectType(t)){ + code+="\t\t\t$this->ainput[\""+sl[i]+"\"][]=WO"+pt+"::fromXml($xml,$el);\n"; + }else{ + code+="\t\t\t$this->ainput[\""+sl[i]+"\"][]=$el->textContent"; + if(trn.isIntType(t))code+="+0"; + code+=";\n"; + } + code+="\t\t}\n"; + }else{ + code+="\t\tforeach($root->getElementsByTagName(\""+sl[i]+"\") as $el){\n"; + if(trn.isObjectType(t)){ + code+="\t\t\t$this->ainput[\""+sl[i]+"\"]=WO"+t+"::fromXml($xml,$el);\n"; + }else{ + code+="\t\t\t$this->ainput[\""+sl[i]+"\"]=$el->textContent"; + if(trn.isIntType(t))code+="+0"; + code+=";\n"; + } + code+="\t\t}\n"; + } + } + } + code+="\t}catch(Exception $e){handleException($e);}\n"; + return code; +} + +QString WocPHPServerOut::trnOutput(const WocTransaction&trn) +{ + QStringList sl=trn.outputNames(); + QString code="\ttry{\n\t\t$xml=new DOMDocument;\n"; + code+="\t\t$root=$xml->createElement(\"WobResponse\");\n"; + code+="\t\t$root->setAttribute(\"status\",statusString());\n"; + for(int i=0;iaoutput[\""+sl[i]+"\"];\n"; + }else{ + if(trn.isListType(t)){ + if(trn.isObjectType(t)){ + code+="\t\tforeach($this->aoutput[\""+sl[i]+"\"] as $o)\n"; + code+="\t\t\tif(is_a($o,\"WO"+trn.plainType(t)+"\"))\n"; + code+="\t\t\t\t$root->appendChild($o->toXml"+trn.typeSerializer(t)+"($xml,\""+sl[i]+"\"));\n"; + }else{ + code+="\t\tforeach($this->aoutput[\""+sl[i]+"\"] as $v)\n"; + code+="\t\t\t$root->appendChild($xml->createElement(\""+sl[i]+"\",xq($v)));\n"; + } + }else{ + if(trn.isObjectType(t)){ + code+="\t\t$o=$this->aoutput[\""+sl[i]+"\"];\n"; + code+="\t\tif(is_a($o,\"WO"+trn.plainType(t)+"\"))\n"; + code+="\t\t\t$root->appendChild($o->toXml"+trn.typeSerializer(t)+"($xml,\""+sl[i]+"\"));\n"; + }else{ + code+="\t\t$root->appendChild($xml->createElement(\""+sl[i]+"\",xq($this->aoutput[\""+sl[i]+"\"])));\n"; + } + } + } + } + code+="\t\t$xml->appendChild($root);\n\t}catch(Exception $e){handleException($e);}\n"; + return code; +} + +QString WocPHPServerOut::trnGetSet(const WocTransaction&trn) { - //TODO: implement transaction + QString code; + //getters + QStringList sl=trn.inputNames(); + for(int i=0;iainput[\""+sl[i]+"\"];}\n"; + } + //setters + sl=trn.outputNames(); + for(int i=0;iaoutput[\""+sl[i]+"\"][]=$vv;\n"; + add+="\tif(is_a($vv,\"WO"+trn.plainType(t)+"\"))$this->aoutput[\""+sl[i]+"\"][]=$vv;\n"; + }else{ + code+="\t\t$this->aoutput[\""+sl[i]+"\"][]=\"\".$vv;\n"; + add+="\t$this->aoutput[\""+sl[i]+"\"][]=\"\".$vv;\n"; + } + code+="\t}\n};"; + add+="}\n"; + }else{ + if(trn.isIntType(t)){ + code+="\tif(is_numeric($v))$this->aoutput[\""+sl[i]+"\"]=$v+0;\n"; + }else + if(trn.isObjectType(t)){ + code+="\tif(is_a($v,\"WO"+trn.plainType(t)+"\"))$this->aoutput[\""+sl[i]+"\"]=$v;\n"; + }else{ + code+="\t$this->aoutput[\""+sl[i]+"\"]=\"\".$v;\n"; + } + } + code+="}\n"+add; + } + + + return code; } diff --git a/woc/phpout.h b/woc/phpout.h index 4ddead4..cd8843a 100644 --- a/woc/phpout.h +++ b/woc/phpout.h @@ -17,10 +17,12 @@ #include "processor.h" +class QDomElement; + class WocPHPServerOut:public WocOutput { public: - WocPHPServerOut(QString srcDir,QString subDir,QString ext,bool clean); + WocPHPServerOut(const QDomElement&); protected: virtual void finalize(); virtual void newClass(const WocClass&); @@ -28,7 +30,8 @@ class WocPHPServerOut:public WocOutput virtual void newTransaction(const WocTransaction&); private: QString m_basedir,m_subdir,m_fileext; - QFile m_loader,m_schema; + QString m_isauth,m_hasrole,m_username; + QFile m_loader,m_schema,m_transact; /**helper: adds a loader line for a class to autoload.php*/ void addLoad(QString classname,QString filename); @@ -55,6 +58,15 @@ class WocPHPServerOut:public WocOutput QString classPropertyScalarGetters(const WocClass&,QString); /**helper: generate setters for sclar properties*/ QString classPropertyScalarSetters(const WocClass&,QString); + + /**helper: create transaction constructor*/ + QString trnConstruct(const WocTransaction&); + /**helper: create transaction input parser*/ + QString trnInput(const WocTransaction&); + /**helper: create transaction output serializer*/ + QString trnOutput(const WocTransaction&); + /**helper: create getters and setters*/ + QString trnGetSet(const WocTransaction&); }; #endif diff --git a/woc/processor.cpp b/woc/processor.cpp index ee29475..095c2fe 100644 --- a/woc/processor.cpp +++ b/woc/processor.cpp @@ -23,16 +23,6 @@ #include -static inline bool str2bool(QString s) -{ - bool b; - int i=s.toInt(&b,0); - if(b)return i?true:false; - s=s.toLower(); - if(s=="yes"||s=="y"||s=="on"||s=="true"||s=="t")return true; - return false; -} - WocProcessor* WocProcessor::inst=0; WocProcessor::WocProcessor() @@ -133,7 +123,7 @@ bool WocProcessor::processFile(QString fn) if(m_error)return false; }else if(tn=="PHPServerOutput"){ - new WocPHPServerOut(el.attribute("sourceDir","."), el.attribute("subDir","phpwob"), el.attribute("extension",".inc"), str2bool(el.attribute("clean","0"))); + new WocPHPServerOut(el); if(m_error)return false; }else if(tn=="Version"){ @@ -873,20 +863,20 @@ WocTransaction::WocTransaction(const QDomElement&root) //TODO: validate type m_input.append(QPair(nm,tp)); } - //calls - nl2=el.elementsByTagName("Call"); - for(int j=0;j1)return l[1]; + else return ""; + } + /**returns true if the type is integer*/ + bool isIntType(QString t)const{return plainType(t)=="int";} + /**returns true if the type is a string*/ + bool isStringType(QString t)const{QString p=plainType(t);return p=="astring"||p=="string";} + /**returns true if the type is to be encoded as attribute*/ + bool isAttributeType(QString t)const{return t=="astring"||t=="int";} + /**returns true if the type is to be encoded as element*/ + bool isElementType(QString t)const{return !isAttributeType(t);} + /**return true if the type is an object type*/ + bool isObjectType(QString t)const{QString p=plainType(t);return p!="astring"&&p!="string"&&p!="int";} private: QString m_name; bool m_valid; AuthMode m_mode; QMap m_call; QList >m_input,m_output; - }; /**base class of all output generators*/ diff --git a/www/inc/classes/autoload.php b/www/inc/classes/autoload.php new file mode 100644 index 0000000..826fa0c --- /dev/null +++ b/www/inc/classes/autoload.php @@ -0,0 +1,26 @@ +, (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// +include('./inc/classes/event.php'); +include('./inc/classes/room.php'); +include("./inc/classes/random.php"); +include("./inc/classes/order.php"); +include("./inc/classes/ticket.php"); +include("./inc/classes/voucher.php"); +include("./inc/classes/cart.php"); +include('./inc/classes/error.php'); +include('./inc/classes/language_manager.php'); +include('./inc/classes/parser.php'); +include('./inc/classes/config_manager.php'); +include('./inc/classes/customer.php'); +include('./inc/classes/websession.php'); +?> \ No newline at end of file diff --git a/www/inc/db/autoload.php b/www/inc/db/autoload.php new file mode 100644 index 0000000..741b725 --- /dev/null +++ b/www/inc/db/autoload.php @@ -0,0 +1,17 @@ +, (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// +$AUTOCLASS["DbEngine"]='./inc/db/db.php'; +$AUTOCLASS["MysqlEngine"]='./inc/db/db_mysql.php'; + +include('./inc/db/db_scheme.php'); +?> \ No newline at end of file diff --git a/www/inc/loader.php b/www/inc/loader.php index 2e51c6b..bc58c94 100644 --- a/www/inc/loader.php +++ b/www/inc/loader.php @@ -5,10 +5,8 @@ include_once("inc/tr.php"); include('./inc/wbase/autoload.php'); include('./inc/wob/autoload.php'); //load DB drivers -include('./inc/db/db.php'); -include('./inc/db/db_mysql.php'); +include('./inc/db/autoload.php'); include('./config.php'); -include('./inc/db/db_scheme.php'); //try to connect $db->tryConnect(); //move on in loader_nonadmin.php (or admin.php) diff --git a/www/inc/loader_nonadmin.php b/www/inc/loader_nonadmin.php index f050da4..67a3aa8 100644 --- a/www/inc/loader_nonadmin.php +++ b/www/inc/loader_nonadmin.php @@ -3,20 +3,7 @@ if(!$db->canUseDb()) die("Database is not correctly configured. Giving up."); //load class-files -include('./inc/classes/event.php'); -include('./inc/classes/room.php'); -include("./inc/classes/random.php"); -include("./inc/classes/order.php"); -include("./inc/classes/ticket.php"); -include("./inc/classes/voucher.php"); -include("./inc/classes/cart.php"); -include('./inc/classes/error.php'); -include('./inc/classes/language_manager.php'); -include('./inc/classes/parser.php'); -include('./inc/classes/config_manager.php'); -include('./inc/classes/customer.php'); -include('./inc/classes/websession.php'); -//load hash lib -include("./inc/machine/cauth_".$HashLib.".php"); +include('./inc/classes/autoload.php'); +include("./inc/machine/autoload.php"); ?> \ No newline at end of file diff --git a/www/inc/machine/autoload.php b/www/inc/machine/autoload.php new file mode 100644 index 0000000..f4602a6 --- /dev/null +++ b/www/inc/machine/autoload.php @@ -0,0 +1,21 @@ +, (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +$AUTOCLASS["Session"]="./inc/machine/session.php"; +$AUTOCLASS["Host"]="./inc/machine/host.php"; +$AUTOCLASS["Template"]="./inc/machine/template.php"; + +//load hash lib +include("./inc/machine/cauth_".$HashLib.".php"); + +?> \ No newline at end of file diff --git a/www/inc/machine/session.php b/www/inc/machine/session.php index f71dfde..8f4f83c 100644 --- a/www/inc/machine/session.php +++ b/www/inc/machine/session.php @@ -13,6 +13,7 @@ /* TRANSLATOR php:: */ //prune session cache +global $db; $db->deleteRows("session","timeout<=".time()); /**initiate new session - $rand should contain some food for the random number generator (from the host request)*/ diff --git a/www/inc/wbase/autoload.php b/www/inc/wbase/autoload.php index 1230229..158203b 100644 --- a/www/inc/wbase/autoload.php +++ b/www/inc/wbase/autoload.php @@ -11,6 +11,7 @@ $AUTOCLASS["WobTable"]="inc/wbase/table.php"; $AUTOCLASS["WobSchemaBase"]="inc/wbase/schema.php"; +$AUTOCLASS["WobTransactionBase"]="inc/wbase/transaction.php"; $AUTOCLASS["WobXmlException"]="inc/wbase/exception.php"; $AUTOCLASS["WObject"]="inc/wbase/object.php"; diff --git a/www/inc/wbase/transaction.php b/www/inc/wbase/transaction.php new file mode 100644 index 0000000..66edbb2 --- /dev/null +++ b/www/inc/wbase/transaction.php @@ -0,0 +1,91 @@ +, (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +/**Ancestor of all Transactions*/ +class WobTransactionBase { + protected $ainput; + protected $tinput; + protected $aoutput; + protected $toutput; + protected $astatus=0; + protected $aerror; + + const Ok=0; + const Error=1; + + /**called to determine the correct transaction, aborts the script if there is none.*/ + static public function getTransactionName(){ + global $_SERVER; + if($_SERVER["REQUEST_METHOD"] != "POST"){ + header("X-WobResponse-Status: Error"); + print("Request is not a POST Request, Aborting.\n"); + exit(); + } + if(!isset($_SERVER["HTTP_X_WOBREQUEST"])){ + header("X-WobResponse-Status: Error"); + print("Request is not a Wob Request, Aborting.\n"); + exit(); + } + return $_SERVER["HTTP_X_WOBREQUEST"]; + } + /**called if the transaction is not known. aborts the script.*/ + static public function noSuchTransaction() + { + header("X-WobResponse-Status: Error"); + print("Request is not known, Aborting.\n"); + exit(); + } + + /**called if authentication fails*/ + public function notAuthenticated(){ + header("X-WobResponse-Status: Error"); + print("User is not authenticated or does not have permission to execute this request, Aborting.\n"); + exit(); + } + + /**called if XML parsing fails*/ + public function xmlParserError(){ + header("X-WobResponse-Status: Error"); + print("Error while parsing request XML, Aborting.\n"); + exit(); + } + + /**called for generic exception handling*/ + public function handleException($ex){ + header("X-WobResponse-Status: Error"); + print("".xq($ex->getMessage())."\n"); + exit(); + } + + /**returns the status of the transaction as string*/ + public function statusString() + { + switch($this->astatus){ + case Ok:return "ok"; + case Error:return "error"; + default:return "unknown"; + } + } + + /**sets the status of the transaction*/ + public function setStatus($s) + { + if($s<0 && $s>1)throw Exception("Illegal Status Code ".$s); + $this->astatus=$s; + } + + /**returns the status of the transaction*/ + public function status(){return $this->astatus;} +}; + +?> \ No newline at end of file diff --git a/www/wob.php b/www/wob.php new file mode 100644 index 0000000..659662e --- /dev/null +++ b/www/wob.php @@ -0,0 +1,20 @@ +, (C) 2009 +// +// Copyright: See README/COPYING files that come with this distribution +// +// + +include_once("inc/loader.php"); +include_once("inc/loader_nonadmin.php"); +$session=new Session; + +WobTransaction::handle(); + +?> \ No newline at end of file -- 1.7.2.5