Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UUID and message handling code copied from OSCAL repo #3

Merged
merged 3 commits into from
Mar 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions message-handler/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# XSLT Message Handler

This directory contains XSLT named templates for handling error and warning messages:

* `x3f:message-handler` template: Emit message to console, or output processing instruction instead.



35 changes: 35 additions & 0 deletions message-handler/message-handler.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:x3f="http://csrc.nist.gov/ns/xslt3-functions"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">

<xsl:param name="x3f:returns_pi" as="xs:boolean" select="false()"/>

<xsl:template name="x3f:message-handler">
<xsl:param name="text" as="xs:string"/>
<xsl:param name="message-type" as="xs:string?"/><!-- e.g., 'Error', 'Warning' -->
<xsl:param name="error-code" as="xs:string?"/>
<xsl:param name="terminate" as="xs:boolean" select="false()"/>
<xsl:param name="returns_pi" as="xs:boolean" select="$x3f:returns_pi"/>
<xsl:variable name="joined-string" as="xs:string"
select="string-join(($message-type, $error-code, $text),': ')"/>
<xsl:choose expand-text="yes">
<xsl:when test="$returns_pi">
<xsl:processing-instruction name="message-handler">{
if ($terminate) then 'Terminating ' else ''
}{
$joined-string
}</xsl:processing-instruction>
<!-- Above, line break inside the text value template instead of outside it
prevents the output PI from including the line break. -->
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="{$terminate}">{$joined-string}</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

</xsl:stylesheet>
71 changes: 71 additions & 0 deletions message-handler/tests/message-handler.xspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<x:description
xmlns:x="http://www.jenitennison.com/xslt/xspec"
xmlns:x3f="http://csrc.nist.gov/ns/xslt3-functions"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
stylesheet="../message-handler.xsl"
xslt-version="3.0">

<x:param name="x3f:returns_pi" as="xs:boolean" select="true()"/>

<x:scenario label="Tests for x3f:message-handler template">
<x:scenario label="Call with text, type, and code">
<x:call template="x3f:message-handler">
<x:param name="text" select="'message text'"/>
<x:param name="message-type" select="'Warning'"/>
<x:param name="error-code" select="'ERR1'"/>
</x:call>
<x:expect label="PI indicating type, code, and text">
<?message-handler Warning: ERR1: message text?>
</x:expect>
</x:scenario>
<x:scenario label="Call with text and type only">
<x:call template="x3f:message-handler">
<x:param name="text" select="'message text'"/>
<x:param name="message-type" select="'Warning'"/>
</x:call>
<x:expect label="PI indicating type and text">
<?message-handler Warning: message text?>
</x:expect>
</x:scenario>
<x:scenario label="Call with text and code only">
<x:call template="x3f:message-handler">
<x:param name="text" select="'message text'"/>
<x:param name="error-code" select="'ERR1'"/>
</x:call>
<x:expect label="PI indicating code and text">
<?message-handler ERR1: message text?>
</x:expect>
</x:scenario>
<x:scenario label="Call with text only">
<x:call template="x3f:message-handler">
<x:param name="text" select="'message text'"/>
</x:call>
<x:expect label="PI indicating text">
<?message-handler message text?>
</x:expect>
</x:scenario>
<x:scenario label="Call with text and type only, with terminate=true: ">
<x:scenario label="Check that message really terminates transform" catch="yes">
<x:call template="x3f:message-handler">
<x:param name="text" select="'message text'"/>
<x:param name="message-type" select="'Error'"/>
<x:param name="terminate" select="true()"/>
<x:param name="returns_pi" select="false()"/>
</x:call>
<x:expect label="Error" test="$x:result instance of map(*) and $x:result('err') instance of map(*)"/>
</x:scenario>
<x:scenario label="Check PI">
<x:call template="x3f:message-handler">
<x:param name="text" select="'message text'"/>
<x:param name="message-type" select="'Error'"/>
<x:param name="terminate" select="true()"/>
<x:param name="returns_pi" select="true()"/>
</x:call>
<x:expect label="PI indicating type and text, where type is 'Terminating Error'">
<?message-handler Terminating Error: message text?>
</x:expect>
</x:scenario>
</x:scenario>
</x:scenario>
</x:description>
11 changes: 11 additions & 0 deletions random-util/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Utilities for Generating Pseudorandom Numbers

This directory contains XSLT functions and named templates for working with pseudorandom numbers:

* `x3f:determine-uuid` template: Return UUID string based on choice of generation options.
* `x3f:make-uuid` function: Return one v4 UUID.
* `x3f:make-uuid-sequence` function: Return sequence of v4 UUIDs.
* `x3f:make-random-string-sequence` function: Return sequence of strings based on user-specified pattern.



122 changes: 122 additions & 0 deletions random-util/random-util.xsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math" exclude-result-prefixes="#all"
xmlns:x3f="http://csrc.nist.gov/ns/xslt3-functions" version="3.0">

<!-- from the spec https://www.w3.org/TR/xpath-functions-31/#func-random-number-generator

declare %public function x3f:random-sequence($length as xs:integer) as xs:double* {
x3f:random-sequence($length, fn:random-number-generator())
};

declare %private function x3f:random-sequence($length as xs:integer,
$G as map(xs:string, item())) {
if ($length eq 0)
then ()
else ($G?number, x3f:random-sequence($length - 1, $G?next()))
};

x3f:random-sequence(200);

v4 UUID
hex fields 8 4 4 4 12
place 13 = 4
place 17 = 8-b

-->
<xsl:output indent="yes"/>

<!-- Set $germ to a string for reproducible outputs of x3f:make-uuid.
Pass in a blind value - and don't save it - for irreproducible outputs. -->

<xsl:param name="germ" select="current-dateTime() || document-uri(/)"/>

<!-- for testing random number features -->
<xsl:template match="/" name="xsl:initial-template" expand-text="true">
<!--<uuid><xsl:value-of select="uuid:randomUUID()" xmlns:uuid="java:java.util.UUID"/></uuid>-->
<randomness>
<now>{ x3f:make-uuid(current-dateTime()) }</now>
<germ>{ x3f:make-uuid($germ) }</germ>
<a>{ x3f:make-uuid('a') }</a>
<a>{ x3f:make-uuid('a') }</a>
<b>{ x3f:make-uuid('b') }</b>
<ten>
<xsl:for-each select="x3f:make-uuid-sequence($germ, 10)">
<uuid>{ . }</uuid>
</xsl:for-each>
</ten>
</randomness>
</xsl:template>

<!-- x3f:make-uuid produces one v4 UUID. Output is repeatable for a given seed.
If the random-number-generator() function is not available,
this function returns an empty sequence. -->
<xsl:function name="x3f:make-uuid" as="xs:string?">
<xsl:param name="seed" as="item()"/>
<xsl:sequence select="x3f:make-uuid-sequence($seed, 1)"/>
</xsl:function>

<!-- x3f:make-uuid-sequence produces a sequence of $seq-length v4 UUIDs.
Output is repeatable for a given seed. If the random-number-generator()
function is not available, this function returns an empty sequence. -->
<xsl:function name="x3f:make-uuid-sequence" as="xs:string*">
<xsl:param name="seed" as="item()"/>
<xsl:param name="seq-length" as="xs:integer"/>
<xsl:variable name="uuid-v4-template" as="xs:string">________-____-4___-=___-____________</xsl:variable>
<!-- a847eaab-cec8-41bd-98e2-02d02900b554 -->
<xsl:sequence select="x3f:make-random-string-sequence($seed, $seq-length, $uuid-v4-template)"/>
</xsl:function>

<!-- x3f:make-random-string-sequence produces a sequence of $seq-length strings.
The $template parameter specifies the pattern of characters in each
string, where:
* '_' becomes a random hex value 0-9a-f
* '=' becomes one of '8','9','a','b' at random
* Any other character is copied to the output string
Output is repeatable for a given seed. If the random-number-generator()
function is not available, this function returns an empty sequence. -->
<xsl:function name="x3f:make-random-string-sequence" as="xs:string*">
<xsl:param name="seed" as="item()"/>
<xsl:param name="seq-length" as="xs:integer"/>
<xsl:param name="template" as="xs:string"/>
<xsl:sequence use-when="function-available('random-number-generator')">
<xsl:variable name="PRNG" as="map(xs:string, item())" select="random-number-generator($seed)"/>
<xsl:variable name="template-length" as="xs:integer" select="string-length($template)"/>
<xsl:variable name="template-char-seq" as="xs:string*"
select="$template ! string-to-codepoints(.) ! codepoints-to-string(.)"/>
<!-- Draw one long stream from PRNG over sequence of characters in concatenated template,
advancing state in each iteration. -->
<xsl:variable name="random-chars" as="xs:string">
<xsl:value-of>
<xsl:iterate select="for $idx in (1 to $seq-length) return $template-char-seq">
<xsl:param name="PRNG" as="map(xs:string, item())" select="$PRNG"/>
<xsl:apply-templates select="current()" mode="uuid-char">
<xsl:with-param name="PRNG" select="$PRNG"/>
</xsl:apply-templates>
<xsl:next-iteration>
<xsl:with-param name="PRNG" select="$PRNG?next()"/>
</xsl:next-iteration>
</xsl:iterate>
</xsl:value-of>
</xsl:variable>
<!-- Divide $random-chars into nonoverlapping strings:
$seq-length of them, each of length $template-length. -->
<xsl:sequence select="for $idx in (0 to $seq-length - 1)
return substring($random-chars, 1 + $idx * $template-length, $template-length)"/>
</xsl:sequence>
</xsl:function>

<xsl:variable name="hex-digits" select="tokenize('0 1 2 3 4 5 6 7 8 9 a b c d e f', ' ')"/>

<xsl:template match=".[. = '_']" mode="uuid-char">
<xsl:param name="PRNG" as="map(xs:string, item())"/>
<xsl:sequence select="$PRNG?permute($hex-digits)[1]"/>
</xsl:template>

<xsl:template match=".[. = '=']" mode="uuid-char">
<xsl:param name="PRNG" as="map(xs:string, item())"/>
<xsl:sequence select="$PRNG?permute(('8', '9', 'a', 'b'))[1]"/>
</xsl:template>

</xsl:stylesheet>
Loading