[X2Go-Commits] [x2goserver] 08/30: x2goserver/lib: add new (stub) file x2goupdateoptionsstring to deal with options string manipulations.

git-admin at x2go.org git-admin at x2go.org
Thu Dec 13 11:22:47 CET 2018


This is an automated email from the git hooks/post-receive script.

x2go pushed a commit to branch master
in repository x2goserver.

commit e705462a3b9f81960cdb12f4b9eb8b0a83724a81
Author: Mihai Moldovan <ionic at ionic.de>
Date:   Thu Dec 6 10:38:18 2018 +0100

    x2goserver/lib: add new (stub) file x2goupdateoptionsstring to deal with options string manipulations.
    
    Currently only parsing into an intermediate state is supported, the
    script dumps that state for now.
---
 debian/changelog                       |   3 +
 x2goserver/lib/x2goupdateoptionsstring | 287 +++++++++++++++++++++++++++++++++
 2 files changed, 290 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index 05a9893..c1567f5 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -21,6 +21,9 @@ x2goserver (4.1.0.4-0x2go1) UNRELEASED; urgency=medium
     - x2goserver/lib/x2gois{int,true}: add newlines to (error) output.
     - x2goserver/lib/x2gois{int,true}: add optional warnings.
     - x2goserver/sbin/x2gocleansessions: rework manpage/POD.
+    - x2goserver/lib: add new (stub) file x2goupdateoptionsstring to deal with
+      options string manipulations. Currently only parsing into an
+      intermediate state is supported, the script dumps that state for now.
   * debian/control:
     + Build-depend upon lsb-release for distro version detection.
   * debian/x2goserver.manpages:
diff --git a/x2goserver/lib/x2goupdateoptionsstring b/x2goserver/lib/x2goupdateoptionsstring
new file mode 100755
index 0000000..f710339
--- /dev/null
+++ b/x2goserver/lib/x2goupdateoptionsstring
@@ -0,0 +1,287 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2018 X2Go Project - https://wiki.x2go.org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+use strict;
+use warnings;
+
+#use X2Go::Utils qw (is_int);
+use Data::Dumper qw (Dumper);
+use Getopt::Long;
+use Pod::Usage;
+
+# Accepts an option string and returns a reference to an array of hashes
+# (actually hash references) corresponding to the parsed key-value pairs.
+#
+# Empty components are allowed, but will issue a warning message. In such a
+# case, the hash at the corresponding array position will be empty.
+#
+# Keys that do not have a value assigned will be given a value of "undef" in
+# order to be able to distinguish them from keys with an empty string as their
+# value.
+#
+# Caveat: the last component will be split from the port definition. DO NOT
+# SIMPLY JOIN THE LIST OR YOU WILL ADD A TRAILING COMMA! The port component
+# hash retains the colon separator.
+#
+# On error, returns an undef reference.
+sub parse_options {
+  my $ret = undef;
+  my @intermediate = ();
+  my $error_detected = 0;
+  my $options = shift;
+  my $next_discard = shift;
+
+  if (defined ($next_discard)) {
+    print STDERR "Multiple arguments passed in, all but the first one are ignored!\n";
+  }
+
+  if (!(defined ($options))) {
+    print STDERR "No argument provided for options string, returning undef.\n";
+    $error_detected = 1;
+  }
+
+  if (!($error_detected)) {
+    my @components = split (/,/sxm, $options, -1);
+    foreach my $option (@components) {
+      # We use undef to denote that some component was not provided at all
+      # to disambiguate non-provided and empty strings.
+      my ($key, $value) = (undef, undef);
+      my %kv_hash = ();
+
+      my @kv = split (/=/, $option, 2);
+
+      if (1 > scalar (@kv)) {
+        print STDERR "Options string has empty component, this is deprecated. Adding empty element.\n";
+
+        push (@intermediate, \%kv_hash);
+      }
+      elsif (3 <= scalar (@kv)) {
+        print STDERR "Options string has three or more components, this is a bug in $0. Erroring out.\n";
+        $error_detected = 1;
+        last;
+      }
+      else {
+        $key = shift (@kv);
+        $value = shift (@kv);
+
+        # Add to hash - every hash will contain a single key-value pair only.
+        $kv_hash{$key} = $value;
+
+        # Then add the hash as an entry in our return array - by reference.
+        push (@intermediate, \%kv_hash);
+      }
+    }
+
+    # Special handling for the last option, which does not use a comma as the
+    # delimiter but a colon.
+    #
+    # Note that it can either be part of the key or the value.
+    if (!($error_detected)) {
+      if ((0 < scalar (@intermediate)) && (defined ($intermediate[0]))) {
+        my $last_hash_ref = pop (@intermediate);
+        my $hash_count = 0;
+        my $last_component = '';
+        my $in_value = 0;
+        my $last_component_key = undef;
+
+        # Fetch last component and check for sanity.
+        # An empty hash is implicitly handled by initializing $last_component to
+        # an empty string, which will fail the splitting later on.
+        foreach my $key (keys %{$last_hash_ref}) {
+          ++$hash_count;
+
+          if (1 < $hash_count) {
+            print STDERR "More than one element found in last element's hash, this is a bug in $0. Ignoring subsequent entries.\n";
+            last;
+          }
+
+          $last_component = $last_component_key = $key;
+
+          if (defined ($last_hash_ref->{$key})) {
+            # If a value exists, the display specifier can not be part of the
+            # key.
+            $in_value = 1;
+            $last_component = $last_hash_ref->{$key};
+          }
+        }
+
+        # Don't use split() here. While we could use a more or less complex
+        # regex to extract the last(!) port specifier only, this would render
+        # the LIMIT parameter to split() useless (since additional capture
+        # groups are not part of the limit).
+        # Thus going the manual route here.
+        my $last_pos = rindex ($last_component, ':');
+
+        if ($[ > $last_pos) {
+          print STDERR "No display port seperator found in the options string. Erroring out.\n";
+          $error_detected = 1;
+        }
+        else {
+          my $last_component_left = substr ($last_component, 0, $last_pos);
+          my $last_component_right = substr ($last_component, $last_pos);
+
+          my %last_component_hash = ();
+
+          if ($in_value) {
+            $last_component_hash{$last_component_key} = $last_component_left;
+          }
+          else {
+            # Sanity check on the key. If it's empty, issue a warning and don't
+            # use it.
+            if (0 == length ($last_component_left)) {
+              print STDERR "Options string has empty component, this is deprecated. Adding empty element.\n";
+            }
+            else {
+              $last_component_hash{$last_component_left} = undef;
+            }
+          }
+
+          # Now add the last component hash to the array again.
+          push (@intermediate, \%last_component_hash);
+
+          # Prepare a new hash object, with the key set to the display port part
+          # and value to undef to mark it invalid.
+          my %display_port_hash = ();
+          $display_port_hash{$last_component_right} = undef;
+
+          # Add this to the return value as well.
+          push (@intermediate, \%display_port_hash);
+        }
+      }
+    }
+  }
+
+  if (!($error_detected)) {
+    $ret = \@intermediate;
+  }
+
+  return $ret;
+}
+
+Getopt::Long::Configure("gnu_getopt", "no_auto_abbrev");
+
+my $help = 0;
+my $man = 0;
+GetOptions('help|?|h' => \$help, 'man' => \$man) or pod2usage(2);
+pod2usage(1) if $help;
+pod2usage(-verbose => 2, -exitval => 0) if $man;
+
+my $options = shift;
+
+print STDERR Dumper (parse_options ($options)) . "\n";
+
+#my $value = shift;
+#my $allow_negative = shift;
+#
+#if (!(defined ($value))) {
+#  print STDERR "No value passed in, assuming empty string.\n";
+#  $value = '';
+#}
+#
+#if (!(defined ($allow_negative))) {
+#  $allow_negative = 0;
+#}
+#
+#exit is_int ($value);
+
+exit 1;
+
+__END__
+
+=head1 NAME
+
+x2goupdateoptionsstring - X2Go Agent Options String Manipulator
+
+=head1 SYNOPSIS
+
+=over
+
+=item B<x2goupdateoptionsstring> B<--help>|B<-h>|B<-?>
+
+=item B<x2goupdateoptionsstring> B<--man>
+
+=item B<x2goupdateoptionsstring> I<options> [B<->]I<key>[B<=>I<value>] ...
+
+=back
+
+=head1 DESCRIPTION
+
+B<x2goupdateoptionsstring> is a utility for manipulating options strings as
+passed to X2Go Agent/NX Agent.
+
+Called it with the options string as the first parameter and the options you
+want to manipulate as additional parameters. At least one additional parameter
+must be provided.
+
+It can either add, remove or replace components.
+
+To add or replace a component, pass I<key>[B<=>I<value>] as a parameter. If the
+options string does not include a B<key> key, it will be appended to the end of
+the options string. If it already exists, either with no value or a different
+value, the component will be replaced with the provided value.
+
+To fully remove a component, pass B<->I<key>. To only remove it if it is set to
+a specific value, pass B<->I<key>B<=>I<value>.
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--help>|B<-?>|B<-h>
+
+Print a brief help message and exits.
+
+=item B<--man>
+
+Prints the manual page and exits.
+
+=back
+
+=head1 EXAMPLE
+
+For an options string such as
+
+ nx/nx,clipboard=both,foo:50
+
+calling C<x2goupdateoptionsstring 'nx/nx,clipboard=both,foo:50'
+'-clipboard'> shall return
+
+ nx/nx,foo:50
+
+while calling C<x2goupdateoptionsstring 'nx/nx,clipboard=both,foo:50'
+'-clipboard=server'> shall return
+
+ nx/nx,clipboard=both,foo:50
+
+Calling C<x2goupdateoptionsstring 'nx/nx,clipboard=both,foo:50' 'bar'> shall
+return
+
+ nx/nx,clipboard=both,foo,bar:50
+
+and calling C<x2goupdateoptionsstring 'nx/nx,clipboard=both,foo:50' 'bar'
+'foo=gulp' '-clipboard=client'> shall return
+
+ nx/nx,clipboard=both,foo=gulp,bar:50
+
+=head1 AUTHOR
+
+This manual has been written by Mihai Moldovan <ionic at ionic.de> for the X2Go
+project (https://www.x2go.org).
+
+=cut

--
Alioth's /home/x2go-admin/maintenancescripts/git/hooks/post-receive-email on /srv/git/code.x2go.org/x2goserver.git


More information about the x2go-commits mailing list