]> git.proxmox.com Git - pve-common.git/blobdiff - src/PVE/JSONSchema.pm
JSONSchema: verify comma-separated property strings
[pve-common.git] / src / PVE / JSONSchema.pm
index 45ce5ba58c3ad5720bdf727d4615ac2d4b8e34d7..0d6860812ff4d37adccec866773942096d0116d9 100644 (file)
@@ -396,8 +396,9 @@ PVE::JSONSchema::register_standard_option('pve-startup-order', {
 });
 
 sub check_format {
-    my ($format, $value) = @_;
+    my ($format, $value, $path) = @_;
 
+    return parse_property_string($format, $value, $path) if ref($format) eq 'HASH';
     return if $format eq 'regex';
 
     if ($format =~ m/^(.*)-a?list$/) {
@@ -427,10 +428,56 @@ sub check_format {
 
        die "undefined format '$format'\n" if !$code;
 
+       return parse_property_string($code, $value, $path) if ref($code) eq 'HASH';
        &$code($value);
     }
 } 
 
+sub parse_property_string {
+    my ($format, $data, $path) = @_;
+
+    my $default_key;
+
+    my $res = {};
+    foreach my $part (split(/,/, $data)) {
+       next if $part =~ /^\s*$/;
+
+       if ($part =~ /^([^=]+)=(.+)$/) {
+           my ($k, $v) = ($1, $2);
+           die "duplicate key in comma-separated list property: $k" if defined($res->{$k});
+           my $schema = $format->{$k};
+           die "invalid key in comma-separated list property: $k" if !$schema;
+           if ($schema->{type} && $schema->{type} eq 'boolean') {
+               $v = 1 if $v =~ m/^(1|on|yes|true)$/i;
+               $v = 0 if $v =~ m/^(0|off|no|false)$/i;
+           }
+           $res->{$k} = $v;
+       } elsif ($part !~ /=/) {
+           die "duplicate key in comma-separated list property: $default_key" if $default_key;
+           foreach my $key (keys %$format) {
+               if ($format->{$key}->{default_key}) {
+                   $default_key = $key;
+                   if (!$res->{$default_key}) {
+                       $res->{$default_key} = $part;
+                       last;
+                   }
+                   die "duplicate key in comma-separated list property: $default_key";
+               }
+           }
+       } else {
+           die "missing key in comma-separated list property";
+       }
+    }
+
+    my $errors = {};
+    check_object($path, $format, $res, undef, $errors);
+    if (scalar(%$errors)) {
+       raise "format error", errors => $errors;
+    }
+
+    return $res;
+}
+
 sub add_error {
     my ($errors, $path, $msg) = @_;
 
@@ -683,7 +730,7 @@ sub check_prop {
     } else {
 
        if (my $format = $schema->{format}) {
-           eval { check_format($format, $value); };
+           eval { check_format($format, $value, $path); };
            if ($@) {
                add_error($errors, $path, "invalid format - $@");
                return;
@@ -870,10 +917,15 @@ my $default_schema_noref = {
            description => "indicates a required property or a schema that must be validated if this property is present",
         },
         format => {
-           type => "string",
+           type => [ "string", "object" ],
            optional => 1,
            description => "This indicates what format the data is among some predefined formats which may include:\n\ndate - a string following the ISO format \naddress \nschema - a schema definition object \nperson \npage \nhtml - a string representing HTML",
         },
+       default_key => {
+           type => "boolean",
+           optional => 1,
+           description => "Whether this is the default key in a comma separated list property string.",
+       },
        default => {
            type => "any",
            optional => 1,