dwww Home | Manual pages | Find package

X2Go::Server::Agent::NUserpContributed PeX2Go::Server::Agent::NX::Options(3pm)

NAME
       X2Go::Server::Agent::NX::Options - NX Options modification module

SYNOPSIS
        use X2Go::Server::Agent::NX::Options;

        # Options string, probably read in from somewhere, but
        # hardcoded here.
        my $options = 'some=option,another=opt,more=values,some=override,more=data:90';

        # Parse into an intermediate form.
        my $intermediate = X2Go::Server::Agent::NX::Options::parse_options ($options);

        # Check for errors.
        die "Unable to parse option string, aborting.\n" unless (defined ($intermediate));

        # (Optionally) compact it, this should make the duplicated "some" and "more"
        # keys unique.
        $intermediate = X2Go::Server::Agent::NX::Options::compact_intermediate ($intermediate);

        # Error handling ...
        die "Unable to compact intermediate array, aborting.\n" unless (defined ($intermediate));

        # Add to options string.
        my $transform_op = '+new=value';

        # Parse and sanitize transform string.
        my $interpreted_transform_ref = X2Go::Server::Agent::NX::Options::interpret_transform ($transform_op);

        # Error handling ...
        die "Invalid transformation passed, aborting.\n" unless (defined ($interpreted_transform_ref));

        # Extract transformation data.
        my ($transform_mode, $sanitized_transform) = @{$interpreted_transform_ref};

        # Apply transformation.
        $intermediate = X2Go::Server::Agent::NX::Options::transform_intermediate ($intermediate, $transform_mode, $sanitized_transform);

        # Error handling ...
        die "Error while transforming intermediate representation, aborting.\n" unless (defined ($intermediate));

        # Try to remove a combination which doesn't exist, this should not modify the
        # intermediate.
        # No more comments for things that were already explained.
        $transform_op = '-another=doesnotexist';
        $interpreted_transform_ref = X2Go::Server::Agent::NX::Options::interpret_transform ($transform_op);
        die "Invalid transformation passed, aborting.\n" unless (defined ($interpreted_transform_ref));
        ($transform_mode, $sanitized_transform) = @{$interpreted_transform_ref};
        $intermediate = X2Go::Server::Agent::NX::Options::transform_intermediate ($intermediate, $transform_mode, $sanitized_transform);
        die "Error while transforming intermediate representation, aborting.\n" unless (defined ($intermediate));

        # Remove a key unconditionally, this should change the intermediate.
        $transform_op = '-some';
        $interpreted_transform_ref = X2Go::Server::Agent::NX::Options::interpret_transform ($transform_op);
        die "Invalid transformation passed, aborting.\n" unless (defined ($interpreted_transform_ref));
        ($transform_mode, $sanitized_transform) = @{$interpreted_transform_ref};
        $intermediate = X2Go::Server::Agent::NX::Options::transform_intermediate ($intermediate, $transform_mode, $sanitized_transform);
        die "Error while transforming intermediate representation, aborting.\n" unless (defined ($intermediate));

        # Modify/update a key.
        $transform_op = '+another=newval';
        $interpreted_transform_ref = X2Go::Server::Agent::NX::Options::interpret_transform ($transform_op);
        die "Invalid transformation passed, aborting.\n" unless (defined ($interpreted_transform_ref));
        ($transform_mode, $sanitized_transform) = @{$interpreted_transform_ref};
        $intermediate = X2Go::Server::Agent::NX::Options::transform_intermediate ($intermediate, $transform_mode, $sanitized_transform);
        die "Error while transforming intermediate representation, aborting.\n" unless (defined ($intermediate));

        # Extract the "more" key.
        my $extract = X2Go::Server::Agent::NX::Options::extract_element ($intermediate, q{more});

        # Error handling ...
        die "Unable to extract 'more' key from intermediate, aborting.\n" unless defined ($extract);

        # Fetching multiple elements could be fine, for instance when the intermediate is not compact.
        # Hence, this need not be a general error, but we'll treat it as one here.
        die "Extract operation returned more than one element, this should not happen with a compacted intermediate, aborting.\n" if (1 < scalar (@{$extract}));

        # Likewise, it would be okay for the result to be empty, but not for us right here.
        die "Extract operation returned no result, aborting.\n" if (1 > scalar (@{$extract}));

        my $extracted_kv = q{};

        # Now, get the actual data in a presentable form.
        foreach my $entry (@{$extract}) {
          foreach my $key (%{$entry}) {
            $extracted_kv .= $key;
            my $value = $entry->{$key};
            if (defined ($value)) {
              $extracted_kv .= q{=} . $value;
            }
            last;
          }
          last;
        }

        # At this point, $extracted_kv should be "more=data".

        # Yet again, but this time extracting a key which does not exist.
        $extract =  X2Go::Server::Agent::NX::Options::extract_element ($intermediate, q{nosuchey});

        # Error handling ...
        die "Unable to extract 'nosuchkey' key from intermediate, aborting.\n" unless defined ($extract);

        # Should be empty.
        die "Extract operation returned a result, aborting.\n" if (0 < scalar (@{$extract}));

        # Transform back into a string.
        my $out = X2Go::Server::Agent::NX::Options::intermediate_to_string ($intermediate);

        # Error handling ...
        die "Unable to transform intermediate back into string, aborting.\n" unless (defined ($out));

        # At this point, $out should be 'another=newval,more=data,new=value:90'.

DESCRIPTION
       Use this module to modify or extract data from X2Go/NX Agent options
       strings.  Refer to "OPTIONS STRINGS" for an in-depth description of
       options strings.

       First, transform the input options string into an intermediate
       representation via "parse_options".  The options string must end with a
       display specification (i.e., it must end in ":displaynumber").  Parsing
       errors are indicated by it returning "undef".  The returned value is
       actually a reference to an array of hash references, but you should
       make no assumptions to the layout or even its actual format.  Treat it
       like a black box.  Crucially, whenever an intermediate is expected,
       such a reference should be passed.

       To remove redundant or empty entries within an options string, pass the
       intermediate to "compact_intermediate".  This is entirely optional and
       can be done at any step, as long as an intermediate is available.  If
       you intend to extract data, it is recommended, but not necessary, to
       compact the intermediate first.

       In order to extract key-value pairs, supply the intermediate and a key-
       value pair to extract to "extract_element".  Its result will be either
       undefined on error, or a reference to an array consisting of references
       to hashes.  Each hash contains exactly one key-value pair.

       The same approach using "extract_element" can be used to check for the
       existence of either keys or full key-value pairs.  If the returned
       array is empty, no such element exists.

       For compacted intermediates, each extraction operation returns an array
       with at most one hash reference entry.  Non-compacted intermediates can
       contain a key multiple times, so no guarantee regarding the result's
       magnitude can be given.

       To parse transformations, pass each one to "interpret_transform".
       Refer to "TRANSFORMATIONS" for documentation on transformation formats.
       This will either return "undef" on error, or an array of two scalars -
       the transformation mode (an internal number) and the sanitized
       transformation string (i.e., the original transformation string with
       any preceding operator removed).

       Pass the intermediate, the transformation mode and the sanitized
       transformation string to "transform_intermediate" to modify the
       intermediate value.

       Repeat this until the intermediate is modified to your liking.

       Finally, pass the intermediate to "intermediate_to_string" in order to
       parse it back into a normal string.  This operation is essentially the
       opposite of "parse_options".  As usual, "undef" is returned on error.

       Generally, parsing an options string to an intermediate via
       "parse_options" and then immediately parsing it back into a string via
       "intermediate_to_string" should always produce an options string that
       is identical to the original options string (assuming no errors
       occurred).

       If this is not the case, please report a bug.

       Any subroutines and constants not marked as exportable are explicitly
       not documented and should be regarded as internal and not be used.
       There is no guarantee regarding their behavior or existence.

OPTIONS STRINGS
       X2Go/NX Agent options strings are fully documented in nxagent's
       documentation and additional, linked places therein.

       This module is not really concerned with the actual content of an
       options string, but mostly its format.

       An options string follows the form [[key[=value,]]:displaynumber.

       This has some interesting implications:

       •   Key-value pairs are entirely optional.  For example, an options
           string like ":42" is well-formed.

       •   Options strings must end with a display number separator, i.e., a
           colon (":") and a display number.

           No parsing is done on the display number, so any string (even the
           empty string) is valid as far as this module is concerned.

           The display number, however, can not contain a colon (":"), since
           that would make it a new display number separator.

           This module will parse the options string from right to left when
           searching for the display number separator and use the first one it
           can find.

       •   Key-value pairs are separated via a comma (",").  Hence, this
           character is not valid in neither keys nor values.  As a
           workaround, it can be URL-encoded, as, e.g., %2C, and then used as
           part of either keys or values.

       •   Key-value pairs can be empty.  This is supported and empty key-
           value pairs will be preserved, but will trigger warnings at parse
           time.

           An options string such as ",,,:65" is hence valid.

           To remove such empty elements, use "compact_intermediate".  An
           implicit empty element is added whenever the resulting options
           string would only contain the display number.  This one can not be
           removed, but also won't show up anywhere.  Adding any non-empty new
           key will automatically replace such an empty element, without any
           need for actual compaction.

       •   In a key-value pair, keys and values are separated from each other
           via an equal sign ("=").

           Hence, this character is not a valid part of a key.  It can,
           however, be a valid part of a value.

           To use this character as part of a key, it can be URL-encoded as,
           e.g., %3D.

           While it is legal as part of a value, it is recommended to also
           URL-encode it when used as part of a value in order to not confuse
           other parsers.

           An options string such as "this%3Dis%3Da=key:38" is just as valid
           as "this=is=a=key:38" or "this=is%3Da%3Dkey:38".

           However, the semantics differ.  While the latter two key-value
           pairs are logically equivalent to each other, they are very much
           different from the first one.

           For the first case, the key will be "this%3Dis%3Da" (or, logically,
           also "this=is=a", which can not be directly represented), while the
           value will be just "key".

           The latter two will parse into a key "this" with a value of
           "is=a=key" (or, logically equivalent, "is%3Da%3Dkey").

       •   Quoting with any character is unsupported.  Quotes and other
           grouping characters (like curly braces ["{}"]) are seen verbatim
           without any special meaning.

       •   Since options strings are typically parsed by C applications, "NUL"
           (control) characters are prematurely terminating the string and
           hence cannot be directly embedded.  Indirectly, they can be
           embedded by URL-encoding them as %00.

           There is, however, no guarantee that an application unpacking such
           a string will be able to scan any data after the first embedded
           "NUL" character.

           It is highly recommended to avoid using embedded "NUL" characters.

           This module will not explicitly scan for them, and, hence, also not
           issue warnings related to those characters.

       •   There are no provisions (other than the mentioned invalid
           characters) on the content of keys and values.

           Importantly, this also means that the same key can show up multiple
           times in the options string.  Semantically, this is redundant,
           since only the last occurrence of a key (assuming the options
           string is parsed from left to right) will take any effect.
           Syntactically, it's completely legal, though.

           It is recommended to avoid duplicate keys in the input options
           string.

           Note that, due to the nature of the supported transformations, keys
           can not be duplicated with this module.

           To remove duplicated keys, use "compact_intermediate".  This will
           preserve the order in a first-seen fashion.

           Additionally, most non-printable control characters can be used
           verbatim.  This includes, but is not limited to, characters like
           "LF" ("\n"), "TAB" ("\t") and "VT" ("\v").

           Naturally, it is recommended to avoid such characters.

       •   A key-value pair with an empty key but a non-empty value is
           allowed.

           Likewise, a key-value pair with a non-empty key, but an empty value
           is allowed.  In this case, the value will be interpreted as an
           empty string in order to differentiate it from a non-existent
           value.

TRANSFORMATIONS
       Transformations follow the form [+]|-key[=value], which means that:

       •   They can be prefixed with a plus character ("+") to indicate either
           additions or modifications.  A missing prefix character is
           interpreted like a plus character.

           If the given key already exists in the intermediate, the key-value
           pair will be updated with the provided value (if any), or a new
           key-value pair added.

           Insertions always take place at the end of the intermediate.

           The value can be omitted, in which case key will be added without a
           value on insertions or a potentially existing value removed on
           updates.

       •   If they are prefixed with a minus character ("-"), deletion mode is
           activated.

           If the given key is not part of the intermediate, no deletion will
           occur.

           Otherwise, the optional value determines deletion: if no value has
           been provided, key will be removed from the intermediate regardless
           of its value.  If the optional value has been provided, key will
           only be removed if both values match.

AUTHOR
       This manual has been written by Mihai Moldovan <ionic@ionic.de>
       <mailto:ionic@ionic.de> for the X2Go project (<https://www.x2go.org>).

perl v5.36.0                      2023-08X2Go::Server::Agent::NX::Options(3pm)

Generated by dwww version 1.15 on Mon Jul 1 03:16:04 CEST 2024.