mirror of
https://github.com/QL-Win/QuickLook.git
synced 2025-09-13 11:09:06 +00:00
Support .deb
This commit is contained in:
@@ -118,7 +118,7 @@
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Version" />
|
||||
Text="Version Name" />
|
||||
<TextBlock x:Name="versionName"
|
||||
Grid.Row="4"
|
||||
Grid.Column="2"
|
||||
|
@@ -70,14 +70,14 @@
|
||||
</TextBlock.Inlines>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
<!-- Application Name -->
|
||||
<TextBlock x:Name="applicationNameTitle"
|
||||
<!-- Package Name -->
|
||||
<TextBlock x:Name="packageNameTitle"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Application Name" />
|
||||
<TextBlock x:Name="applicationName"
|
||||
Text="Package Name" />
|
||||
<TextBlock x:Name="packageName"
|
||||
Grid.Row="3"
|
||||
Grid.Column="2"
|
||||
Margin="8,0,0,0"
|
||||
@@ -92,7 +92,7 @@
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Version" />
|
||||
Text="Version Name" />
|
||||
<TextBlock x:Name="versionName"
|
||||
Grid.Row="4"
|
||||
Grid.Column="2"
|
||||
@@ -102,14 +102,14 @@
|
||||
Text="Searching..."
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="Wrap" />
|
||||
<!-- Version Code -->
|
||||
<TextBlock x:Name="versionCodeTitle"
|
||||
<!-- Maintainer -->
|
||||
<TextBlock x:Name="maintainerTitle"
|
||||
Grid.Row="5"
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Version Code" />
|
||||
<TextBlock x:Name="versionCode"
|
||||
Text="Maintainer" />
|
||||
<TextBlock x:Name="maintainer"
|
||||
Grid.Row="5"
|
||||
Grid.Column="2"
|
||||
Margin="8,0,0,0"
|
||||
@@ -147,8 +147,8 @@
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Searching..."
|
||||
TextTrimming="CharacterEllipsis" />
|
||||
<!-- Permissions -->
|
||||
<GroupBox x:Name="permissionsGroupBox"
|
||||
<!-- Description -->
|
||||
<GroupBox x:Name="descriptionGroupBox"
|
||||
Grid.Row="8"
|
||||
Grid.Column="1"
|
||||
Grid.ColumnSpan="2"
|
||||
@@ -157,7 +157,7 @@
|
||||
Background="{DynamicResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{DynamicResource CardStrokeColorDefaultBrush}"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Header="Capabilities">
|
||||
Header="Description">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||
<ScrollViewer.Resources>
|
||||
<Style TargetType="{x:Type TextBox}">
|
||||
@@ -167,15 +167,12 @@
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
</Style>
|
||||
</ScrollViewer.Resources>
|
||||
<ItemsControl x:Name="permissions">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBox Margin="8,3,16,3"
|
||||
IsReadOnly="True"
|
||||
Text="{Binding ., Mode=OneTime}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<TextBox x:Name="description"
|
||||
Margin="8,3,16,3"
|
||||
AcceptsReturn="True"
|
||||
IsReadOnly="True"
|
||||
TextWrapping="Wrap"
|
||||
VerticalScrollBarVisibility="Auto" />
|
||||
</ScrollViewer>
|
||||
</GroupBox>
|
||||
</Grid>
|
||||
|
@@ -40,12 +40,12 @@ public partial class DebInfoPanel : UserControl, IAppInfoPanel
|
||||
InitializeComponent();
|
||||
|
||||
string translationFile = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Translations.config");
|
||||
applicationNameTitle.Text = TranslationHelper.Get("APP_NAME", translationFile);
|
||||
packageNameTitle.Text = TranslationHelper.Get("PACKAGE_NAME", translationFile);
|
||||
versionNameTitle.Text = TranslationHelper.Get("APP_VERSION_NAME", translationFile);
|
||||
versionCodeTitle.Text = TranslationHelper.Get("APP_VERSION_CODE", translationFile);
|
||||
maintainerTitle.Text = TranslationHelper.Get("MAINTAINER", translationFile);
|
||||
totalSizeTitle.Text = TranslationHelper.Get("TOTAL_SIZE", translationFile);
|
||||
modDateTitle.Text = TranslationHelper.Get("LAST_MODIFIED", translationFile);
|
||||
permissionsGroupBox.Header = TranslationHelper.Get("PERMISSIONS", translationFile);
|
||||
descriptionGroupBox.Header = TranslationHelper.Get("DESCRIPTION", translationFile);
|
||||
}
|
||||
|
||||
public void DisplayInfo(string path)
|
||||
@@ -58,17 +58,17 @@ public partial class DebInfoPanel : UserControl, IAppInfoPanel
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var size = new FileInfo(path).Length;
|
||||
DebInfo wgtInfo = DebParser.Parse(path);
|
||||
DebInfo debInfo = DebParser.Parse(path);
|
||||
var last = File.GetLastWriteTime(path);
|
||||
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
//applicationName.Text = wgtInfo.AppNameLocale ?? wgtInfo.AppName;
|
||||
//versionName.Text = wgtInfo.AppVersionName;
|
||||
//versionCode.Text = wgtInfo.AppVersionCode;
|
||||
//totalSize.Text = size.ToPrettySize(2);
|
||||
//modDate.Text = last.ToString(CultureInfo.CurrentCulture);
|
||||
//permissions.ItemsSource = wgtInfo.Permissions;
|
||||
packageName.Text = debInfo.Package;
|
||||
versionName.Text = debInfo.Version;
|
||||
maintainer.Text = debInfo.Maintainer;
|
||||
totalSize.Text = size.ToPrettySize(2);
|
||||
modDate.Text = last.ToString(CultureInfo.CurrentCulture);
|
||||
description.Text = debInfo.Description;
|
||||
|
||||
_context.IsBusy = false;
|
||||
});
|
||||
|
@@ -168,7 +168,7 @@
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Version" />
|
||||
Text="Version Name" />
|
||||
<TextBlock x:Name="versionName"
|
||||
Grid.Row="5"
|
||||
Grid.Column="2"
|
||||
|
@@ -119,7 +119,7 @@
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Version" />
|
||||
Text="Version Name" />
|
||||
<TextBlock x:Name="versionName"
|
||||
Grid.Row="4"
|
||||
Grid.Column="2"
|
||||
|
@@ -92,7 +92,7 @@
|
||||
Grid.Column="1"
|
||||
Padding="3"
|
||||
Foreground="{DynamicResource WindowTextForegroundAlternative}"
|
||||
Text="Version" />
|
||||
Text="Version Name" />
|
||||
<TextBlock x:Name="versionName"
|
||||
Grid.Row="4"
|
||||
Grid.Column="2"
|
||||
|
@@ -1,4 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
// Copyright © 2017-2025 QL-Win Contributors
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
|
@@ -17,6 +17,20 @@
|
||||
|
||||
namespace QuickLook.Plugin.AppViewer.PackageParsers.Deb;
|
||||
|
||||
/// <summary>
|
||||
/// https://www.debian.org/doc/debian-policy/ch-controlfields.html
|
||||
/// </summary>
|
||||
public class DebInfo
|
||||
{
|
||||
public string Package { get; set; }
|
||||
|
||||
public string Maintainer { get; set; }
|
||||
|
||||
public string Uploaders { get; set; }
|
||||
|
||||
public string Version { get; set; }
|
||||
|
||||
public string Architecture { get; set; }
|
||||
|
||||
public string Description { get; set; }
|
||||
}
|
||||
|
@@ -21,7 +21,51 @@ public static class DebParser
|
||||
{
|
||||
public static DebInfo Parse(string path)
|
||||
{
|
||||
ArEntry[] ar = ArReader.Read(path);
|
||||
return new();
|
||||
DebReader reader = new(path);
|
||||
DebInfo info = new();
|
||||
|
||||
{
|
||||
if (reader.ControlDict.TryGetValue("Package", out string value))
|
||||
{
|
||||
info.Package = value;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (reader.ControlDict.TryGetValue("Maintainer", out string value))
|
||||
{
|
||||
info.Maintainer = value;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (reader.ControlDict.TryGetValue("Uploaders", out string value))
|
||||
{
|
||||
info.Uploaders = value;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (reader.ControlDict.TryGetValue("Version", out string value))
|
||||
{
|
||||
info.Version = value;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (reader.ControlDict.TryGetValue("Architecture", out string value))
|
||||
{
|
||||
info.Architecture = value;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (reader.ControlDict.TryGetValue("Description", out string value))
|
||||
{
|
||||
info.Description = value;
|
||||
}
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,185 @@
|
||||
// Copyright © 2017-2025 QL-Win Contributors
|
||||
//
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
using PureSharpCompress.Archives;
|
||||
using PureSharpCompress.Compressors;
|
||||
using PureSharpCompress.Compressors.BZip2;
|
||||
using PureSharpCompress.Compressors.Deflate;
|
||||
using PureSharpCompress.Compressors.Deflate64;
|
||||
using PureSharpCompress.Compressors.LZMA;
|
||||
using PureSharpCompress.Compressors.Xz;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace QuickLook.Plugin.AppViewer.PackageParsers.Deb;
|
||||
|
||||
public class DebReader
|
||||
{
|
||||
public ArEntry[] ArEntries { get; set; } = [];
|
||||
|
||||
public string Control { get; set; }
|
||||
|
||||
public Dictionary<string, string> ControlDict { get; set; } = [];
|
||||
|
||||
public DebReader(string path)
|
||||
{
|
||||
Open(path);
|
||||
}
|
||||
|
||||
public void Open(string path)
|
||||
{
|
||||
ArEntry[] ar = ArReader.Read(path);
|
||||
var controlEntry = ar.Where(entry => entry.FileName.StartsWith("control.tar"))
|
||||
.FirstOrDefault();
|
||||
|
||||
if (controlEntry != null)
|
||||
{
|
||||
ZipCompressionMethod method = GetCompressionMethodFromFileName(controlEntry.FileName);
|
||||
string control = ExtractControl(controlEntry.Data, method);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(control))
|
||||
{
|
||||
Control = control;
|
||||
|
||||
TextReader reader = new StringReader(control);
|
||||
string line;
|
||||
|
||||
while ((line = reader.ReadLine()) != null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
if (line.StartsWith(" ") || line.IndexOf(':') == -1)
|
||||
continue;
|
||||
|
||||
var split = line.Split([':'], 2);
|
||||
ControlDict.Add(split[0], split[1].Trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string ExtractControl(byte[] data, ZipCompressionMethod method)
|
||||
{
|
||||
using var stream = new MemoryStream(data);
|
||||
using var decompressedTar = new MemoryStream();
|
||||
|
||||
using (var decompressor = CreateDecompressionStream(stream, method))
|
||||
{
|
||||
decompressor?.CopyTo(decompressedTar);
|
||||
}
|
||||
|
||||
decompressedTar.Position = 0;
|
||||
|
||||
using var archive = ArchiveFactory.Open(decompressedTar);
|
||||
foreach (var entry in archive.Entries)
|
||||
{
|
||||
if (!entry.IsDirectory)
|
||||
{
|
||||
if (entry.Key == "./control")
|
||||
{
|
||||
using var reader = new StreamReader(entry.OpenEntryStream());
|
||||
string content = reader.ReadToEnd();
|
||||
|
||||
return content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static ZipCompressionMethod GetCompressionMethodFromFileName(string fileName)
|
||||
{
|
||||
fileName = fileName.ToLowerInvariant();
|
||||
if (fileName.EndsWith(".tar.gz") || fileName.EndsWith(".tgz"))
|
||||
return ZipCompressionMethod.Deflate;
|
||||
else if (fileName.EndsWith(".tar.xz"))
|
||||
return ZipCompressionMethod.Xz;
|
||||
else if (fileName.EndsWith(".tar.bz2"))
|
||||
return ZipCompressionMethod.BZip2;
|
||||
else if (fileName.EndsWith(".tar.lzma"))
|
||||
return ZipCompressionMethod.LZMA;
|
||||
else if (fileName.EndsWith(".tar.zst"))
|
||||
return ZipCompressionMethod.ZStd;
|
||||
|
||||
return ZipCompressionMethod.None;
|
||||
}
|
||||
|
||||
private static Stream CreateDecompressionStream(Stream stream, ZipCompressionMethod method)
|
||||
{
|
||||
switch (method)
|
||||
{
|
||||
case ZipCompressionMethod.Deflate:
|
||||
{
|
||||
return new DeflateStream(stream, CompressionMode.Decompress);
|
||||
}
|
||||
case ZipCompressionMethod.Deflate64:
|
||||
{
|
||||
return new Deflate64Stream(stream, CompressionMode.Decompress);
|
||||
}
|
||||
case ZipCompressionMethod.BZip2:
|
||||
{
|
||||
return new BZip2Stream(stream, CompressionMode.Decompress, false);
|
||||
}
|
||||
case ZipCompressionMethod.LZMA:
|
||||
{
|
||||
var reader = new BinaryReader(stream);
|
||||
reader.ReadUInt16(); //LZMA version
|
||||
var props = new byte[reader.ReadUInt16()];
|
||||
reader.Read(props, 0, props.Length);
|
||||
return new LzmaStream(
|
||||
props,
|
||||
stream,
|
||||
stream.Length - 4,
|
||||
-1
|
||||
);
|
||||
}
|
||||
case ZipCompressionMethod.Xz:
|
||||
{
|
||||
return new XZStream(stream);
|
||||
}
|
||||
case ZipCompressionMethod.ZStd:
|
||||
{
|
||||
// Not supported for ZStd
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
private enum ZipCompressionMethod
|
||||
{
|
||||
None = 0,
|
||||
Shrink = 1,
|
||||
Reduce1 = 2,
|
||||
Reduce2 = 3,
|
||||
Reduce3 = 4,
|
||||
Reduce4 = 5,
|
||||
Explode = 6,
|
||||
Deflate = 8,
|
||||
Deflate64 = 9,
|
||||
BZip2 = 12,
|
||||
LZMA = 14,
|
||||
ZStd = 93,
|
||||
Xz = 95,
|
||||
PPMd = 98,
|
||||
WinzipAes = 0x63,
|
||||
}
|
||||
}
|
@@ -49,7 +49,7 @@ public class Plugin : IViewer
|
||||
//".har", // HarmonyOS Archive
|
||||
|
||||
// Ubuntu
|
||||
//".deb", // Debian Package
|
||||
".deb", // Debian Package
|
||||
|
||||
// Others
|
||||
".wgt", ".wgtu", // UniApp Widget
|
||||
|
@@ -77,6 +77,7 @@
|
||||
<PackageReference Include="SharpZipLib" Version="1.4.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="ApkReader" Version="2.0.1.1" />
|
||||
<PackageReference Include="PureSharpCompress" Version="0.39.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@@ -24,6 +24,8 @@
|
||||
<APP_MIN_API_VERSION>Minimum API Version</APP_MIN_API_VERSION>
|
||||
<APP_TARGET_API_VERSION>Target API Version</APP_TARGET_API_VERSION>
|
||||
<COMPILE_SDK_VERSION>Compile SDK Version</COMPILE_SDK_VERSION>
|
||||
<MAINTAINER>Maintainer</MAINTAINER>
|
||||
<DESCRIPTION>Description</DESCRIPTION>
|
||||
</en>
|
||||
<pt-BR>
|
||||
<PRODUCT_VERSION>Versão do produto</PRODUCT_VERSION>
|
||||
@@ -48,6 +50,8 @@
|
||||
<APP_MIN_API_VERSION>Versão mínima do API</APP_MIN_API_VERSION>
|
||||
<APP_TARGET_API_VERSION>Versão mínima do API</APP_TARGET_API_VERSION>
|
||||
<COMPILE_SDK_VERSION>Versão do SDK de compilação</COMPILE_SDK_VERSION>
|
||||
<MAINTAINER>Mantenedor</MAINTAINER>
|
||||
<DESCRIPTION>Descrição</DESCRIPTION>
|
||||
</pt-BR>
|
||||
<zh-CN>
|
||||
<PRODUCT_VERSION>产品版本</PRODUCT_VERSION>
|
||||
@@ -72,6 +76,8 @@
|
||||
<APP_MIN_API_VERSION>最低支持 API 版本</APP_MIN_API_VERSION>
|
||||
<APP_TARGET_API_VERSION>目标 API 版本</APP_TARGET_API_VERSION>
|
||||
<COMPILE_SDK_VERSION>编译 SDK 版本</COMPILE_SDK_VERSION>
|
||||
<MAINTAINER>维护者</MAINTAINER>
|
||||
<DESCRIPTION>描述</DESCRIPTION>
|
||||
</zh-CN>
|
||||
<zh-TW>
|
||||
<PRODUCT_VERSION>產品版本</PRODUCT_VERSION>
|
||||
@@ -96,6 +102,8 @@
|
||||
<APP_MIN_API_VERSION>最低支援 API 版本</APP_MIN_API_VERSION>
|
||||
<APP_TARGET_API_VERSION>目標 API 版本</APP_TARGET_API_VERSION>
|
||||
<COMPILE_SDK_VERSION>編譯 SDK 版本</COMPILE_SDK_VERSION>
|
||||
<MAINTAINER>維護者</MAINTAINER>
|
||||
<DESCRIPTION>描述</DESCRIPTION>
|
||||
</zh-TW>
|
||||
<ja>
|
||||
<PRODUCT_VERSION>製品バージョン</PRODUCT_VERSION>
|
||||
@@ -120,5 +128,7 @@
|
||||
<APP_MIN_API_VERSION>最小APIバージョン</APP_MIN_API_VERSION>
|
||||
<APP_TARGET_API_VERSION>ターゲットAPIバージョン</APP_TARGET_API_VERSION>
|
||||
<COMPILE_SDK_VERSION>コンパイルSDKバージョン</COMPILE_SDK_VERSION>
|
||||
<MAINTAINER>メンテナー</MAINTAINER>
|
||||
<DESCRIPTION>説明</DESCRIPTION>
|
||||
</ja>
|
||||
</Translations>
|
||||
|
Reference in New Issue
Block a user