#include "Action.h"
#include "DBError.h"
#include "DBHandler.h"
extern EnvObject * userdata;
extern DBGate * dbgate;
extern HTTP * http;
extern Security * security;
extern Configuration * config;
extern string LoopKey;
Action::Action () {
string fname;
// cout << "\n\n **** trying to make a new Action" ;
/* open up the last page */
fname = config->getBasePageDir() + (security->getLastPage());
parser->newFile (fname);
//update the LoopInfo object
loopinfo->setFile( security->getLastPage() );
// cout << "\n **** the action is using file: " << fname;
// NOTE: the "this" namespace was set up in the Check section
}
Error Action::doAction (void) {
Error err;
SGMLTokenList & stl = parser->actionTokens();
if (parser->errors().numFatalErrors() > 0 ||
parser->errors().numWarnings() > 0){
outputErrors(parser->errors(),security->getLastPage());
}
// tell the userdata object wo we are
userdata->setExec (this);
if (stl.size() != 0) {
try {
recurseOnTokens ( stl , err );
}
catch (ExecutorAbort ea){
// Return gracefully
}
}
return (err);
}
/* look at each token, and make it 'go' */
void Action::recurseOnTokens (SGMLTokenList & tokenlist , Error & err) {
SGMLTokenList::iterator i;
i = tokenlist.begin();
while (i != tokenlist.end()) {
callFunction ( *i, err);
i++;
}
}
void Action::callFunction (SGMLToken * t, Error & err) {
string command = t->command();
char test[255];
strcpy (test, command.c_str());
if (command == "ERROR") {
processERROR ( (SGMLContainer *) t, err);
} else if (command == "LOOP") {
processLOOP ( (SGMLContainer *) t, err);
} else if (command == "DATFORM" || command == "SBFORM") {
processDATFORM ( (SGMLContainer *) t, err);
} else if (command == "REDIRECT") {
processREDIRECT ( (SGMLTag *) t, err);
} else {
BaseSBModule::callFunction (t, err);
}
}
/*
@nodoc
*/
void Action::processLOOP (SGMLContainer * t, Error & err) {
AssocArray * flags = &(t->flags());
AssocArrayPtrDLList * data = NULL; // the stuff we are looping over
string OrigLoopKey = LoopKey;
string name;
int i;
char temp [10]; //hack!
int length;
EnvObject * old_userdata = userdata;
interpretString ((*flags)["NAME"], name); //get the name of the loop
name = OrigLoopKey + "_" + name;
if (flags->contains("WHILE")){ // Support both BOOL and WHILE
(*flags)["BOOL"] = (*flags)["WHILE"];
}
if ( ! hasDataSource ( (SGMLTag *) t) ) {
// get the number of times this loop has played before
// and init data to the right number of empty assoc arrays
length = loopinfo->getLoopInfo (name);
data = new AssocArrayPtrDLList();
for (int i=0;i<length;i++) {
AssocArray * a = new AssocArray();
data->push_back(a);
}
} else if ( ! flags->contains("BOOL") ) {
//they specified a non-dynamic data source
try {
data = getList (t); // get the data they want to loop over
}
catch (DBError dbe) {
if (!handle (dbe, err)) {
throw ("Unhandled exception thrown by LOOP tag");
} else {
data = new AssocArrayPtrDLList();
}
}
}
if (data != NULL) {
length = data->size();
// open up a new environemnt
userdata = new EnvObject (userdata);
for (i = 0; i < length; i++) {
AssocArray * aaptr;
sprintf (temp, "%d", i);
LoopKey = name + "_" + temp;
// grab the first 'row' of info that we are looping over
aaptr = data->front();
data->pop_front();
// store this in the namespace = flags[NAME]
userdata->setNameSpace ((*flags)["NAME"], aaptr);
recurseOnTokens ( t->contents() , err);
}
// clean up and reset environment
delete (userdata);
userdata = old_userdata;
delete (data);
} else if ( flags->contains("BOOL") ) {
// open up a new environemnt
userdata = new EnvObject (userdata);
length = 0;
while ( evalSimpleBool((SGMLTag *) t, err) ) {
sprintf (temp, "%d", length++);
LoopKey = name + "_" + temp;
// store this in the namespace = flags[NAME]
userdata->setNameSpace ((*flags)["NAME"], new AssocArray());
recurseOnTokens ( t->contents() , err );
}
// clean up and reset environment
delete (userdata);
userdata = old_userdata;
}
// save the loopinfo so we can access it by name later
// if this is a nested loop, only save it if they INSIST on
// it since the performance penelty is huge
if (OrigLoopKey == "" || flags->contains("SAVELOOPINFO") ) {
loopinfo->setLoopInfo (name, length);
}
LoopKey = OrigLoopKey;
}
/*
@nodoc
this function will check to see if a hidden var that was embeded
in the DATFORM created by the Sender is in the http object's data
if it is, it will recurse on the tokens contents */
void Action::processDATFORM (SGMLContainer * t, Error & err) {
AssocArray * flags = &(t->flags());
string temp;
if ( (t->flags().contains("NAME")) ) {
temp = "form_" + (*flags)["NAME"];
if ((http->data).contains(temp)){
recurseOnTokens (t->contents(), err);
}
} else {
// they didn't give a name flag!
err.addWarning ("SBFORM tag without NAME flag in ACTION section");
}
}
/*
@usehtml
@seealso _SBREF_ _SBFORM_
@usage <REDIRECT SCREEN="filename">
@IFLAG SCREEN Destination SteelBlue filename (relative to BasePages)
@sections CHECK, ACTION
@index Changes the destination SteelBlue page.
Changes the destination SteelBlue page from one given in
an _SBFORM_ or _SBREF_ tag.
@ex <HTML>
@ex <BODY>
@ex <SBREF SCREEN="somewhere">
@ex Go somewhere
@ex </SBREF>
@ex </BODY>
@ex </HTML>
@ex
@ex <ACTION>
@ex <!-- redirect destination to the welcome page -->
@ex <redirect screen="welcome.sb">
@ex </ACTION>
*/
void Action::processREDIRECT (SGMLTag * t, Error & err) {
AssocArray * flags = &(t->flags());
string dest = interpretString ((*flags)["SCREEN"]);
security->setDest (dest);
}
/*
@usehtml
@seealso _SHOWERRORS_
@usage <ERROR TEXT="string">
@IFLAG TEXT Text to appear in the error message
@sections CHECK, ACTION
@index Causes the previous HTML page to be redisplayed with the given error message.
Causes the previous HTML page to be redisplayed with the given
error message. If an ERROR flag is in the CHECK section,
the rest of the CHECK section is executed (but not the ACTION
section) and then the HTML section is redisplayed. If an ERROR
flag is in the ACTION section, the rest of the ACTION section
is executed and then the HTML section is redisplayed. Input boxes
in the HTML section are automatically restored for the _SBFORM_ that
was submitted. Additional ERROR flags will cause a list of
errors to be displayed.
@ex <HTML>
@ex <BODY>
@ex <showerrors>
@ex <sbref screen="welcome.sb">
@ex Press to make an error
@ex </sbref>
@ex </BODY>
@ex </HTML>
@ex <CHECK>
@ex <ERROR text="This is an error">
@ex <ERROR text="This is another error">
@ex </CHECK>
*/
void Action::processERROR (SGMLContainer * t, Error & err) {
AssocArray * flags = &(t->flags());
string error_text = interpretString ((*flags)["TEXT"]);
string old_err_fname = err.getFilename();
string emptyname = "";
err.setFilename(emptyname); // surpress printing of filename in error
err.addFatalError (error_text);
err.setFilename(old_err_fname);
}
/*
@NODOC
*/
void Action::processGeneric (SGMLToken * t, Error & err) {
// bogus code to avoid warnings
if ( !t ) {
err.addWarning ("processGeneric called with bad argument");
}
}