diff --git a/.editorconfig b/.editorconfig index 49de0d3..6a559d6 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,6 +5,9 @@ # All files [*] indent_style = space + +[*.csproj] +indent_size = 2 # Code files [*.{cs,csx,vb,vbx}] indent_size = 4 diff --git a/.github/workflows/create_pre-release-on-pr.yml b/.github/workflows/create_pre-release-on-pr.yml new file mode 100644 index 0000000..bae6e55 --- /dev/null +++ b/.github/workflows/create_pre-release-on-pr.yml @@ -0,0 +1,75 @@ +name: Create pre-release on PR + +on: pull_request + + +jobs: + create-prerelease: + runs-on: windows-latest + permissions: + pull-requests: write + + steps: + - uses: actions/checkout@v3 + + - uses: microsoft/setup-msbuild@v2 + + - name: publish + run: | + msbuild -t:restore,build -m -p:"Configuration=Release;Platform=Any Cpu" GoogleDriveSync.sln + + # The publish needs to be run separately, since the PLGX build task seems to not run on first build + msbuild -t:publish -m -p:"Configuration=Release;Platform=Any Cpu" .\src\KPSyncForDrive.csproj ` + -p:'CompileTimeConfig_ClientId=${{vars.GCPCLIENTID}}' -p:'CompileTimeConfig_GoogleDrivePickerAppId=${{vars.GDRIVEAPPID}}' ` + -p:'CompileTimeConfig_DriveFilePickerPublicApiKey=${{vars.GDRIVEFILEPICKERAPIKEY}}' ` + -p:'CompileTimeConfig_PublicClientSecret=${{vars.PublicClientSecret }}' + + + - name: zip results + env: + PR_NUMBER: ${{ github.event.number }} + shell: pwsh + run: | + $randString = -join ((48..57) + (97..122) | Get-Random -Count 10 | % {[char]$_}) + mkdir ./dist + move-item "./src/bin/Any Cpu/Release/net48/*.plgx" -Destination ./dist/pr-$ENV:PR_NUMBER.$randString.plgx + Compress-Archive -Path "./src/bin/Any Cpu/Release/net48/publish/*" -DestinationPath ./dist/pr-$ENV:PR_NUMBER.$randString.zip -CompressionLevel Optimal -Force + [System.IO.FileSystemInfo[]]$files = Get-ChildItem ./dist/ + Write-Host "$($files.Count) files found in dist directory:" + $files + + - name: Upload plgx Artifact + uses: actions/upload-artifact@v4 + id: plgx-upload + with: + name: plgx-artifact + retention-days: 15 + path: ./dist/*.plgx + if-no-files-found: error + + - name: Upload zipped Artifacts + uses: actions/upload-artifact@v4 + id: zip-upload + with: + name: zip-artifact + retention-days: 15 + path: ./dist/*.zip + if-no-files-found: error + + - uses: actions/github-script@v6 + env: + PR_NUMBER: ${{ github.event.number }} + PR_NOTES: | + Build artifacts (expire in 15 days): + | Name | Link | + |------|------| + | PLGX | ${{ steps.plgx-upload.outputs.artifact-url }} | + | zip | ${{ steps.zip-upload.outputs.artifact-url }} | + with: + script: | + github.rest.issues.createComment({ + issue_number: process.env.PR_NUMBER, + owner: context.repo.owner, + repo: context.repo.repo, + body: process.env.PR_NOTES + }) \ No newline at end of file diff --git a/.github/workflows/publish-on-release.yml b/.github/workflows/publish-on-release.yml new file mode 100644 index 0000000..b9d766b --- /dev/null +++ b/.github/workflows/publish-on-release.yml @@ -0,0 +1,89 @@ +name: Publish artifacts on release + +on: + release: + types: + - published + +jobs: + build-and-publish: + runs-on: windows-latest + permissions: + id-token: write + contents: write + attestations: write + + steps: + - uses: actions/checkout@v3 + + - uses: microsoft/setup-msbuild@v2 + + - name: publish + env: + VersionNumber: ${{github.event.release.name}} + run: | + msbuild -t:restore,build -m -p:"Configuration=Release;Platform=Any Cpu" GoogleDriveSync.sln + + # The publish needs to be run separately, since the PLGX build task seems to not run on first build + msbuild -t:publish -m -p:"Configuration=Release;Platform=Any Cpu" .\src\KPSyncForDrive.csproj ` + -p:'CompileTimeConfig_ClientId=${{vars.GCPCLIENTID}}' ` + -p:'CompileTimeConfig_GoogleDrivePickerAppId=${{vars.GDRIVEAPPID}}' ` + -p:'CompileTimeConfig_DriveFilePickerPublicApiKey=${{vars.GDRIVEFILEPICKERAPIKEY}}' ` + -p:'CompileTimeConfig_PublicClientSecret=${{vars.PublicClientSecret }}' ` + -p:Version=$Env:VersionNumber ` + -p:'CompileTimeConfig_UpdateUrlPubKey=${{vars.UpdateUrlPubKey}}' ` + -p:'CompileTimeConfig_UpdateUrl=https://github.com/${{github.repository}}/releases/latest/download/kpsync_final.txt' + + - name: Create dist directory + run: mkdir ./dist + + - name: Generate AutoUpdate file + run: | + "${{secrets.SIGNING_PRIVATEKEY_XML}}" | Set-Content .\lib\src\GenVerInfo\privateKey.xml -Force + msbuild -t:publish -p:Configuration=Release .\lib\src\GenVerInfo\GenVerInfo.csproj + & ".\lib\src\GenVerInfo\bin\Release\net48\GenVerInfo.exe" "./src/bin/Any Cpu/Release/net48/publish/KPSyncForDrive.dll" ./dist/kpsync_final.txt + + - name: zip results + shell: pwsh + env: + VersionNumber: ${{github.event.release.name}} + run: | + move-item "./src/bin/Any Cpu/Release/net48/*.plgx" -Destination ./dist/KPSyncForDrive-$Env:VersionNumber.plgx + Compress-Archive -Path "./src/bin/Any Cpu/Release/net48/publish/*" -DestinationPath ./dist/KPSyncForDrive-$Env:VersionNumber.zip -CompressionLevel Optimal -Force + [System.IO.FileSystemInfo[]]$files = Get-ChildItem ./dist/ + Write-Host "$($files.Count) files found in dist directory:" + $files + + - name: Generate artifact attestation + uses: actions/attest-build-provenance@v1 + with: + subject-path: './dist/*' + + - uses: actions/github-script@v6 + env: + ReleaseName: ${{github.event.release.name}} + with: + script: | + const { ReleaseName } = process.env + const fs = require('fs').promises; + await github.rest.repos.uploadReleaseAsset({ + name: `KPSyncForDrive-${ReleaseName}.plgx`, + owner: context.repo.owner, + repo: context.repo.repo, + release_id: ${{ github.event.release.id }}, + data: await fs.readFile(`./dist/KPSyncForDrive-${ReleaseName}.plgx`) + }); + await github.rest.repos.uploadReleaseAsset({ + name: `KPSyncForDrive-${ReleaseName}.zip`, + owner: context.repo.owner, + repo: context.repo.repo, + release_id: ${{ github.event.release.id }}, + data: await fs.readFile(`./dist/KPSyncForDrive-${ReleaseName}.zip`) + }); + await github.rest.repos.uploadReleaseAsset({ + name: 'kpsync_final.txt', + owner: context.repo.owner, + repo: context.repo.repo, + release_id: ${{ github.event.release.id }}, + data: await fs.readFile('./dist/kpsync_final.txt') + }); \ No newline at end of file diff --git a/.gitignore b/.gitignore index 6557d5e..048edbe 100644 --- a/.gitignore +++ b/.gitignore @@ -179,3 +179,4 @@ kp/ # Local VS settings /src/Properties/launchSettings.json +/.idea diff --git a/BuildMe.bat b/BuildMe.bat index fb92965..2868c3d 100644 --- a/BuildMe.bat +++ b/BuildMe.bat @@ -26,7 +26,7 @@ set archname=KPSyncForDrive set kp_version_manifest_name=kpsync_final set versionPrefix=4.1.0 set versionSuffix=unstable -set netsdkver=net45 +set netsdkver=net48 set sevenzip="%ProgramFiles%\7-Zip\7z.exe" :: set dotnetPgm="%ProgramFiles%\dotnet\dotnet.exe" diff --git a/GoogleDriveSync.sln b/GoogleDriveSync.sln index 37750db..0291a4a 100644 --- a/GoogleDriveSync.sln +++ b/GoogleDriveSync.sln @@ -4,11 +4,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 VisualStudioVersion = 16.0.29920.165 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KPSyncForDrive", "src\KPSyncForDrive.csproj", "{4C1BB6F8-D2CD-49C2-9053-21705681356C}" - ProjectSection(ProjectDependencies) = postProject - {F7B92FBF-F5D8-45E0-B357-4CA8F05AD652} = {F7B92FBF-F5D8-45E0-B357-4CA8F05AD652} - EndProjectSection -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GenClientId", "lib\src\GenClientId\GenClientId.csproj", "{F7B92FBF-F5D8-45E0-B357-4CA8F05AD652}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GenVerInfo", "lib\src\GenVerInfo\GenVerInfo.csproj", "{552F1DC6-E4B4-4766-B0B3-7A37276AB86B}" EndProject @@ -24,20 +19,18 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsControls", "lib\src\WindowsControls\WindowsControls.csproj", "{31D48296-6B88-4532-B0C3-6DDBF183499F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FilePicker", "lib\src\FilePicker\FilePicker.csproj", "{89B54C4A-00DF-49FD-BD57-4DA01AAF9710}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CompileTimeConfigGenerator", "lib\src\CompileTimeConfigGenerator\CompileTimeConfigGenerator.csproj", "{C9EABBC7-D089-46E8-996B-F34F3C6C8CBD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CompileTimeConfigPublicMembers", "lib\src\CompileTimeConfigPublicMembers\CompileTimeConfigPublicMembers.csproj", "{1960BE1C-5EB4-4679-9510-976F1A085CA3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {4C1BB6F8-D2CD-49C2-9053-21705681356C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4C1BB6F8-D2CD-49C2-9053-21705681356C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4C1BB6F8-D2CD-49C2-9053-21705681356C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4C1BB6F8-D2CD-49C2-9053-21705681356C}.Release|Any CPU.Build.0 = Release|Any CPU - {F7B92FBF-F5D8-45E0-B357-4CA8F05AD652}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F7B92FBF-F5D8-45E0-B357-4CA8F05AD652}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F7B92FBF-F5D8-45E0-B357-4CA8F05AD652}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F7B92FBF-F5D8-45E0-B357-4CA8F05AD652}.Release|Any CPU.Build.0 = Release|Any CPU {552F1DC6-E4B4-4766-B0B3-7A37276AB86B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {552F1DC6-E4B4-4766-B0B3-7A37276AB86B}.Debug|Any CPU.Build.0 = Debug|Any CPU {552F1DC6-E4B4-4766-B0B3-7A37276AB86B}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -46,6 +39,22 @@ Global {31D48296-6B88-4532-B0C3-6DDBF183499F}.Debug|Any CPU.Build.0 = Debug|Any CPU {31D48296-6B88-4532-B0C3-6DDBF183499F}.Release|Any CPU.ActiveCfg = Release|Any CPU {31D48296-6B88-4532-B0C3-6DDBF183499F}.Release|Any CPU.Build.0 = Release|Any CPU + {89B54C4A-00DF-49FD-BD57-4DA01AAF9710}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {89B54C4A-00DF-49FD-BD57-4DA01AAF9710}.Debug|Any CPU.Build.0 = Debug|Any CPU + {89B54C4A-00DF-49FD-BD57-4DA01AAF9710}.Release|Any CPU.ActiveCfg = Release|Any CPU + {89B54C4A-00DF-49FD-BD57-4DA01AAF9710}.Release|Any CPU.Build.0 = Release|Any CPU + {C9EABBC7-D089-46E8-996B-F34F3C6C8CBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C9EABBC7-D089-46E8-996B-F34F3C6C8CBD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C9EABBC7-D089-46E8-996B-F34F3C6C8CBD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C9EABBC7-D089-46E8-996B-F34F3C6C8CBD}.Release|Any CPU.Build.0 = Release|Any CPU + {1960BE1C-5EB4-4679-9510-976F1A085CA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1960BE1C-5EB4-4679-9510-976F1A085CA3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1960BE1C-5EB4-4679-9510-976F1A085CA3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1960BE1C-5EB4-4679-9510-976F1A085CA3}.Release|Any CPU.Build.0 = Release|Any CPU + {4C1BB6F8-D2CD-49C2-9053-21705681356C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4C1BB6F8-D2CD-49C2-9053-21705681356C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4C1BB6F8-D2CD-49C2-9053-21705681356C}.Release|Any CPU.ActiveCfg = Debug|Any CPU + {4C1BB6F8-D2CD-49C2-9053-21705681356C}.Release|Any CPU.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/lib/src/CompileTimeConfigGenerator/CompileTimeConfigGenerator.csproj b/lib/src/CompileTimeConfigGenerator/CompileTimeConfigGenerator.csproj new file mode 100644 index 0000000..9a66999 --- /dev/null +++ b/lib/src/CompileTimeConfigGenerator/CompileTimeConfigGenerator.csproj @@ -0,0 +1,25 @@ + + + + netstandard2.0 + 12 + enable + true + false + true + + + + + + + + + + + + + + + diff --git a/lib/src/CompileTimeConfigGenerator/ConfigSourceGenerator.cs b/lib/src/CompileTimeConfigGenerator/ConfigSourceGenerator.cs new file mode 100644 index 0000000..1d718e3 --- /dev/null +++ b/lib/src/CompileTimeConfigGenerator/ConfigSourceGenerator.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace CompileTimeConfigGenerator; + +public record MetadataOnAccessorConfigRecordsToGenerate +{ + public string RecordFullClassName { get; set; } = ""; + public List Properties { get; set; } = []; +} + +public record MetadataOnAccessorToGenerate +{ + public List Records { get; set; } = []; + public string AccessorClassName { get; set; } = ""; + public string AccessorNamespace { get; set; } = ""; +} + +[Generator] +public class ConfigSourceGenerator : IIncrementalGenerator +{ + public void Initialize(IncrementalGeneratorInitializationContext context) + { + var metadataOnAccessorsToGenerate = context.SyntaxProvider + .ForAttributeWithMetadataName( + "CompileTimeConfigPublicMembers.GenerateConfigAccessorAttribute", + predicate: static (_, _) => true, + transform: (ctx, _) => + { + if (ctx.SemanticModel.GetDeclaredSymbol(ctx.TargetNode) is not INamedTypeSymbol generatorSymbol) + return null; + + var records = ctx.Attributes + .Select(attributeData => attributeData.ConstructorArguments[0].Value) + .OfType() + .Select(recordSymbol => + { + var properties = recordSymbol.GetMembers() + .OfType() + .Where(x => x.SetMethod?.DeclaredAccessibility == Accessibility.Public && + x.Type.Name == nameof(String)); + + return new MetadataOnAccessorConfigRecordsToGenerate + { + RecordFullClassName = + recordSymbol.ToDisplayString( + new SymbolDisplayFormat(SymbolDisplayGlobalNamespaceStyle.Included)), + Properties = properties.Select(x => x.Name).ToList() + }; + }).ToList(); + + + return new MetadataOnAccessorToGenerate + { + Records = records, + AccessorNamespace = generatorSymbol.ContainingNamespace.Name, + AccessorClassName = generatorSymbol.Name, + }; + }).Collect(); + + var combine = metadataOnAccessorsToGenerate.Combine(context.AnalyzerConfigOptionsProvider); + + context.RegisterSourceOutput(combine, + static (spc, tuple) => + { + foreach (var metadata in tuple.Left) + { + if (metadata == null) continue; + + var interfacesToImplement = metadata.Records.Select(CreateInterfaceString); + var accessorMethods = metadata.Records.Select(x => GenerateRecordAccessMethod(x, tuple.Right)); + + string generatorString = + $$""" + using CompileTimeConfigPublicMembers; + + namespace {{metadata.AccessorNamespace}} { + public partial class {{metadata.AccessorClassName}}: {{string.Join(", ", interfacesToImplement)}} { + {{string.Join("\n", accessorMethods)}} + } + } + """; + + spc.AddSource( + $"CompileTimeConfigAccessors.{metadata.AccessorClassName}.g.cs", + generatorString); + } + }); + } + + private static string? GetBuildParam(string paramName, AnalyzerConfigOptionsProvider context) + { + context.GlobalOptions.TryGetValue($"build_property.CompileTimeConfig_{paramName}", out string? value); + return value; + } + + private static string CreateInterfaceString(MetadataOnAccessorConfigRecordsToGenerate record) + { + return $"ICompileTimeConfigAccessor<{record.RecordFullClassName}>"; + } + + private static string GenerateRecordAccessMethod(MetadataOnAccessorConfigRecordsToGenerate record, + AnalyzerConfigOptionsProvider configOptionsProvider) + { + return $$""" + {{record.RecordFullClassName}} {{CreateInterfaceString(record)}}.GetConfig() { + return new {{record.RecordFullClassName}} { + {{ + string.Join("\n\t\t\t\t", record.Properties.Select(y => $"""{y} = "{GetBuildParam(y, configOptionsProvider)}",""")) + }} + }; + } + """; + } +} diff --git a/lib/src/CompileTimeConfigPublicMembers/CompileTimeConfigPublicMembers.csproj b/lib/src/CompileTimeConfigPublicMembers/CompileTimeConfigPublicMembers.csproj new file mode 100644 index 0000000..ec0e84d --- /dev/null +++ b/lib/src/CompileTimeConfigPublicMembers/CompileTimeConfigPublicMembers.csproj @@ -0,0 +1,7 @@ + + + + netstandard2.0 + 5 + + \ No newline at end of file diff --git a/lib/src/CompileTimeConfigPublicMembers/GenerateConfigAccessorAttribute.cs b/lib/src/CompileTimeConfigPublicMembers/GenerateConfigAccessorAttribute.cs new file mode 100644 index 0000000..2dccf13 --- /dev/null +++ b/lib/src/CompileTimeConfigPublicMembers/GenerateConfigAccessorAttribute.cs @@ -0,0 +1,15 @@ +using System; + +namespace CompileTimeConfigPublicMembers +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + public class GenerateConfigAccessorAttribute : Attribute + { + public Type ConfigRecordType { get; private set; } + + public GenerateConfigAccessorAttribute(Type configRecordType) + { + ConfigRecordType = configRecordType; + } + } +} diff --git a/lib/src/CompileTimeConfigPublicMembers/ICompileTimeConfigAccessor.cs b/lib/src/CompileTimeConfigPublicMembers/ICompileTimeConfigAccessor.cs new file mode 100644 index 0000000..e4b4d39 --- /dev/null +++ b/lib/src/CompileTimeConfigPublicMembers/ICompileTimeConfigAccessor.cs @@ -0,0 +1,7 @@ +namespace CompileTimeConfigPublicMembers +{ + public interface ICompileTimeConfigAccessor where T : class + { + T GetConfig(); + } +} diff --git a/lib/src/FilePicker/FilePicker.cs b/lib/src/FilePicker/FilePicker.cs new file mode 100644 index 0000000..2867f04 --- /dev/null +++ b/lib/src/FilePicker/FilePicker.cs @@ -0,0 +1,164 @@ +using System.Diagnostics; +using System.IO; +using System.Net; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using Newtonsoft.Json; +using HttpListener = System.Net.HttpListener; + +namespace FilePicker +{ + public class FilePicker : IFilePicker + { + private readonly Serilog.ILogger _logger; + + public FilePicker(Serilog.ILogger logger) + { + _logger = logger; + } + + private static bool TryBindListenerOnFreePort(out HttpListener httpListener, out int port) + { + // IANA suggested range for dynamic or private ports + const int minPort = 49215; + const int maxPort = 65535; + + for (port = minPort; port < maxPort; port++) + { + httpListener = new HttpListener(); + httpListener.Prefixes.Add("http://localhost:" + port + "/"); + try + { + httpListener.Start(); + return true; + } + catch (HttpListenerException) + { + // nothing to do here -- the listener disposes itself when Start throws + } + } + + port = 0; + httpListener = null; + return false; + } + + public async Task SelectFile(FilePickerOptions options, CancellationToken cancellationToken) + { + int port; + HttpListener listener; + if (!TryBindListenerOnFreePort(out listener, out port)) + { + throw new FilePickerException("No available ports"); + } + + using (listener) + { + var uri = "http://localhost:" + port + "/"; + _logger.Debug("Listening for '{uri}'...", uri); + var _ = await Task.Run(() => Process.Start(uri), cancellationToken); + + while (!cancellationToken.IsCancellationRequested) + { + HttpListenerContext context; + try + { + using (var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)) + { + + var contextAsync = listener.GetContextAsync(); + // Allows us to cancel the GetContextAsync call despite its lack of cancellation token support + var completed = await Task.WhenAny(contextAsync, Task.Delay(Timeout.Infinite, cts.Token)); + if (completed != contextAsync) + { + return null; + } + + cts.Cancel(); // cancel the infinite task.Delay + context = contextAsync.Result; + } + } + catch (HttpListenerException ex) + { + _logger.Error(ex, "Failed to get context: {0}", ex.ErrorCode); + throw new FilePickerException("Http listener failed to open", ex); + } + + if (context.Request.HttpMethod == "POST") + { + return await HandlePost(context); + } + + await HandleGet(options, context); + } + } + + return null; + } + + private async Task HandleGet(FilePickerOptions viewModel, HttpListenerContext context) + { + string html; + using (var stream = Assembly.GetExecutingAssembly() + .GetManifestResourceStream("FilePicker.FilePickerView.html")) + { + if (stream == null) + { + throw new FilePickerException("File picker view could not be loaded"); + } + + using (var reader = new StreamReader(stream)) + { + html = await reader.ReadToEndAsync(); + } + } + + html = html.Replace("@AccessToken", viewModel.AccessToken) + .Replace("@AppId", viewModel.AppId) + .Replace("@GDrivePickerApiKey", viewModel.GDrivePickerApiKey); + + context.Response.KeepAlive = false; + using (StreamWriter streamWriter = new StreamWriter(context.Response.OutputStream)) + { + await streamWriter.WriteAsync(html); + } + + _logger.Debug("File picker page returned to browser."); + } + + private async Task HandlePost(HttpListenerContext context) + { + string input; + using (var sr = new StreamReader(context.Request.InputStream)) + { + input = await sr.ReadToEndAsync(); + } + + FilePick pick; + try + { + pick = JsonConvert.DeserializeObject(input); + } + catch (JsonSerializationException ex) + { + _logger.Error(ex, "Failed to deserialize file pick {response}", input); + throw new FilePickerException("Invalid post request submitted to listener", ex); + } + + if (pick == null) + { + throw new FilePickerException("Invalid post request submitted to listener") + { + Data = { { "Payload", input } } + }; + } + + _logger.Debug("Picked {0}, {1}", pick.Id, pick.Name); + context.Response.StatusCode = 200; + context.Response.Close(); + + return pick; + } + } +} diff --git a/lib/src/FilePicker/FilePicker.csproj b/lib/src/FilePicker/FilePicker.csproj new file mode 100644 index 0000000..f9e3b6d --- /dev/null +++ b/lib/src/FilePicker/FilePicker.csproj @@ -0,0 +1,19 @@ + + + + netStandard2.0 + 5 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/src/FilePicker/FilePickerException.cs b/lib/src/FilePicker/FilePickerException.cs new file mode 100644 index 0000000..82a01b1 --- /dev/null +++ b/lib/src/FilePicker/FilePickerException.cs @@ -0,0 +1,10 @@ +using System; + +namespace FilePicker +{ + public class FilePickerException : Exception + { + public FilePickerException(string message) : base(message) { } + public FilePickerException(string message, Exception innerException) : base(message, innerException) { } + } +} diff --git a/lib/src/FilePicker/FilePickerOptions.cs b/lib/src/FilePicker/FilePickerOptions.cs new file mode 100644 index 0000000..821f1f7 --- /dev/null +++ b/lib/src/FilePicker/FilePickerOptions.cs @@ -0,0 +1,9 @@ +namespace FilePicker +{ + public class FilePickerOptions + { + public string GDrivePickerApiKey { get; set; } + public string AppId { get; set; } + public string AccessToken { get; set; } + } +} diff --git a/lib/src/FilePicker/FilePickerView.html b/lib/src/FilePicker/FilePickerView.html new file mode 100644 index 0000000..5ac8bce --- /dev/null +++ b/lib/src/FilePicker/FilePickerView.html @@ -0,0 +1,67 @@ + + + + + Google Drive File Picker + + + + + + + + + \ No newline at end of file diff --git a/lib/src/FilePicker/IFilePicker.cs b/lib/src/FilePicker/IFilePicker.cs new file mode 100644 index 0000000..26ef8c3 --- /dev/null +++ b/lib/src/FilePicker/IFilePicker.cs @@ -0,0 +1,17 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace FilePicker +{ + public interface IFilePicker + { + Task SelectFile(FilePickerOptions options, CancellationToken cancellationToken); + } + + + public class FilePick + { + public string Id { get; set; } + public string Name { get; set; } + } +} diff --git a/lib/src/GenClientId/GenClientId.csproj b/lib/src/GenClientId/GenClientId.csproj deleted file mode 100644 index 736851c..0000000 --- a/lib/src/GenClientId/GenClientId.csproj +++ /dev/null @@ -1,26 +0,0 @@ - - - - Exe - net45 - 1.0.0 - 1.0.0.0 - KPSync For Google Drive - GenClientId - Build-time helper for credential obfuscation. - Copyright © 2020-2021 - en-US - AnyCPU - - - - DEBUG;$(DefineConstants) - - - - - ..\..\bin\KeePass.exe - - - - diff --git a/lib/src/GenClientId/Generator.cs b/lib/src/GenClientId/Generator.cs deleted file mode 100644 index 8f57950..0000000 --- a/lib/src/GenClientId/Generator.cs +++ /dev/null @@ -1,124 +0,0 @@ -/** - * KPSync for Google Drive - * Copyright(C) 2020 Walter Goodwin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . -**/ - -using KeePassLib.Security; -using System; -using System.IO; -using System.Security.Cryptography; -using System.Text; - -namespace GenClientId -{ - public class Generator - { - static string GenSrc(byte[] bytes) - { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < bytes.Length; i++) - { - if (0 == i % 8) - { - sb.Append(" "); - } - sb.AppendFormat("0x{0:x2},", bytes[i]); - if (0 != (i + 1) % 8 && - (i + 1) < bytes.Length) - { - sb.Append(' '); - } - else - { - sb.Append(Environment.NewLine); - } - } - return sb.ToString(); - } - - public Generator() - { - } - - public string SourceFilePath { get; set; } - - public string LegacyIdCsharpConstant { get; set; } - public string LegacyIdPadCsharpConstant { get; set; } - public string LegacySecretCsharpConstant { get; set; } - public string LegacySecretPadCsharpConstant { get; set; } - public string ClientIdCsharpConstant { get; set; } - public string ClientIdPadCsharpConstant { get; set; } - public string ClientSecretCsharpConstant { get; set; } - public string ClientSecretPadCsharpConstant { get; set; } - - byte[] LegacyIdBytes { get; set; } - byte[] LegacyIdPadBytes { get; set; } - byte[] LegacySecretBytes { get; set; } - byte[] LegacySecretPadBytes { get; set; } - byte[] ClientIdBytes { get; set; } - byte[] ClientIdPadBytes { get; set; } - byte[] ClientSecretBytes { get; set; } - byte[] ClientSecretPadBytes { get; set; } - - public void Run() - { - using (StreamReader reader = File.OpenText(SourceFilePath)) - { - LegacyIdBytes = Encoding.UTF8.GetBytes( - reader.ReadLine().Trim()); - LegacySecretBytes = Encoding.UTF8.GetBytes( - reader.ReadLine().Trim()); - ClientIdBytes = Encoding.UTF8.GetBytes( - reader.ReadLine().Trim()); - ClientSecretBytes = Encoding.UTF8.GetBytes( - reader.ReadLine().Trim()); - LegacyIdPadBytes = new byte[LegacyIdBytes.Length]; - LegacySecretPadBytes = new byte[LegacySecretBytes.Length]; - ClientIdPadBytes = new byte[ClientIdBytes.Length]; - ClientSecretPadBytes = new byte[ClientSecretBytes.Length]; - - using (RandomNumberGenerator rng = - RandomNumberGenerator.Create()) - { - rng.GetNonZeroBytes(LegacyIdPadBytes); - rng.GetNonZeroBytes(LegacySecretPadBytes); - rng.GetNonZeroBytes(ClientIdPadBytes); - rng.GetNonZeroBytes(ClientSecretPadBytes); - } - - XorredBuffer clientIdBuf = new XorredBuffer(LegacyIdBytes, - LegacyIdPadBytes); - XorredBuffer secretBuf = new XorredBuffer(LegacySecretBytes, - LegacySecretPadBytes); - - LegacyIdCsharpConstant = GenSrc(clientIdBuf.ReadPlainText()); - LegacyIdPadCsharpConstant = GenSrc(LegacyIdPadBytes); - LegacySecretCsharpConstant = GenSrc(secretBuf.ReadPlainText()); - LegacySecretPadCsharpConstant = GenSrc(LegacySecretPadBytes); - - clientIdBuf = new XorredBuffer(ClientIdBytes, - ClientIdPadBytes); - secretBuf = new XorredBuffer(ClientSecretBytes, - ClientSecretPadBytes); - - ClientIdCsharpConstant = GenSrc(clientIdBuf.ReadPlainText()); - ClientIdPadCsharpConstant = GenSrc(ClientIdPadBytes); - ClientSecretCsharpConstant = GenSrc(secretBuf.ReadPlainText()); - ClientSecretPadCsharpConstant = GenSrc(ClientSecretPadBytes); - } - } - } -} diff --git a/lib/src/GenClientId/Program.cs b/lib/src/GenClientId/Program.cs deleted file mode 100644 index daac73f..0000000 --- a/lib/src/GenClientId/Program.cs +++ /dev/null @@ -1,111 +0,0 @@ -/** - * KPSync for Google Drive - * Copyright(C) 2020 Walter Goodwin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . -**/ - -using System.Diagnostics; -using System.IO; -using System.Text; - -namespace GenClientId -{ - class Program - { - static void Main(string[] args) - { - // FOR TESTING PURPOSES ONLY. - - // Two arguments: - // 1. The path of a source file. - // 2. The path of a target file. - // - // The UTF8-encoded source file must contain two lines of text: - // 1. An OAuth2.0 client ID. - // 2. The cleartext secret associated with the client ID - // - - Generator gen = new Generator() - { - SourceFilePath = args[0] - }; - gen.Run(); - - StringBuilder src = new StringBuilder(@" -namespace KPSyncForDrive -{ - static partial class GdsDefs - { - static readonly byte[] s_legacyClientIdBytes = new byte[] - { -"); - src.Append(gen.LegacyIdCsharpConstant); - src.Append(@" - }; - static readonly byte[] s_legacyClientIdPad = new byte[] - { -"); - src.Append(gen.LegacyIdPadCsharpConstant); - src.Append(@" - }; - static readonly byte[] s_legacyClientSecretBytes = new byte[] - { -"); - src.Append(gen.LegacySecretCsharpConstant); - src.Append(@" - }; - static readonly byte[] s_legacyClientSecretPad = new byte[] - { -"); - src.Append(gen.LegacySecretPadCsharpConstant); - src.Append(@" - }; - static readonly byte[] s_clientIdBytes = new byte[] - { -"); - src.Append(gen.ClientIdCsharpConstant); - src.Append(@" - }; - static readonly byte[] s_clientIdPad = new byte[] - { -"); - src.Append(gen.ClientIdPadCsharpConstant); - src.Append(@" - }; - static readonly byte[] s_clientSecretBytes = new byte[] - { -"); - src.Append(gen.ClientSecretCsharpConstant); - src.Append(@" - }; - static readonly byte[] s_clientSecretPad = new byte[] - { -"); - src.Append(gen.ClientSecretPadCsharpConstant); - src.Append(@" - }; - - } -}"); - - Debug.WriteLine(src.ToString()); - - using (StreamWriter sw = File.CreateText(args[1])) - { - sw.Write(src.ToString()); - } - } - } -} diff --git a/lib/src/GenClientId/Properties/AssemblyInfo.cs b/lib/src/GenClientId/Properties/AssemblyInfo.cs deleted file mode 100644 index 5efbe80..0000000 --- a/lib/src/GenClientId/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,22 +0,0 @@ -/** - * KPSync for Google Drive - * Copyright(C) 2021-2021 Walter Goodwin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . -**/ - -using System.Runtime.InteropServices; - -[assembly: ComVisible(false)] -[assembly: Guid("f7b92fbf-f5d8-45e0-b357-4ca8f05ad652")] diff --git a/lib/src/GenVerInfo/GenVerInfo.csproj b/lib/src/GenVerInfo/GenVerInfo.csproj index c052e91..9930121 100644 --- a/lib/src/GenVerInfo/GenVerInfo.csproj +++ b/lib/src/GenVerInfo/GenVerInfo.csproj @@ -2,7 +2,7 @@ Exe - net45 + net48 1.0.0 1.0.0.0 KPSync For Google Drive diff --git a/lib/src/WindowsControls/WindowsControls.csproj b/lib/src/WindowsControls/WindowsControls.csproj index f8dd967..6b27e17 100644 --- a/lib/src/WindowsControls/WindowsControls.csproj +++ b/lib/src/WindowsControls/WindowsControls.csproj @@ -1,14 +1,9 @@ - - - 4.1.0 - - KPSyncWindows KPSyncForDrive.WindowsControls - v4.5 - net45 + v4.8 + net48 true true KPSync For Google Drive diff --git a/src/AuthWaitOrCancel.cs b/src/AuthWaitOrCancel.cs index 9792687..d6f1b46 100644 --- a/src/AuthWaitOrCancel.cs +++ b/src/AuthWaitOrCancel.cs @@ -25,7 +25,10 @@ using KeePass.UI; using KeePass.Util; using System; +using System.Threading; +using System.Threading.Tasks; using System.Windows.Forms; +using KeePass; namespace KPSyncForDrive { @@ -67,6 +70,24 @@ internal AuthWaitOrCancel(IPluginHost host, DatabaseContext dbCtx, GdsDefs.ProductName), string.Format("{0} {1}", GdsDefs.ProductName, GdsDefs.Version)); } + + public async Task ShowDialogAsync(CancellationTokenSource cts) + { + FormClosing += (o, e) => + { + cts.Cancel(); + }; + + if (Program.MainForm.InvokeRequired || InvokeRequired != Program.MainForm.InvokeRequired) + { + Log.Debug("Form not created or shown on UI thread - aborting."); + return DialogResult.Abort; + } + + await Task.Yield(); + return IsDisposed ? DialogResult.Cancel : ShowDialog(); + } + private void lnkHelp_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { diff --git a/src/ConfigurationForm.Designer.cs b/src/ConfigurationForm.Designer.cs index 4019d35..f88ac02 100644 --- a/src/ConfigurationForm.Designer.cs +++ b/src/ConfigurationForm.Designer.cs @@ -45,15 +45,8 @@ private void InitializeComponent() this.m_chkUploadEnabled = new System.Windows.Forms.CheckBox(); this.m_chkSyncEnabled = new System.Windows.Forms.CheckBox(); this.m_grpDriveAuthDefaults = new System.Windows.Forms.GroupBox(); - this.m_chkDefaultUseLegacyCreds = new System.Windows.Forms.CheckBox(); this.m_lnkGoogle2 = new System.Windows.Forms.LinkLabel(); this.m_lnkHelp2 = new System.Windows.Forms.LinkLabel(); - this.m_chkDefaultDriveScope = new System.Windows.Forms.CheckBox(); - this.m_lblDefaultClientSecret = new System.Windows.Forms.Label(); - this.m_lblDefaultClientId = new System.Windows.Forms.Label(); - this.m_txtDefaultClientSecret = new System.Windows.Forms.TextBox(); - this.m_txtDefaultClientId = new System.Windows.Forms.TextBox(); - this.m_chkDefaultLegacyClientId = new System.Windows.Forms.CheckBox(); this.m_grpFolderDefaults = new System.Windows.Forms.GroupBox(); this.m_btnGetColors = new System.Windows.Forms.Button(); this.m_cbColors = new System.Windows.Forms.ComboBox(); @@ -70,15 +63,10 @@ private void InitializeComponent() this.m_lnkAuthTokenHelp = new System.Windows.Forms.LinkLabel(); this.m_chkDontSaveAuthToken = new System.Windows.Forms.CheckBox(); this.m_grpDriveAuth = new System.Windows.Forms.GroupBox(); - this.m_chkUseLegacyCreds = new System.Windows.Forms.CheckBox(); - this.m_chkDriveScope = new System.Windows.Forms.CheckBox(); + this.AuthorizeFiles_label = new System.Windows.Forms.Label(); + this.AuthorizeFiles_btn = new System.Windows.Forms.Button(); this.m_lnkGoogle = new System.Windows.Forms.LinkLabel(); this.m_lnkHelp = new System.Windows.Forms.LinkLabel(); - this.m_lblClientSecret = new System.Windows.Forms.Label(); - this.m_chkLegacyClientId = new System.Windows.Forms.CheckBox(); - this.m_lblClientId = new System.Windows.Forms.Label(); - this.m_txtClientSecret = new System.Windows.Forms.TextBox(); - this.m_txtClientId = new System.Windows.Forms.TextBox(); this.m_grpEntry = new System.Windows.Forms.GroupBox(); this.m_cbAccount = new System.Windows.Forms.ComboBox(); this.m_lblAccount = new System.Windows.Forms.Label(); @@ -87,6 +75,7 @@ private void InitializeComponent() this.m_txtFolder = new System.Windows.Forms.TextBox(); this.m_lblFolder = new System.Windows.Forms.Label(); this.m_tabMain = new System.Windows.Forms.TabControl(); + this.AuthorizeFiles_tooltip = new System.Windows.Forms.ToolTip(this.components); ((System.ComponentModel.ISupportInitialize)(this.m_bannerImage)).BeginInit(); this.m_tabOptions.SuspendLayout(); this.m_grpAuthTokenSecurityDefaults.SuspendLayout(); @@ -105,9 +94,10 @@ private void InitializeComponent() // m_btnCancel // this.m_btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; - this.m_btnCancel.Location = new System.Drawing.Point(497, 524); + this.m_btnCancel.Location = new System.Drawing.Point(746, 806); + this.m_btnCancel.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_btnCancel.Name = "m_btnCancel"; - this.m_btnCancel.Size = new System.Drawing.Size(75, 23); + this.m_btnCancel.Size = new System.Drawing.Size(112, 35); this.m_btnCancel.TabIndex = 102; this.m_btnCancel.Text = "Btn_DlgCancel"; this.m_btnCancel.UseVisualStyleBackColor = true; @@ -115,9 +105,10 @@ private void InitializeComponent() // m_btnOK // this.m_btnOK.DialogResult = System.Windows.Forms.DialogResult.OK; - this.m_btnOK.Location = new System.Drawing.Point(416, 524); + this.m_btnOK.Location = new System.Drawing.Point(624, 806); + this.m_btnOK.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_btnOK.Name = "m_btnOK"; - this.m_btnOK.Size = new System.Drawing.Size(75, 23); + this.m_btnOK.Size = new System.Drawing.Size(112, 35); this.m_btnOK.TabIndex = 100; this.m_btnOK.Text = "Btn_DlgOK"; this.m_btnOK.UseVisualStyleBackColor = true; @@ -125,10 +116,10 @@ private void InitializeComponent() // m_btnAbout // this.m_btnAbout.ImageList = this.m_imgList; - this.m_btnAbout.Location = new System.Drawing.Point(12, 524); - this.m_btnAbout.Margin = new System.Windows.Forms.Padding(4); + this.m_btnAbout.Location = new System.Drawing.Point(18, 806); + this.m_btnAbout.Margin = new System.Windows.Forms.Padding(6); this.m_btnAbout.Name = "m_btnAbout"; - this.m_btnAbout.Size = new System.Drawing.Size(145, 23); + this.m_btnAbout.Size = new System.Drawing.Size(217, 35); this.m_btnAbout.TabIndex = 103; this.m_btnAbout.Text = "Btn_About"; this.m_btnAbout.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; @@ -144,8 +135,9 @@ private void InitializeComponent() // this.m_bannerImage.Dock = System.Windows.Forms.DockStyle.Top; this.m_bannerImage.Location = new System.Drawing.Point(0, 0); + this.m_bannerImage.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_bannerImage.Name = "m_bannerImage"; - this.m_bannerImage.Size = new System.Drawing.Size(580, 60); + this.m_bannerImage.Size = new System.Drawing.Size(870, 92); this.m_bannerImage.TabIndex = 1; this.m_bannerImage.TabStop = false; // @@ -156,9 +148,10 @@ private void InitializeComponent() this.m_tabOptions.Controls.Add(this.m_grpDriveAuthDefaults); this.m_tabOptions.Controls.Add(this.m_grpFolderDefaults); this.m_tabOptions.Controls.Add(this.m_grpAutoSync); - this.m_tabOptions.Location = new System.Drawing.Point(4, 23); + this.m_tabOptions.Location = new System.Drawing.Point(4, 29); + this.m_tabOptions.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_tabOptions.Name = "m_tabOptions"; - this.m_tabOptions.Size = new System.Drawing.Size(552, 423); + this.m_tabOptions.Size = new System.Drawing.Size(832, 659); this.m_tabOptions.TabIndex = 3; this.m_tabOptions.Text = "Title_DefaultsTab"; this.m_tabOptions.UseVisualStyleBackColor = true; @@ -168,9 +161,11 @@ private void InitializeComponent() this.m_grpAuthTokenSecurityDefaults.Controls.Add(this.m_lnkAuthTokenDefaultsHelp); this.m_grpAuthTokenSecurityDefaults.Controls.Add(this.m_chkWarnAuthToken); this.m_grpAuthTokenSecurityDefaults.Controls.Add(this.m_chkDontSaveAuthDefault); - this.m_grpAuthTokenSecurityDefaults.Location = new System.Drawing.Point(6, 98); + this.m_grpAuthTokenSecurityDefaults.Location = new System.Drawing.Point(9, 151); + this.m_grpAuthTokenSecurityDefaults.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_grpAuthTokenSecurityDefaults.Name = "m_grpAuthTokenSecurityDefaults"; - this.m_grpAuthTokenSecurityDefaults.Size = new System.Drawing.Size(538, 80); + this.m_grpAuthTokenSecurityDefaults.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.m_grpAuthTokenSecurityDefaults.Size = new System.Drawing.Size(807, 122); this.m_grpAuthTokenSecurityDefaults.TabIndex = 2; this.m_grpAuthTokenSecurityDefaults.TabStop = false; this.m_grpAuthTokenSecurityDefaults.Text = "Group_AuthTokenSecurityDefaults"; @@ -179,9 +174,10 @@ private void InitializeComponent() // this.m_lnkAuthTokenDefaultsHelp.AutoSize = true; this.m_lnkAuthTokenDefaultsHelp.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline; - this.m_lnkAuthTokenDefaultsHelp.Location = new System.Drawing.Point(133, 61); + this.m_lnkAuthTokenDefaultsHelp.Location = new System.Drawing.Point(199, 94); + this.m_lnkAuthTokenDefaultsHelp.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.m_lnkAuthTokenDefaultsHelp.Name = "m_lnkAuthTokenDefaultsHelp"; - this.m_lnkAuthTokenDefaultsHelp.Size = new System.Drawing.Size(125, 13); + this.m_lnkAuthTokenDefaultsHelp.Size = new System.Drawing.Size(188, 20); this.m_lnkAuthTokenDefaultsHelp.TabIndex = 2; this.m_lnkAuthTokenDefaultsHelp.TabStop = true; this.m_lnkAuthTokenDefaultsHelp.Text = "Lnk_AuthTokenAppHelp"; @@ -189,9 +185,10 @@ private void InitializeComponent() // m_chkWarnAuthToken // this.m_chkWarnAuthToken.AutoSize = true; - this.m_chkWarnAuthToken.Location = new System.Drawing.Point(136, 42); + this.m_chkWarnAuthToken.Location = new System.Drawing.Point(204, 65); + this.m_chkWarnAuthToken.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_chkWarnAuthToken.Name = "m_chkWarnAuthToken"; - this.m_chkWarnAuthToken.Size = new System.Drawing.Size(149, 17); + this.m_chkWarnAuthToken.Size = new System.Drawing.Size(221, 24); this.m_chkWarnAuthToken.TabIndex = 1; this.m_chkWarnAuthToken.Text = "Lbl_WarnEntryAuthToken"; this.m_chkWarnAuthToken.UseVisualStyleBackColor = true; @@ -199,9 +196,10 @@ private void InitializeComponent() // m_chkDontSaveAuthDefault // this.m_chkDontSaveAuthDefault.AutoSize = true; - this.m_chkDontSaveAuthDefault.Location = new System.Drawing.Point(136, 19); + this.m_chkDontSaveAuthDefault.Location = new System.Drawing.Point(204, 29); + this.m_chkDontSaveAuthDefault.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_chkDontSaveAuthDefault.Name = "m_chkDontSaveAuthDefault"; - this.m_chkDontSaveAuthDefault.Size = new System.Drawing.Size(150, 17); + this.m_chkDontSaveAuthDefault.Size = new System.Drawing.Size(224, 24); this.m_chkDontSaveAuthDefault.TabIndex = 0; this.m_chkDontSaveAuthDefault.Text = "Lbl_DontSaveAuthDefault"; this.m_chkDontSaveAuthDefault.UseVisualStyleBackColor = true; @@ -211,9 +209,11 @@ private void InitializeComponent() this.m_grpCmdEnabled.Controls.Add(this.m_chkDownloadEnabled); this.m_grpCmdEnabled.Controls.Add(this.m_chkUploadEnabled); this.m_grpCmdEnabled.Controls.Add(this.m_chkSyncEnabled); - this.m_grpCmdEnabled.Location = new System.Drawing.Point(6, 6); + this.m_grpCmdEnabled.Location = new System.Drawing.Point(9, 9); + this.m_grpCmdEnabled.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_grpCmdEnabled.Name = "m_grpCmdEnabled"; - this.m_grpCmdEnabled.Size = new System.Drawing.Size(236, 86); + this.m_grpCmdEnabled.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.m_grpCmdEnabled.Size = new System.Drawing.Size(354, 132); this.m_grpCmdEnabled.TabIndex = 0; this.m_grpCmdEnabled.TabStop = false; this.m_grpCmdEnabled.Text = "Group_CmdEnabled"; @@ -221,9 +221,10 @@ private void InitializeComponent() // m_chkDownloadEnabled // this.m_chkDownloadEnabled.AutoSize = true; - this.m_chkDownloadEnabled.Location = new System.Drawing.Point(18, 62); + this.m_chkDownloadEnabled.Location = new System.Drawing.Point(27, 95); + this.m_chkDownloadEnabled.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_chkDownloadEnabled.Name = "m_chkDownloadEnabled"; - this.m_chkDownloadEnabled.Size = new System.Drawing.Size(133, 17); + this.m_chkDownloadEnabled.Size = new System.Drawing.Size(197, 24); this.m_chkDownloadEnabled.TabIndex = 2; this.m_chkDownloadEnabled.Text = "Lbl_DownloadEnabled"; this.m_chkDownloadEnabled.UseVisualStyleBackColor = true; @@ -231,9 +232,10 @@ private void InitializeComponent() // m_chkUploadEnabled // this.m_chkUploadEnabled.AutoSize = true; - this.m_chkUploadEnabled.Location = new System.Drawing.Point(18, 40); + this.m_chkUploadEnabled.Location = new System.Drawing.Point(27, 61); + this.m_chkUploadEnabled.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_chkUploadEnabled.Name = "m_chkUploadEnabled"; - this.m_chkUploadEnabled.Size = new System.Drawing.Size(119, 17); + this.m_chkUploadEnabled.Size = new System.Drawing.Size(175, 24); this.m_chkUploadEnabled.TabIndex = 1; this.m_chkUploadEnabled.Text = "Lbl_UploadEnabled"; this.m_chkUploadEnabled.UseVisualStyleBackColor = true; @@ -241,48 +243,34 @@ private void InitializeComponent() // m_chkSyncEnabled // this.m_chkSyncEnabled.AutoSize = true; - this.m_chkSyncEnabled.Location = new System.Drawing.Point(18, 18); + this.m_chkSyncEnabled.Location = new System.Drawing.Point(27, 28); + this.m_chkSyncEnabled.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_chkSyncEnabled.Name = "m_chkSyncEnabled"; - this.m_chkSyncEnabled.Size = new System.Drawing.Size(109, 17); + this.m_chkSyncEnabled.Size = new System.Drawing.Size(160, 24); this.m_chkSyncEnabled.TabIndex = 0; this.m_chkSyncEnabled.Text = "Lbl_SyncEnabled"; this.m_chkSyncEnabled.UseVisualStyleBackColor = true; // // m_grpDriveAuthDefaults // - this.m_grpDriveAuthDefaults.Controls.Add(this.m_chkDefaultUseLegacyCreds); this.m_grpDriveAuthDefaults.Controls.Add(this.m_lnkGoogle2); this.m_grpDriveAuthDefaults.Controls.Add(this.m_lnkHelp2); - this.m_grpDriveAuthDefaults.Controls.Add(this.m_chkDefaultDriveScope); - this.m_grpDriveAuthDefaults.Controls.Add(this.m_lblDefaultClientSecret); - this.m_grpDriveAuthDefaults.Controls.Add(this.m_lblDefaultClientId); - this.m_grpDriveAuthDefaults.Controls.Add(this.m_txtDefaultClientSecret); - this.m_grpDriveAuthDefaults.Controls.Add(this.m_txtDefaultClientId); - this.m_grpDriveAuthDefaults.Controls.Add(this.m_chkDefaultLegacyClientId); - this.m_grpDriveAuthDefaults.Location = new System.Drawing.Point(6, 276); + this.m_grpDriveAuthDefaults.Location = new System.Drawing.Point(9, 425); + this.m_grpDriveAuthDefaults.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_grpDriveAuthDefaults.Name = "m_grpDriveAuthDefaults"; - this.m_grpDriveAuthDefaults.Size = new System.Drawing.Size(538, 144); + this.m_grpDriveAuthDefaults.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.m_grpDriveAuthDefaults.Size = new System.Drawing.Size(807, 221); this.m_grpDriveAuthDefaults.TabIndex = 5; this.m_grpDriveAuthDefaults.TabStop = false; // - // m_chkDefaultUseLegacyCreds - // - this.m_chkDefaultUseLegacyCreds.AutoSize = true; - this.m_chkDefaultUseLegacyCreds.Location = new System.Drawing.Point(6, 0); - this.m_chkDefaultUseLegacyCreds.Name = "m_chkDefaultUseLegacyCreds"; - this.m_chkDefaultUseLegacyCreds.Size = new System.Drawing.Size(129, 17); - this.m_chkDefaultUseLegacyCreds.TabIndex = 4; - this.m_chkDefaultUseLegacyCreds.Text = "Btn_UseLegacyCreds"; - this.m_chkDefaultUseLegacyCreds.UseVisualStyleBackColor = true; - this.m_chkDefaultUseLegacyCreds.CheckedChanged += new System.EventHandler(this.m_chkDefaultUseLegacyCreds_CheckedChanged); - // // m_lnkGoogle2 // this.m_lnkGoogle2.AutoSize = true; this.m_lnkGoogle2.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline; - this.m_lnkGoogle2.Location = new System.Drawing.Point(192, 124); + this.m_lnkGoogle2.Location = new System.Drawing.Point(288, 191); + this.m_lnkGoogle2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.m_lnkGoogle2.Name = "m_lnkGoogle2"; - this.m_lnkGoogle2.Size = new System.Drawing.Size(85, 13); + this.m_lnkGoogle2.Size = new System.Drawing.Size(128, 20); this.m_lnkGoogle2.TabIndex = 6; this.m_lnkGoogle2.TabStop = true; this.m_lnkGoogle2.Text = "Lnk_GoogleDev"; @@ -291,66 +279,14 @@ private void InitializeComponent() // this.m_lnkHelp2.AutoSize = true; this.m_lnkHelp2.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline; - this.m_lnkHelp2.Location = new System.Drawing.Point(133, 124); + this.m_lnkHelp2.Location = new System.Drawing.Point(199, 191); + this.m_lnkHelp2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.m_lnkHelp2.Name = "m_lnkHelp2"; - this.m_lnkHelp2.Size = new System.Drawing.Size(53, 13); + this.m_lnkHelp2.Size = new System.Drawing.Size(80, 20); this.m_lnkHelp2.TabIndex = 5; this.m_lnkHelp2.TabStop = true; this.m_lnkHelp2.Text = "Lnk_Help"; // - // m_chkDefaultDriveScope - // - this.m_chkDefaultDriveScope.AutoSize = true; - this.m_chkDefaultDriveScope.Location = new System.Drawing.Point(136, 46); - this.m_chkDefaultDriveScope.Name = "m_chkDefaultDriveScope"; - this.m_chkDefaultDriveScope.Size = new System.Drawing.Size(146, 17); - this.m_chkDefaultDriveScope.TabIndex = 2; - this.m_chkDefaultDriveScope.Text = "Lbl_UseAppFileApiScope"; - this.m_chkDefaultDriveScope.UseVisualStyleBackColor = true; - // - // m_lblDefaultClientSecret - // - this.m_lblDefaultClientSecret.Location = new System.Drawing.Point(12, 103); - this.m_lblDefaultClientSecret.Name = "m_lblDefaultClientSecret"; - this.m_lblDefaultClientSecret.Size = new System.Drawing.Size(115, 13); - this.m_lblDefaultClientSecret.TabIndex = 17; - this.m_lblDefaultClientSecret.Text = "Lbl_DefaultClientSecret"; - this.m_lblDefaultClientSecret.TextAlign = System.Drawing.ContentAlignment.TopRight; - // - // m_lblDefaultClientId - // - this.m_lblDefaultClientId.Location = new System.Drawing.Point(12, 77); - this.m_lblDefaultClientId.Name = "m_lblDefaultClientId"; - this.m_lblDefaultClientId.Size = new System.Drawing.Size(115, 13); - this.m_lblDefaultClientId.TabIndex = 16; - this.m_lblDefaultClientId.Text = "Lbl_DefaultClientID"; - this.m_lblDefaultClientId.TextAlign = System.Drawing.ContentAlignment.TopRight; - // - // m_txtDefaultClientSecret - // - this.m_txtDefaultClientSecret.Location = new System.Drawing.Point(136, 100); - this.m_txtDefaultClientSecret.Name = "m_txtDefaultClientSecret"; - this.m_txtDefaultClientSecret.Size = new System.Drawing.Size(391, 20); - this.m_txtDefaultClientSecret.TabIndex = 4; - this.m_txtDefaultClientSecret.UseSystemPasswordChar = true; - // - // m_txtDefaultClientId - // - this.m_txtDefaultClientId.Location = new System.Drawing.Point(136, 74); - this.m_txtDefaultClientId.Name = "m_txtDefaultClientId"; - this.m_txtDefaultClientId.Size = new System.Drawing.Size(391, 20); - this.m_txtDefaultClientId.TabIndex = 3; - // - // m_chkDefaultLegacyClientId - // - this.m_chkDefaultLegacyClientId.AutoSize = true; - this.m_chkDefaultLegacyClientId.Location = new System.Drawing.Point(136, 23); - this.m_chkDefaultLegacyClientId.Name = "m_chkDefaultLegacyClientId"; - this.m_chkDefaultLegacyClientId.Size = new System.Drawing.Size(137, 17); - this.m_chkDefaultLegacyClientId.TabIndex = 1; - this.m_chkDefaultLegacyClientId.Text = "Lbl_UseLegacyClientID"; - this.m_chkDefaultLegacyClientId.UseVisualStyleBackColor = true; - // // m_grpFolderDefaults // this.m_grpFolderDefaults.Controls.Add(this.m_btnGetColors); @@ -359,18 +295,21 @@ private void InitializeComponent() this.m_grpFolderDefaults.Controls.Add(this.m_txtFolderDefault); this.m_grpFolderDefaults.Controls.Add(this.m_lblDefaultFolderLabel); this.m_grpFolderDefaults.Controls.Add(this.m_lblDefFolderColor); - this.m_grpFolderDefaults.Location = new System.Drawing.Point(6, 184); + this.m_grpFolderDefaults.Location = new System.Drawing.Point(9, 282); + this.m_grpFolderDefaults.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_grpFolderDefaults.Name = "m_grpFolderDefaults"; - this.m_grpFolderDefaults.Size = new System.Drawing.Size(538, 86); + this.m_grpFolderDefaults.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.m_grpFolderDefaults.Size = new System.Drawing.Size(807, 132); this.m_grpFolderDefaults.TabIndex = 3; this.m_grpFolderDefaults.TabStop = false; this.m_grpFolderDefaults.Text = "Group_FolderDefaults"; // // m_btnGetColors // - this.m_btnGetColors.Location = new System.Drawing.Point(311, 49); + this.m_btnGetColors.Location = new System.Drawing.Point(467, 75); + this.m_btnGetColors.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_btnGetColors.Name = "m_btnGetColors"; - this.m_btnGetColors.Size = new System.Drawing.Size(167, 23); + this.m_btnGetColors.Size = new System.Drawing.Size(251, 35); this.m_btnGetColors.TabIndex = 2; this.m_btnGetColors.Text = "Btn_GetColors"; this.m_btnGetColors.UseVisualStyleBackColor = true; @@ -378,42 +317,47 @@ private void InitializeComponent() // m_cbColors // this.m_cbColors.FormattingEnabled = true; - this.m_cbColors.Location = new System.Drawing.Point(183, 50); + this.m_cbColors.Location = new System.Drawing.Point(274, 78); + this.m_cbColors.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_cbColors.Name = "m_cbColors"; - this.m_cbColors.Size = new System.Drawing.Size(122, 21); + this.m_cbColors.Size = new System.Drawing.Size(181, 28); this.m_cbColors.TabIndex = 1; // // m_lblHintDefaultFolder // this.m_lblHintDefaultFolder.AutoSize = true; this.m_lblHintDefaultFolder.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.m_lblHintDefaultFolder.Location = new System.Drawing.Point(187, 10); + this.m_lblHintDefaultFolder.Location = new System.Drawing.Point(280, 15); + this.m_lblHintDefaultFolder.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.m_lblHintDefaultFolder.Name = "m_lblHintDefaultFolder"; - this.m_lblHintDefaultFolder.Size = new System.Drawing.Size(140, 13); + this.m_lblHintDefaultFolder.Size = new System.Drawing.Size(187, 17); this.m_lblHintDefaultFolder.TabIndex = 29; this.m_lblHintDefaultFolder.Text = "Lbl_DefaultTargetFolderHint"; // // m_txtFolderDefault // - this.m_txtFolderDefault.Location = new System.Drawing.Point(184, 24); + this.m_txtFolderDefault.Location = new System.Drawing.Point(276, 38); + this.m_txtFolderDefault.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_txtFolderDefault.Name = "m_txtFolderDefault"; - this.m_txtFolderDefault.Size = new System.Drawing.Size(294, 20); + this.m_txtFolderDefault.Size = new System.Drawing.Size(439, 26); this.m_txtFolderDefault.TabIndex = 0; // // m_lblDefaultFolderLabel // - this.m_lblDefaultFolderLabel.Location = new System.Drawing.Point(12, 27); + this.m_lblDefaultFolderLabel.Location = new System.Drawing.Point(18, 41); + this.m_lblDefaultFolderLabel.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.m_lblDefaultFolderLabel.Name = "m_lblDefaultFolderLabel"; - this.m_lblDefaultFolderLabel.Size = new System.Drawing.Size(165, 13); + this.m_lblDefaultFolderLabel.Size = new System.Drawing.Size(248, 20); this.m_lblDefaultFolderLabel.TabIndex = 24; this.m_lblDefaultFolderLabel.Text = "Lbl_DefaultTargetFolder"; this.m_lblDefaultFolderLabel.TextAlign = System.Drawing.ContentAlignment.TopRight; // // m_lblDefFolderColor // - this.m_lblDefFolderColor.Location = new System.Drawing.Point(15, 53); + this.m_lblDefFolderColor.Location = new System.Drawing.Point(22, 81); + this.m_lblDefFolderColor.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.m_lblDefFolderColor.Name = "m_lblDefFolderColor"; - this.m_lblDefFolderColor.Size = new System.Drawing.Size(162, 13); + this.m_lblDefFolderColor.Size = new System.Drawing.Size(243, 20); this.m_lblDefFolderColor.TabIndex = 26; this.m_lblDefFolderColor.Text = "Lbl_DefaultTgtFolderColor"; this.m_lblDefFolderColor.TextAlign = System.Drawing.ContentAlignment.TopRight; @@ -423,9 +367,11 @@ private void InitializeComponent() this.m_grpAutoSync.Controls.Add(this.m_chkSyncOnReopen); this.m_grpAutoSync.Controls.Add(this.m_chkSyncOnSave); this.m_grpAutoSync.Controls.Add(this.m_chkSyncOnOpen); - this.m_grpAutoSync.Location = new System.Drawing.Point(248, 6); + this.m_grpAutoSync.Location = new System.Drawing.Point(372, 9); + this.m_grpAutoSync.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_grpAutoSync.Name = "m_grpAutoSync"; - this.m_grpAutoSync.Size = new System.Drawing.Size(296, 86); + this.m_grpAutoSync.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.m_grpAutoSync.Size = new System.Drawing.Size(444, 132); this.m_grpAutoSync.TabIndex = 1; this.m_grpAutoSync.TabStop = false; this.m_grpAutoSync.Text = "Group_AutoSync"; @@ -434,9 +380,10 @@ private void InitializeComponent() // this.m_chkSyncOnReopen.AutoSize = true; this.m_chkSyncOnReopen.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.m_chkSyncOnReopen.Location = new System.Drawing.Point(39, 62); + this.m_chkSyncOnReopen.Location = new System.Drawing.Point(58, 95); + this.m_chkSyncOnReopen.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_chkSyncOnReopen.Name = "m_chkSyncOnReopen"; - this.m_chkSyncOnReopen.Size = new System.Drawing.Size(144, 17); + this.m_chkSyncOnReopen.Size = new System.Drawing.Size(186, 21); this.m_chkSyncOnReopen.TabIndex = 2; this.m_chkSyncOnReopen.Text = "Lbl_AutoSyncOnReopen"; this.m_chkSyncOnReopen.UseVisualStyleBackColor = true; @@ -444,9 +391,10 @@ private void InitializeComponent() // m_chkSyncOnSave // this.m_chkSyncOnSave.AutoSize = true; - this.m_chkSyncOnSave.Location = new System.Drawing.Point(18, 41); + this.m_chkSyncOnSave.Location = new System.Drawing.Point(27, 62); + this.m_chkSyncOnSave.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_chkSyncOnSave.Name = "m_chkSyncOnSave"; - this.m_chkSyncOnSave.Size = new System.Drawing.Size(131, 17); + this.m_chkSyncOnSave.Size = new System.Drawing.Size(193, 24); this.m_chkSyncOnSave.TabIndex = 1; this.m_chkSyncOnSave.Text = "Lbl_AutoSyncOnSave"; this.m_chkSyncOnSave.UseVisualStyleBackColor = true; @@ -454,9 +402,10 @@ private void InitializeComponent() // m_chkSyncOnOpen // this.m_chkSyncOnOpen.AutoSize = true; - this.m_chkSyncOnOpen.Location = new System.Drawing.Point(18, 18); + this.m_chkSyncOnOpen.Location = new System.Drawing.Point(27, 28); + this.m_chkSyncOnOpen.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_chkSyncOnOpen.Name = "m_chkSyncOnOpen"; - this.m_chkSyncOnOpen.Size = new System.Drawing.Size(132, 17); + this.m_chkSyncOnOpen.Size = new System.Drawing.Size(196, 24); this.m_chkSyncOnOpen.TabIndex = 0; this.m_chkSyncOnOpen.Text = "Lbl_AutoSyncOnOpen"; this.m_chkSyncOnOpen.UseVisualStyleBackColor = true; @@ -467,10 +416,11 @@ private void InitializeComponent() this.m_tabGSignIn.Controls.Add(this.m_grpDriveAuth); this.m_tabGSignIn.Controls.Add(this.m_grpEntry); this.m_tabGSignIn.Controls.Add(this.m_grpDriveOptions); - this.m_tabGSignIn.Location = new System.Drawing.Point(4, 23); + this.m_tabGSignIn.Location = new System.Drawing.Point(4, 29); + this.m_tabGSignIn.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_tabGSignIn.Name = "m_tabGSignIn"; - this.m_tabGSignIn.Padding = new System.Windows.Forms.Padding(3); - this.m_tabGSignIn.Size = new System.Drawing.Size(552, 423); + this.m_tabGSignIn.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.m_tabGSignIn.Size = new System.Drawing.Size(832, 659); this.m_tabGSignIn.TabIndex = 0; this.m_tabGSignIn.Text = "Title_SyncAuthTab"; this.m_tabGSignIn.UseVisualStyleBackColor = true; @@ -479,9 +429,11 @@ private void InitializeComponent() // this.m_grpAuthTokenSecurity.Controls.Add(this.m_lnkAuthTokenHelp); this.m_grpAuthTokenSecurity.Controls.Add(this.m_chkDontSaveAuthToken); - this.m_grpAuthTokenSecurity.Location = new System.Drawing.Point(6, 182); + this.m_grpAuthTokenSecurity.Location = new System.Drawing.Point(9, 280); + this.m_grpAuthTokenSecurity.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_grpAuthTokenSecurity.Name = "m_grpAuthTokenSecurity"; - this.m_grpAuthTokenSecurity.Size = new System.Drawing.Size(540, 80); + this.m_grpAuthTokenSecurity.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.m_grpAuthTokenSecurity.Size = new System.Drawing.Size(810, 122); this.m_grpAuthTokenSecurity.TabIndex = 2; this.m_grpAuthTokenSecurity.TabStop = false; this.m_grpAuthTokenSecurity.Text = "Group_AuthTokenSecurity"; @@ -491,9 +443,10 @@ private void InitializeComponent() this.m_lnkAuthTokenHelp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.m_lnkAuthTokenHelp.AutoSize = true; this.m_lnkAuthTokenHelp.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline; - this.m_lnkAuthTokenHelp.Location = new System.Drawing.Point(128, 50); + this.m_lnkAuthTokenHelp.Location = new System.Drawing.Point(192, 78); + this.m_lnkAuthTokenHelp.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.m_lnkAuthTokenHelp.Name = "m_lnkAuthTokenHelp"; - this.m_lnkAuthTokenHelp.Size = new System.Drawing.Size(106, 13); + this.m_lnkAuthTokenHelp.Size = new System.Drawing.Size(159, 20); this.m_lnkAuthTokenHelp.TabIndex = 1; this.m_lnkAuthTokenHelp.TabStop = true; this.m_lnkAuthTokenHelp.Text = "Lnk_AuthTokenHelp"; @@ -501,59 +454,60 @@ private void InitializeComponent() // m_chkDontSaveAuthToken // this.m_chkDontSaveAuthToken.AutoSize = true; - this.m_chkDontSaveAuthToken.Location = new System.Drawing.Point(131, 28); + this.m_chkDontSaveAuthToken.Location = new System.Drawing.Point(197, 42); + this.m_chkDontSaveAuthToken.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_chkDontSaveAuthToken.Name = "m_chkDontSaveAuthToken"; - this.m_chkDontSaveAuthToken.Size = new System.Drawing.Size(147, 17); + this.m_chkDontSaveAuthToken.Size = new System.Drawing.Size(215, 24); this.m_chkDontSaveAuthToken.TabIndex = 0; this.m_chkDontSaveAuthToken.Text = "Lbl_DontSaveAuthToken"; this.m_chkDontSaveAuthToken.UseVisualStyleBackColor = true; // // m_grpDriveAuth // - this.m_grpDriveAuth.Controls.Add(this.m_chkUseLegacyCreds); - this.m_grpDriveAuth.Controls.Add(this.m_chkDriveScope); + this.m_grpDriveAuth.Controls.Add(this.AuthorizeFiles_label); + this.m_grpDriveAuth.Controls.Add(this.AuthorizeFiles_btn); this.m_grpDriveAuth.Controls.Add(this.m_lnkGoogle); this.m_grpDriveAuth.Controls.Add(this.m_lnkHelp); - this.m_grpDriveAuth.Controls.Add(this.m_lblClientSecret); - this.m_grpDriveAuth.Controls.Add(this.m_chkLegacyClientId); - this.m_grpDriveAuth.Controls.Add(this.m_lblClientId); - this.m_grpDriveAuth.Controls.Add(this.m_txtClientSecret); - this.m_grpDriveAuth.Controls.Add(this.m_txtClientId); - this.m_grpDriveAuth.Location = new System.Drawing.Point(6, 268); + this.m_grpDriveAuth.Location = new System.Drawing.Point(9, 412); + this.m_grpDriveAuth.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_grpDriveAuth.Name = "m_grpDriveAuth"; - this.m_grpDriveAuth.Size = new System.Drawing.Size(540, 149); + this.m_grpDriveAuth.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.m_grpDriveAuth.Size = new System.Drawing.Size(810, 162); this.m_grpDriveAuth.TabIndex = 4; this.m_grpDriveAuth.TabStop = false; - // - // m_chkUseLegacyCreds - // - this.m_chkUseLegacyCreds.AutoSize = true; - this.m_chkUseLegacyCreds.Location = new System.Drawing.Point(6, 0); - this.m_chkUseLegacyCreds.Name = "m_chkUseLegacyCreds"; - this.m_chkUseLegacyCreds.Size = new System.Drawing.Size(129, 17); - this.m_chkUseLegacyCreds.TabIndex = 3; - this.m_chkUseLegacyCreds.Text = "Btn_UseLegacyCreds"; - this.m_chkUseLegacyCreds.UseVisualStyleBackColor = true; - this.m_chkUseLegacyCreds.CheckedChanged += new System.EventHandler(this.m_chkUseLegacyCreds_CheckedChanged); - // - // m_chkDriveScope - // - this.m_chkDriveScope.AutoSize = true; - this.m_chkDriveScope.Location = new System.Drawing.Point(131, 48); - this.m_chkDriveScope.Name = "m_chkDriveScope"; - this.m_chkDriveScope.Size = new System.Drawing.Size(146, 17); - this.m_chkDriveScope.TabIndex = 2; - this.m_chkDriveScope.Text = "Lbl_UseAppFileApiScope"; - this.m_chkDriveScope.UseVisualStyleBackColor = true; + this.m_grpDriveAuth.Text = "Group_gDriveAuth"; + // + // AuthorizeFiles_label + // + this.AuthorizeFiles_label.Location = new System.Drawing.Point(27, 46); + this.AuthorizeFiles_label.Name = "AuthorizeFiles_label"; + this.AuthorizeFiles_label.Size = new System.Drawing.Size(156, 39); + this.AuthorizeFiles_label.TabIndex = 8; + this.AuthorizeFiles_label.Text = "AuthorizeFiles_label"; + this.AuthorizeFiles_label.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.AuthorizeFiles_label.UseCompatibleTextRendering = true; + // + // AuthorizeFiles_btn + // + this.AuthorizeFiles_btn.Location = new System.Drawing.Point(197, 46); + this.AuthorizeFiles_btn.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4); + this.AuthorizeFiles_btn.Name = "AuthorizeFiles_btn"; + this.AuthorizeFiles_btn.Size = new System.Drawing.Size(153, 39); + this.AuthorizeFiles_btn.TabIndex = 7; + this.AuthorizeFiles_btn.Text = "AuthorizeFiles_btn"; + this.AuthorizeFiles_btn.UseCompatibleTextRendering = true; + this.AuthorizeFiles_btn.UseVisualStyleBackColor = true; + this.AuthorizeFiles_btn.Click += new System.EventHandler(this.HandleAuthorizeFilesAction); // // m_lnkGoogle // this.m_lnkGoogle.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.m_lnkGoogle.AutoSize = true; this.m_lnkGoogle.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline; - this.m_lnkGoogle.Location = new System.Drawing.Point(187, 129); + this.m_lnkGoogle.Location = new System.Drawing.Point(280, 132); + this.m_lnkGoogle.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.m_lnkGoogle.Name = "m_lnkGoogle"; - this.m_lnkGoogle.Size = new System.Drawing.Size(85, 13); + this.m_lnkGoogle.Size = new System.Drawing.Size(128, 20); this.m_lnkGoogle.TabIndex = 6; this.m_lnkGoogle.TabStop = true; this.m_lnkGoogle.Text = "Lnk_GoogleDev"; @@ -563,63 +517,23 @@ private void InitializeComponent() this.m_lnkHelp.Anchor = System.Windows.Forms.AnchorStyles.Bottom; this.m_lnkHelp.AutoSize = true; this.m_lnkHelp.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline; - this.m_lnkHelp.Location = new System.Drawing.Point(128, 129); + this.m_lnkHelp.Location = new System.Drawing.Point(192, 132); + this.m_lnkHelp.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.m_lnkHelp.Name = "m_lnkHelp"; - this.m_lnkHelp.Size = new System.Drawing.Size(53, 13); + this.m_lnkHelp.Size = new System.Drawing.Size(80, 20); this.m_lnkHelp.TabIndex = 5; this.m_lnkHelp.TabStop = true; this.m_lnkHelp.Text = "Lnk_Help"; // - // m_lblClientSecret - // - this.m_lblClientSecret.Location = new System.Drawing.Point(18, 107); - this.m_lblClientSecret.Name = "m_lblClientSecret"; - this.m_lblClientSecret.Size = new System.Drawing.Size(104, 13); - this.m_lblClientSecret.TabIndex = 12; - this.m_lblClientSecret.Text = "Lbl_ClientSecret"; - this.m_lblClientSecret.TextAlign = System.Drawing.ContentAlignment.TopRight; - // - // m_chkLegacyClientId - // - this.m_chkLegacyClientId.AutoSize = true; - this.m_chkLegacyClientId.Location = new System.Drawing.Point(131, 25); - this.m_chkLegacyClientId.Name = "m_chkLegacyClientId"; - this.m_chkLegacyClientId.Size = new System.Drawing.Size(137, 17); - this.m_chkLegacyClientId.TabIndex = 1; - this.m_chkLegacyClientId.Text = "Lbl_UseLegacyClientID"; - this.m_chkLegacyClientId.UseVisualStyleBackColor = true; - // - // m_lblClientId - // - this.m_lblClientId.Location = new System.Drawing.Point(18, 81); - this.m_lblClientId.Name = "m_lblClientId"; - this.m_lblClientId.Size = new System.Drawing.Size(104, 13); - this.m_lblClientId.TabIndex = 10; - this.m_lblClientId.Text = "Lbl_ClientID"; - this.m_lblClientId.TextAlign = System.Drawing.ContentAlignment.TopRight; - // - // m_txtClientSecret - // - this.m_txtClientSecret.Location = new System.Drawing.Point(131, 104); - this.m_txtClientSecret.Name = "m_txtClientSecret"; - this.m_txtClientSecret.Size = new System.Drawing.Size(391, 20); - this.m_txtClientSecret.TabIndex = 4; - this.m_txtClientSecret.UseSystemPasswordChar = true; - // - // m_txtClientId - // - this.m_txtClientId.Location = new System.Drawing.Point(131, 78); - this.m_txtClientId.Name = "m_txtClientId"; - this.m_txtClientId.Size = new System.Drawing.Size(391, 20); - this.m_txtClientId.TabIndex = 3; - // // m_grpEntry // this.m_grpEntry.Controls.Add(this.m_cbAccount); this.m_grpEntry.Controls.Add(this.m_lblAccount); - this.m_grpEntry.Location = new System.Drawing.Point(6, 6); + this.m_grpEntry.Location = new System.Drawing.Point(9, 9); + this.m_grpEntry.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_grpEntry.Name = "m_grpEntry"; - this.m_grpEntry.Size = new System.Drawing.Size(540, 81); + this.m_grpEntry.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.m_grpEntry.Size = new System.Drawing.Size(810, 125); this.m_grpEntry.TabIndex = 0; this.m_grpEntry.TabStop = false; this.m_grpEntry.Text = "Group_Entry"; @@ -628,16 +542,18 @@ private void InitializeComponent() // this.m_cbAccount.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.m_cbAccount.FormattingEnabled = true; - this.m_cbAccount.Location = new System.Drawing.Point(131, 33); + this.m_cbAccount.Location = new System.Drawing.Point(197, 51); + this.m_cbAccount.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_cbAccount.Name = "m_cbAccount"; - this.m_cbAccount.Size = new System.Drawing.Size(391, 21); + this.m_cbAccount.Size = new System.Drawing.Size(584, 28); this.m_cbAccount.TabIndex = 0; // // m_lblAccount // - this.m_lblAccount.Location = new System.Drawing.Point(18, 36); + this.m_lblAccount.Location = new System.Drawing.Point(27, 55); + this.m_lblAccount.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.m_lblAccount.Name = "m_lblAccount"; - this.m_lblAccount.Size = new System.Drawing.Size(104, 13); + this.m_lblAccount.Size = new System.Drawing.Size(156, 20); this.m_lblAccount.TabIndex = 5; this.m_lblAccount.Text = "Lbl_AuthPwEntry"; this.m_lblAccount.TextAlign = System.Drawing.ContentAlignment.TopRight; @@ -647,9 +563,11 @@ private void InitializeComponent() this.m_grpDriveOptions.Controls.Add(this.m_lblHintFolder); this.m_grpDriveOptions.Controls.Add(this.m_txtFolder); this.m_grpDriveOptions.Controls.Add(this.m_lblFolder); - this.m_grpDriveOptions.Location = new System.Drawing.Point(6, 93); + this.m_grpDriveOptions.Location = new System.Drawing.Point(9, 142); + this.m_grpDriveOptions.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_grpDriveOptions.Name = "m_grpDriveOptions"; - this.m_grpDriveOptions.Size = new System.Drawing.Size(540, 83); + this.m_grpDriveOptions.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.m_grpDriveOptions.Size = new System.Drawing.Size(810, 128); this.m_grpDriveOptions.TabIndex = 1; this.m_grpDriveOptions.TabStop = false; this.m_grpDriveOptions.Text = "Group_DriveOptions"; @@ -658,24 +576,27 @@ private void InitializeComponent() // this.m_lblHintFolder.AutoSize = true; this.m_lblHintFolder.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.m_lblHintFolder.Location = new System.Drawing.Point(128, 19); + this.m_lblHintFolder.Location = new System.Drawing.Point(192, 29); + this.m_lblHintFolder.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.m_lblHintFolder.Name = "m_lblHintFolder"; - this.m_lblHintFolder.Size = new System.Drawing.Size(140, 13); + this.m_lblHintFolder.Size = new System.Drawing.Size(187, 17); this.m_lblHintFolder.TabIndex = 30; this.m_lblHintFolder.Text = "Lbl_DefaultTargetFolderHint"; // // m_txtFolder // - this.m_txtFolder.Location = new System.Drawing.Point(131, 35); + this.m_txtFolder.Location = new System.Drawing.Point(197, 54); + this.m_txtFolder.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_txtFolder.Name = "m_txtFolder"; - this.m_txtFolder.Size = new System.Drawing.Size(289, 20); + this.m_txtFolder.Size = new System.Drawing.Size(432, 26); this.m_txtFolder.TabIndex = 0; // // m_lblFolder // - this.m_lblFolder.Location = new System.Drawing.Point(18, 38); + this.m_lblFolder.Location = new System.Drawing.Point(27, 59); + this.m_lblFolder.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.m_lblFolder.Name = "m_lblFolder"; - this.m_lblFolder.Size = new System.Drawing.Size(104, 13); + this.m_lblFolder.Size = new System.Drawing.Size(156, 20); this.m_lblFolder.TabIndex = 22; this.m_lblFolder.Text = "Lbl_TargetFolder"; this.m_lblFolder.TextAlign = System.Drawing.ContentAlignment.TopRight; @@ -685,23 +606,25 @@ private void InitializeComponent() this.m_tabMain.Controls.Add(this.m_tabGSignIn); this.m_tabMain.Controls.Add(this.m_tabOptions); this.m_tabMain.ImageList = this.m_imgList; - this.m_tabMain.Location = new System.Drawing.Point(12, 66); + this.m_tabMain.Location = new System.Drawing.Point(18, 101); + this.m_tabMain.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.m_tabMain.Name = "m_tabMain"; this.m_tabMain.SelectedIndex = 0; - this.m_tabMain.Size = new System.Drawing.Size(560, 450); + this.m_tabMain.Size = new System.Drawing.Size(840, 692); this.m_tabMain.TabIndex = 0; // // ConfigurationForm // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(580, 557); + this.ClientSize = new System.Drawing.Size(870, 854); this.Controls.Add(this.m_btnCancel); this.Controls.Add(this.m_btnOK); this.Controls.Add(this.m_btnAbout); this.Controls.Add(this.m_tabMain); this.Controls.Add(this.m_bannerImage); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D; + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "ConfigurationForm"; @@ -730,9 +653,12 @@ private void InitializeComponent() this.m_grpDriveOptions.PerformLayout(); this.m_tabMain.ResumeLayout(false); this.ResumeLayout(false); - } + private System.Windows.Forms.Label AuthorizeFiles_label; + + private System.Windows.Forms.Button AuthorizeFiles_btn; + #endregion private System.Windows.Forms.PictureBox m_bannerImage; @@ -751,15 +677,8 @@ private void InitializeComponent() private System.Windows.Forms.CheckBox m_chkUploadEnabled; private System.Windows.Forms.CheckBox m_chkSyncEnabled; private System.Windows.Forms.GroupBox m_grpDriveAuthDefaults; - private System.Windows.Forms.CheckBox m_chkDefaultUseLegacyCreds; private System.Windows.Forms.LinkLabel m_lnkGoogle2; private System.Windows.Forms.LinkLabel m_lnkHelp2; - private System.Windows.Forms.CheckBox m_chkDefaultDriveScope; - private System.Windows.Forms.Label m_lblDefaultClientSecret; - private System.Windows.Forms.Label m_lblDefaultClientId; - private System.Windows.Forms.TextBox m_txtDefaultClientSecret; - private System.Windows.Forms.TextBox m_txtDefaultClientId; - private System.Windows.Forms.CheckBox m_chkDefaultLegacyClientId; private System.Windows.Forms.GroupBox m_grpFolderDefaults; private System.Windows.Forms.Button m_btnGetColors; private System.Windows.Forms.ComboBox m_cbColors; @@ -776,15 +695,8 @@ private void InitializeComponent() private System.Windows.Forms.LinkLabel m_lnkAuthTokenHelp; private System.Windows.Forms.CheckBox m_chkDontSaveAuthToken; private System.Windows.Forms.GroupBox m_grpDriveAuth; - private System.Windows.Forms.CheckBox m_chkUseLegacyCreds; - private System.Windows.Forms.CheckBox m_chkDriveScope; private System.Windows.Forms.LinkLabel m_lnkGoogle; private System.Windows.Forms.LinkLabel m_lnkHelp; - private System.Windows.Forms.Label m_lblClientSecret; - private System.Windows.Forms.CheckBox m_chkLegacyClientId; - private System.Windows.Forms.Label m_lblClientId; - private System.Windows.Forms.TextBox m_txtClientSecret; - private System.Windows.Forms.TextBox m_txtClientId; private System.Windows.Forms.GroupBox m_grpEntry; private System.Windows.Forms.ComboBox m_cbAccount; private System.Windows.Forms.Label m_lblAccount; @@ -793,5 +705,6 @@ private void InitializeComponent() private System.Windows.Forms.TextBox m_txtFolder; private System.Windows.Forms.Label m_lblFolder; private System.Windows.Forms.TabControl m_tabMain; + private System.Windows.Forms.ToolTip AuthorizeFiles_tooltip; } } diff --git a/src/ConfigurationForm.cs b/src/ConfigurationForm.cs index 3276e3f..1f61868 100644 --- a/src/ConfigurationForm.cs +++ b/src/ConfigurationForm.cs @@ -28,7 +28,7 @@ using System.Diagnostics; using System.Drawing; using System.Linq; -using System.Reflection; +using System.Threading.Tasks; using System.Windows.Forms; namespace KPSyncForDrive @@ -47,9 +47,6 @@ public ConfigurationForm(ConfigurationFormData data) { InitializeComponent(); - EnsureCheckEnabledGroupBox(m_chkDefaultUseLegacyCreds, - m_grpDriveAuthDefaults); - EnsureCheckEnabledGroupBox(m_chkUseLegacyCreds, m_grpDriveAuth); Text = GdsDefs.ProductName; DatabaseFilePath = string.Empty; @@ -66,10 +63,6 @@ public ConfigurationForm(ConfigurationFormData data) m_grpEntry, m_grpDriveAuth, m_lblAccount, - m_lblClientId, - m_lblClientSecret, - m_chkDriveScope, - m_chkLegacyClientId, m_grpDriveOptions, m_lblHintFolder, m_lblFolder, @@ -83,17 +76,11 @@ public ConfigurationForm(ConfigurationFormData data) m_grpAutoSync, m_chkSyncOnOpen, m_chkSyncOnSave, - m_lblDefaultClientId, - m_lblDefaultClientSecret, - m_chkDefaultDriveScope, - m_chkDefaultLegacyClientId, m_grpFolderDefaults, m_lblHintDefaultFolder, m_lblDefaultFolderLabel, m_lblDefFolderColor, m_btnGetColors, - m_chkDefaultUseLegacyCreds, - m_chkUseLegacyCreds, m_grpAuthTokenSecurityDefaults, m_chkDontSaveAuthDefault, m_chkWarnAuthToken, @@ -102,12 +89,17 @@ public ConfigurationForm(ConfigurationFormData data) m_chkDontSaveAuthToken, m_lnkAuthTokenHelp, m_chkSyncOnReopen, + AuthorizeFiles_btn, + AuthorizeFiles_label }; foreach (Control c in textCx) { c.Text = Resources.GetString(c.Text); } + m_grpDriveAuth.Text = Strings.AuthorizeFiles_sectionHeader; + AuthorizeFiles_tooltip.SetToolTip(AuthorizeFiles_btn, Strings.AuthorizeFiles_tooltip); + m_data = data; // Wire events and such for the folder color picker. @@ -141,24 +133,6 @@ public ConfigurationForm(ConfigurationFormData data) m_bColorsQueried = false; } - static void EnsureCheckEnabledGroupBox(CheckBox chk, GroupBox grp) - { - grp.Enabled = chk.Checked; - if (chk.Parent == grp) - { - // Move checkbox to the groupbox parent. - grp.Parent.Controls.Add(chk); - - // Translate position relative to parent. - chk.Location = new Point( - chk.Left + grp.Left, - chk.Top + grp.Top); - - // Checkbox covers the groupbox. - chk.BringToFront(); - } - } - // Do most event and binding stitching here because KeePass likes to // dispose forms quickly. Also, the presentation object can change // before the form is shown. @@ -172,55 +146,11 @@ protected override void OnLoad(EventArgs args) m_cbAccount.ValueMember = "Entry"; // Entry sync config controls. - Binding binding; - Debug.Assert(m_txtClientId is TextBox); - binding = new Binding("Text", - bindingSource, - "ClientId"); - m_txtClientId.DataBindings.Add(binding); - binding = new Binding("Enabled", - bindingSource, - "UseLegacyKp3ClientId", true); - binding.Format += HandleBoolNegation; - binding.Parse += HandleBoolNegation; - m_txtClientId.DataBindings.Add(binding); - Debug.Assert(m_txtClientSecret is TextBox); - binding = new Binding("Text", - bindingSource, - "ClientSecret", true); - binding.Format += HandleProtectedStringFormatting; - binding.Parse += HandleProtectedStringParsing; - m_txtClientSecret.DataBindings.Add(binding); - binding = new Binding("Enabled", - bindingSource, - "UseLegacyKp3ClientId", true); - binding.Format += HandleBoolNegation; - binding.Parse += HandleBoolNegation; - m_txtClientSecret.DataBindings.Add(binding); Debug.Assert(m_txtFolder is TextBox); - binding = new Binding("Text", + var binding = new Binding("Text", bindingSource, "ActiveFolder"); m_txtFolder.DataBindings.Add(binding); - Debug.Assert(m_chkDriveScope is CheckBox); - binding = new Binding("Checked", - bindingSource, - "IsLegacyRestrictedDriveScope", true); - binding.Format += HandleBoolNegation; - binding.Parse += HandleBoolNegation; - m_chkDriveScope.DataBindings.Add(binding); - Debug.Assert(m_chkLegacyClientId is CheckBox); - binding = new Binding("Checked", - bindingSource, - "UseLegacyKp3ClientId"); - binding.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged; - m_chkLegacyClientId.DataBindings.Add(binding); - Debug.Assert(m_chkUseLegacyCreds is CheckBox); - binding = new Binding("Checked", - bindingSource, - "UseLegacyCreds"); - binding.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged; - m_chkUseLegacyCreds.DataBindings.Add(binding); Debug.Assert(m_chkDontSaveAuthToken is CheckBox); binding = new Binding("Checked", bindingSource, "DontSaveAuthToken"); @@ -232,43 +162,6 @@ protected override void OnLoad(EventArgs args) binding = new Binding("Text", m_data, "DefaultAppFolder"); m_txtFolderDefault.DataBindings.Add(binding); - Debug.Assert(m_chkDefaultDriveScope is CheckBox); - binding = new Binding("Checked", - m_data, "DefaultIsLegacyRestrictedDriveScope"); - binding.Format += HandleBoolNegation; - binding.Parse += HandleBoolNegation; - m_chkDefaultDriveScope.DataBindings.Add(binding); - Debug.Assert(m_txtDefaultClientId is TextBox); - binding = new Binding("Text", - m_data, "DefaultLegacyClientId"); - m_txtDefaultClientId.DataBindings.Add(binding); - binding = new Binding("Enabled", - m_data, "DefaultUseKpgs3ClientId", true); - binding.Format += HandleBoolNegation; - binding.Parse += HandleBoolNegation; - m_txtDefaultClientId.DataBindings.Add(binding); - Debug.Assert(m_txtDefaultClientSecret is TextBox); - binding = new Binding("Text", m_data, - "DefaultLegacyClientSecret", true); - binding.Format += HandleProtectedStringFormatting; - binding.Parse += HandleProtectedStringParsing; - m_txtDefaultClientSecret.DataBindings.Add(binding); - binding = new Binding("Enabled", - m_data, "DefaultUseKpgs3ClientId", true); - binding.Format += HandleBoolNegation; - binding.Parse += HandleBoolNegation; - m_txtDefaultClientSecret.DataBindings.Add(binding); - Debug.Assert(m_chkDefaultLegacyClientId is CheckBox); - binding = new Binding("Checked", - m_data, "DefaultUseKpgs3ClientId"); - binding.DataSourceUpdateMode = - DataSourceUpdateMode.OnPropertyChanged; - m_chkDefaultLegacyClientId.DataBindings.Add(binding); - binding = new Binding("Checked", - m_data, "DefaultUseLegacyCredentials"); - binding.DataSourceUpdateMode = - DataSourceUpdateMode.OnPropertyChanged; - m_chkDefaultUseLegacyCreds.DataBindings.Add(binding); // Enabled command controls. Debug.Assert(m_chkSyncEnabled is CheckBox); @@ -428,7 +321,7 @@ private void HandleCommandDisabled(object sender, EventArgs e) { CheckBox cb = sender as CheckBox; Debug.Assert(cb != null, "invalid sender"); - if (cb != null && !cb.Checked) + if (!cb.Checked) { cb.Checked = !m_chkDownloadEnabled.Checked && !m_chkUploadEnabled.Checked && @@ -529,8 +422,6 @@ private async void HandleColorsComboLazyLoad(object sender, catch (Exception e) { Debug.Fail(e.ToString()); - m_cbColors.Items.AddRange( - new object[] { new GoogleColor(Color.DimGray) }); } finally { @@ -612,30 +503,21 @@ private void HandleOkClicked(object sender, EventArgs e) bool EntryClientIdStateIsValid() { - // Unless legacy checked, client & secret must have something. - return m_chkLegacyClientId.Checked || - !string.IsNullOrEmpty(m_txtClientId.Text.Trim()) && - !string.IsNullOrEmpty(m_txtClientSecret.Text.Trim()); + // Deprecated, always returns valid because the underlying item no longer exists + return true; } bool DefaultClientIdStateIsValid() { - // Unless legacy checked, client & secret must have something. - return m_chkDefaultLegacyClientId.Checked || - !string.IsNullOrEmpty(m_txtDefaultClientId.Text.Trim()) && - !string.IsNullOrEmpty(m_txtDefaultClientSecret.Text.Trim()); + // Deprecated, always returns valid because the underlying item no longer exists + return true; } public string DatabaseFilePath { get; set; } - void m_chkDefaultUseLegacyCreds_CheckedChanged(object sender, EventArgs e) - { - m_grpDriveAuthDefaults.Enabled = m_chkDefaultUseLegacyCreds.Checked; - } - - private void m_chkUseLegacyCreds_CheckedChanged(object sender, EventArgs e) + private async void HandleAuthorizeFilesAction(object sender, EventArgs e) { - m_grpDriveAuth.Enabled = m_chkUseLegacyCreds.Checked; + await m_data.PickFile(); } } } diff --git a/src/ConfigurationForm.resx b/src/ConfigurationForm.resx index dd217fe..87887bf 100644 --- a/src/ConfigurationForm.resx +++ b/src/ConfigurationForm.resx @@ -118,9 +118,12 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - 138, 17 + 17, 55 - 244, 17 + 17, 93 + + + 17, 17 \ No newline at end of file diff --git a/src/ConfigurationFormData.cs b/src/ConfigurationFormData.cs index 5a49a49..2e0016d 100644 --- a/src/ConfigurationFormData.cs +++ b/src/ConfigurationFormData.cs @@ -20,9 +20,7 @@ * along with this program. If not, see . **/ -using Google.Apis.Drive.v3; using KeePassLib; -using KeePassLib.Security; using System; using System.Collections.Generic; using System.ComponentModel; @@ -30,6 +28,8 @@ using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; +using FilePicker; +using Microsoft.CodeAnalysis; namespace KPSyncForDrive { @@ -40,13 +40,16 @@ class ConfigurationFormData : IDisposable, INotifyPropertyChanged public delegate Task> ColorProvider( EntryConfiguration ec, DatabaseContext dbCtx); + public delegate Task> FilePickerDelegate(EntryConfiguration ec); + IEnumerable m_colors; readonly ColorProvider m_colorProvider; + readonly FilePickerDelegate _mPickerDelegate; readonly PwDatabase m_db; PluginConfig m_config; public ConfigurationFormData(IList entries, - ColorProvider colorProvider, PwDatabase db) + ColorProvider colorProvider, FilePickerDelegate pickerDelegate, PwDatabase db) { Entries = entries; EntryBindingSource = new BindingSource @@ -56,11 +59,8 @@ public ConfigurationFormData(IList entries, m_colors = null; m_colorProvider = colorProvider; + _mPickerDelegate = pickerDelegate; m_db = db; - DefaultUseKpgs3ClientId = - SyncConfiguration.IsEmpty( - PluginConfig.Default.PersonalClientId, - PluginConfig.Default.PersonalClientSecret); m_config = PluginConfig.GetCopyOfDefault(); } @@ -212,77 +212,6 @@ public GoogleColor DefaultAppFolderColor } } - public bool DefaultIsLegacyRestrictedDriveScope - { - get - { - return m_config.LegacyDriveScope == - DriveService.Scope.Drive; - } - set - { - if (DefaultIsLegacyRestrictedDriveScope != value) - { - m_config.LegacyDriveScope = value ? - DriveService.Scope.Drive : DriveService.Scope.DriveFile; - RaisePropertyChanged("DefaultIsLegacyRestrictedDriveScope"); - } - } - } - - public string DefaultLegacyClientId - { - get - { - return DefaultUseKpgs3ClientId ? - string.Empty : m_config.PersonalClientId; - } - set - { - if (DefaultLegacyClientId != value) - { - m_config.PersonalClientId = value; - RaisePropertyChanged("DefaultLegacyClientId"); - } - } - } - - public ProtectedString DefaultLegacyClientSecret - { - get - { - return DefaultUseKpgs3ClientId ? - GdsDefs.PsEmptyEx : m_config.PersonalClientSecret; - } - set - { - if (!DefaultLegacyClientSecret.OrdinalEquals(value, false)) - { - m_config.PersonalClientSecret = value == null ? - GdsDefs.PsEmptyEx : value; - RaisePropertyChanged("DefaultLegacyClientSecret"); - } - } - } - - public bool DefaultUseKpgs3ClientId { get; set; } - - public bool DefaultUseLegacyCredentials - { - get - { - return m_config.UseLegacyAppCredentials; - } - set - { - if (m_config.UseLegacyAppCredentials != value) - { - m_config.UseLegacyAppCredentials = value; - RaisePropertyChanged("DefaultUseLegacyCredentials"); - } - } - } - public bool DefaultDontSaveAuthToken { get @@ -355,5 +284,10 @@ void RaisePropertyChanged(string propName) PropertyChanged(this, new PropertyChangedEventArgs(propName)); } } + + public async Task PickFile() + { + await _mPickerDelegate(EntryBindingSource.Current as EntryConfiguration); + } } } diff --git a/src/DatabaseContext.cs b/src/DatabaseContext.cs index c7e254f..2745810 100644 --- a/src/DatabaseContext.cs +++ b/src/DatabaseContext.cs @@ -27,7 +27,7 @@ namespace KPSyncForDrive { - class DatabaseContext + public class DatabaseContext { readonly PwDatabase m_db; readonly Guid m_uuid; diff --git a/src/FilePickerForm.cs b/src/FilePickerForm.cs new file mode 100644 index 0000000..24aeead --- /dev/null +++ b/src/FilePickerForm.cs @@ -0,0 +1,79 @@ +using System; +using System.Drawing; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using CompileTimeConfigPublicMembers; +using FilePicker; +using KeePass; +using KeePass.Plugins; +using Microsoft.CodeAnalysis; +using Serilog; + +namespace KPSyncForDrive +{ + public class FilePickerForm + { + private readonly IPluginHost _mHost; + private readonly IFilePicker _filePicker; + private readonly ILogger _logger; + private readonly IDatabaseContextAccessor _databaseContextAccessor; + private readonly ICompileTimeConfigAccessor _compileTimeConfigAccessor; + + public FilePickerForm(IPluginHost host, + IFilePicker filePicker, + ILogger logger, + IDatabaseContextAccessor databaseContextAccessor, + ICompileTimeConfigAccessor compileTimeConfigAccessor) + { + _filePicker = filePicker; + _logger = logger; + _databaseContextAccessor = databaseContextAccessor; + _compileTimeConfigAccessor = compileTimeConfigAccessor; + _mHost = host; + } + + public async Task> SelectFile(string accessToken, SyncConfiguration syncConfig, CancellationToken cancellationToken) + { + using (CancellationTokenSource cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)) + { + cts.CancelAfter(TimeSpan.FromMinutes(5)); + return await ShowFilePickForm(accessToken, syncConfig, cts); + } + } + + private async Task> ShowFilePickForm(string accessToken, + SyncConfiguration syncConfig, + CancellationTokenSource cts) + { + using (AuthWaitOrCancel form = new AuthWaitOrCancel(_mHost, _databaseContextAccessor.GetDatabaseContext(), syncConfig as EntryConfiguration)) + { + form.StartPosition = FormStartPosition.CenterParent; + FilePick res; + var dialogTask = form.ShowDialogAsync(cts); + try + { + res = await _filePicker.SelectFile(new FilePickerOptions + { + AccessToken = accessToken, + AppId = _compileTimeConfigAccessor.GetConfig().GoogleDrivePickerAppId, + GDrivePickerApiKey = _compileTimeConfigAccessor.GetConfig().DriveFilePickerPublicApiKey + }, cts.Token); + _mHost.MainWindow.BeginInvoke(new MethodInvoker(_mHost.MainWindow.Activate)); + } + catch(FilePickerException ex){ + _logger.Error(ex, "An error occured during file picker form, returning without authorizing file"); + return null; + } + finally + { + form.Close(); + } + + await dialogTask; + return res; + } + } + } +} diff --git a/src/GdsDefs.Data.tt b/src/GdsDefs.Data.tt deleted file mode 100644 index 42e2255..0000000 --- a/src/GdsDefs.Data.tt +++ /dev/null @@ -1,57 +0,0 @@ -<#@ template hostspecific="true" language="C#" #> -<#@ parameter type="System.String" name="ClientIdSrcFolder" #> -<#@ output extension=".cs" encoding="utf-8" #> -<#@ assembly name="System.dll" #> -<#@ assembly name="$(GenClientIdFolder)GenClientId.exe" #> -<#@ import namespace="GenClientId" #> -<# var clientIdSrc = this.Host.ResolveParameterValue("-", "-", "ClientIdSrcFolder"); #> -<# clientIdSrc += "GdsDefs.OAuthCreds.txt"; #> -<# - Generator gen = new Generator() - { - SourceFilePath = this.Host.ResolvePath(clientIdSrc) - }; - gen.Run(); -#> -// -// Design-time generated file. Do not modify or check into source control. -// <#= DateTime.Now #> -// -namespace KPSyncForDrive -{ - static partial class GdsDefs - { - static readonly byte[] s_legacyClientIdBytes = new byte[] - { -<#= gen.LegacyIdCsharpConstant #> - }; - static readonly byte[] s_legacyClientIdPad = new byte[] - { -<#= gen.LegacyIdPadCsharpConstant #> - }; - static readonly byte[] s_legacyClientSecretBytes = new byte[] - { -<#= gen.LegacySecretCsharpConstant #> - }; - static readonly byte[] s_legacyClientSecretPad = new byte[] - { -<#= gen.LegacySecretPadCsharpConstant #> - }; - static readonly byte[] s_clientIdBytes = new byte[] - { -<#= gen.ClientIdCsharpConstant #> - }; - static readonly byte[] s_clientIdPad = new byte[] - { -<#= gen.ClientIdPadCsharpConstant #> - }; - static readonly byte[] s_clientSecretBytes = new byte[] - { -<#= gen.ClientSecretCsharpConstant #> - }; - static readonly byte[] s_clientSecretPad = new byte[] - { -<#= gen.ClientSecretPadCsharpConstant #> - }; - } -} \ No newline at end of file diff --git a/src/GdsDefs.OAuthCreds.txt b/src/GdsDefs.OAuthCreds.txt deleted file mode 100644 index ba924ae..0000000 --- a/src/GdsDefs.OAuthCreds.txt +++ /dev/null @@ -1,4 +0,0 @@ -replace the text on this line with the KPGS 3.0 (legacy) built-in ClientId -replace the text on this line with the KPGS 3.0 (legacy) ClientId secret -replace the text on this line with the current built-in ClientId -replace the text on this line with the current ClientId secret \ No newline at end of file diff --git a/src/GdsDefs.cs b/src/GdsDefs.cs index cdf4205..6d2aba4 100644 --- a/src/GdsDefs.cs +++ b/src/GdsDefs.cs @@ -21,7 +21,6 @@ **/ using KeePassLib.Security; -using System; using System.Reflection; namespace KPSyncForDrive @@ -31,28 +30,6 @@ static partial class GdsDefs static string s_productName; static string s_productVersion; static ProtectedString s_emptyEx; - static ProtectedString s_legacyClientId; - static ProtectedString s_legacyClientSecret; - static ProtectedString s_currentClientId; - static ProtectedString s_currentClientSecret; - - static ProtectedString GetData(byte[] data, byte[] pad) - { - XorredBuffer buf = null; - try - { - buf = new XorredBuffer(data, pad); - return new ProtectedString(true, buf); - } - finally - { - // $$REVIEW - // XorredBuffer isn't IDisposable until sometime after KeePass - // v2.35, so fool the compiler and dispose if necessary. - object unknown = buf; - using (IDisposable disposable = unknown as IDisposable) { } - } - } public static string ProductName { @@ -71,14 +48,6 @@ public static string ProductName } } - public static string ProductAttributedTitle - { - get - { - return "KPSync for Google Drive™"; - } - } - public static string Version { get @@ -111,71 +80,6 @@ public static ProtectedString PsEmptyEx } } - public static string UpdateUrl - { - get - { - return string.Format(UrlUpdateFormat, GitHubProjectName); - } - } - - public static ProtectedString ClientSecret - { - get - { - if (s_currentClientSecret == null) - { - s_currentClientSecret = GetData( - s_clientSecretBytes, - s_clientSecretPad); - } - return s_currentClientSecret; - } - } - - public static ProtectedString ClientId - { - get - { - if (s_currentClientId == null) - { - s_currentClientId = GetData( - s_clientIdBytes, - s_clientIdPad); - } - return s_currentClientId; - } - } - - public static ProtectedString LegacyClientSecret - { - get - { - if (s_legacyClientSecret == null) - { - s_legacyClientSecret = GetData( - s_legacyClientSecretBytes, - s_legacyClientSecretPad); - } - return s_legacyClientSecret; - } - } - - public static ProtectedString LegacyClientId - { - get - { - if (s_legacyClientId == null) - { - s_legacyClientId = GetData( - s_legacyClientIdBytes, - s_legacyClientIdPad); - } - return s_legacyClientId; - } - } - - public const string GitHubProjectName = "google-drive-sync"; public const string ConfigUUID = "GoogleSync.AccountUUID"; public const string ConfigTrue = "TRUE"; @@ -185,11 +89,9 @@ public static ProtectedString LegacyClientId public const string UrlDomainRoot = "kpsync.org"; public const string UrlDomain = "www." + UrlDomainRoot; public const string UrlHome = "https://" + UrlDomain; - public const string UrlLegacyHome = "https://sourceforge.net/p/kp-googlesync"; public const string UrlHelp = UrlHome; public const string UrlGoogleDev = "https://console.developers.google.com/start"; public const string UrlGoogleDrive = "https://drive.google.com"; - public const string UrlUpdateFormat = "https://raw.githubusercontent.com/walterpg/"+ GitHubProjectName + "/master/kpsync_final.txt"; public const string UrlSignInHelp = "https://developers.google.com/identity/sign-in/web/troubleshooting"; public const string UrlSharedFileHelp = UrlHome + "/notices/sharedsec"; public const string UrlPersonalAppCreds = UrlHome + "/usage/oauth"; @@ -197,8 +99,6 @@ public static ProtectedString LegacyClientId public const string UrlUpgradeV1 = UrlHome + "/install/upgrade1"; public const string UrlPrivacy = UrlHome + "/privacy"; public const string GsyncBackupExt = ".gsyncbak"; - public const string AppDefaultFolderName = "KeePass Sync"; - public const string AppFolderColor = "#4986e7"; // "Rainy Sky" public const string MimeTypeFolder = "application/vnd.google-apps.folder"; public const string MimeTypeShortcut = "application/vnd.google-apps.shortcut"; public const int DefaultDotNetFileBufferSize = 4096; diff --git a/src/GoogleDriveSyncExt.cs b/src/GoogleDriveSyncExt.cs index 07183a5..606c145 100644 --- a/src/GoogleDriveSyncExt.cs +++ b/src/GoogleDriveSyncExt.cs @@ -33,6 +33,7 @@ using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; +using FilePicker; using Google.Apis.Auth.OAuth2; using Google.Apis.Auth.OAuth2.Flows; using Google.Apis.Auth.OAuth2.Requests; @@ -50,12 +51,15 @@ using KeePass.Util; using KeePassLib; using KeePassLib.Cryptography; -using KeePassLib.Delegates; using KeePassLib.Interfaces; using KeePassLib.Security; using KeePassLib.Serialization; +using CompileTimeConfigPublicMembers; using File = System.IO.File; using GDriveFile = Google.Apis.Drive.v3.Data.File; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.CodeAnalysis; +using EventArgs = System.EventArgs; namespace KPSyncForDrive { @@ -85,6 +89,7 @@ public sealed class KPSyncForDriveExt : Plugin { private IPluginHost m_host = null; + private IServiceProvider _serviceProvider; private ToolStripSeparator m_tsSeparator = null; private ToolStripMenuItem m_tsmiPopup = null; private ToolStripMenuItem m_tsmiSync = null; @@ -106,7 +111,7 @@ public override string UpdateUrl { get { - return GdsDefs.UpdateUrl; + return _serviceProvider.GetRequiredService>().GetConfig().UpdateUrl; } } @@ -129,9 +134,22 @@ public override bool Initialize(IPluginHost host) } Log.Configure(); - - UpdateCheckEx.SetFileSigKey(UpdateUrl, Images.PubKey); - + var serviceCollection = new ServiceCollection(); + serviceCollection + .AddSingleton() + .AddSingleton(host) + .AddSingleton(Log.Default) + .AddSingleton, OptionsAccessor>() + .AddTransient() + .AddSingleton(); + + _serviceProvider = serviceCollection.BuildServiceProvider(); + + + UpdateCheckEx.SetFileSigKey( + UpdateUrl, + _serviceProvider.GetRequiredService>() + .GetConfig().UpdateUrlPubKey); m_host = host; PluginConfig appDefaults = PluginConfig.InitDefault(host); @@ -314,11 +332,11 @@ void OnFileSaving(object sender, FileSavingEventArgs e) { return; } - PwDatabase db = e.Database; - FileEventFlags flags = db.GetClosingEvent(bErase: true); + _serviceProvider.GetRequiredService().DatabaseContext = new DatabaseContext(e.Database); + FileEventFlags flags = e.Database.GetClosingEvent(bErase: true); if (PluginConfig.Default.IsAutoSync(AutoSyncMode.SAVE)) { - db.SetDeferrredAutoSync(flags); + e.Database.SetDeferrredAutoSync(flags); } } @@ -333,10 +351,10 @@ private async void OnFileSaved(object sender, FileSavedEventArgs e) { return; } - PwDatabase db = e.Database; - DatabaseContext dbCtx = new DatabaseContext(db); - FileEventFlags flags = db.GetDeferredAutoSync(bErase: !e.Success); - if (e.Success && db.IsOpen && + DatabaseContext dbCtx = new DatabaseContext(e.Database); + _serviceProvider.GetRequiredService().DatabaseContext = dbCtx; + FileEventFlags flags = e.Database.GetDeferredAutoSync(bErase: !e.Success); + if (e.Success && e.Database.IsOpen && CanSyncOnOpenOrSaveCmd(AutoSyncMode.SAVE, dbCtx)) { if (flags == FileEventFlags.None) @@ -347,7 +365,7 @@ await ConfigAndSyncWithGoogle(SyncCommands.SYNC, dbCtx, else { Log.Info("Marking database {0} for deferred Auto Sync " + - "(reason {1}).", db.GetDisplayNameAndPath(), + "(reason {1}).", e.Database.GetDisplayNameAndPath(), (int)flags); } } @@ -367,15 +385,15 @@ private async void OnFileOpened(object sender, FileOpenedEventArgs e) { return; } - PwDatabase db = e.Database; - DatabaseContext dbCtx = new DatabaseContext(db); + DatabaseContext dbCtx = new DatabaseContext(e.Database); + _serviceProvider.GetRequiredService().DatabaseContext = dbCtx; // Clear stale flags if any. - db.SetClosingEvent(FileEventFlags.None); - FileEventFlags f = db.GetDeferredAutoSync(bErase: true); + e.Database.SetClosingEvent(FileEventFlags.None); + FileEventFlags f = e.Database.GetDeferredAutoSync(bErase: true); if (CanSyncOnOpenOrSaveCmd(AutoSyncMode.OPEN, dbCtx)) { Log.Info("Auto Sync engaged for opening {0}.", - db.GetDisplayNameAndPath()); + e.Database.GetDisplayNameAndPath()); await ConfigAndSyncWithGoogle(SyncCommands.SYNC, dbCtx, autoSync: true); } @@ -383,7 +401,7 @@ await ConfigAndSyncWithGoogle(SyncCommands.SYNC, dbCtx, CanSyncOnOpenOrSaveCmd(AutoSyncMode.SAVE, dbCtx)) { Log.Info("Database {0} opened and flagged for deferred " + - "Auto Sync.", db.GetDisplayNameAndPath()); + "Auto Sync.", e.Database.GetDisplayNameAndPath()); if (!PluginConfig.Default.AutoResumeSaveSync) { string reason = (f & FileEventFlags.Exiting) @@ -392,7 +410,7 @@ await ConfigAndSyncWithGoogle(SyncCommands.SYNC, dbCtx, Resources.GetString("OpName_KpAutoLock"); DialogResult dr = MessageBox.Show(m_host.MainWindow, Resources.GetFormat("Msg_DeferredAutoSyncFmt", - db.GetDisplayNameAndPath(), reason), + e.Database.GetDisplayNameAndPath(), reason), GdsDefs.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (dr != DialogResult.Yes) @@ -414,8 +432,8 @@ void OnFileClosingBeforeSave(object sender, FileClosingEventArgs e) { return; } - PwDatabase db = e.Database; - db.SetClosingEvent(e.Flags); + _serviceProvider.GetRequiredService().DatabaseContext = new DatabaseContext(e.Database); + e.Database.SetClosingEvent(e.Flags); } void OnFileClosingAfterSave(object sender, FileClosingEventArgs e) @@ -424,8 +442,8 @@ void OnFileClosingAfterSave(object sender, FileClosingEventArgs e) { return; } - PwDatabase db = e.Database; - db.SetClosingEvent(FileEventFlags.None); + _serviceProvider.GetRequiredService().DatabaseContext = new DatabaseContext(e.Database); + e.Database.SetClosingEvent(FileEventFlags.None); } /// @@ -434,8 +452,7 @@ void OnFileClosingAfterSave(object sender, FileClosingEventArgs e) private async void OnSyncWithGoogle(object sender, EventArgs e) { string status; - PwDatabase db = m_host.Database; - if (!db.IsOpen) + if (!m_host.Database.IsOpen) { status = Resources.GetString("Msg_FirstOpenDb"); m_host.ShowDlgMessage(status); @@ -444,7 +461,9 @@ private async void OnSyncWithGoogle(object sender, EventArgs e) ToolStripItem item = (ToolStripItem)sender; SyncCommands syncCommand = (SyncCommands)item.Tag; - DatabaseContext dbCtx = new DatabaseContext(db); + DatabaseContext dbCtx = new DatabaseContext(m_host.Database); + _serviceProvider.GetRequiredService().DatabaseContext = dbCtx; + // If config not loaded, sync op will prompt for // config asynchronously. @@ -467,6 +486,8 @@ private void OnConfigure(object sender, EventArgs e) } else { + _serviceProvider.GetRequiredService().DatabaseContext = new DatabaseContext(db); + EntryConfiguration config = AskForConfiguration(db); if (config != null) @@ -578,7 +599,7 @@ internal async Task ConfigAndUseDriveService( ProtectedString RefreshToken = config.RefreshToken; // Invoke service user. - status = await UseDriveService(config, dbCtx, use); + status = await UseDriveService(config, use); // Update the configuration if necessary. if (status != "ERROR" && @@ -592,19 +613,6 @@ internal async Task ConfigAndUseDriveService( // database entry. string status2 = Resources.GetString("Msg_SaveUserAuth"); m_host.ShowStatusMessage(status2); - - - // Traditionally, the plugin's indicator for "use default - // clientId" is empty strings for clientId & secret. Maintain - // that compatibility point. - if (config.UseLegacyCreds && - GdsDefs.LegacyClientId.ReadString() == config.ClientId && - GdsDefs.LegacyClientSecret - .OrdinalEquals(config.ClientSecret, true)) - { - config.ClientId = string.Empty; - config.ClientSecret = null; - } } config.CommitChangesIfAny(); @@ -613,8 +621,7 @@ internal async Task ConfigAndUseDriveService( return status; } - internal async Task UseDriveService(SyncConfiguration authData, - DatabaseContext dbCtx, + private async Task UseDriveService(SyncConfiguration authData, Func> use) { string status; @@ -623,12 +630,12 @@ internal async Task UseDriveService(SyncConfiguration authData, // Create the drive service and call the caller. DriveService service = new DriveService( new BaseClientService.Initializer() - { - HttpClientInitializer - = await GetAuthorization(m_host, dbCtx, authData), - ApplicationName = GdsDefs.ProductName, - HttpClientFactory = new ProxyHttpClientFactory() - }); + { + HttpClientInitializer + = await GetAuthorization(authData), + ApplicationName = GdsDefs.ProductName, + HttpClientFactory = new ProxyHttpClientFactory() + }); status = await use(service, authData); } catch (TokenResponseException ex) @@ -709,8 +716,8 @@ private async Task ConfigAndSyncUnsafe(SyncCommands sync, status = null; List folders = await GetFolders(service, config.ActiveFolder); - GDriveFile file = await GetFile(service, folders, fileName, - config, autoSync); + var file = await GetFile(service, folders, fileName, config, autoSync); + if (file == null) { if (sync == SyncCommands.DOWNLOAD) @@ -764,8 +771,7 @@ private async Task ConfigAndSyncUnsafe(SyncCommands sync, } else { - string syncStatus = SyncFromThenDeleteFile( - dbCtx, fileCopy, autoSync); + string syncStatus = SyncFromThenDeleteFile(fileCopy, autoSync); status = Resources.GetString("Msg_UploadingSync"); m_host.ShowStatusMessage(status); status = String.Format("{0} {1}", syncStatus, @@ -784,7 +790,7 @@ await UpdateFile(service, file, filePath, m_host.MainWindow.UpdateUI(false, null, true, null, true, null, false); if (!string.IsNullOrEmpty(status))// && - //status != "ERROR") + //status != "ERROR") { m_host.ShowStatusMessage(status); } @@ -894,7 +900,7 @@ private async Task> GetFolders(DriveService service, string folderP Folder.RootFolder }; } - + FolderName links = FolderName.GetFolderNameLinks(folderPath); List folders = await links.ResolveLeafFolders(service, status => m_host.ShowStatusMessage(status)); @@ -1009,8 +1015,7 @@ private async Task GetFile(DriveService service, { Log.Info("Drive file '{0}' is 'shared', or assumed to " + "be so.", fileName); - DialogResult dr = SharedFileError.ShowIfNeeded(m_host, - fileName, config, autoSync); + DialogResult dr = SharedFileError.ShowIfNeeded(fileName, config, autoSync); if (dr == DialogResult.OK) { throw new PluginStatusException( @@ -1097,16 +1102,17 @@ FilesResource.GetRequest listReq /// Full path of database file to sync /// with /// Return status of the update - private string SyncFromThenDeleteFile(DatabaseContext dbCtx, - string tempFilePath, bool bIsAutoSync) + private string SyncFromThenDeleteFile(string tempFilePath, bool bIsAutoSync) { + var dbContext = _serviceProvider.GetRequiredService().GetDatabaseContext(); + string status = null; Form fParent = m_host.MainWindow; if (fParent.InvokeRequired) { fParent.Invoke(new MethodInvoker(() => { - status = SyncFromThenDeleteFile(dbCtx, tempFilePath, + status = SyncFromThenDeleteFile(tempFilePath, bIsAutoSync); })); return status; @@ -1122,7 +1128,7 @@ private string SyncFromThenDeleteFile(DatabaseContext dbCtx, bool? success; using (new MruFreezer(m_host)) { - success = ImportUtil.Synchronize(dbCtx.Database, uiOps, + success = ImportUtil.Synchronize(dbContext.Database, uiOps, connection, bForceSave: true, fParent: fParent); } @@ -1141,7 +1147,7 @@ private string SyncFromThenDeleteFile(DatabaseContext dbCtx, }); if ((!success.HasValue || !success.Value) && - bIsAutoSync && !dbCtx.Database.IsOpen) + bIsAutoSync && !dbContext.Database.IsOpen) { throw new PluginException( Resources.GetString("Exc_DbClosedOnAutoSync")); @@ -1372,88 +1378,48 @@ void KpOpenDatabase(string file) /// Get Access Token from Google OAuth 2.0 API /// /// The Sign-in credentials (access token) - private static async Task GetAuthorization(IPluginHost host, - DatabaseContext dbCtx, SyncConfiguration config) + private async Task GetAuthorization(SyncConfiguration config) { - string clientId; - ProtectedString secret; - if (!config.UseLegacyCreds) - { - Log.Debug("Using built-in app creds for authorization."); - clientId = GdsDefs.ClientId.ReadString().Trim(); - secret = GdsDefs.ClientSecret; - } - else if (config.IsEmptyOauthCredentials) - { - Log.Debug("Using GSync 3.0 app creds for authorization."); - clientId = GdsDefs.LegacyClientId.ReadString().Trim(); - secret = GdsDefs.LegacyClientSecret; - } - else - { - Log.Debug("Using personal app creds for authorization."); - clientId = config.ClientId; - secret = config.ClientSecret; - } - - // Scope choice only available with legacy creds. - string scope; - if (config.UseLegacyCreds && - !string.IsNullOrEmpty(config.LegacyDriveScope)) - { - Log.Debug("Requesting scope '{0}' for legacy app creds.", - config.LegacyDriveScope); - scope = config.LegacyDriveScope; - } - else - { - scope = DriveService.Scope.Drive; - } - + var pluginStaticConfiguration = _serviceProvider.GetRequiredService>().GetConfig(); + var dbContext = _serviceProvider.GetRequiredService().GetDatabaseContext(); // Set up the Installed App OAuth 2.0 Flow for Google APIs with a // custom code receiver that uses the system browser to // authenticate the Google user and/or authorize the use of the // API by this program. - GoogleAuthorizationCodeFlow.Initializer init; - init = new GoogleAuthorizationCodeFlow.Initializer + var init = new GoogleAuthorizationCodeFlow.Initializer { DataStore = DataStore.Default, ClientSecrets = new ClientSecrets() { - ClientId = clientId, - ClientSecret = secret.ReadString().Trim() + ClientId = pluginStaticConfiguration.ClientId, + ClientSecret = pluginStaticConfiguration.PublicClientSecret }, - Scopes = new[] { scope }, + Scopes = new[] { DriveService.Scope.DriveFile }, HttpClientFactory = new ProxyHttpClientFactory() }; - GoogleAuthorizationCodeFlow codeFlow - = new GoogleAuthorizationCodeFlow(init); - NativeCodeReceiver codeReceiver - = new NativeCodeReceiver(host, dbCtx, config); - AuthorizationCodeInstalledApp authCode; - authCode = new AuthorizationCodeInstalledApp(codeFlow, codeReceiver); + GoogleAuthorizationCodeFlow codeFlow = new GoogleAuthorizationCodeFlow(init); + NativeCodeReceiver codeReceiver = new NativeCodeReceiver(m_host, dbContext, config); + var authCode = new AuthorizationCodeInstalledApp(codeFlow, codeReceiver); UserCredential credential = null; string status; // Look for the auth token in the session state first, then // check in the config entry. - ProtectedString authToken = GdsDefs.PsEmptyEx; - if (!dbCtx.Database.TryGetSessionToken(out authToken) && - !config.DontSaveAuthToken) + ProtectedString authToken; + if (!dbContext.Database.TryGetSessionToken(out authToken) && !config.DontSaveAuthToken) { Log.Debug("Retrieving refresh token from config."); authToken = config.RefreshToken; } // Warn user that there is a stored auth token if desired. - if (!config.RefreshToken.IsNullOrEmpty() && - PluginConfig.Default.WarnOnSavedAuthToken) + if (!config.RefreshToken.IsNullOrEmpty() && PluginConfig.Default.WarnOnSavedAuthToken) { DialogResult dlgRes = await Task.Run(() => { status = Resources.GetString("Msg_AuthTokenPrompting"); - host.ShowStatusMessage(status); + m_host.ShowStatusMessage(status); return ShowModalDialogAndDestroy(); }); @@ -1468,14 +1434,14 @@ NativeCodeReceiver codeReceiver { // Try using an existing Refresh Token to get a new Access Token status = Resources.GetString("Msg_RefreshTokenAuth"); - host.ShowStatusMessage(status); + m_host.ShowStatusMessage(status); try { - TokenResponse token; - token = await authCode.Flow.RefreshTokenAsync("user", - authToken.ReadString(), - CancellationToken.None); + var token = await authCode.Flow.RefreshTokenAsync( + "user", + authToken.ReadString(), + CancellationToken.None); credential = new UserCredential(codeFlow, "user", token); } catch (TokenResponseException ex) @@ -1489,7 +1455,7 @@ NativeCodeReceiver codeReceiver "attempt reauth ('{0}').", ex.Error.Error); credential = null; config.RefreshToken = null; - dbCtx.Database.RemoveSessionToken(); + dbContext.Database.RemoveSessionToken(); break; default: throw; @@ -1504,7 +1470,7 @@ NativeCodeReceiver codeReceiver // authorize the access to Drive. status = Resources.GetString("Msg_UserAuth"); - host.ShowStatusMessage(status); + m_host.ShowStatusMessage(status); credential = await authCode.AuthorizeAsync("user", CancellationToken.None); @@ -1525,7 +1491,7 @@ NativeCodeReceiver codeReceiver config.RefreshToken = authToken; } - dbCtx.Database.SetSessionToken(authToken); + dbContext.Database.SetSessionToken(authToken); return credential; } @@ -1628,33 +1594,9 @@ internal static DialogResult ShowModalDialogAndDestroy() async Task> GetColors(SyncConfiguration authData, DatabaseContext dbCtx) { - SyncConfiguration originalAuthData = authData; - if (!authData.UseLegacyCreds) - { - authData = new TransientConfiguration(authData) - { - ClientId = GdsDefs.ClientId.ReadString(), - ClientSecret = GdsDefs.ClientSecret - }; - - } - else if (authData.IsEmptyOauthCredentials) - { - authData = new TransientConfiguration(authData) - { - ClientId = GdsDefs.LegacyClientId.ReadString(), - ClientSecret = GdsDefs.LegacyClientSecret - }; - } - else - { - originalAuthData = null; - } - int[] palette = new int[0]; - string status; - status = await UseDriveService(authData, dbCtx, + var status = await UseDriveService(authData, async (service, config) => { AboutResource aboutResource = new AboutResource(service); @@ -1669,15 +1611,6 @@ async Task> GetColors(SyncConfiguration authData, }); m_host.ShowStatusMessage(status); - - if (originalAuthData != null && - (authData.RefreshToken == null || originalAuthData.RefreshToken == null || - !authData.RefreshToken.OrdinalEquals(originalAuthData.RefreshToken, true))) - { - // Copy new refresh token for caller. - originalAuthData.RefreshToken = authData.RefreshToken; - } - return palette.Select(i => Color.FromArgb((int)(0xFF000000|(uint)i))); } @@ -1694,8 +1627,7 @@ private EntryConfiguration AskForConfiguration(PwDatabase db) List acctList = db.GetLegacyAccounts(); // Create a "presentation" object for dialog data binding. - ConfigurationFormData options; - options = new ConfigurationFormData(acctList, GetColors, db); + var options = new ConfigurationFormData(acctList, GetColors, GetFile, db); ConfigurationForm optionsForm = new ConfigurationForm(options) { DatabaseFilePath = db.IOConnectionInfo.Path, @@ -1831,8 +1763,6 @@ DialogResult result { return false; } - - entryConfig.UseLegacyCreds = DialogResult.No == result; if (DialogResult.Yes == result) { entryConfig.RefreshToken = null; @@ -1879,20 +1809,6 @@ private EntryConfiguration GetConfiguration(DatabaseContext dbCtx) if (config != null) { SaveConfiguration(config, dbCtx.Database); - - // Seed the effective credentials. - if (!config.UseLegacyCreds) - { - config.ClientId = GdsDefs.ClientId.ReadString(); - config.ClientSecret = GdsDefs.ClientSecret; - } - else if (config.IsEmptyOauthCredentials) - { - // Use legacy OAuth 2.0 credentials if personal creds - // are missing. - config.ClientId = GdsDefs.LegacyClientId.ReadString(); - config.ClientSecret = GdsDefs.LegacyClientSecret; - } } } return config; @@ -1966,6 +1882,13 @@ private bool SaveConfiguration(EntryConfiguration entryConfig, return true; } + + async Task> GetFile(SyncConfiguration authData) + { + var res = await GetAuthorization(authData); + + return await _serviceProvider.GetRequiredService().SelectFile(res.Token.AccessToken, authData, CancellationToken.None); + } } public class NativeCodeReceiver : ICodeReceiver diff --git a/src/IDatabaseContextAccessor.cs b/src/IDatabaseContextAccessor.cs new file mode 100644 index 0000000..d57b6fc --- /dev/null +++ b/src/IDatabaseContextAccessor.cs @@ -0,0 +1,54 @@ +using System; +using System.Threading; +using Microsoft.CodeAnalysis; + +namespace KPSyncForDrive +{ + public interface IDatabaseContextAccessor + { + Optional DatabaseContext { get; set; } + DatabaseContext GetDatabaseContext(); + } + public class DatabaseContextAccessor : IDatabaseContextAccessor + { + private static readonly AsyncLocal _databaseContextCurrent = new AsyncLocal(); + + public Optional DatabaseContext + { + get + { + return _databaseContextCurrent.Value.Context; + } + set + { + var holder = _databaseContextCurrent.Value; + if (holder != null) + { + // Clear current HttpContext trapped in the AsyncLocals, as its done. + holder.Context = null; + } + + if (value.HasValue) + { + // Use an object indirection to hold the HttpContext in the AsyncLocal, + // so it can be cleared in all ExecutionContexts when its cleared. + _databaseContextCurrent.Value = new DatabaseContextHolder { Context = value }; + } + } + } + + public DatabaseContext GetDatabaseContext() + { + if (DatabaseContext.HasValue) + { + return DatabaseContext.Value; + } + throw new InvalidOperationException("Database context was not initialized"); + } + private sealed class DatabaseContextHolder + { + public Optional Context; + } + + } +} diff --git a/src/Images.Designer.cs b/src/Images.Designer.cs deleted file mode 100644 index f7119bc..0000000 --- a/src/Images.Designer.cs +++ /dev/null @@ -1,264 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace KPSyncForDrive { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Images { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Images() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("KPSyncForDrive.Images", typeof(Images).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap btn_google_signin_dark_pressed_web { - get { - object obj = ResourceManager.GetObject("btn_google_signin_dark_pressed_web", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). - /// - internal static System.Drawing.Icon DriveIcon { - get { - object obj = ResourceManager.GetObject("DriveIcon", resourceCulture); - return ((System.Drawing.Icon)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap gdsync { - get { - object obj = ResourceManager.GetObject("gdsync", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). - /// - internal static System.Drawing.Icon GdsyncIcon { - get { - object obj = ResourceManager.GetObject("GdsyncIcon", resourceCulture); - return ((System.Drawing.Icon)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap keepass_thumbnail { - get { - object obj = ResourceManager.GetObject("keepass_thumbnail", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap outline_security_black_18dp { - get { - object obj = ResourceManager.GetObject("outline_security_black_18dp", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap outline_security_black_36dp { - get { - object obj = ResourceManager.GetObject("outline_security_black_36dp", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap outline_security_black_48dp { - get { - object obj = ResourceManager.GetObject("outline_security_black_48dp", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap outline_settings_black_18dp { - get { - object obj = ResourceManager.GetObject("outline_settings_black_18dp", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap outline_settings_black_36dp { - get { - object obj = ResourceManager.GetObject("outline_settings_black_36dp", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap outline_settings_black_48dp { - get { - object obj = ResourceManager.GetObject("outline_settings_black_48dp", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" ?> - ///<RSAKeyValue> - /// <Modulus>qgygjOOrPVoXdytZARmu2f8vV0omYqeclHBSIpeon7xIsYx8TiCOiecUD3NfnANdaneFOZZ1Att4rOLrDewhJnT6MOI4WBdXzpF36PMtL4ndIIGEYu0zOGO+Qi1sXPZWshrueO2IYIt9NK5RBI8YeejYJDU2BaqBE5ZsXFiDQ6o5fZftC57j1vD88Gg/V50klq00Q0q4vm0939B/HYz45ZzXZvn26pbUDyLH7ZqxacSTfdGlDN7pQ+Q7vaYOqnCtbGD8vfujV/X2LlqCpKc5iPD6Dx3iINOhByfyZ5udDtYaxbZKSumfI2OHBQT+L6Jw2RuMcH40n1aXdJaJ1KLCQMqbmOOEwM1ejbXgWtPBvo5oYjKgUUtKnBOHjZL2d3jKIWy7SSAIWmd0wDpIuA1KSORjNslgEzMRCkz5TAg9makAQ3e764FBJsy9anR [rest of string was truncated]";. - /// - internal static string PubKey { - get { - return ResourceManager.GetString("PubKey", resourceCulture); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap round_cloud_download_black_18dp { - get { - object obj = ResourceManager.GetObject("round_cloud_download_black_18dp", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap round_cloud_upload_black_18dp { - get { - object obj = ResourceManager.GetObject("round_cloud_upload_black_18dp", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap round_help_outline_black_18dp { - get { - object obj = ResourceManager.GetObject("round_help_outline_black_18dp", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap round_help_outline_black_36dp { - get { - object obj = ResourceManager.GetObject("round_help_outline_black_36dp", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap round_help_outline_black_48dp { - get { - object obj = ResourceManager.GetObject("round_help_outline_black_48dp", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap round_settings_black_18dp { - get { - object obj = ResourceManager.GetObject("round_settings_black_18dp", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap round_settings_black_48dp { - get { - object obj = ResourceManager.GetObject("round_settings_black_48dp", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap round_sync_black_18dp { - get { - object obj = ResourceManager.GetObject("round_sync_black_18dp", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - } -} diff --git a/src/Images.resx b/src/Images.resx index fa4adfb..f821b2b 100644 --- a/src/Images.resx +++ b/src/Images.resx @@ -151,9 +151,6 @@ images\outline_settings_black_48dp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - images\pubkey.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 - images\round_cloud_download_black_18dp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a diff --git a/src/Images/PubKey.xml b/src/Images/PubKey.xml deleted file mode 100644 index 67d7d43..0000000 --- a/src/Images/PubKey.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - qgygjOOrPVoXdytZARmu2f8vV0omYqeclHBSIpeon7xIsYx8TiCOiecUD3NfnANdaneFOZZ1Att4rOLrDewhJnT6MOI4WBdXzpF36PMtL4ndIIGEYu0zOGO+Qi1sXPZWshrueO2IYIt9NK5RBI8YeejYJDU2BaqBE5ZsXFiDQ6o5fZftC57j1vD88Gg/V50klq00Q0q4vm0939B/HYz45ZzXZvn26pbUDyLH7ZqxacSTfdGlDN7pQ+Q7vaYOqnCtbGD8vfujV/X2LlqCpKc5iPD6Dx3iINOhByfyZ5udDtYaxbZKSumfI2OHBQT+L6Jw2RuMcH40n1aXdJaJ1KLCQMqbmOOEwM1ejbXgWtPBvo5oYjKgUUtKnBOHjZL2d3jKIWy7SSAIWmd0wDpIuA1KSORjNslgEzMRCkz5TAg9makAQ3e764FBJsy9anR2Yweeux5KuurYfswuBvyIkAP8yf1f/JvMKxJzvpYLcld8+tQYCNDYiDZzUDUtdYJb3r3QYbltwjUVnPdRIhSOunsn89CAs0HLEsRPtUtk1veSPYdyh9pwpERjBun796OcNbjKzbXqq16Bb5M/I2RouaHS6aDHbhMyORA0YUF9qYAQ5PHz0iJuDo/DIqA9qTeBrgPTtAZZBoeQrjo983HafBVDcNTsjkRwGGZGMWSMDwQcLSk= - AQAB - \ No newline at end of file diff --git a/src/KPSyncForDrive.csproj b/src/KPSyncForDrive.csproj index f241197..645e987 100644 --- a/src/KPSyncForDrive.csproj +++ b/src/KPSyncForDrive.csproj @@ -1,104 +1,58 @@  - - - 4.1.0 - - Library - net45 + net48 KeePass Plugin KPSync For Google Drive Safely synchronize KeePass database files with Google Drive. - Copyright © 2020-2021 + Copyright © 2020-2021 en Images\gdsync.ico AnyCPU 5 true - $(MSBuildProjectDirectory)\..\lib\src\GenClientId\bin\$(Configuration)\$(TargetFramework)\ - $(MSBuildProjectDirectory)\ true true KeePass Plugin Satellite Resources 2.35 + DevClientId + DevPublicApiKey + DevAppId + DevClientSecret + https://github.com/YourFork/google-drive-sync/releases/latest/download/kpsync_final.txt - - DEBUG;$(DefineConstants) - - + + + + + + + + + + + + + + - + - - + + ..\lib\bin\KeePass.exe False - - - - - - - true - - - TextTemplatingFileGenerator - GdsDefs.Data.cs - true - true - - - $(ClientIdSrcFolder) - false - true - - - $(GenClientIdFolder) - false - true - - - True - True - GdsDefs.Data.tt - - - - - - - SavedAuthWarning.cs - - - - ConfigurationForm.cs - - - - AuthWaitOrCancel.cs - - - - AppCredsUpgrade.cs - - - True - True - Images.resx - - - - SharedFileError.cs - + @@ -116,31 +70,24 @@ AppCredsUpgrade.cs - Designer - ResXFileCodeGenerator - Images.Designer.cs - KPSyncForDrive + MSBuild:Compile + $(IntermediateOutputPath)/Images.g.cs + CSharp + Images + KPSyncForDrive SharedFileError.cs - - Designer - - Designer + MSBuild:Compile + $(IntermediateOutputPath)/Strings.g.cs + CSharp + KPSyncForDrive + Strings - - - - - - - - - - + $(AssemblyName)-$(Version) diff --git a/src/OptionsAccessor.cs b/src/OptionsAccessor.cs new file mode 100644 index 0000000..c90696c --- /dev/null +++ b/src/OptionsAccessor.cs @@ -0,0 +1,19 @@ +using CompileTimeConfigPublicMembers; + +namespace KPSyncForDrive +{ + [GenerateConfigAccessor(typeof(PluginStaticConfiguration))] + public partial class OptionsAccessor + { + } + + public class PluginStaticConfiguration + { + public string ClientId { get; set; } + public string PublicClientSecret { get; set; } + public string DriveFilePickerPublicApiKey { get; set; } + public string GoogleDrivePickerAppId { get; set; } + public string UpdateUrl { get; set; } + public string UpdateUrlPubKey { get; set; } + } +} diff --git a/src/PluginConfig.cs b/src/PluginConfig.cs index cd90edd..9a00b8a 100644 --- a/src/PluginConfig.cs +++ b/src/PluginConfig.cs @@ -27,7 +27,6 @@ using System.Text; using Google.Apis.Drive.v3; using KeePass.Plugins; -using KeePassLib.Security; using Newtonsoft.Json; namespace KPSyncForDrive @@ -56,31 +55,6 @@ class PluginConfig public const string CurrentVer = "1.1"; const string ConfigPluginKey = "Plugin.KeePassSyncForDrive"; - class ProtectedStringConverter : JsonConverter - { - public override ProtectedString ReadJson(JsonReader reader, - Type objectType, ProtectedString existingValue, - bool hasExistingValue, JsonSerializer serializer) - { - string stringVal = reader.Value as string; - return !string.IsNullOrEmpty(stringVal) ? - new ProtectedString(true, stringVal) : null; - } - - public override void WriteJson(JsonWriter writer, - ProtectedString value, JsonSerializer serializer) - { - if (value == null || value == GdsDefs.PsEmptyEx) - { - writer.WriteNull(); - } - else - { - writer.WriteValue(value.ReadString()); - } - } - } - class ColorConverter : JsonConverter { public override GoogleColor ReadJson(JsonReader reader, @@ -131,10 +105,6 @@ public static PluginConfig Default SyncCommands m_enabledCmds; string m_defaultFolder; GoogleColor m_defaultFolderColor; - string m_defaultDriveScope; - string m_defaultClientId; - ProtectedString m_defaultClientSecret; - bool m_useLegacyCreds; bool m_dontSaveAuthToken; bool m_warnSavedAuthToken; bool m_isDirty; @@ -145,16 +115,12 @@ public static PluginConfig Default { m_autoSync = AutoSyncMode.DISABLED; m_enabledCmds = SyncCommands.All; - m_defaultFolder = null; + m_defaultFolder = ""; m_defaultFolderColor = null; - m_defaultDriveScope = null; - m_defaultClientId = string.Empty; - m_defaultClientSecret = GdsDefs.PsEmptyEx; - m_useLegacyCreds = false; m_dontSaveAuthToken = false; m_warnSavedAuthToken = false; m_isDirty = true; - m_ver = null; + m_ver = ""; m_autoResumeSave = false; } @@ -164,10 +130,6 @@ public static PluginConfig Default m_enabledCmds = c.m_enabledCmds; m_defaultFolder = c.m_defaultFolder; m_defaultFolderColor = c.m_defaultFolderColor; - m_defaultDriveScope = c.m_defaultDriveScope; - m_defaultClientId = c.m_defaultClientId; - m_defaultClientSecret = c.m_defaultClientSecret; - m_useLegacyCreds = c.m_useLegacyCreds; m_dontSaveAuthToken = c.m_dontSaveAuthToken; m_warnSavedAuthToken = c.m_warnSavedAuthToken; m_isDirty = c.m_isDirty; @@ -281,71 +243,6 @@ public GoogleColor FolderColor } } - public string LegacyDriveScope - { - get { return m_defaultDriveScope; } - set - { - if (!string.Equals(m_defaultDriveScope, value, - StringComparison.Ordinal)) - { - m_defaultDriveScope = value; - m_isDirty = true; - } - } - } - - public string PersonalClientId - { - get { return m_defaultClientId; } - set - { - if (!string.Equals(m_defaultClientId, value, - StringComparison.Ordinal)) - { - m_defaultClientId = value; - m_isDirty = true; - } - } - } - - [JsonConverter(typeof(ProtectedStringConverter))] - public ProtectedString PersonalClientSecret - { - get { return m_defaultClientSecret; } - set - { - if (value == null) - { - if (m_defaultClientSecret == null) - { - return; - } - m_defaultClientSecret = null; - m_isDirty = true; - } - else - { - m_isDirty = !value.OrdinalEquals(m_defaultClientSecret, - true); - } - m_defaultClientSecret = value; - } - } - - public bool UseLegacyAppCredentials - { - get { return m_useLegacyCreds; } - set - { - if (m_useLegacyCreds != value) - { - m_isDirty = true; - m_useLegacyCreds = value; - } - } - } - public string ConfigVersion { get @@ -490,9 +387,6 @@ static PluginConfig InitLegacyDefault(IPluginHost host) const string ConfigAutoSyncKey = "GoogleSync.AutoSync"; const string ConfigEnabledCmdsKey = "GoogleSync.EnabledCmds"; const string ConfigDefaultAppFolderKey = "GoogleSync.DefaultAppFolder"; - const string ConfigDriveScopeKey = "GoogleSync.DriveApiScope"; - const string ConfigDefaultClientIdKey = "GoogleSync.DefaultClientId"; - const string ConfigDefaultClientSecretKey = "GoogleSync.DefaultClientSecret"; const string ConfigVersionKey = "GoogleSync.ConfigVersion"; const string Ver0 = "0.0"; // virtual version @@ -551,26 +445,6 @@ static PluginConfig InitLegacyDefault(IPluginHost host) update.Folder = host.GetConfig(ConfigDefaultAppFolderKey, string.Empty); update.FolderColor = null; - - update.LegacyDriveScope - = host.GetConfig(ConfigDriveScopeKey, - DriveService.Scope.Drive); - - // Default is no OAuth 2.0 credentials. - update.PersonalClientId - = host.GetConfig(ConfigDefaultClientIdKey, string.Empty); - string secretVal - = host.GetConfig(ConfigDefaultClientSecretKey, string.Empty); - update.PersonalClientSecret - = string.IsNullOrEmpty(update.PersonalClientId) ? - null : new ProtectedString(true, secretVal); - - // If the user wants to enable legacy creds, there is nothing - // stopping her. This is not a compatibility point. - update.UseLegacyAppCredentials - = host.GetConfig(SyncConfiguration.EntryUseLegacyCredsKey, - false); - return update; } } diff --git a/src/PluginEntryFactory.cs b/src/PluginEntryFactory.cs index c21f25f..8ce36d8 100644 --- a/src/PluginEntryFactory.cs +++ b/src/PluginEntryFactory.cs @@ -37,15 +37,13 @@ internal class PluginEntryFactory : FileFormatProvider public static PluginEntryFactory CreateDefault(string title) { PluginConfig appConfig = PluginConfig.Default; - return Create(title, appConfig.LegacyDriveScope, - appConfig.PersonalClientId, appConfig.PersonalClientSecret, - appConfig.Folder, appConfig.UseLegacyAppCredentials, + return Create(title, + appConfig.Folder, appConfig.DontSaveAuthToken); } - public static PluginEntryFactory Create(string title, - string driveScope, string clientId, ProtectedString clientSecret, - string folder, bool useLegacyCreds, bool dontSaveAuthToken) + private static PluginEntryFactory Create(string title, + string folder, bool dontSaveAuthToken) { PwEntry entry = new PwEntry(true, true); ProtectedStringDictionary strings = entry.Strings; @@ -59,19 +57,9 @@ public static PluginEntryFactory Create(string title, new ProtectedString(false, GdsDefs.AccountSearchString)); StringDictionaryEx data = entry.CustomData; - if (useLegacyCreds) - { - data.Set(SyncConfiguration.EntryDriveScopeKey, driveScope); - data.Set(SyncConfiguration.EntryClientIdKey, clientId); - data.Set(SyncConfiguration.EntryClientSecretKey, - clientSecret == null ? - string.Empty : clientSecret.ReadString()); - } data.Set(SyncConfiguration.EntryActiveAppFolderKey, folder); data.Set(SyncConfiguration.EntryActiveAccountKey, SyncConfiguration.EntryActiveAccountTrueKey); - data.Set(SyncConfiguration.EntryUseLegacyCredsKey, useLegacyCreds ? - GdsDefs.ConfigTrue : GdsDefs.ConfigFalse); data.Set(SyncConfiguration.EntryDontCacheAuthTokenKey, dontSaveAuthToken ? GdsDefs.ConfigTrue : GdsDefs.ConfigFalse); diff --git a/src/SharedFileError.cs b/src/SharedFileError.cs index 22cfa18..d0f042a 100644 --- a/src/SharedFileError.cs +++ b/src/SharedFileError.cs @@ -29,11 +29,9 @@ namespace KPSyncForDrive { public partial class SharedFileError : Form { - internal static DialogResult ShowIfNeeded(IPluginHost host, - string fileName, SyncConfiguration config, bool bIsAutoSync) + internal static DialogResult ShowIfNeeded(string fileName, SyncConfiguration config, bool bIsAutoSync) { - if (config.DontSaveAuthToken || - config.IsUsingPersonalOauthCreds) + if (config.DontSaveAuthToken) { return DialogResult.None; } diff --git a/src/Strings.es.resx b/src/Strings.es.resx index 1ebd7ac..58e3987 100644 --- a/src/Strings.es.resx +++ b/src/Strings.es.resx @@ -597,4 +597,16 @@ Es posible que la base de datos local no esté sincronizada con el archivo de Dr Política de privacidad + + Autorizar + + + Utilice archivos gDrive existentes: + + + Este complemento utiliza el alcance restringido de Google Drive.Files. Como tal, solo puede acceder a archivos no creados por sí mismo si usted le da acceso explícitamente a esos archivos; de lo contrario, el complemento crea archivos duplicados en la ubicación de destino. + + + Autorización de archivos de Google Drive + \ No newline at end of file diff --git a/src/Strings.resx b/src/Strings.resx index 69dc76f..e1817c0 100644 --- a/src/Strings.resx +++ b/src/Strings.resx @@ -604,4 +604,17 @@ The local database could be out of sync with the Drive file. Would you like to Privacy Policy + + Authorize + + + Use existing gDrive files: + + + This plugin uses the restricted Drive.Files google scope. As such, it can only access files not created by itself if you explicitly give it access to those files. +Otherwise the plugin creates duplicate files at the target location + + + Google Drive File Authorization + \ No newline at end of file diff --git a/src/SyncConfiguration.cs b/src/SyncConfiguration.cs index 3024cf1..905bd78 100644 --- a/src/SyncConfiguration.cs +++ b/src/SyncConfiguration.cs @@ -20,7 +20,6 @@ * along with this program. If not, see . **/ -using Google.Apis.Drive.v3; using KeePassLib; using KeePassLib.Collections; using KeePassLib.Security; @@ -53,15 +52,11 @@ public abstract class SyncConfiguration protected const string Ver1_1 = "1.1"; protected const string CurrentVer = Ver1_1; - public const string EntryClientIdKey = "GoogleSync.ClientID"; - public const string EntryClientSecretKey = "GoogleSync.ClientSecret"; public const string EntryRefreshTokenKey = "GoogleSync.RefreshToken"; public const string EntryActiveAccountKey = "GoogleSync.ActiveAccount"; public const string EntryActiveAccountFalseKey = EntryActiveAccountKey + "." + GdsDefs.ConfigFalse; public const string EntryActiveAccountTrueKey = EntryActiveAccountKey + "." + GdsDefs.ConfigTrue; public const string EntryActiveAppFolderKey = "GoogleSync.ActiveAppFolder"; - public const string EntryDriveScopeKey = "GoogleSync.DriveApiScope"; - public const string EntryUseLegacyCredsKey = "GoogleSync.UseLegacyAppCreds"; public const string EntryVersionKey = "GoogleSync.ConfigVersion"; public const string EntryDontCacheAuthTokenKey = "GoogleSync.NoAuthTokens"; @@ -75,155 +70,14 @@ public static bool IsPriorToVer1_0(SyncConfiguration config) return config.Version < Version.Parse(Ver1_0); } - public static SyncConfiguration GetEmpty() - { - return new TransientConfiguration(); - } - - public static bool IsEmpty(string clientId, - ProtectedString clientSecret) - { - return string.IsNullOrEmpty(clientId) || - clientSecret == null || - clientSecret.IsEmpty; - } - - public bool IsEmptyOauthCredentials - { - get - { - return IsEmpty(ClientId, ClientSecret); - } - } - - public bool IsUsingPersonalOauthCreds - { - get - { - return UseLegacyCreds && - ClientId != GdsDefs.LegacyClientId.ReadString(); - } - } - // KeePass string fields. - public abstract string Title { get; } - public abstract string User { get; } - public abstract ProtectedString Password { get; } public abstract string LoginHint { get; } - - // Plugin string fields. - public abstract bool? ActiveAccount { get; set; } - public abstract string ClientId { get; set; } - public abstract ProtectedString ClientSecret { get; set; } public abstract ProtectedString RefreshToken { get; set; } public abstract string ActiveFolder { get; set; } - public abstract string LegacyDriveScope { get; set; } - public abstract bool UseLegacyCreds { get; set; } public abstract bool DontSaveAuthToken { get; set; } public abstract Version Version { get; } } - class TransientConfiguration : SyncConfiguration - { - static ProtectedString NullOrCopy(ProtectedString copyee) - { - if (copyee == null) - { - return null; - } - return new ProtectedString(copyee.IsProtected, copyee.ReadString()); - } - - readonly string m_title; - readonly string m_user; - readonly ProtectedString m_password; - readonly string m_loginHint; - readonly Version m_ver; - - public TransientConfiguration() - { - ActiveAccount = null; - m_user = null; - m_password = null; - m_loginHint = null; - m_title = null; - ClientId = null; - ClientSecret = null; - RefreshToken = null; - ActiveFolder = null; - LegacyDriveScope = null; - m_ver = Version.Parse(CurrentVer); - } - - public TransientConfiguration(SyncConfiguration copyee) - { - ActiveAccount = copyee.ActiveAccount; - m_user = copyee.User; - m_password = NullOrCopy(copyee.Password); - ClientId = copyee.ClientId; - ClientSecret = NullOrCopy(copyee.ClientSecret); - RefreshToken = NullOrCopy(copyee.RefreshToken); - m_loginHint = copyee.LoginHint; - m_title = copyee.Title; - ActiveFolder = copyee.ActiveFolder; - LegacyDriveScope = copyee.LegacyDriveScope; - m_ver = copyee.Version; - } - - public override bool? ActiveAccount { get; set; } - - public override string Title - { - get - { - return m_title; - } - } - - public override string User - { - get - { - return m_user; - } - } - - public override ProtectedString Password - { - get - { - return m_password; - } - } - - public override string LoginHint - { - get - { - return m_loginHint; - } - } - - public override string ClientId { get; set; } - - public override ProtectedString ClientSecret { get; set; } - - public override ProtectedString RefreshToken { get; set; } - - public override string ActiveFolder { get; set; } - - public override bool UseLegacyCreds { get; set; } - - public override string LegacyDriveScope { get; set; } - - public override bool DontSaveAuthToken { get; set; } - - public override Version Version - { - get { return m_ver; } - } - } - /// /// Mirror, and defer incremental modifications to, PwEntry object /// "Strings" properties. This mainly serves as the data model @@ -232,7 +86,6 @@ public override Version Version public class EntryConfiguration : SyncConfiguration { readonly Dictionary m_changes; - string m_title; DateTime m_touched; bool m_credsChanged; @@ -240,11 +93,8 @@ public EntryConfiguration(PwEntry entry) { Entry = entry; m_changes = new Dictionary(5); - m_title = null; m_touched = Entry.LastModificationTime; m_credsChanged = false; - - UseLegacyKp3ClientId = IsEmptyOauthCredentials; ChangesCommitted = false; } @@ -269,44 +119,24 @@ StringDictionaryEx CustomData public PwEntry CommitChangesIfAny() { EnsureSettingsMigration(); - if (UseLegacyKp3ClientId) - { - // Traditionally, the plugin's indicator for "use default - // clientId" is empty strings for clientId & secret. Maintain - // that compatibility point. - ClientId = string.Empty; - ClientSecret = null; - } if (!IsModified) { ChangesCommitted = false; } else { - // Handle client ID changes or legacy creds option toggle. - if (m_changes.Select(kv => kv.Key) - .Any(k => k == EntryClientIdKey || - k == EntryUseLegacyCredsKey)) - { - // Show that credentials were changed - m_credsChanged = true; - } foreach (KeyValuePair kv in m_changes) { switch (kv.Key) { - case EntryUseLegacyCredsKey: case EntryActiveAccountKey: - case EntryClientIdKey: case EntryActiveAppFolderKey: - case EntryDriveScopeKey: case EntryVersionKey: case EntryDontCacheAuthTokenKey: string stringVal = kv.Value as string; CustomData.Set(kv.Key, stringVal == null ? string.Empty : stringVal); break; - case EntryClientSecretKey: case EntryRefreshTokenKey: ProtectedString ps = kv.Value as ProtectedString; CustomData.Set(kv.Key, @@ -346,14 +176,10 @@ public bool IsStaleRefreshToken { get { - return (m_changes.Keys.Any(k => k == EntryClientIdKey || - k == EntryClientSecretKey || - k == EntryUseLegacyCredsKey) && - !RefreshToken.IsNullOrEmpty()) || - (m_changes.Keys.Any(k => - k == EntryRefreshTokenKey) && - RefreshToken.IsNullOrEmpty() && - !Get(EntryRefreshTokenKey).IsNullOrEmpty()); + return (m_changes.Keys.Any(k => + k == EntryRefreshTokenKey) && + RefreshToken.IsNullOrEmpty() && + !Get(EntryRefreshTokenKey).IsNullOrEmpty()); } } @@ -414,7 +240,7 @@ public override string LoginHint } } - public override string User + public string User { get { @@ -422,7 +248,7 @@ public override string User } } - public override ProtectedString Password + public ProtectedString Password { get { @@ -430,24 +256,6 @@ public override ProtectedString Password } } - public override string Title - { - get - { - if (m_title == null) - { - m_title = Strings.ReadSafe(PwDefs.TitleField); - string userName = User; - if (!string.IsNullOrEmpty(userName)) - { - m_title = string.Format("{0} - {1}", - userName, m_title); - } - } - return m_title; - } - } - T GetValue(string key, Func getter) where T : class { object retVal; @@ -563,7 +371,7 @@ ProtectedString Get(string key) return null; } - public override bool? ActiveAccount + public bool? ActiveAccount { get { @@ -595,34 +403,6 @@ public override bool? ActiveAccount } } - public override string ClientId - { - get - { - return GetValue(EntryClientIdKey, ReadSafe); - } - set - { - SetValue(EntryClientIdKey, value); - } - } - - public override ProtectedString ClientSecret - { - get - { - // Use GetSafe so this property can be bound to - // SecureTextBoxEx.TextEx. - return GetValue(EntryClientSecretKey, GetSafe); - } - set - { - SetValue(EntryClientSecretKey, value); - } - } - - public bool UseLegacyKp3ClientId { get; set; } - public override ProtectedString RefreshToken { get @@ -649,47 +429,6 @@ public override string ActiveFolder } } - public override string LegacyDriveScope - { - get - { - return GetValue(EntryDriveScopeKey, ReadSafe); - } - set - { - SetValue(EntryDriveScopeKey, value); - } - } - - public bool IsLegacyRestrictedDriveScope - { - get - { - return string.IsNullOrEmpty(LegacyDriveScope) || - LegacyDriveScope == DriveService.Scope.Drive; - } - set - { - LegacyDriveScope = value ? - DriveService.Scope.Drive : DriveService.Scope.DriveFile; - } - } - - // Custom or KP3 app creds. - public override bool UseLegacyCreds - { - get - { - return GdsDefs.ConfigTrue == - GetValue(EntryUseLegacyCredsKey, ReadSafe); - } - set - { - SetValue(EntryUseLegacyCredsKey, - value ? GdsDefs.ConfigTrue : GdsDefs.ConfigFalse); - } - } - public override bool DontSaveAuthToken { get diff --git a/src/app.config b/src/app.config deleted file mode 100644 index 377c87e..0000000 --- a/src/app.config +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - -