1X2Go::Server::Agent::NXU:s:eOrptCioonntsr(i3b)uted PerlXD2oGcou:m:eSnetravteiro:n:Agent::NX::Options(3)
2
3
4
6 X2Go::Server::Agent::NX::Options - NX Options modification module
7
9 use X2Go::Server::Agent::NX::Options;
10
11 # Options string, probably read in from somewhere, but
12 # hardcoded here.
13 my $options = 'some=option,another=opt,more=values,some=override,more=data:90';
14
15 # Parse into an intermediate form.
16 my $intermediate = X2Go::Server::Agent::NX::Options::parse_options ($options);
17
18 # Check for errors.
19 die "Unable to parse option string, aborting.\n" unless (defined ($intermediate));
20
21 # (Optionally) compact it, this should make the duplicated "some" and "more"
22 # keys unique.
23 $intermediate = X2Go::Server::Agent::NX::Options::compact_intermediate ($intermediate);
24
25 # Error handling ...
26 die "Unable to compact intermediate array, aborting.\n" unless (defined ($intermediate));
27
28 # Add to options string.
29 my $transform_op = '+new=value';
30
31 # Parse and sanitize transform string.
32 my $interpreted_transform_ref = X2Go::Server::Agent::NX::Options::interpret_transform ($transform_op);
33
34 # Error handling ...
35 die "Invalid transformation passed, aborting.\n" unless (defined ($interpreted_transform_ref));
36
37 # Extract transformation data.
38 my ($transform_mode, $sanitized_transform) = @{$interpreted_transform_ref};
39
40 # Apply transformation.
41 $intermediate = X2Go::Server::Agent::NX::Options::transform_intermediate ($intermediate, $transform_mode, $sanitized_transform);
42
43 # Error handling ...
44 die "Error while transforming intermediate representation, aborting.\n" unless (defined ($intermediate));
45
46 # Try to remove a combination which doesn't exist, this should not modify the
47 # intermediate.
48 # No more comments for things that were already explained.
49 $transform_op = '-another=doesnotexist';
50 $interpreted_transform_ref = X2Go::Server::Agent::NX::Options::interpret_transform ($transform_op);
51 die "Invalid transformation passed, aborting.\n" unless (defined ($interpreted_transform_ref));
52 ($transform_mode, $sanitized_transform) = @{$interpreted_transform_ref};
53 $intermediate = X2Go::Server::Agent::NX::Options::transform_intermediate ($intermediate, $transform_mode, $sanitized_transform);
54 die "Error while transforming intermediate representation, aborting.\n" unless (defined ($intermediate));
55
56 # Remove a key unconditionally, this should change the intermediate.
57 $transform_op = '-some';
58 $interpreted_transform_ref = X2Go::Server::Agent::NX::Options::interpret_transform ($transform_op);
59 die "Invalid transformation passed, aborting.\n" unless (defined ($interpreted_transform_ref));
60 ($transform_mode, $sanitized_transform) = @{$interpreted_transform_ref};
61 $intermediate = X2Go::Server::Agent::NX::Options::transform_intermediate ($intermediate, $transform_mode, $sanitized_transform);
62 die "Error while transforming intermediate representation, aborting.\n" unless (defined ($intermediate));
63
64 # Modify/update a key.
65 $transform_op = '+another=newval';
66 $interpreted_transform_ref = X2Go::Server::Agent::NX::Options::interpret_transform ($transform_op);
67 die "Invalid transformation passed, aborting.\n" unless (defined ($interpreted_transform_ref));
68 ($transform_mode, $sanitized_transform) = @{$interpreted_transform_ref};
69 $intermediate = X2Go::Server::Agent::NX::Options::transform_intermediate ($intermediate, $transform_mode, $sanitized_transform);
70 die "Error while transforming intermediate representation, aborting.\n" unless (defined ($intermediate));
71
72 # Extract the "more" key.
73 my $extract = X2Go::Server::Agent::NX::Options::extract_element ($intermediate, q{more});
74
75 # Error handling ...
76 die "Unable to extract 'more' key from intermediate, aborting.\n" unless defined ($extract);
77
78 # Fetching multiple elements could be fine, for instance when the intermediate is not compact.
79 # Hence, this need not be a general error, but we'll treat it as one here.
80 die "Extract operation returned more than one element, this should not happen with a compacted intermediate, aborting.\n" if (1 < scalar (@{$extract}));
81
82 # Likewise, it would be okay for the result to be empty, but not for us right here.
83 die "Extract operation returned no result, aborting.\n" if (1 > scalar (@{$extract}));
84
85 my $extracted_kv = q{};
86
87 # Now, get the actual data in a presentable form.
88 foreach my $entry (@{$extract}) {
89 foreach my $key (%{$entry}) {
90 $extracted_kv .= $key;
91 my $value = $entry->{$key};
92 if (defined ($value)) {
93 $extracted_kv .= q{=} . $value;
94 }
95 last;
96 }
97 last;
98 }
99
100 # At this point, $extracted_kv should be "more=data".
101
102 # Yet again, but this time extracting a key which does not exist.
103 $extract = X2Go::Server::Agent::NX::Options::extract_element ($intermediate, q{nosuchey});
104
105 # Error handling ...
106 die "Unable to extract 'nosuchkey' key from intermediate, aborting.\n" unless defined ($extract);
107
108 # Should be empty.
109 die "Extract operation returned a result, aborting.\n" if (0 < scalar (@{$extract}));
110
111 # Transform back into a string.
112 my $out = X2Go::Server::Agent::NX::Options::intermediate_to_string ($intermediate);
113
114 # Error handling ...
115 die "Unable to transform intermediate back into string, aborting.\n" unless (defined ($out));
116
117 # At this point, $out should be 'another=newval,more=data,new=value:90'.
118
120 Use this module to modify or extract data from X2Go/NX Agent options
121 strings. Refer to "OPTIONS STRINGS" for an in-depth description of
122 options strings.
123
124 First, transform the input options string into an intermediate
125 representation via "parse_options". The options string must end with a
126 display specification (i.e., it must end in ":displaynumber"). Parsing
127 errors are indicated by it returning "undef". The returned value is
128 actually a reference to an array of hash references, but you should
129 make no assumptions to the layout or even its actual format. Treat it
130 like a black box. Crucially, whenever an intermediate is expected,
131 such a reference should be passed.
132
133 To remove redundant or empty entries within an options string, pass the
134 intermediate to "compact_intermediate". This is entirely optional and
135 can be done at any step, as long as an intermediate is available. If
136 you intend to extract data, it is recommended, but not necessary, to
137 compact the intermediate first.
138
139 In order to extract key-value pairs, supply the intermediate and a key-
140 value pair to extract to "extract_element". Its result will be either
141 undefined on error, or a reference to an array consisting of references
142 to hashes. Each hash contains exactly one key-value pair.
143
144 The same approach using "extract_element" can be used to check for the
145 existence of either keys or full key-value pairs. If the returned
146 array is empty, no such element exists.
147
148 For compacted intermediates, each extraction operation returns an array
149 with at most one hash reference entry. Non-compacted intermediates can
150 contain a key multiple times, so no guarantee regarding the result's
151 magnitude can be given.
152
153 To parse transformations, pass each one to "interpret_transform".
154 Refer to "TRANSFORMATIONS" for documentation on transformation formats.
155 This will either return "undef" on error, or an array of two scalars -
156 the transformation mode (an internal number) and the sanitized
157 transformation string (i.e., the original transformation string with
158 any preceding operator removed).
159
160 Pass the intermediate, the transformation mode and the sanitized
161 transformation string to "transform_intermediate" to modify the
162 intermediate value.
163
164 Repeat this until the intermediate is modified to your liking.
165
166 Finally, pass the intermediate to "intermediate_to_string" in order to
167 parse it back into a normal string. This operation is essentially the
168 opposite of "parse_options". As usual, "undef" is returned on error.
169
170 Generally, parsing an options string to an intermediate via
171 "parse_options" and then immediately parsing it back into a string via
172 "intermediate_to_string" should always produce an options string that
173 is identical to the original options string (assuming no errors
174 occurred).
175
176 If this is not the case, please report a bug.
177
178 Any subroutines and constants not marked as exportable are explicitly
179 not documented and should be regarded as internal and not be used.
180 There is no guarantee regarding their behavior or existence.
181
183 X2Go/NX Agent options strings are fully documented in nxagent's
184 documentation and additional, linked places therein.
185
186 This module is not really concerned with the actual content of an
187 options string, but mostly its format.
188
189 An options string follows the form [[key[=value,]]:displaynumber.
190
191 This has some interesting implications:
192
193 • Key-value pairs are entirely optional. For example, an options
194 string like ":42" is well-formed.
195
196 • Options strings must end with a display number separator, i.e., a
197 colon (":") and a display number.
198
199 No parsing is done on the display number, so any string (even the
200 empty string) is valid as far as this module is concerned.
201
202 The display number, however, can not contain a colon (":"), since
203 that would make it a new display number separator.
204
205 This module will parse the options string from right to left when
206 searching for the display number separator and use the first one it
207 can find.
208
209 • Key-value pairs are separated via a comma (","). Hence, this
210 character is not valid in neither keys nor values. As a
211 workaround, it can be URL-encoded, as, e.g., %2C, and then used as
212 part of either keys or values.
213
214 • Key-value pairs can be empty. This is supported and empty key-
215 value pairs will be preserved, but will trigger warnings at parse
216 time.
217
218 An options string such as ",,,:65" is hence valid.
219
220 To remove such empty elements, use "compact_intermediate". An
221 implicit empty element is added whenever the resulting options
222 string would only contain the display number. This one can not be
223 removed, but also won't show up anywhere. Adding any non-empty new
224 key will automatically replace such an empty element, without any
225 need for actual compaction.
226
227 • In a key-value pair, keys and values are separated from each other
228 via an equal sign ("=").
229
230 Hence, this character is not a valid part of a key. It can,
231 however, be a valid part of a value.
232
233 To use this character as part of a key, it can be URL-encoded as,
234 e.g., %3D.
235
236 While it is legal as part of a value, it is recommended to also
237 URL-encode it when used as part of a value in order to not confuse
238 other parsers.
239
240 An options string such as "this%3Dis%3Da=key:38" is just as valid
241 as "this=is=a=key:38" or "this=is%3Da%3Dkey:38".
242
243 However, the semantics differ. While the latter two key-value
244 pairs are logically equivalent to each other, they are very much
245 different from the first one.
246
247 For the first case, the key will be "this%3Dis%3Da" (or, logically,
248 also "this=is=a", which can not be directly represented), while the
249 value will be just "key".
250
251 The latter two will parse into a key "this" with a value of
252 "is=a=key" (or, logically equivalent, "is%3Da%3Dkey").
253
254 • Quoting with any character is unsupported. Quotes and other
255 grouping characters (like curly braces ["{}"]) are seen verbatim
256 without any special meaning.
257
258 • Since options strings are typically parsed by C applications, "NUL"
259 (control) characters are prematurely terminating the string and
260 hence cannot be directly embedded. Indirectly, they can be
261 embedded by URL-encoding them as %00.
262
263 There is, however, no guarantee that an application unpacking such
264 a string will be able to scan any data after the first embedded
265 "NUL" character.
266
267 It is highly recommended to avoid using embedded "NUL" characters.
268
269 This module will not explicitly scan for them, and, hence, also not
270 issue warnings related to those characters.
271
272 • There are no provisions (other than the mentioned invalid
273 characters) on the content of keys and values.
274
275 Importantly, this also means that the same key can show up multiple
276 times in the options string. Semantically, this is redundant,
277 since only the last occurrence of a key (assuming the options
278 string is parsed from left to right) will take any effect.
279 Syntactically, it's completely legal, though.
280
281 It is recommended to avoid duplicate keys in the input options
282 string.
283
284 Note that, due to the nature of the supported transformations, keys
285 can not be duplicated with this module.
286
287 To remove duplicated keys, use "compact_intermediate". This will
288 preserve the order in a first-seen fashion.
289
290 Additionally, most non-printable control characters can be used
291 verbatim. This includes, but is not limited to, characters like
292 "LF" ("\n"), "TAB" ("\t") and "VT" ("\v").
293
294 Naturally, it is recommended to avoid such characters.
295
296 • A key-value pair with an empty key but a non-empty value is
297 allowed.
298
299 Likewise, a key-value pair with a non-empty key, but an empty value
300 is allowed. In this case, the value will be interpreted as an
301 empty string in order to differentiate it from a non-existent
302 value.
303
305 Transformations follow the form [+]|-key[=value], which means that:
306
307 • They can be prefixed with a plus character ("+") to indicate either
308 additions or modifications. A missing prefix character is
309 interpreted like a plus character.
310
311 If the given key already exists in the intermediate, the key-value
312 pair will be updated with the provided value (if any), or a new
313 key-value pair added.
314
315 Insertions always take place at the end of the intermediate.
316
317 The value can be omitted, in which case key will be added without a
318 value on insertions or a potentially existing value removed on
319 updates.
320
321 • If they are prefixed with a minus character ("-"), deletion mode is
322 activated.
323
324 If the given key is not part of the intermediate, no deletion will
325 occur.
326
327 Otherwise, the optional value determines deletion: if no value has
328 been provided, key will be removed from the intermediate regardless
329 of its value. If the optional value has been provided, key will
330 only be removed if both values match.
331
333 This manual has been written by Mihai Moldovan <ionic@ionic.de>
334 <mailto:ionic@ionic.de> for the X2Go project (<https://www.x2go.org>).
335
336
337
338perl v5.38.0 2023-07-22X2Go::Server::Agent::NX::Options(3)