diff --git a/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PasswordControl.xaml b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PasswordControl.xaml
new file mode 100644
index 0000000..0ec65d8
--- /dev/null
+++ b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PasswordControl.xaml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PasswordControl.xaml.cs b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PasswordControl.xaml.cs
new file mode 100644
index 0000000..afa8ce4
--- /dev/null
+++ b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PasswordControl.xaml.cs
@@ -0,0 +1,74 @@
+// Copyright © 2024 ema
+//
+// This file is part of QuickLook program.
+//
+// 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 QuickLook.Common.Helpers;
+using System;
+using System.Reflection;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace QuickLook.Plugin.PDFViewer;
+
+public partial class PasswordControl : UserControl
+{
+ public event Func PasswordRequested;
+
+ public bool Result { get; private set; } = false;
+ public string Password => passwordBox.Dispatcher.Invoke(() => passwordBox.Password);
+
+ public PasswordControl()
+ {
+ InitializeComponent();
+
+ string domain = Assembly.GetExecutingAssembly().GetName().Name;
+ titleTextBlock.Text = TranslationHelper.Get("PW_Title", domain: domain);
+ hintTextBlock.Text = TranslationHelper.Get("Pw_Hint", domain: domain);
+ passwordErrorTextBlock.Text = TranslationHelper.Get("PW_Error", domain: domain);
+ openFileButton.Content = TranslationHelper.Get("BTN_OpenFile", domain: domain);
+ cancelButton.Content = TranslationHelper.Get("BTN_Cancel", domain: domain);
+ openFileButton.Click += OpenFileButton_Click;
+ cancelButton.Click += CancelButton_Click;
+ }
+
+ private void OpenFileButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (!string.IsNullOrEmpty(Password))
+ {
+ Result = true;
+
+ if (PasswordRequested != null)
+ {
+ bool accepted = PasswordRequested.Invoke(Password);
+
+ if (!accepted)
+ {
+ passwordErrorTextBlock.Dispatcher.Invoke(() => passwordErrorTextBlock.Visibility = Visibility.Visible);
+ }
+ }
+ }
+ }
+
+ private void CancelButton_Click(object sender, RoutedEventArgs e)
+ {
+ Result = false;
+
+ if (Window.GetWindow(this) is Window window)
+ {
+ window.Close();
+ }
+ }
+}
diff --git a/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfDocumentWrapper.cs b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfDocumentWrapper.cs
index 7b65c5b..cba2b63 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfDocumentWrapper.cs
+++ b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfDocumentWrapper.cs
@@ -23,12 +23,12 @@ namespace QuickLook.Plugin.PDFViewer;
public class PdfDocumentWrapper : IDisposable
{
- public PdfDocumentWrapper(Stream stream)
+ public PdfDocumentWrapper(Stream stream, string password = null)
{
PdfStream = new MemoryStream((int)stream.Length);
stream.CopyTo(PdfStream);
- PdfDocument = PdfDocument.Load(PdfStream);
+ PdfDocument = PdfDocument.Load(PdfStream, password);
}
public PdfDocument PdfDocument { get; private set; }
diff --git a/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfViewerControl.xaml.cs b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfViewerControl.xaml.cs
index b85a709..e30db1c 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfViewerControl.xaml.cs
+++ b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/PdfViewerControl.xaml.cs
@@ -213,13 +213,13 @@ public partial class PdfViewerControl : UserControl, INotifyPropertyChanged, IDi
}
}
- public static Size GetDesiredControlSizeByFirstPage(string path)
+ public static Size GetDesiredControlSizeByFirstPage(string path, string password = null)
{
Size size;
using (var s = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
- using (var tempHandle = PdfDocument.Load(s))
+ using (var tempHandle = PdfDocument.Load(s, password))
{
size = new Size(0, 0);
tempHandle.PageSizes.Take(5).ForEach(p =>
@@ -236,10 +236,10 @@ public partial class PdfViewerControl : UserControl, INotifyPropertyChanged, IDi
return new Size(size.Width * 3, size.Height * 3);
}
- public void LoadPdf(string path)
+ public void LoadPdf(string path, string password = null)
{
var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
- PdfDocumentWrapper = new PdfDocumentWrapper(stream);
+ PdfDocumentWrapper = new PdfDocumentWrapper(stream, password);
_pdfLoaded = true;
if (PdfDocumentWrapper.PdfDocument.PageCount < 2)
diff --git a/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/Plugin.cs b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/Plugin.cs
index e09faea..30cbf3b 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/Plugin.cs
+++ b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/Plugin.cs
@@ -15,11 +15,13 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+using PdfiumViewer;
using QuickLook.Common.Plugin;
using System;
using System.IO;
using System.Runtime.ExceptionServices;
using System.Text;
+using System.Windows;
using System.Windows.Threading;
namespace QuickLook.Plugin.PDFViewer;
@@ -29,6 +31,7 @@ public class Plugin : IViewer
private ContextObject _context;
private string _path;
private PdfViewerControl _pdfControl;
+ private PasswordControl _passwordControl;
public int Priority => 0;
@@ -55,9 +58,16 @@ public class Plugin : IViewer
_context = context;
_path = path;
- var desiredSize = PdfViewerControl.GetDesiredControlSizeByFirstPage(path);
-
- context.SetPreferredSizeFit(desiredSize, 0.9);
+ try
+ {
+ var desiredSize = PdfViewerControl.GetDesiredControlSizeByFirstPage(path);
+ context.SetPreferredSizeFit(desiredSize, 0.9);
+ }
+ catch (PdfException ex) when (ex.Message == "Password required or incorrect password")
+ {
+ // Fallback to a size to request the password
+ context.PreferredSize = new Size { Width = 800, Height = 600 };
+ }
}
public void View(string path, ContextObject context)
@@ -67,7 +77,7 @@ public class Plugin : IViewer
Exception exception = null;
- _pdfControl.Dispatcher.BeginInvoke(new Action(() =>
+ _ = _pdfControl.Dispatcher.BeginInvoke(() =>
{
try
{
@@ -78,11 +88,46 @@ public class Plugin : IViewer
_pdfControl.CurrentPageChanged += UpdateWindowCaption;
context.IsBusy = false;
}
- catch (Exception e)
+ catch (PdfException ex) when (ex.Message == "Password required or incorrect password")
{
- exception = e;
+ // Fallback to request a password
+ _passwordControl = new PasswordControl();
+ _passwordControl.PasswordRequested += (string password) =>
+ {
+ try
+ {
+ var desiredSize = PdfViewerControl.GetDesiredControlSizeByFirstPage(path, password);
+ context.SetPreferredSizeFit(desiredSize, 0.9); // Actually it is no longer effective here
+
+ context.ViewerContent = _pdfControl;
+
+ context.IsBusy = true;
+ _pdfControl.LoadPdf(path, password);
+
+ context.Title = $"1 / {_pdfControl.TotalPages}: {Path.GetFileName(path)}";
+
+ _pdfControl.CurrentPageChanged += UpdateWindowCaption;
+ context.IsBusy = false;
+ }
+ catch (PdfException ex) when (ex.Message == "Password required or incorrect password")
+ {
+ // This password is not accepted
+ return false;
+ }
+
+ // This password is accepted
+ return true;
+ };
+
+ context.ViewerContent = _passwordControl;
+ context.Title = $"[PASSWORD PROTECTED] {Path.GetFileName(path)}";
+ context.IsBusy = false;
}
- }), DispatcherPriority.Loaded).Wait();
+ catch (Exception ex)
+ {
+ exception = ex;
+ }
+ }, DispatcherPriority.Loaded).Wait();
if (exception != null)
ExceptionDispatchInfo.Capture(exception).Throw();
diff --git a/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/QuickLook.Plugin.PdfViewer.csproj b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/QuickLook.Plugin.PdfViewer.csproj
index 263cd53..d3c098c 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/QuickLook.Plugin.PdfViewer.csproj
+++ b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/QuickLook.Plugin.PdfViewer.csproj
@@ -86,6 +86,12 @@
+
+
+ PreserveNewest
+
+
+
Properties\GitVersion.cs
diff --git a/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/Translations.config b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/Translations.config
new file mode 100644
index 0000000..4cff2c1
--- /dev/null
+++ b/QuickLook.Plugin/QuickLook.Plugin.PDFViewer/Translations.config
@@ -0,0 +1,32 @@
+
+
+
+
+ Enter Password
+ This file is password protected. Please enter the password to open the file.
+ Check your password
+ Open File
+ BTN_Cancel
+
+
+ パスワード入力
+ このファイルではパスワードで保護されています。ファイルを開くにはパスワードを入力してください。
+ パスワードを確認してください
+ ファイルを開く
+ キャンセル
+
+
+ 输入密码
+ 此文件受密码保护。请输入密码以打开文件。
+ 检查您的密码
+ 打开文件
+ 取消
+
+
+ 輸入密碼
+ 此檔案受密碼保護。請輸入密碼以開啟檔案。
+ 檢查您的密碼
+ 開啟檔案
+ 取消
+
+