This commit is contained in:
2021-01-04 00:01:10 +01:00
parent c953aa0e91
commit 7f7b313b51
12 changed files with 601 additions and 0 deletions

25
UtilitatPdf.sln Normal file
View File

@@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30717.126
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UtilitatPdf", "UtilitatPdf\UtilitatPdf.csproj", "{A9DF4881-D24E-47F7-BA67-3DFC73ECE9FD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A9DF4881-D24E-47F7-BA67-3DFC73ECE9FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A9DF4881-D24E-47F7-BA67-3DFC73ECE9FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A9DF4881-D24E-47F7-BA67-3DFC73ECE9FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A9DF4881-D24E-47F7-BA67-3DFC73ECE9FD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B8A8AFEB-F7F6-49A6-A01F-39778DA34AC2}
EndGlobalSection
EndGlobal

9
UtilitatPdf/App.xaml Normal file
View File

@@ -0,0 +1,9 @@
<Application x:Class="UtilitatPdf.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:UtilitatPdf"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

17
UtilitatPdf/App.xaml.cs Normal file
View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace UtilitatPdf
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

View File

@@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]

View File

@@ -0,0 +1,80 @@
<Window x:Class="UtilitatPdf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:UtilitatPdf"
mc:Ignorable="d"
Loaded="Window_Loaded"
Title="Utilitats Pdf" Height="450" Width="550" Icon="pdf.ico" WindowStartupLocation="CenterScreen" ResizeMode="NoResize">
<TabControl>
<TabItem Header="Merge PDF">
<Grid>
<StackPanel>
<Button x:Name="AfegirPdf" Content="Afegir Fitxers" Margin="0,10,0,10" Height="30" Width="180" HorizontalAlignment="Center" Click="SelectOpenFile_Button_Click"/>
<ListView x:Name="MyListView" Height="190" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListView.View>
<GridView AllowsColumnReorder="true" ColumnHeaderToolTip="Arxius Pdf a Fusionar">
<GridViewColumn Header="Arxius a fusionar" Width="460">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Width="300" >
<TextBlock Text="{Binding FileName}"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn x:Name="gridClm_SelectRow" Width="90">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button x:Name="btnDelete"
BorderThickness="0"
Tag="{Binding Index}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Click="btnDelete_Click">
<StackPanel>
<Image Source="delete.png" Width="20" Height="20" />
</StackPanel>
<Button.Background>
<SolidColorBrush Color="Gray" Opacity="0.0" />
</Button.Background>
</Button>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<Separator Height="10" Margin="15,15,15,0"/>
<DockPanel Margin="0,15,0,0">
<TextBlock Margin="5,0,0,0" Width="60">Destinació:</TextBlock>
<TextBox x:Name="MergeFileOut" Margin="20,0,0,0" Height="23" Width="400"/>
<Button x:Name="SelectFile7" Margin="0,0,0,0" Width="30" Click="SelectSaveFile_Button_Click">...</Button>
</DockPanel>
<Button Margin="130,30,130,0" Height="30" Click="MergeFile_Button_Click">Fusionar</Button>
</StackPanel>
</Grid>
</TabItem>
<TabItem Header="Treure Signatura">
<Grid>
<StackPanel Margin="0,20,0,0">
<DockPanel>
<TextBlock Width="60" Margin="5,0,0,0" HorizontalAlignment="Right">Origen:</TextBlock>
<TextBox x:Name="InSignFile" Margin="20,0,0,0" Height="23" Width="400"/>
<Button x:Name="SelectFile5" Margin="0,0,0,0" Width="30" Click="SelectOpenFile_Button_Click">...</Button>
</DockPanel>
<DockPanel Margin="0,15,0,0">
<TextBlock Width="60" Margin="5,0,0,0" HorizontalAlignment="Right">Destinació:</TextBlock>
<TextBox x:Name="OutSignFile" Margin="20,0,0,0" Height="23" Width="400"/>
<Button x:Name="SelectFile6" Margin="0,0,0,0" Width="30" Click="SelectSaveFile_Button_Click">...</Button>
</DockPanel>
<Button Margin="130,30,130,0" Height="30" Click="RemoveSign_Button_Click">Treure Signatura</Button>
</StackPanel>
</Grid>
</TabItem>
</TabControl>
</Window>

View File

@@ -0,0 +1,286 @@
using System;
using System.IO;
using System.Windows;
using Microsoft.Win32;
using iText.Kernel.Pdf;
using iText.Forms;
using iText.Signatures;
using iText.Kernel.Pdf.Annot;
using iText.Forms.Fields;
using Org.BouncyCastle.X509;
using iText.Kernel.Pdf.Xobject;
using iText.Kernel.Pdf.Canvas.Parser.Listener;
using iText.Kernel.Pdf.Canvas.Parser;
using System.Text.RegularExpressions;
using iText.Layout.Element;
using Paragraph = iText.Layout.Element.Paragraph;
using Rectangle = iText.Kernel.Geom.Rectangle;
using System.Windows.Controls;
using Canvas = iText.Layout.Canvas;
using System.Collections.ObjectModel;
namespace UtilitatPdf
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
ObservableCollection<PdfInfo> list = new ObservableCollection<PdfInfo>();
public MainWindow()
{
InitializeComponent();
}
#region ButtonText
private void SelectOpenFile_Button_Click(object sender, RoutedEventArgs e)
{
string content = (sender as Button).Name;
string FileSelected = SelectOpenPDFile();
if(content == "AfegirPdf")
{
if (!string.IsNullOrEmpty(FileSelected))
{
list.Add(new PdfInfo(FileSelected));
SetOrder(list);
}
}
else if(content == "SelectFile5")
{
InSignFile.Text = FileSelected;
}
}
private void SelectSaveFile_Button_Click(object sender, RoutedEventArgs e)
{
string content = (sender as Button).Name;
string FileSelected = SaveFileDialog();
if (content == "SelectFile6")
{
OutSignFile.Text = FileSelected;
}
else if (content == "SelectFile7")
{
MergeFileOut.Text = FileSelected;
}
}
#endregion
public void SetOrder(ObservableCollection<PdfInfo> data)
{
for (int i = 0; i < data.Count; i++)
{
PdfInfo ei = (PdfInfo)data[i];
ei.Index = i.ToString();
}
}
private void btnDelete_Click(object sender, RoutedEventArgs e)
{
Button btn = (Button)sender;
int index = int.Parse(btn.Tag.ToString());
list.RemoveAt(index);
SetOrder(list);
MyListView.ItemsSource = null;
MyListView.ItemsSource = list;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
MyListView.ItemsSource = list;
}
#region ActionsRegion
private void MergeFile_Button_Click(object sender, RoutedEventArgs e)
{
if (list.Count == 0)
{
MessageBox.Show("Per a poder fusionar, has de seleccionar un fitxer com a mínim", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
else
{
string FinalPdfFile = MergeFileOut.Text;
if (string.IsNullOrEmpty(FinalPdfFile))
{
MessageBox.Show("El Fitxer de destí no pot estar buit.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
else
{
FileInfo currentFile = new FileInfo(FinalPdfFile);
if (currentFile.Exists) File.Delete(FinalPdfFile);
if(list.Count == 1)
{
File.Copy(list[0].FileName, FinalPdfFile);
}
else
{
try
{
PdfMergeFiles mClas = new PdfMergeFiles(FinalPdfFile);
foreach (PdfInfo fi in list)
{
mClas.AddFile(fi.FileName);
}
mClas.Copy();
}
catch (IOException ex)
{
MessageBox.Show("S'ha produit un error quan s'intentava escriure el fitxer:\n" + ex.Message,"Error", MessageBoxButton.OK,MessageBoxImage.Error);
}
catch(Exception exc)
{
MessageBox.Show("S'ha produit un error desconegut:\n" + exc.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
MergeFileOut.Text = string.Empty;
list.Clear();
MessageBox.Show("S'han fusionat correctament el fitxers.", "Info", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
}
private void RemoveSign_Button_Click(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(InSignFile.Text) || string.IsNullOrEmpty(OutSignFile.Text))
{
MessageBox.Show("Has de seleccioner l'arxiu d'origen i destí.", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
else
{
if (ManipulatePdf(InSignFile.Text, OutSignFile.Text))
{
InSignFile.Text = string.Empty;
OutSignFile.Text = string.Empty;
MessageBox.Show("S'ha ocultat el Cif/Nif de les signatures del document.", "Info", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
}
#endregion
#region File Dialogs
private string SaveFileDialog()
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
saveFileDialog.Filter = "pdf files (*.pdf)|*.pdf";
saveFileDialog.FilterIndex = 2;
if (saveFileDialog.ShowDialog() == true)
{
return saveFileDialog.FileName;
}
return string.Empty;
}
private string SelectOpenPDFile()
{
string fichero = string.Empty;
try
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
openFileDialog.Filter = "pdf files (*.pdf)|*.pdf";
openFileDialog.FilterIndex = 2;
openFileDialog.RestoreDirectory = true;
if (openFileDialog.ShowDialog() == true)
{
fichero = openFileDialog.FileName;
}
}
catch (Exception ex)
{
MessageBox.Show("Error: No es pot llegir el fitxer del disc.\n Original error: " + ex.Message);
return null;
}
return fichero;
}
#endregion
#region RemoveSignature
private bool ManipulatePdf(string resource, string result)
{
string patronCif = @"([a-zA-Z]-?[0-9]{8})";
string patronNif = @"([0-9]{8}-?[a-zA-Z])";
string cleanRegex = string.Empty;
string widgetText = string.Empty;
bool doneOk = false;
try
{
using (PdfReader pdfReader = new PdfReader(resource))
using (PdfWriter pdfWriter = new PdfWriter(result))
using (PdfDocument pdfDocument = new PdfDocument(pdfReader, pdfWriter))
{
SignatureUtil signatureUtil = new SignatureUtil(pdfDocument);
PdfAcroForm acroForm = PdfAcroForm.GetAcroForm(pdfDocument, false);
foreach (String name in signatureUtil.GetSignatureNames())
{
PdfPKCS7 pkcs7 = signatureUtil.ReadSignatureData(name);
X509Certificate signerCert = (X509Certificate)pkcs7.GetSigningCertificate();
String signerName = CertificateInfo.GetSubjectFields(signerCert).GetField("CN");
PdfFormField field = acroForm.GetField(name);
field.SetModified();
foreach (PdfWidgetAnnotation pdfWidgetAnnotation in field.GetWidgets())
{
widgetText = extractText(pdfWidgetAnnotation);
Regex regCif = new Regex(patronCif);
Regex regNif = new Regex(patronNif);
MatchCollection matchesCif = regCif.Matches(widgetText);
MatchCollection matchesNif = regNif.Matches(widgetText);
if (matchesCif.Count > 0 || matchesNif.Count > 0)
{
cleanRegex = Regex.Replace(widgetText, patronCif, "<NIF_EDITAT>");
cleanRegex = Regex.Replace(cleanRegex, patronNif, "<NIF_EDITAT>");
PdfArray annotationRect = pdfWidgetAnnotation.GetRectangle();
pdfWidgetAnnotation.SetRectangle(annotationRect);
PdfFormXObject form = new PdfFormXObject(new Rectangle(annotationRect.ToRectangle()));
Canvas canvas = new Canvas(form, pdfDocument);
canvas.Add(CreateNewCell(cleanRegex.Replace("\n", "").Replace("\r", "")).SetFontSize(7));
pdfWidgetAnnotation.SetNormalAppearance(form.GetPdfObject());
}
acroForm.PartialFormFlattening(name);
}
}
acroForm.FlattenFields();
doneOk = true;
}
}
catch (IOException ioException)
{
MessageBox.Show("S'ha produit un error:\n" + ioException.Message, "Eror", MessageBoxButton.OK, MessageBoxImage.Error);
}
return doneOk;
}
private static Cell CreateNewCell(string texto)
{
Cell celda = new Cell();
Paragraph p = new Paragraph(texto);
celda.Add(p);
return celda;
}
private String extractText(PdfWidgetAnnotation pdfWidgetAnnotation)
{
PdfDictionary normal = pdfWidgetAnnotation.GetNormalAppearanceObject();
if (normal is PdfStream appearance)
{
PdfDictionary resourceDictionary = appearance.GetAsDictionary(PdfName.Resources);
PdfResources resources = resourceDictionary != null ? new PdfResources(resourceDictionary) : new PdfResources();
ITextExtractionStrategy strategy = new SimpleTextExtractionStrategy();
PdfCanvasProcessor parser = new PdfCanvasProcessor(strategy);
parser.ProcessContent(appearance.GetBytes(), resources);
return strategy.GetResultantText();
}
return string.Empty;
}
#endregion
} // END Window Class
} // END Namespace

24
UtilitatPdf/PdfInfo.cs Normal file
View File

@@ -0,0 +1,24 @@
namespace UtilitatPdf
{
/// <summary>
/// Class for ListView Filenames
/// </summary>
public class PdfInfo
{
private string _fileName;
public string FileName
{
get { return _fileName; }
set { _fileName = value; }
}
public string Index { set; get; }
public PdfInfo(string filename)
{
_fileName = filename;
}
} // END PdfInfo Class
}

View File

@@ -0,0 +1,100 @@
using System;
using System.IO;
using iText.Kernel.Pdf;
using iText.Kernel.Utils;
namespace UtilitatPdf
{
public class PdfMergeFiles
{
private PdfDocument _pdfDocument = null;
private PdfDocument _pdfDocument2 = null;
private PdfMerger _pdfMerger = null;
private static string tmpFolder = System.IO.Path.GetTempPath();
private string _oldtmpFile = string.Empty;
private string _tmpFile = string.Empty;
private string _tmpFile2 = string.Empty;
private bool _mergeOK = false;
private string _FinalPdfFile = string.Empty;
public PdfMergeFiles(string FinalPdfFile, bool DeleteIfExists = true)
{
if (string.IsNullOrEmpty(FinalPdfFile))
{
throw new Exception();
}
else
{
_FinalPdfFile = FinalPdfFile;
if (DeleteIfExists)
{
if (new FileInfo(_FinalPdfFile).Exists) File.Delete(_FinalPdfFile);
}
}
}
public bool AddFile(string PdfFilename)
{
checkVars(PdfFilename);
if (_mergeOK)
{
Random numr = new Random();
_oldtmpFile = tmpFolder + numr.Next(1, 99999).ToString() + "tmpfile.pdf";
try
{
_pdfDocument = new PdfDocument(new PdfReader(_tmpFile), new PdfWriter(_oldtmpFile), new StampingProperties().UseAppendMode());
_pdfDocument2 = new PdfDocument(new PdfReader(_tmpFile2));
_pdfMerger = new PdfMerger(_pdfDocument);
_pdfMerger.Merge(_pdfDocument2, 1, _pdfDocument2.GetNumberOfPages());
this.Close();
}
catch (IOException)
{
throw new IOException();
}
catch(Exception)
{
throw new Exception();
}
finally
{
_tmpFile = _oldtmpFile;
_tmpFile2 = string.Empty;
_oldtmpFile = string.Empty;
_mergeOK = false;
}
}
return true;
}
public void Copy()
{
File.Copy(_tmpFile, _FinalPdfFile);
}
private void Close()
{
_pdfDocument?.Close();
_pdfDocument2?.Close();
_pdfMerger?.Close();
}
private void checkVars(string file)
{
if (string.IsNullOrEmpty(_tmpFile))
{
_tmpFile = file;
}
else
{
_tmpFile2 = file;
}
if (!string.IsNullOrEmpty(_tmpFile) && !string.IsNullOrEmpty(_tmpFile2)) _mergeOK = true;
}
}
}

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>C:\Users\Vicente\git-repos\UtilitatPdf\bin</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<TargetFramework>netcoreapp3.1</TargetFramework>
<SelfContained>false</SelfContained>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<PublishSingleFile>True</PublishSingleFile>
<PublishReadyToRun>False</PublishReadyToRun>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>embedded</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>embedded</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<None Remove="delete.png" />
<None Remove="pdf.ico" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="itext7" Version="7.1.13" />
</ItemGroup>
<ItemGroup>
<Resource Include="delete.png" />
<Resource Include="pdf.ico" />
</ItemGroup>
</Project>

BIN
UtilitatPdf/delete.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1006 B

BIN
UtilitatPdf/pdf.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 444 KiB