lipkau / PsIni

Work with INI files in PowerShell using hashtables
http://lipkau.github.io/PsIni
MIT License
151 stars 50 forks source link

Quotation marks that encapsulate values are truncated #75

Open CanMonster opened 1 year ago

CanMonster commented 1 year ago

I have noticed an issue that the Get-IniContent CmdLet does not maintain the fidelity of .INI/.INF values that are encapsulated within quotation marks. This issue will probably also affect values encapsulated win apostrophes as well.

For example, here is a file name Gpttmpl.inf that is used within Active Directory Group Policy Objects. The header of the file contains a single-entry key "signature" whose value is encapsulated in quotation marks ...

[Unicode]
Unicode=yes
[Version]
signature="$CHICAGO$"
Revision=1

When this file is updated via the Set-IniContent CmdLet (which calls Get-IniContent) the quotation marks are truncated resulting in ...

[Unicode]
Unicode=yes
[Version]
signature=$CHICAGO$
Revision=1

Under normal circumstances this would not be problem but some scenarios, such as when updating and importing a Group Policy Object, there is no tolerance for the loss of this fidelity.

I have tracked this change to the Get-IniContent CmdLet line 144 ...

$name, $value = $matches[1, 3]

The $value is populated with the results of the capture group 3 from the REGEX expression ...

$keyRegex     = "^\s*(.+?)\s*=\s*(['`"]?)(.*)\2\s*$"

Using that REGEX expression the following capture groups are returned ...

Capture Group 1 - signature
Capture Group 2 - "
Capture Group 3 - $CHICAGO$

Capture group 3 has the value $CHICAGO$ (no quotation marks). The result is that the quotation marks are not picked up and therefore not restored to the resulting output file.

To work around this issue temporarily I am using a different REGEX expression. The following REGEX expression which will extract the apostrophe and or quotation marks (if present) into capture group 2 and 4 respectively.

^\s*(.+?)\s*=\s*(['`"]?)(.*?)(['`"]?)$

for signature="$CHICAGO$" this results in ...

Capture Group 1 - signature
Capture Group 2 - "
Capture Group 3 - $CHICAGO$
Capture Group 4 - "

In addition I am adding some additional logic into lines 144-149 (inclusive) ...

if (($matches[2] -eq "`"") -and ($matches[4] -eq "`"")) {
    $matches[3] = "$($matches[2])$($matches[3])$($matches[4])"
}elseif (($matches[2] -eq "`'") -and ($matches[4] -eq "`'")) {
    $matches[3] = "$($matches[2])$($matches[3])$($matches[4])"
}

If capture groups 2 and 4 both have an apostrophe or quotation mark these will be restored to the value maintaining fidelity with the original value.