mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-09 19:13:26 +03:00
lib.generators.toPlist: escape XML syntax in strings & keys
Before this patch, code like this would break generate invalid XML: lib.generators.toPlist {} "ab<cd" That's obviously bad, since the call to toPlist often happens through indirection, as is the case in e.g. the nix-darwin project. A user might not realize that they have to escape the strings. This patch adds the argument 'escape' to lib.generators.plist and emits a warning if it is not set to true. In a future release, this behavior should become the default. I have also added a note for future maintainers, in case I forget to actually remove the deprecated functionality in a future release.
This commit is contained in:
parent
122adac328
commit
d1cb670ee6
4 changed files with 92 additions and 8 deletions
|
@ -70,6 +70,7 @@ let
|
||||||
split
|
split
|
||||||
toJSON
|
toJSON
|
||||||
typeOf
|
typeOf
|
||||||
|
escapeXML
|
||||||
;
|
;
|
||||||
|
|
||||||
## -- HELPER FUNCTIONS & DEFAULTS --
|
## -- HELPER FUNCTIONS & DEFAULTS --
|
||||||
|
@ -548,13 +549,17 @@ in rec {
|
||||||
|
|
||||||
# Inputs
|
# Inputs
|
||||||
|
|
||||||
Options
|
Structured function argument
|
||||||
: Empty set, there may be configuration options in the future
|
|
||||||
|
: escape (optional, default: `false`)
|
||||||
|
: If this option is true, XML special characters are escaped in string values and keys
|
||||||
|
|
||||||
Value
|
Value
|
||||||
: The value to be converted to Plist
|
: The value to be converted to Plist
|
||||||
*/
|
*/
|
||||||
toPlist = {}: v: let
|
toPlist = {
|
||||||
|
escape ? false
|
||||||
|
}: v: let
|
||||||
expr = ind: x:
|
expr = ind: x:
|
||||||
if x == null then "" else
|
if x == null then "" else
|
||||||
if isBool x then bool ind x else
|
if isBool x then bool ind x else
|
||||||
|
@ -568,10 +573,12 @@ in rec {
|
||||||
|
|
||||||
literal = ind: x: ind + x;
|
literal = ind: x: ind + x;
|
||||||
|
|
||||||
|
maybeEscapeXML = if escape then escapeXML else x: x;
|
||||||
|
|
||||||
bool = ind: x: literal ind (if x then "<true/>" else "<false/>");
|
bool = ind: x: literal ind (if x then "<true/>" else "<false/>");
|
||||||
int = ind: x: literal ind "<integer>${toString x}</integer>";
|
int = ind: x: literal ind "<integer>${toString x}</integer>";
|
||||||
str = ind: x: literal ind "<string>${x}</string>";
|
str = ind: x: literal ind "<string>${maybeEscapeXML x}</string>";
|
||||||
key = ind: x: literal ind "<key>${x}</key>";
|
key = ind: x: literal ind "<key>${maybeEscapeXML x}</key>";
|
||||||
float = ind: x: literal ind "<real>${toString x}</real>";
|
float = ind: x: literal ind "<real>${toString x}</real>";
|
||||||
|
|
||||||
indent = ind: expr "\t${ind}";
|
indent = ind: expr "\t${ind}";
|
||||||
|
@ -597,7 +604,10 @@ in rec {
|
||||||
(expr "\t${ind}" value)
|
(expr "\t${ind}" value)
|
||||||
]) x));
|
]) x));
|
||||||
|
|
||||||
in ''<?xml version="1.0" encoding="UTF-8"?>
|
in
|
||||||
|
# TODO: As discussed in #356502, deprecated functionality should be removed sometime after 25.11.
|
||||||
|
lib.warnIf (!escape && lib.oldestSupportedReleaseIsAtLeast 2505) "Using `lib.generators.toPlist` without `escape = true` is deprecated"
|
||||||
|
''<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
${expr "" v}
|
${expr "" v}
|
||||||
|
|
|
@ -1635,7 +1635,7 @@ runTests {
|
||||||
expected = "«foo»";
|
expected = "«foo»";
|
||||||
};
|
};
|
||||||
|
|
||||||
testToPlist = {
|
testToPlistUnescaped = {
|
||||||
expr = mapAttrs (const (generators.toPlist { })) {
|
expr = mapAttrs (const (generators.toPlist { })) {
|
||||||
value = {
|
value = {
|
||||||
nested.values = {
|
nested.values = {
|
||||||
|
@ -1651,10 +1651,34 @@ runTests {
|
||||||
emptylist = [];
|
emptylist = [];
|
||||||
attrs = { foo = null; "foo b/ar" = "baz"; };
|
attrs = { foo = null; "foo b/ar" = "baz"; };
|
||||||
emptyattrs = {};
|
emptyattrs = {};
|
||||||
|
"keys are not <escaped>" = "and < neither are string values";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
expected = { value = builtins.readFile ./test-to-plist-expected.plist; };
|
expected = { value = builtins.readFile ./test-to-plist-unescaped-expected.plist; };
|
||||||
|
};
|
||||||
|
|
||||||
|
testToPlistEscaped = {
|
||||||
|
expr = mapAttrs (const (generators.toPlist { escape = true; })) {
|
||||||
|
value = {
|
||||||
|
nested.values = {
|
||||||
|
int = 42;
|
||||||
|
float = 0.1337;
|
||||||
|
bool = true;
|
||||||
|
emptystring = "";
|
||||||
|
string = "fn\${o}\"r\\d";
|
||||||
|
newlinestring = "\n";
|
||||||
|
path = /. + "/foo";
|
||||||
|
null_ = null;
|
||||||
|
list = [ 3 4 "test" ];
|
||||||
|
emptylist = [];
|
||||||
|
attrs = { foo = null; "foo b/ar" = "baz"; };
|
||||||
|
emptyattrs = {};
|
||||||
|
"keys are <escaped>" = "and < so are string values";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
expected = { value = builtins.readFile ./test-to-plist-escaped-expected.plist; };
|
||||||
};
|
};
|
||||||
|
|
||||||
testToLuaEmptyAttrSet = {
|
testToLuaEmptyAttrSet = {
|
||||||
|
|
48
lib/tests/test-to-plist-escaped-expected.plist
Normal file
48
lib/tests/test-to-plist-escaped-expected.plist
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>nested</key>
|
||||||
|
<dict>
|
||||||
|
<key>values</key>
|
||||||
|
<dict>
|
||||||
|
<key>attrs</key>
|
||||||
|
<dict>
|
||||||
|
<key>foo b/ar</key>
|
||||||
|
<string>baz</string>
|
||||||
|
</dict>
|
||||||
|
<key>bool</key>
|
||||||
|
<true/>
|
||||||
|
<key>emptyattrs</key>
|
||||||
|
<dict>
|
||||||
|
|
||||||
|
</dict>
|
||||||
|
<key>emptylist</key>
|
||||||
|
<array>
|
||||||
|
|
||||||
|
</array>
|
||||||
|
<key>emptystring</key>
|
||||||
|
<string></string>
|
||||||
|
<key>float</key>
|
||||||
|
<real>0.133700</real>
|
||||||
|
<key>int</key>
|
||||||
|
<integer>42</integer>
|
||||||
|
<key>keys are <escaped></key>
|
||||||
|
<string>and < so are string values</string>
|
||||||
|
<key>list</key>
|
||||||
|
<array>
|
||||||
|
<integer>3</integer>
|
||||||
|
<integer>4</integer>
|
||||||
|
<string>test</string>
|
||||||
|
</array>
|
||||||
|
<key>newlinestring</key>
|
||||||
|
<string>
|
||||||
|
</string>
|
||||||
|
<key>path</key>
|
||||||
|
<string>/foo</string>
|
||||||
|
<key>string</key>
|
||||||
|
<string>fn${o}"r\d</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -27,6 +27,8 @@
|
||||||
<real>0.133700</real>
|
<real>0.133700</real>
|
||||||
<key>int</key>
|
<key>int</key>
|
||||||
<integer>42</integer>
|
<integer>42</integer>
|
||||||
|
<key>keys are not <escaped></key>
|
||||||
|
<string>and < neither are string values</string>
|
||||||
<key>list</key>
|
<key>list</key>
|
||||||
<array>
|
<array>
|
||||||
<integer>3</integer>
|
<integer>3</integer>
|
Loading…
Add table
Add a link
Reference in a new issue