MODULE WebStd; (** AUTHOR "Luc Blaeser"; PURPOSE "Standard Active Element Library for Dynamic Webpage Generation"*)
IMPORT DynamicWebpage, PrevalenceSystem, HTTPSupport, HTTPSession, GenericSort, XML, XMLObjects, DynamicStrings,
Dates, Strings, TFClasses, KernelLog, WebHTTP;
CONST
DateTimeFormat* = "dd.mm.yyyy hh:nn:ss";
SessionContainerNamePrefix = "dxp-WebStd-sessioncontainer-";
SessionVariableNamePrefix = "dxp-WebStd-variable-";
SessionGuardNamePrefix = "dxp-WebStd-Guard-";
SessionVisitorCounterPrefix = "dxp-WebStd-VisitorCounter-";
TYPE
(** normal XHTML attribute and element names should be lowercase *)
(** hyperlink with implicit delegation of sessionid if target is not another webserver.
* if href is not specified then the previously requested page is used as href .
* usage expamle:
* text or image *)
Hyperlink* = OBJECT (DynamicWebpage.StateLessActiveElement)
PROCEDURE Transform*(input: XML.Element; request: HTTPSupport.HTTPRequest) : XML.Content;
VAR a: XML.Element; hrefString, attrName, sessionCounterStr: Strings.String; newUri: ARRAY 4096 OF CHAR;
enum: XMLObjects.Enumerator; p: ANY; attr: XML.Attribute; content: XML.Content;
dynStr: DynamicStrings.DynamicString; session: HTTPSession.Session;
BEGIN
session := HTTPSession.GetSession(request); (* session # NIL *)
hrefString := input.GetAttributeValue("href");
IF ((hrefString = NIL) OR (~IsExternalHyperlink(hrefString^, request.header.host))) THEN
IF (hrefString # NIL) THEN
COPY(hrefString^, newUri);
IF (Strings.Pos("?", hrefString^) = -1) THEN
Strings.Append(newUri, "?")
ELSE
Strings.Append(newUri, "&")
END
ELSE
(* href is the previous requested page *)
Strings.Concat(request.shortUri, "?", newUri)
END;
Strings.Append(newUri, HTTPSession.HTTPVarSessionIdName);
Strings.Append(newUri, "=");
Strings.Append(newUri, session.sessionId);
p := session.GetVariableValue(DynamicWebpage.StateCounterVariable);
IF ((p # NIL) & (p IS DynamicStrings.DynamicString)) THEN
dynStr := p(DynamicStrings.DynamicString); sessionCounterStr := dynStr.ToArrOfChar(); (* sessionCounterStr # NIL *)
Strings.Append(newUri, "&");
Strings.Append(newUri, DynamicWebpage.StateCounterVariable);
Strings.Append(newUri, "=");
Strings.Append(newUri, sessionCounterStr^)
END
ELSE
COPY(hrefString^, newUri)
END;
NEW(a); a.SetName("a"); a.SetAttributeValue("href", newUri);
enum := input.GetAttributes();
WHILE (enum.HasMoreElements()) DO
p := enum.GetNext(); attr := p(XML.Attribute);
attrName := attr.GetName();
IF ((attrName # NIL) & (attrName^ # "href") & (Strings.Pos("xmlns", attrName^) # 0)) THEN
a.AddAttribute(attr)
END
END;
enum := input.GetContents();
WHILE (enum.HasMoreElements()) DO
p := enum.GetNext(); content := p(XML.Content);
a.AddContent(content)
END;
RETURN a
END Transform;
END Hyperlink;
(** returns a HTTP header field value specified by name attribute and special header properties like "#ip", "#port", "#method"
*
*)
GetHeaderField* = OBJECT(DynamicWebpage.StateLessActiveElement)
PROCEDURE Transform*(elem: XML.Element; request: HTTPSupport.HTTPRequest) : XML.Content;
VAR fieldName : Strings.String;
result : ARRAY 256 OF CHAR;
BEGIN
fieldName := elem.GetAttributeValue("name");
IF (fieldName # NIL) THEN
WebHTTP.GetRequestPropertyValue(request.header, fieldName^, result);
RETURN CreateXMLText(result)
ELSE RETURN NIL
END
END Transform;
END GetHeaderField;
(** set a session global variable, usage example:
*
*)
SetVariable* = OBJECT(DynamicWebpage.StateLessActiveElement)
PROCEDURE Transform*(elem: XML.Element; request: HTTPSupport.HTTPRequest) : XML.Content;
VAR varName, varValue, encVarName: Strings.String; session: HTTPSession.Session;
dynVarValue, dynVarName: DynamicStrings.DynamicString;
BEGIN (* only DynamicString can have a type guard for PTR *)
varName := elem.GetAttributeValue("name");
varValue := elem.GetAttributeValue("value");
IF ((varName # NIL) & (varValue # NIL)) THEN
NEW(dynVarValue); dynVarValue.Append(varValue^);
NEW(dynVarName); Concat(dynVarName, SessionVariableNamePrefix);
dynVarName.Append(varName^);
encVarName := dynVarName.ToArrOfChar();
session := HTTPSession.GetSession(request);
session.AddVariableValue(encVarName^, dynVarValue)
END;
RETURN NIL
END Transform;
END SetVariable;
(** get a session global variable, usage example:
*
*)
GetVariable* = OBJECT(DynamicWebpage.StateLessActiveElement)
PROCEDURE Transform*(elem: XML.Element; request: HTTPSupport.HTTPRequest) : XML.Content;
VAR varName, varValue, encVarName: Strings.String; session: HTTPSession.Session;
dynVarValue, dynVarName: DynamicStrings.DynamicString; p: ANY;
BEGIN
varName := elem.GetAttributeValue("name");
IF (varName # NIL) THEN
NEW(dynVarName); Concat(dynVarName, SessionVariableNamePrefix);
dynVarName.Append(varName^);
encVarName := dynVarName.ToArrOfChar();
session := HTTPSession.GetSession(request);
p := session.GetVariableValue(encVarName^);
IF ((p # NIL) & (p IS DynamicStrings.DynamicString)) THEN
dynVarValue := p(DynamicStrings.DynamicString);
IF (dynVarValue.Length() > 0) THEN
varValue := dynVarValue.ToArrOfChar();
RETURN CreateXMLText(varValue^)
END
END
END;
RETURN NIL
END Transform;
END GetVariable;
(** conditional element. If 'condition' contains exactly the text "true" then the 'Expression'-content is the result.
* If 'condition' contains exactly the text 'false' then no result will be generated and active elements apearing
* under the 'Expression'-element will not be transformed.
* The condition value could be the result of another active element like
* "WebStd:IsEqual". Usage example:
*
* true|false
* ..
*
*)
Guard* = OBJECT (DynamicWebpage.StateLessActiveElement)
(* the 'Expression' subtree is only transformed if the condition has the value 'true'. Since the condition can have
* further active element in its content, it can only be decided in the Transform()-method if the contents of
* the 'Expression'-element will be used for the transformation result.
* Therefore in PreTransform the 'Expression'-subtree is cut out and stored into the session using the
* SessionGuardNamePrefix followed by the request.shortUri to support parallel requests of the same client
* for different documents with if statements. The use of a state full active element would result in worse
* performance, since each 'Guard'-occurence would have its own instances *)
PROCEDURE Transform*(elem: XML.Element; request: HTTPSupport.HTTPRequest) : XML.Content;
VAR conditionElem, expressionElem: XML.Element; session: HTTPSession.Session;
dynVarName: DynamicStrings.DynamicString; varName, condText: Strings.String; p: ANY;
outContainer: XML.Container;
BEGIN
session := HTTPSession.GetSession(request);
NEW(dynVarName); Concat(dynVarName, SessionGuardNamePrefix);
dynVarName.Append(request.shortUri);
varName := dynVarName.ToArrOfChar();
p := session.GetVariableValue(varName^);
IF ((p # NIL) & (p IS XML.Element)) THEN
expressionElem := p(XML.Element)
ELSE
expressionElem := NIL
END;
session.RemoveVariable(varName^);
conditionElem := GetXMLSubElement(elem, "Condition");
IF (conditionElem # NIL) THEN
condText := GetXMLCharContent(conditionElem);
IF ((condText # NIL) & (condText^ = "true")) THEN
IF (expressionElem # NIL) THEN
NEW(outContainer);
CopyXMLSubContents(expressionElem, outContainer);
RETURN outContainer
ELSE
RETURN NIL
END
ELSIF ((condText # NIL) & (condText^ = "false")) THEN
RETURN NIL
ELSE
NEW(outContainer);
AppendXMLContent(outContainer, CreateXMLText("WebStd:Guard: Condition value must be either 'true' or 'false' but not "));
IF (condText # NIL) THEN AppendXMLContent(outContainer, CreateXMLText(condText^)) END;
RETURN outContainer
END
ELSE
RETURN CreateXMLText("No condition specified for WebStd:Guard.")
END
END Transform;
PROCEDURE PreTransform*(elem: XML.Element; request: HTTPSupport.HTTPRequest) : XML.Content;
VAR expressionElem: XML.Element; session: HTTPSession.Session; dynVarName: DynamicStrings.DynamicString;
varName: Strings.String;
BEGIN
session := HTTPSession.GetSession(request);
expressionElem := GetXMLSubElement(elem, "Expression");
NEW(dynVarName); Concat(dynVarName, SessionGuardNamePrefix);
dynVarName.Append(request.shortUri);
varName := dynVarName.ToArrOfChar();
session.AddVariableValue(varName^, expressionElem);
IF (expressionElem # NIL) THEN
elem.RemoveContent(expressionElem)
END;
RETURN elem
END PreTransform;
END Guard;
(** sequence over multiple requests of one page for a session. If the attribute 'circular' is set to 'true' then at the end of the
* sequence the sequence will be restarted. if the sequence is non circular and has reached the last state then it stays in
* the last state. Usage example:
*
* ..
* ..
* ..
*
* the event "SetState" with parameter "pos" can be used to set the actual state position for a sequence *)
Sequence* = OBJECT (DynamicWebpage.StateFullActiveElement)
VAR
stateCounter: LONGINT;
PROCEDURE &Init*;
BEGIN stateCounter := 0
END Init;
PROCEDURE Transform*(elem: XML.Element; request: HTTPSupport.HTTPRequest) : XML.Content;
BEGIN RETURN elem
END Transform;
PROCEDURE PreTransform*(elem: XML.Element; request: HTTPSupport.HTTPRequest) : XML.Content;
VAR p: ANY; enum: XMLObjects.Enumerator; counter: LONGINT; state, actState: XML.Element;
stateName: Strings.String; container: XML.Container; content: XML.Content; circularVal: Strings.String;
BEGIN
actState:= NIL; counter := 0;
enum := elem.GetContents();
WHILE (enum.HasMoreElements()) DO
p := enum.GetNext();
IF (p IS XML.Element) THEN
state := p(XML.Element); stateName := state.GetName();
IF ((stateName # NIL) & (stateName^ = "State")) THEN
IF (stateCounter = counter) THEN
actState := state
END;
INC(counter);
END
END
END;
INC(stateCounter);
circularVal := elem.GetAttributeValue("circular");
IF ((counter > 0) & (stateCounter >= counter)) THEN
IF ((circularVal # NIL) & (circularVal^ = "true")) THEN
stateCounter := stateCounter MOD counter
ELSE
stateCounter := counter-1
END
END;
IF (actState # NIL) THEN
NEW(container);
enum := actState.GetContents();
WHILE (enum.HasMoreElements()) DO
p := enum.GetNext(); content := p(XML.Content);
container.AddContent(content)
END;
RETURN container
ELSE (* end of the sequence was already reached *)
RETURN NIL
END
END PreTransform;
PROCEDURE SetState(request: HTTPSupport.HTTPRequest; params: DynamicWebpage.ParameterList);
(* parameters "pos" *)
VAR posStr: Strings.String;
BEGIN
posStr := params.GetParameterValueByName("pos");
IF (posStr # NIL) THEN
Strings.StrToInt(posStr^, stateCounter)
ELSE
KernelLog.String("WebStd:Sequence - event handler 'SetState' has parameter 'pos'.");
KernelLog.Ln
END
END SetState;
PROCEDURE GetEventHandlers*() : DynamicWebpage.EventHandlerList;
VAR list: DynamicWebpage.EventHandlerList;
BEGIN
NEW(list, 1);
NEW(list[0], "SetState", SetState);
RETURN list
END GetEventHandlers;
END Sequence;
(** an equal comparison for two XML subforests in 'Arg1' and 'Arg2'.
* Returns 'true' iff the subforests are equal otherwise 'false'. Usage example:
*
*
*
* *)
IsEqual* = OBJECT (DynamicWebpage.StateLessActiveElement)
PROCEDURE Compare(arg1, arg2: XML.Content) : BOOLEAN;
VAR chars1, chars2: XML.Chars; str1, str2: Strings.String; cref1, cref2: XML.CharReference;
ncont1, ncont2: XML.NameContent; attr1, attr2: XML.Attribute; cont1, cont2: XML.Container;
enum1, enum2: XMLObjects.Enumerator; p1, p2: ANY; content1, content2: XML.Content;
elem1, elem2: XML.Element;
BEGIN
IF ((arg1 = NIL) OR (arg2 = NIL)) THEN
RETURN arg1 = arg2
ELSIF (arg1 IS XML.Chars) THEN
IF (arg2 IS XML.Chars) THEN
chars1 := arg1(XML.Chars); chars2 := arg2(XML.Chars);
str1 := chars1.GetStr(); str2 := chars2.GetStr();
IF ((str1 # NIL) & (str2 # NIL)) THEN
RETURN str1^ = str2^
ELSE
RETURN str1 = str2
END
ELSE
RETURN FALSE
END
ELSIF (arg1 IS XML.CharReference) THEN
IF (arg2 IS XML.CharReference) THEN
cref1 := arg1(XML.CharReference); cref2 := arg2(XML.CharReference);
RETURN cref1.GetCode() = cref2.GetCode()
ELSE
RETURN FALSE
END
ELSIF (arg1 IS XML.NameContent) THEN
IF (arg2 IS XML.NameContent) THEN
ncont1 := arg1(XML.NameContent); ncont2 := arg2(XML.NameContent);
str1 := ncont1.GetName(); str2 := ncont2.GetName();
IF ((str1 = NIL) OR (str2 = NIL)) THEN
IF (str1 # str2) THEN RETURN FALSE END
ELSIF (str1^ # str2^) THEN
RETURN FALSE
END;
IF (ncont1 IS XML.Attribute) THEN
IF (ncont2 IS XML.Attribute) THEN
attr1 := ncont1(XML.Attribute); attr2 := ncont2(XML.Attribute);
str1 := attr1.GetValue(); str2 := attr2.GetValue();
IF ((str1 # NIL) & (str2 # NIL)) THEN
RETURN str1^ = str2^
ELSE
RETURN str1 = str2
END
ELSE
RETURN FALSE
END
END;
RETURN TRUE
ELSE
RETURN FALSE
END
ELSIF (arg1 IS XML.Container) THEN
IF (arg2 IS XML.Container) THEN
cont1 := arg1(XML.Container); cont2 := arg2(XML.Container);
enum1 := cont1.GetContents(); enum2 := cont2.GetContents();
WHILE ((enum1.HasMoreElements()) & (enum2.HasMoreElements())) DO
p1 := enum1.GetNext(); p2 := enum2.GetNext();
content1 := p1(XML.Content); content2 := p2(XML.Content);
IF (~Compare(content1, content2)) THEN RETURN FALSE END
END;
IF ((enum1.HasMoreElements()) OR (enum2.HasMoreElements())) THEN RETURN FALSE END;
IF (cont1 IS XML.Element) THEN
IF (cont2 IS XML.Element) THEN
elem1 := cont1(XML.Element); elem2 := cont2(XML.Element);
str1 := elem1.GetName(); str2 := elem2.GetName();
IF ((str1 # NIL) & (str2 # NIL)) THEN
IF (str1^ # str2^) THEN RETURN FALSE END
ELSE
IF (str1 # str2) THEN RETURN FALSE END
END;
enum1 := elem1.GetAttributes(); enum2 := elem2.GetAttributes();
WHILE ((enum1.HasMoreElements()) & (enum2.HasMoreElements())) DO
p1 := enum1.GetNext(); p2 := enum2.GetNext();
content1 := p1(XML.Content); content2 := p2(XML.Content);
IF (~Compare(content1, content2)) THEN RETURN FALSE END
END;
IF ((enum1.HasMoreElements()) OR (enum2.HasMoreElements())) THEN RETURN FALSE END;
RETURN TRUE
ELSE
RETURN FALSE
END;
END;
RETURN TRUE
ELSE
RETURN FALSE
END
ELSE
(* not supported *)
RETURN FALSE
END
END Compare;
PROCEDURE Transform*(elem: XML.Element; request: HTTPSupport.HTTPRequest) : XML.Content;
VAR arg1, arg2: XML.Element; enum1, enum2: XMLObjects.Enumerator; p1, p2: ANY; content1, content2: XML.Content;
BEGIN
arg1 := GetXMLSubElement(elem, "Arg1"); arg2 := GetXMLSubElement(elem, "Arg2");
IF ((arg1 # NIL) & (arg2 # NIL)) THEN
enum1 := arg1.GetContents(); enum2 := arg2.GetContents();
WHILE ((enum1.HasMoreElements()) & (enum2.HasMoreElements())) DO
p1 := enum1.GetNext(); p2 := enum2.GetNext();
content1 := p1(XML.Content); content2 := p2(XML.Content);
IF (~Compare(content1, content2)) THEN
RETURN CreateXMLText("false")
END
END;
IF ((enum1.HasMoreElements()) OR (enum2.HasMoreElements())) THEN
RETURN CreateXMLText("false")
END;
RETURN CreateXMLText("true")
ELSE
RETURN CreateXMLText("WebStd:IsEqual: Missing 'Arg1' or 'Arg2' subelement")
END
END Transform;
END IsEqual;
(** returns 'true' if the content is 'false'. If the content is 'false' then it returns 'true'. Usage example
* The content could be the results of active elements like 'IsEqual'.
* true|false *)
Not* = OBJECT(DynamicWebpage.StateLessActiveElement)
PROCEDURE Transform*(elem: XML.Element; request: HTTPSupport.HTTPRequest) : XML.Content;
VAR str: Strings.String;
BEGIN
str := GetXMLCharContent(elem);
IF ((str # NIL) & (str^ = "true")) THEN
RETURN CreateXMLText("false")
ELSIF ((str # NIL) & (str^ = "false")) THEN
RETURN CreateXMLText("true")
ELSE
RETURN CreateXMLText("WebStd:Not - Content must be either 'true' or 'false'.")
END
END Transform;
END Not;
(** returns 'true' if both arguments 'Arg1' and 'Arg2' have content 'true'. If one of them has content 'false' the result will be
* 'false'. The contents could be the results of active elements like 'IsEqual'. Usage example:
*
* true|false
* true|false
* *)
And* = OBJECT(DynamicWebpage.StateLessActiveElement)
PROCEDURE Transform*(elem: XML.Element; request: HTTPSupport.HTTPRequest) : XML.Content;
VAR arg1, arg2: XML.Element; str1, str2: Strings.String;
BEGIN
arg1 := GetXMLSubElement(elem, "Arg1");
arg2 := GetXMLSubElement(elem, "Arg2");
IF ((arg1 # NIL) & (arg2 # NIL)) THEN
str1 := GetXMLCharContent(arg1);
str2 := GetXMLCharContent(arg2);
IF ((str1 # NIL) & (str1^ = "true") & (str2 # NIL) & (str2^ = "true")) THEN
RETURN CreateXMLText("true")
ELSIF ((str1 # NIL) & (str1^ = "true") & (str2 # NIL) & (str2^ = "false")) THEN
RETURN CreateXMLText("false")
ELSIF ((str1 # NIL) & (str1^ = "false") & (str2 # NIL) & (str2^ = "true")) THEN
RETURN CreateXMLText("false")
ELSIF ((str1 # NIL) & (str1^ = "false") & (str2 # NIL) & (str2^ = "false")) THEN
RETURN CreateXMLText("false")
ELSE
RETURN CreateXMLText("WebStd:And - Content of 'Arg1' and 'Arg2' must be either 'true' or 'false'.")
END
ELSE
RETURN CreateXMLText("WebStd:And - 'Arg1' or 'Arg2' subelements missing.")
END
END Transform;
END And;
(** returns 'true' if argument 'Arg1' or 'Arg2' (or both) has content 'true'. If both of them have content 'false'
* the result will be 'false'. The contents could be the results of active elements like 'IsEqual'. Usage example:
*
* true|false
* true|false
* *)
Or* = OBJECT(DynamicWebpage.StateLessActiveElement)
PROCEDURE Transform*(elem: XML.Element; request: HTTPSupport.HTTPRequest) : XML.Content;
VAR arg1, arg2: XML.Element; str1, str2: Strings.String;
BEGIN
arg1 := GetXMLSubElement(elem, "Arg1");
arg2 := GetXMLSubElement(elem, "Arg2");
IF ((arg1 # NIL) & (arg2 # NIL)) THEN
str1 := GetXMLCharContent(arg1);
str2 := GetXMLCharContent(arg2);
IF ((str1 # NIL) & (str1^ = "false") & (str2 # NIL) & (str2^ = "false")) THEN
RETURN CreateXMLText("false")
ELSIF ((str1 # NIL) & (str1^ = "true") & (str2 # NIL) & (str2^ = "false")) THEN
RETURN CreateXMLText("true")
ELSIF ((str1 # NIL) & (str1^ = "false") & (str2 # NIL) & (str2^ = "true")) THEN
RETURN CreateXMLText("true")
ELSIF ((str1 # NIL) & (str1^ = "true") & (str2 # NIL) & (str2^ = "true")) THEN
RETURN CreateXMLText("true")
ELSE
RETURN CreateXMLText("WebStd:Or - Content of 'Arg1' and 'Arg2' must be either 'true' or 'false'.")
END
ELSE
RETURN CreateXMLText("WebStd:Or - 'Arg1' or 'Arg2' subelements missing.")
END
END Transform;
END Or;
(** returns 'true' if argument either 'Arg1' or 'Arg2' has content 'true'. If both of them have the same content 'true' or 'false'
* the result will be 'false'. The contents could be the results of active elements like 'IsEqual'. Usage example:
*
* true|false
* true|false
* *)
Xor* = OBJECT(DynamicWebpage.StateLessActiveElement)
PROCEDURE Transform*(elem: XML.Element; request: HTTPSupport.HTTPRequest) : XML.Content;
VAR arg1, arg2: XML.Element; str1, str2: Strings.String;
BEGIN
arg1 := GetXMLSubElement(elem, "Arg1");
arg2 := GetXMLSubElement(elem, "Arg2");
IF ((arg1 # NIL) & (arg2 # NIL)) THEN
str1 := GetXMLCharContent(arg1);
str2 := GetXMLCharContent(arg2);
IF ((str1 # NIL) & (str1^ = "true") & (str2 # NIL) & (str2^ = "false")) THEN
RETURN CreateXMLText("true")
ELSIF ((str1 # NIL) & (str1^ = "false") & (str2 # NIL) & (str2^ = "true")) THEN
RETURN CreateXMLText("true")
ELSIF ((str1 # NIL) & (str1^ = "false") & (str2 # NIL) & (str2^ = "false")) THEN
RETURN CreateXMLText("false")
ELSIF ((str1 # NIL) & (str1^ = "true") & (str2 # NIL) & (str2^ = "true")) THEN
RETURN CreateXMLText("false")
ELSE
RETURN CreateXMLText("WebStd:Xor - Content of 'Arg1' and 'Arg2' must be either 'true' or 'false'.")
END
ELSE
RETURN CreateXMLText("WebStd:Xor - 'Arg1' or 'Arg2' subelements missing.")
END
END Transform;
END Xor;
(** a button that triggers a user event, usage example:
* EventButton can optionally have an attribute 'href' to specify another target page as the current one.
* If the target object is a statefull active element then 'objectid' has to used to specify the instance.
*
*
*
* ...
* *)
EventButton* = OBJECT (DynamicWebpage.StateLessActiveElement)
PROCEDURE Transform*(elem: XML.Element; request: HTTPSupport.HTTPRequest) : XML.Content;
VAR labelName, methodName, objectName, objectIdName, moduleName, elemName, paramName, paramValue,
hrefString, sessionCounterStr: Strings.String; form, input, param: XML.Element; enum: XMLObjects.Enumerator;
p: ANY; newParamName, encStr: ARRAY 128 OF CHAR; content: XML.Content; session: HTTPSession.Session;
dynStr: DynamicStrings.DynamicString;
BEGIN
session := HTTPSession.GetSession(request); (* session # NIL *)
labelName := elem.GetAttributeValue("label");
methodName := elem.GetAttributeValue("method");
objectName := elem.GetAttributeValue("object");
objectIdName := elem.GetAttributeValue("objectid");
moduleName := elem.GetAttributeValue("module");
IF ((moduleName # NIL) & (methodName# NIL) & (objectName # NIL)) THEN
NEW(form); form.SetName("form");
form.SetAttributeValue("method", "POST");
hrefString := elem.GetAttributeValue("href");
IF (hrefString # NIL) THEN
form.SetAttributeValue("action", hrefString^)
ELSE
form.SetAttributeValue("action", request.shortUri)
END;
NEW(input); input.SetName("input");
input.SetAttributeValue("type", "hidden");
input.SetAttributeValue("name", DynamicWebpage.HTTPVarCommandModule);
input.SetAttributeValue("value", moduleName^);
form.AddContent(input);
NEW(input); input.SetName("input");
input.SetAttributeValue("type", "hidden");
input.SetAttributeValue("name", DynamicWebpage.HTTPVarCommandObject);
input.SetAttributeValue("value", objectName^);
form.AddContent(input);
NEW(input); input.SetName("input");
input.SetAttributeValue("type", "hidden");
input.SetAttributeValue("name", DynamicWebpage.HTTPVarCommandMethod);
input.SetAttributeValue("value", methodName^);
form.AddContent(input);
IF (objectIdName # NIL) THEN
NEW(input); input.SetName("input");
input.SetAttributeValue("type", "hidden");
input.SetAttributeValue("name", DynamicWebpage.HTTPVarCommandObjectId);
input.SetAttributeValue("value", objectIdName^);
form.AddContent(input)
END;
enum := elem.GetContents();
WHILE (enum.HasMoreElements()) DO
p := enum.GetNext();
IF (p IS XML.Element) THEN
param := p(XML.Element); elemName := param.GetName();
IF ((elemName # NIL) & (elemName^ = "Param")) THEN
paramName := param.GetAttributeValue("name");
paramValue := param.GetAttributeValue("value");
IF ((paramName # NIL) & (paramValue # NIL)) THEN
HTTPSupport.HTTPEncode(paramName^, encStr);
Strings.Concat(DynamicWebpage.HTTPVarCommandParamPrefix, encStr, newParamName);
NEW(input); input.SetName("input");
input.SetAttributeValue("type", "hidden");
input.SetAttributeValue("name", newParamName);
HTTPSupport.HTTPEncode(paramValue^, encStr);
input.SetAttributeValue("value", encStr);
form.AddContent(input)
ELSE
form.AddContent(param)
END
ELSE
content := p(XML.Content); form.AddContent(content)
END
END
END;
NEW(input); input.SetName("input");
input.SetAttributeValue("type", "hidden");
input.SetAttributeValue("name", HTTPSession.HTTPVarSessionIdName);
input.SetAttributeValue("value", session.sessionId);
form.AddContent(input);
p := session.GetVariableValue(DynamicWebpage.StateCounterVariable);
IF ((p # NIL) & (p IS DynamicStrings.DynamicString)) THEN
dynStr := p(DynamicStrings.DynamicString); sessionCounterStr := dynStr.ToArrOfChar(); (* sessionCounterStr # NIL *)
NEW(input); input.SetName("input");
input.SetAttributeValue("type", "hidden");
input.SetAttributeValue("name", DynamicWebpage.StateCounterVariable);
input.SetAttributeValue("value", sessionCounterStr^);
form.AddContent(input)
END;
NEW(input); input.SetName("input");
input.SetAttributeValue("type", "submit");
IF (labelName # NIL) THEN
input.SetAttributeValue("value", labelName^)
END;
form.AddContent(input);
RETURN form
ELSE
RETURN CreateXMLText("Missing module, object or method name for WebStd:EventButton")
END
END Transform;
END EventButton;
(** a hyperlink that triggers a user event.
* EventLink can optionally have an attribute 'href' to specify another target page as the current one.
* If the target object is a statefull active element then 'objectid' is used to specify the instance.
* usage example:
*
*
*
*
* ...
* *)
EventLink* = OBJECT(DynamicWebpage.StateLessActiveElement)
PROCEDURE Transform*(elem: XML.Element; request: HTTPSupport.HTTPRequest) : XML.Content;
VAR a: XML.Element; newUri: ARRAY 4096 OF CHAR; enum, labelEnum: XMLObjects.Enumerator;
p, labelp: ANY; attr: XML.Attribute; content, labelContent: XML.Content;
methodName, objectName, objectIdName, moduleName, attrName, subElemName, paramName, paramValue,
hrefString, sessionCounterStr: Strings.String; encStr: ARRAY 128 OF CHAR; subElem: XML.Element;
session: HTTPSession.Session; dynStr: DynamicStrings.DynamicString;
BEGIN
session := HTTPSession.GetSession(request);
methodName := elem.GetAttributeValue("method");
objectName := elem.GetAttributeValue("object");
objectIdName := elem.GetAttributeValue("objectid");
moduleName := elem.GetAttributeValue("module");
IF ((moduleName # NIL) & (methodName# NIL) & (objectName # NIL)) THEN
hrefString := elem.GetAttributeValue("href");
IF (hrefString # NIL) THEN
COPY(hrefString^, newUri);
IF (Strings.Pos("?", hrefString^) = -1) THEN
Strings.Append(newUri, "?")
ELSE
Strings.Append(newUri, "&")
END
ELSE
Strings.Concat(request.shortUri, "?", newUri)
END;
Strings.Append(newUri, HTTPSession.HTTPVarSessionIdName);
Strings.Append(newUri, "=");
Strings.Append(newUri, session.sessionId);
Strings.Append(newUri, "&");
Strings.Append(newUri, DynamicWebpage.HTTPVarCommandModule);
Strings.Append(newUri, "=");
Strings.Append(newUri, moduleName^);
Strings.Append(newUri, "&");
Strings.Append(newUri, DynamicWebpage.HTTPVarCommandObject);
Strings.Append(newUri, "=");
Strings.Append(newUri, objectName^);
Strings.Append(newUri, "&");
Strings.Append(newUri, DynamicWebpage.HTTPVarCommandMethod);
Strings.Append(newUri, "=");
Strings.Append(newUri, methodName^);
IF (objectIdName # NIL) THEN
Strings.Append(newUri, "&");
Strings.Append(newUri, DynamicWebpage.HTTPVarCommandObjectId);
Strings.Append(newUri, "=");
Strings.Append(newUri, objectIdName^)
END;
p := session.GetVariableValue(DynamicWebpage.StateCounterVariable);
IF ((p # NIL) & (p IS DynamicStrings.DynamicString)) THEN
dynStr := p(DynamicStrings.DynamicString); sessionCounterStr := dynStr.ToArrOfChar(); (* sessionCounterStr # NIL *)
Strings.Append(newUri, "&");
Strings.Append(newUri, DynamicWebpage.StateCounterVariable);
Strings.Append(newUri, "=");
Strings.Append(newUri, sessionCounterStr^)
END;
NEW(a); a.SetName("a");
enum := elem.GetAttributes();
WHILE (enum.HasMoreElements()) DO
p := enum.GetNext(); attr := p(XML.Attribute);
attrName := attr.GetName();
IF ((attrName # NIL) & (attrName^ # "href") & (attrName^ # "method") & (attrName^ # "object") &
(attrName^ # "objectid") & (attrName^ # "module") & (Strings.Pos("xmlns", attrName^) # 0)) THEN
a.AddAttribute(attr)
END
END;
enum := elem.GetContents();
WHILE (enum.HasMoreElements()) DO
p := enum.GetNext(); content := p(XML.Content);
IF (content IS XML.Element) THEN
subElem := content(XML.Element); subElemName := subElem.GetName();
IF (subElemName^ = "Param") THEN
paramName := subElem.GetAttributeValue("name");
paramValue := subElem.GetAttributeValue("value");
IF ((paramName # NIL) & (paramValue # NIL)) THEN
Strings.Append(newUri, "&");
Strings.Append(newUri, DynamicWebpage.HTTPVarCommandParamPrefix);
HTTPSupport.HTTPEncode(paramName^, encStr);
Strings.Append(newUri, encStr);
Strings.Append(newUri, "=");
HTTPSupport.HTTPEncode(paramValue^, encStr);
Strings.Append(newUri, encStr)
END
ELSIF ((subElemName # NIL) & (subElemName^ = "Label")) THEN
labelEnum := subElem.GetContents();
WHILE (labelEnum.HasMoreElements()) DO
labelp := labelEnum.GetNext(); labelContent := labelp(XML.Content);
a.AddContent(labelContent)
END
END
END
END;
a.SetAttributeValue("href", newUri);
RETURN a
ELSE
RETURN CreateXMLText("Missing module, object or method name for WebStd:EventLink")
END
END Transform;
END EventLink;
(** a formular that triggers a user event with parameters if submitted.
* transfer-method is HTTP POST.
* Formular can have an optionally attribute 'href' to specify another target page as the current one.
* If the target object is a statefull active element then 'objectid' has to used to specfiy the instance.
* usage example:
*
* ...
*
*
*
* ...
*
* ...
* *)
Formular* = OBJECT(DynamicWebpage.StateLessActiveElement)
PROCEDURE Transform*(elem: XML.Element; request: HTTPSupport.HTTPRequest) : XML.Content;
VAR methodName, objectName, objectIdName, moduleName, attrName, hrefString, sessionCounterStr: Strings.String;
session: HTTPSession.Session; form, input: XML.Element; enum: XMLObjects.Enumerator; p: ANY;
content: XML.Content; attr: XML.Attribute; dynStr: DynamicStrings.DynamicString;
BEGIN
session := HTTPSession.GetSession(request); (* session # NIL *)
methodName := elem.GetAttributeValue("method");
objectName := elem.GetAttributeValue("object");
objectIdName := elem.GetAttributeValue("objectid");
moduleName := elem.GetAttributeValue("module");
IF ((moduleName # NIL) & (methodName# NIL) & (objectName # NIL)) THEN
NEW(form); form.SetName("form");
form.SetAttributeValue("method", "post");
hrefString := elem.GetAttributeValue("href");
IF (hrefString # NIL) THEN
form.SetAttributeValue("action", hrefString^)
ELSE
form.SetAttributeValue("action", request.shortUri)
END;
enum := elem.GetAttributes();
WHILE (enum.HasMoreElements()) DO
p := enum.GetNext(); attr := p(XML.Attribute);
attrName := attr.GetName();
IF ((attrName # NIL) & (attrName^ # "href") & (attrName^ # "method")) THEN
form.AddAttribute(attr)
END
END;
NEW(input); input.SetName("input");
input.SetAttributeValue("type", "hidden");
input.SetAttributeValue("name", DynamicWebpage.HTTPVarCommandModule);
input.SetAttributeValue("value", moduleName^);
form.AddContent(input);
NEW(input); input.SetName("input");
input.SetAttributeValue("type", "hidden");
input.SetAttributeValue("name", DynamicWebpage.HTTPVarCommandObject);
input.SetAttributeValue("value", objectName^);
form.AddContent(input);
NEW(input); input.SetName("input");
input.SetAttributeValue("type", "hidden");
input.SetAttributeValue("name", DynamicWebpage.HTTPVarCommandMethod);
input.SetAttributeValue("value", methodName^);
form.AddContent(input);
IF (objectIdName # NIL) THEN
NEW(input); input.SetName("input");
input.SetAttributeValue("type", "hidden");
input.SetAttributeValue("name", DynamicWebpage.HTTPVarCommandObjectId);
input.SetAttributeValue("value", objectIdName^);
form.AddContent(input)
END;
NEW(input); input.SetName("input");
input.SetAttributeValue("type", "hidden");
input.SetAttributeValue("name", HTTPSession.HTTPVarSessionIdName);
input.SetAttributeValue("value", session.sessionId);
form.AddContent(input);
enum := elem.GetContents();
WHILE (enum.HasMoreElements()) DO
p := enum.GetNext(); content := p(XML.Content);
RenameInputAttr(content);
form.AddContent(content)
END;
p := session.GetVariableValue(DynamicWebpage.StateCounterVariable);
IF ((p # NIL) & (p IS DynamicStrings.DynamicString)) THEN
dynStr := p(DynamicStrings.DynamicString); sessionCounterStr := dynStr.ToArrOfChar(); (* sessionCounterStr # NIL *)
NEW(input); input.SetName("input");
input.SetAttributeValue("type", "hidden");
input.SetAttributeValue("name", DynamicWebpage.StateCounterVariable);
input.SetAttributeValue("value", sessionCounterStr^);
form.AddContent(input)
END;
RETURN form
ELSE
RETURN CreateXMLText("Missing module, object or method name for WebStd:Formular")
END
END Transform;
(* rename 'name' attribute for ,