functions/sync.ps1
function get-propertynames($obj) { # Measure-function "$($MyInvocation.MyCommand.Name)" { if ($obj -is [System.Collections.IDictionary]) { return $obj.keys } return $obj.psobject.Properties | select -ExpandProperty name # } } function ConvertTo-Hashtable([Parameter(ValueFromPipeline=$true)]$obj, [switch][bool]$recurse) { # Measure-function "$($MyInvocation.MyCommand.Name)" { $object =$obj if (!$recurse -and ($object -is [System.Collections.IDictionary] -or $object -is [array])) { return $object } if($object -is [array]) { if ($recurse) { for($i = 0; $i -lt $object.Length; $i++) { $object[$i] = ConvertTo-Hashtable $object[$i] -recurse:$recurse } } return $object } elseif ($object -is [System.Collections.IDictionary] -or $object -is [System.Management.Automation.PSCustomObject] -or $true) { $h = @{} $props = get-propertynames $object foreach ($p in $props) { if ($recurse) { $h[$p] = ConvertTo-Hashtable $object.$p -recurse:$recurse } else { $h[$p] = $object.$p } } return $h } else { throw "could not convert object to hashtable" #return $object } # } } function get-syncdir() { if (test-path "HKCU:\Software\Microsoft\OneDrive") { $prop = get-itemproperty "HKCU:\Software\Microsoft\OneDrive\" "UserFolder" if ($prop -ne $null) { $dir = $prop.userfolder } } if ($dir -ne $null) { $syncdir = join-path $dir ".powershell-data" if (!(test-path $syncdir)) { $null = mkdir $syncdir } return $syncdir } } function set-globalpassword { Get-CredentialsCached -message "Global settings password" -reset -container "global-key" } function _getenckey { [CmdletBinding()] param() $pass = get-passwordcached -message "Global settings password" -container "global-key" -allowuserui $rfc = new-object System.Security.Cryptography.Rfc2898DeriveBytes $pass,@(1,2,3,4,5,6,7,8),1000 $enckey = $rfc.GetBytes(256/8); #write-verbose "key=$($enckey | convertto-base64) length=$($enckey.length)" return $enckey } function new-credentials( [Parameter(Mandatory=$true)]$username, [Parameter(Mandatory=$true)][securestring]$password) { return New-Object 'system.management.automation.pscredential' $username,$password } function convertto-plaintext([Parameter(Mandatory=$true,ValueFromPipeline=$true,Position=1)][securestring]$password) { return (new-credentials $="dummy" $password).GetNetworkCredential().password } function import-settings { [CmdletBinding()] param () $syncdir = get-syncdir if ($syncdir -eq $null) { write-warning "couldn't find OneDrive synced folder" return } $settings = import-cache -container "user-settings" -dir $syncdir | convertto-hashtable if ($settings -eq $null) { $settings = @{} } $decrypted = @{} foreach($kvp in $settings.GetEnumerator()) { if ($kvp.value.startswith("enc:")) { try { $enckey = _getenckey $encvalue = $kvp.value.substring("enc:".length) $secvalue = convertto-securestring $encvalue -Key $enckey -ErrorAction stop $decrypted[$kvp.key] = $secvalue #$creds = new-object system.management.automation.pscredential ("dummy",$secvalue) #$pass = $creds.getnetworkcredential().password } catch { write-warning "failed to decode key $($kvp.key): $_" $decrypted[$kvp.key] = $kvp.value } } else { $decrypted[$kvp.key] = $kvp.value } } $settings = $decrypted write-verbose "imported $($settings.Count) settings from '$syncdir'" $global:settings = $settings return $settings } function export-setting { [CmdletBinding()] param( [Parameter(Mandatory=$true)] $key, [Parameter(Mandatory=$true)] $value, [Switch][bool]$force, [Alias("secure")][Switch][bool]$encrypt ) $syncdir = get-syncdir if ($syncdir -eq $null) { write-warning "couldn't find OneDrive synced folder" return } $settings = import-cache -container "user-settings" -dir $syncdir | convertto-hashtable if ($settings -eq $null) { $settings = @{} } if ($settings[$key] -ne $null) { if (!$force) { write-warning "a setting with key $key already exists. Use -Force to override" return } } write-verbose "storing setting $key=$value at '$syncdir'" if ($encrypt) { $enckey = _getenckey $secvalue = convertto-securestring $value -asplaintext -force $encvalue = convertfrom-securestring $secvalue -key $enckey $settings[$key] = "enc:$encvalue" } else { $settings[$key] = "$value" } export-cache -data $settings -container "user-settings" -dir $syncdir import-settings } |