minLength => 2, maxLength => 20,
});
-PVE::JSONSchema::register_standard_option('pve-storage-id', {
+register_standard_option('pve-storage-id', {
description => "The storage identifier.",
type => 'string', format => 'pve-storage-id',
});
-PVE::JSONSchema::register_standard_option('pve-config-digest', {
+register_standard_option('pve-config-digest', {
description => 'Prevent changes if current configuration file has different SHA1 digest. This can be used to prevent concurrent modifications.',
type => 'string',
optional => 1,
maxLength => 40, # sha1 hex digest lenght is 40
});
-PVE::JSONSchema::register_standard_option('extra-args', {
+register_standard_option('extra-args', {
description => "Extra arguments as array",
type => 'array',
items => { type => 'string' },
register_format('string', sub {}); # allow format => 'string-list'
+register_format('urlencoded', \&pve_verify_urlencoded);
+sub pve_verify_urlencoded {
+ my ($text, $noerr) = @_;
+ if ($text !~ /^[-%a-zA-Z0-9_.!~*'()]*$/) {
+ return undef if $noerr;
+ die "invalid urlencoded string: $text\n";
+ }
+ return $text;
+}
+
register_format('pve-configid', \&pve_verify_configid);
sub pve_verify_configid {
my ($id, $noerr) = @_;
sub pve_verify_vmid {
my ($vmid, $noerr) = @_;
- if ($vmid !~ m/^[1-9][0-9]+$/) {
+ if ($vmid !~ m/^[1-9][0-9]{2,8}$/) {
return undef if $noerr;
die "value does not look like a valid VM ID\n";
}
};
sub parse_property_string {
- my ($format, $data, $path) = @_;
+ my ($format, $data, $path, $additional_properties) = @_;
+
+ # In property strings we default to not allowing additional properties
+ $additional_properties = 0 if !defined($additional_properties);
my $default_key;
die "duplicate key in comma-separated list property: $default_key\n";
}
}
+ die "value without key, but schema does not define a default key\n" if !$default_key;
} else {
die "missing key in comma-separated list property\n";
}
}
my $errors = {};
- check_object($path, $format, $res, undef, $errors);
+ check_object($path, $format, $res, $additional_properties, $errors);
if (scalar(%$errors)) {
raise "format error\n", errors => $errors;
}
if (ref($format) ne 'HASH') {
my $schema = $format_list->{$format};
- die "not a valid format: $format" if !$schema;
+ die "not a valid format: $format\n" if !$schema;
$format = $schema;
}
# Skip default keys
if ($format->{$key}->{default_key}) {
if ($default_key) {
- warn "multiple default keys in schema ($default_key, $key)";
+ warn "multiple default keys in schema ($default_key, $key)\n";
} else {
$default_key = $key;
$skipped{$key} = 1;
}
foreach my $key (sort keys %$data) {
- die "invalid key: $key" if !$allowed{$key};
delete $required{$key};
next if $skipped{$key};
+ die "invalid key: $key\n" if !$allowed{$key};
my $typeformat = $format->{$key}->{format};
my $value = $data->{$key};
+ next if !defined($value);
$text .= $comma;
$comma = ',';
if ($typeformat && $typeformat eq 'disk-size') {
$text .= "$key=" . format_size($value);
} else {
+ die "illegal value with commas for $key\n" if $value =~ /,/;
$text .= "$key=$value";
}
}
if (my $missing = join(',', keys %required)) {
- die "missing properties: $missing";
+ die "missing properties: $missing\n";
}
return $text;