This commit is contained in:
Brad Arant 2024-12-02 15:46:49 -08:00
parent ae57e06778
commit 90540d3c44
8 changed files with 493 additions and 13 deletions

View File

@ -40,6 +40,16 @@ Keywords are not defined as part of the tag definition and any
attribute added to the implementation of the tag is passed into the attribute added to the implementation of the tag is passed into the
tag process as a local variable for that container. tag process as a local variable for that container.
Tag definitions can also be defined as scoped or unscoped, as follows:
scoped - local variables using the #[n] format can be scoped to just
your tag contents. Access to local variables where your tag is being
used must use the 'parent' scope option to retrieve variables from the
parent.
unscoped - local variables are shared with the parent tag environment
and are not unique to your tag definition.
A <container /> tag can be inserted into the container and will take A <container /> tag can be inserted into the container and will take
the contents of the container at runtime and insert it into the output the contents of the container at runtime and insert it into the output
when processing the user defined tag definition. The container tag of when processing the user defined tag definition. The container tag of
@ -57,7 +67,11 @@ higher tag.
Variables are used to contain dynamic content values and can be Variables are used to contain dynamic content values and can be
sourced from several locations and limited in scope depending on use. sourced from several locations and limited in scope depending on use.
Some variable types can be set to reflect script state or are read Some variable types can be set to reflect script state or are read
only from other outside sources of data. The following is a list of only from other outside sources of data.
Jet tags can be either scoped or unscoped.
The following is a list of
variable types and a brief description of their source: variable types and a brief description of their source:
\begin{itemize} \begin{itemize}
@ -71,6 +85,9 @@ specifying the scope of global.
\section{Global Variables} \section{Global Variables}
Global variables are available to all logic once the values have been
set.
Global is the default if the scope is Global is the default if the scope is
not specified for any function that writes to a variable. not specified for any function that writes to a variable.
@ -81,7 +98,9 @@ not specified for any function that writes to a variable.
\section{CGI Variables} \section{CGI Variables}
When operating Jet in CGI mode you have access to the form data
submitted by the remote client (usually a browser or curl request)
using the POST method.
\chapter{Expressions} \chapter{Expressions}
@ -178,6 +197,8 @@ input
error error
The call tag is unscoped.
\begin{verbatim} \begin{verbatim}
<call pgm="ls" arg1="-al" name="listing" /> <call pgm="ls" arg1="-al" name="listing" />
\end{verbatim} \end{verbatim}
@ -216,7 +237,10 @@ end
step step
name name - defines a name for the iterator that will be available within
the loop.
scope - defines the scope of the iterator for the loop.
\section{header} \section{header}

View File

@ -54,9 +54,9 @@ namespace jet {
if(!variableDefined("scope") || (variables["scope"] == "global")) if(!variableDefined("scope") || (variables["scope"] == "global"))
global.variables[variables["name"]].read(fdo[0]); global.variables[variables["name"]].read(fdo[0]);
else if(variables["scope"] == "local") else if(variables["scope"] == "local")
parent->variables[variables["name"]].read(fdo[0]); local->variables[variables["name"]].read(fdo[0]);
else if(variables["scope"] == "parent") else if(variables["scope"] == "parent")
parent->parent->variables[variables["name"]].read(fdo[0]); local->parent->local->variables[variables["name"]].read(fdo[0]);
else else
throw coreutils::Exception("scope value is not valid."); throw coreutils::Exception("scope value is not valid.");

View File

@ -3,7 +3,7 @@
namespace jet { namespace jet {
__dotag::__dotag(coreutils::ZString &in, coreutils::MString &parentOut, Global &global, Tag *parent, Tag *local) : Tag(in, parentOut, global, parent, this) { __dotag::__dotag(coreutils::ZString &in, coreutils::MString &parentOut, Global &global, Tag *parent, Tag *local) : Tag(in, parentOut, global, parent, local) {
if(hasContainer) if(hasContainer)
parseContainer(container, containerOut); parseContainer(container, containerOut);
containerOut.reset(); containerOut.reset();

View File

@ -14,7 +14,23 @@ namespace jet {
coreutils::File file(variables["file"]); coreutils::File file(variables["file"]);
file.read(); file.read();
container = file.asZString(); container = file.asZString();
processContainer(container); try {
processContainer(container);
}
catch(coreutils::Exception e) {
container.setCursor(global.errorCursor);
container.moveBackToLineStart();
std::cout << "-----------------------------" << std::endl;
std::cout << "Error in included script '" << variables["file"] << "' at line " << container.getLineNumberAtCursor() << std::endl;
std::cout << "Error text: " << e.text << std::endl;
std::cout << "-----------------------------" << std::endl;
std::cout << container.parsed() << std::endl;
std::cout << "******** Error caught: " << e.text << std::endl;
std::cout << container.unparsed() << std::endl;
global.errorCursor = in.getCursor();
throw coreutils::Exception("error in included file.");
}
} }
} }

View File

@ -1,16 +1,22 @@
#include "__stream.h" #include "__stream.h"
#include "Exception.h" #include "Exception.h"
#include <unistd.h>
#include <fcntl.h>
namespace jet { namespace jet {
__stream::__stream(coreutils::ZString &in, coreutils::MString &parentOut, Global &global, Tag *parent, Tag *local) : Tag(in, parentOut, global, parent, this) { __stream::__stream(coreutils::ZString &in, coreutils::MString &parentOut, Global &global, Tag *parent, Tag *local) : Tag(in, parentOut, global, parent, this) {
output = false;
if(!variableDefined("name")) if(!variableDefined("name"))
throw coreutils::Exception("stream tag must have a file name to stream."); throw coreutils::Exception("stream tag must have a file name to stream.");
global.outputHeaders();
// TODO: Output headers that have been written so far. int len;
// TODO: Open file with fairly small buffer size and write to end to cout and not the out buffers. char buffer[1024];
// TODO: Force no further output from jet-2.0 at end of stream. int fd = open(variables["name"].c_str(), O_RDONLY);
do {
len = read(fd, &buffer, 1024);
std::cout << buffer;
} while (len > 0);
} }
} }

433
sessionctl/sessionctl.tag Executable file
View File

@ -0,0 +1,433 @@
# --------------------------------------------------------------
# SESSIONCTL lib
#
# Session Control Function Library
#
#
# --------------------------------------------------------------
#==============================================================================
# RETAIN tag definition.
#==============================================================================
<tag name="retain" keywords="name value empty">
<if value1="#[empty]" value2="" type=eq>
<if value1="#[value]" value2="" type=eq>
<set name='tmp_#[name]' value="$[#[name]]" format=tobrowser>
<input type="hidden" name="#[name]" value="$[tmp_#[name]]">
<else>
<set name='tmp_#[name]' value="#[value]" format=tobrowser>
<input type="hidden" name="#[name]" value="$[tmp_#[name]]">
</if>
<else>
<input type="hidden" name="#[name]" value="">
</if>
</tag>
#==============================================================================
# IFNOTSESSION tag definition.
#==============================================================================
<tag name="ifnotsession">
<if value1="$[_SESSIONID]" value2="" type="eq"><container></if>
</tag>
#------------------------------------------------------------------------------
# LINKBUTTON tag definition.
#------------------------------------------------------------------------------
<TAG NAME=LINKBUTTON KEYWORDS="PAGEDIR PAGE PROCESS NAME NAME2 VALUE VALUE2 TARGET CLASS MULTIPART">
<A HREF="javascript:
<IF VALUE1="#[PAGEDIR]" VALUE2="" TYPE=NE>
<SET NAME=X_LEVEL EXPR="$[N_LEVEL] + 1">
</IF>
<IF VALUE1="#[PROCESS]" VALUE2="" TYPE="EQ">
document.forms[0].PROCESS.value='';
<ELSE>
document.forms[0].PROCESS.value='#[PROCESS]';
</IF>
<IF VALUE1="#[PAGE]" VALUE2="" TYPE="EQ">
document.forms[0].PAGE.value='$[PAGE]';
<ELSE>
document.forms[0].PAGE.value='#[PAGE]';
</IF>
<IF VALUE1="#[NAME]" VALUE2="" TYPE="NE">
document.forms[0].#[NAME].value='#[VALUE]';
</IF>
<IF VALUE1="#[NAME2]" VALUE2="" TYPE="NE">
document.forms[0].#[NAME2].value='#[VALUE2]';
</IF>
<IF VALUE1="#[MULTIPART]" VALUE2="YES" TYPE="EQ">
document.forms[0].encoding='multipart/form-data';
</IF>
<IF VALUE1="#[TARGET]" VALUE2="" TYPE="NE">
document.forms[0].target='#[TARGET]';
</IF>
<IF VALUE1="#[PAGEDIR]" VALUE2="" TYPE="NE">
document.forms[0].P_$[L_LEVEL].value='$[PAGE]';
document.forms[0].L_$[L_LEVEL].value='$[X_TITLE]';
document.forms[0].D_$[N_LEVEL].value='#[PAGEDIR]';
document.forms[0].P_$[N_LEVEL].value='#[PAGE]';
document.forms[0].P_LEVEL.value=$[L_LEVEL];
document.forms[0].L_LEVEL.value=$[N_LEVEL];
document.forms[0].N_LEVEL.value='$[X_LEVEL]';
</IF>
document.forms[0].submit();
document.forms[0].target='';"
<if value1="#[CLASS]" value2="" type="ne">
CLASS="#[CLASS]"
</if>
><EVAL><CONTAINER></EVAL></A>
</TAG>
#------------------------------------------------------------------------------
# ABUTTON tag definition.
#------------------------------------------------------------------------------
<TAG NAME="ABUTTON" KEYWORDS="PAGE PROCESS NAME VALUE MULTIPART">
<BUTTON ONCLICK="javascript:
<IF VALUE1="#[PAGE]" VALUE2="" TYPE="NE">
document.forms[0].PAGE.value='#[PAGE]';
<else>
document.forms[0].PAGE.value='$[PAGE]';
</IF>
<IF VALUE1="#[PROCESS]" VALUE2="" TYPE="NE">
document.forms[0].PROCESS.value='#[PROCESS]';
</IF>
<IF VALUE1="#[NAME]" VALUE2="" TYPE="NE">
document.forms[0].#[NAME].value='#[VALUE]';
</IF>
<IF VALUE1="#[MULTIPART]" VALUE2="YES" TYPE="EQ">
document.forms[0].encoding='multipart/form-data';
</IF>
document.forms[0].submit();">&nbsp;<CONTAINER>&nbsp;</BUTTON>
</TAG>
# ----------------------------------------------
# CREATESESSION
# ----------------------------------------------
<tag name="createsession" keywords="page timeout">
<if value1="$[_session_id]" value2="" type="ne">
<sql>
delete from sessions
where uuid='$[_session_id]'
</sql>
</if>
<set name="_uuid" expr="uuid()">
<set name="_timestamp" expr="now()">
<if value1="#[timeout]" value2="" type="eq">
<set name="timeout" value="0" scope="local">
</if>
<sql>
insert into sessions
set uuid='$[_uuid]',
timestamp='$[_timestamp]',
timeout_page='#[page]',
timeout=#[timeout]
</sql>
<setcookie name="_session_id" value="$[_uuid]">
</tag>
# ----------------------------------------------
# ENDSESSION
# ----------------------------------------------
<tag name="endsession">
<if value1="$[_session_id]" value2="" type="ne">
<sql>
delete from sessions
where uuid='$[_session_id]'
</sql>
<setcookie name="_session_id" value="">
</if>
</tag>
#--------------------------------------------------
#SETENV
#--------------------------------------------------
<tag name="setenv" keywords="name">
<if value1="$[_session_id]" value2="" type="ne">
<eval name="_envvalue" scope="local"><container></eval>
<set name="_envvalue" value="#[_envvalue]" format="binary" scope="local">
<sql>
replace into sessionenv
set session_uuid='$[_session_id]',
name='#[name]',
value='#[_envvalue]'
</sql>$[sqlerror]
<eval name="#[name]"><container></eval>
</if>
</tag>
#--------------------------------------------------
#CLEARENV
#--------------------------------------------------
<TAG NAME='CLEARENV' KEYWORDS='NAME'>
<IF VALUE1='$[_SESSIONID]' VALUE2='' TYPE=NE>
<SQL SESSIONID="_SESSIONCTL">
DELETE FROM sessionenv
WHERE seid='$[_SESSIONID]'
AND sename='#[NAME]'
</SQL>
<SET NAME='#[NAME]' VALUE="">
</IF>
</TAG>
#--------------------------------------------------
#SETPAGE
#--------------------------------------------------
<tag name="setpage" keywords="NAME DIR">
<SET NAME=PAGE VALUE='#[NAME]'>
<IF VALUE1="#[DIR]" VALUE2="" TYPE="NE">
<SET NAME="DIR" VALUE="$[DIR]/#[DIR]">
<set name="_CTLDIR" value="$[DIR]">
</IF>
</TAG>
#--------------------------------------------------
#SETPROCESS
#--------------------------------------------------
<TAG NAME='SETPROCESS' KEYWORDS='VALUE'>
<SET NAME=PROCESS VALUE='#[VALUE]'>
</TAG>
#--------------------------------------------------
#CHECKSESSION
#--------------------------------------------------
<tag name="checksession">
<sql>
select *,
if((timeout > 0) && (unix_timestamp(now()) - unix_timestamp(timestamp) > (timeout * 60)),'0','1') as session_valid
from sessions
where uuid="$[_session_id]"
</sql>$[sqlerror]
<ifrow>
<if value1="$[.session_valid]" value2="1" type="eq">
<set name="session_timestamp" value="$[.timestamp]">
<set name="_timestamp" expr="now()">
<sql>
update sessions
set timestamp='$[_timestamp]'
where uuid="$[_session_id]"
</sql>
<sql>
select * from sessionenv where session_uuid="$[_session_id]"
</sql>$[sqlerror]
<whilerow>
<eval name="$[.name]">$[.value]</eval>
</whilerow>
<else>
<setpage name="$[.timeout_page]">
<set name="_session_id" value="">
</if>
<else>
<setpage name="">
<set name="_session_id" value="">
</ifrow>
</tag>
#--------------------------------------------------
#FIRST RUN - See FETCHPROC in SESSIONCTL tag
#--------------------------------------------------
<TAG NAME='FIRSTRUN'>
<IF VALUE1='$[_PROCESSRAN]' VALUE2='FALSE' TYPE=EQ>
<EVAL NAME='_FIRSTRUN'>$[_FIRSTRUN] <CONTAINER></EVAL>
</IF>
</TAG>
#--------------------------------------------------
#RUNERROR - See FETCHPROC in SESSIONCTL tag
#--------------------------------------------------
<TAG NAME='RUNERROR'>
<IF VALUE1='$[_PROCESSRAN]' VALUE2='TRUE' TYPE=EQ>
<EVAL NAME="_RUNERROR">$[_RUNERROR] <CONTAINER></EVAL>
</IF>
</TAG>
#--------------------------------------------------
#SESSIONCTL
#--------------------------------------------------
<TAG NAME='SESSIONCTL' KEYWORDS="PAGE STYLESHEET">
<tag name="defaultnav">
<if expr="('$[PAGE]' = '') and ('$[PROCESS]' = '')">
<eval><container></eval>
</if>
</tag>
<DATABASE NAME="$[database]" HOST="$[host]" USER="$[user]" PASSWORD="$[password]" SESSIONID="_SESSIONCTL">
<TAG NAME='FETCHPAGE'>
<tag name="directory" keywords="NAME PAGE">
<set name="DIR" value="$[DIR]/#[NAME]">
<set name="PAGE" value="#[PAGE]">
<fetchpage>
</tag>
<tag name="page" keywords="TEMPLATE CLASS onload secure loggedin" SCOPE=LOCAL>
<TAG NAME='AUTHOR' SCOPE=LOCAL>
<EVAL NAME=AUTHOR SCOPE=PARENT><CONTAINER></EVAL>
</TAG>
<TAG NAME='DESCRIPTION' SCOPE=LOCAL>
<CONTAINER NAME="DESCRIPTION" EVAL="NO" SCOPE="PARENT">
</TAG>
<TAG NAME='KEYWORDS' SCOPE=LOCAL>
<CONTAINER NAME="KEYWORDS" EVAL="NO" SCOPE="PARENT">
</TAG>
<TAG NAME='CONTENTS' SCOPE=LOCAL>
<EVAL NAME="_BODY"><CONTAINER></EVAL>
</TAG>
<TAG NAME='TEMPLATE' SCOPE=LOCAL>
<TAG NAME='CONTENTS' SCOPE=LOCAL>
$[_BODY]
</TAG>
<EVAL NAME=TEMPLATEDATA SCOPE=PARENT><CONTAINER EVAL="NO"></EVAL>
</TAG>
<if expr="('$[HTTPS]'!='on') and ('#[secure]'='yes')">
<html><head><meta http-equiv="refresh" content="0; url=https://$[HTTP_HOST]$[REQUEST_URI]"></head></html>
<else>
<if expr="('$[__account_id]'='') and ('#[loggedin]'='yes')">
<html><head><meta http-equiv="refresh" content="0; url=https://$[HTTP_HOST]/login"></head></html>
<else>
<!DOCTYPE html>
<!--[if lt IE 7 ]><html class="ie ie6" lang="en"> <![endif]-->
<!--[if IE 7 ]><html class="ie ie7" lang="en"> <![endif]-->
<!--[if IE 8 ]><html class="ie ie8" lang="en"> <![endif]-->
<!--[if (gte IE 9)|!(IE)]><!--><html lang="en"> <!--<![endif]-->
<head>
<EVAL><CONTAINER eval="no"></EVAL>
<META NAME=AUTHOR CONTENT="#[AUTHOR]">
<META NAME=DESCRIPTION CONTENT="#[DESCRIPTION]">
<META NAME=KEYWORDS CONTENT="#[KEYWORDS]">
<if value1="$[_STYLESHEET]" value2="" type="NE">
<link rel="stylesheet" type="text/css" href="$[_STYLESHEET]">
</if>
$[head]
</head>
<body <if value1="#[CLASS]" value2="" type="ne">class="#[CLASS]"</if>
<if value1="#[onload]" value2="" type="ne">onload="#[onload]"</if>>
<form method="post" enctype="application/x-www-form-urlencoded">
<INPUT TYPE=HIDDEN NAME="_LASTPAGE" VALUE="$[PAGE]" >
<INPUT TYPE=HIDDEN NAME="PROCESS" VALUE="" >
<INPUT TYPE=HIDDEN NAME="EXITPROCESS" VALUE="$[EXITPROCESS]" >
<input type="hidden" name="DIR" value="$[DIR]">
<input type="hidden" name="_CTLDIR" value="$[_CTLDIR]">
<INPUT TYPE=HIDDEN NAME="PAGE" VALUE="$[PAGE]" >
<INPUT TYPE=HIDDEN NAME="_TIMESTAMP" VALUE="$[_timestamp]" >
<IF VALUE1="#[TEMPLATE]" VALUE2="" TYPE="EQ">
$[_BODY]
<ELSE>
<EVAL><INCLUDE FILE="./$[DIR]/#[TEMPLATE].temp"></EVAL>
#[TEMPLATEDATA]
</IF>
</form>
</body>
</html>
</if>
</if>
</TAG>
<eval><INCLUDE FILE="./$[DIR]/$[PAGE].page"></eval>
</TAG>
<tag name="fetchproc">
<tag name="process">
<if value1="$[_TIMESTAMP:0]" value2="$[session_timestamp]" type="eq">
<set name="_PROCESSRAN" value="FALSE">
<else>
<set name="_PROCESSRAN" value="TRUE">
</if>
<eval><container></eval>
<eval>$[_FIRSTRUN]</eval>
<eval>$[_RUNERROR]</eval>
</tag>
<EVAL><INCLUDE FILE="./$[DIR]/$[PROCESS].proc"></EVAL>
</TAG>
<tag name="virtual" keywords="SERVER DIR">
<if value1="$[PAGE]" value2="" type="eq">
<if value1="#[SERVER]" value2="$[$SERVER_NAME]" type="eq">
<set name="DIR" value="#[DIR]">
<set name="_CTLDIR" value="#[DIR]">
</if>
</if>
</tag>
<if value1="$[_session_id]" value2="" type="ne">
<checksession>
</if>
<eval name="head"><container></eval>
<if value1="$[PROCESS]" value2="" type="ne">
<fetchproc>
</if>
<if value1="$[PAGE]" value2="" type="eq">
<setpage name="#[PAGE]">
<else>
<script>
window.history.replaceState('','','/$[PAGE]');
</script>
</if>
<fetchpage>
</database>
</tag>

View File

@ -8,7 +8,7 @@ divisor=[8]
error=[] error=[]
include=[yes] include=[yes]
ix=[1] ix=[1]
lefty=[01234] lefty=[]
modified1=[ABCD] modified1=[ABCD]
multiplication=[15] multiplication=[15]
nested=[64] nested=[64]

View File

@ -1,6 +1,7 @@
<set name="localvar" scope="local">This is a container set with '#[name1]'</set> <set name="localvar" scope="local">This is a container set with '#[name1]'</set>
This is from an include tag. This is from an include tag.
localname='#[name1]' localname='#[name1]'
$[$xxxx]
<set name="include" value="yes" /> <set name="include" value="yes" />
<set name="testinclude" value="x#[localvar]x" scope="local" /> <set name="testinclude" value="x#[localvar]x" scope="local" />
test='#[testinclude]' test='#[testinclude]'