diff --git a/UtilitatPdf.sln b/UtilitatPdf.sln
new file mode 100644
index 0000000..c9c3b56
--- /dev/null
+++ b/UtilitatPdf.sln
@@ -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
diff --git a/UtilitatPdf/App.xaml b/UtilitatPdf/App.xaml
new file mode 100644
index 0000000..29a97bd
--- /dev/null
+++ b/UtilitatPdf/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/UtilitatPdf/App.xaml.cs b/UtilitatPdf/App.xaml.cs
new file mode 100644
index 0000000..874e192
--- /dev/null
+++ b/UtilitatPdf/App.xaml.cs
@@ -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
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/UtilitatPdf/AssemblyInfo.cs b/UtilitatPdf/AssemblyInfo.cs
new file mode 100644
index 0000000..8b5504e
--- /dev/null
+++ b/UtilitatPdf/AssemblyInfo.cs
@@ -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)
+)]
diff --git a/UtilitatPdf/MainWindow.xaml b/UtilitatPdf/MainWindow.xaml
new file mode 100644
index 0000000..3491df2
--- /dev/null
+++ b/UtilitatPdf/MainWindow.xaml
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Destinació:
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Origen:
+
+
+
+
+ Destinació:
+
+
+
+
+
+
+
+
+
diff --git a/UtilitatPdf/MainWindow.xaml.cs b/UtilitatPdf/MainWindow.xaml.cs
new file mode 100644
index 0000000..08e7417
--- /dev/null
+++ b/UtilitatPdf/MainWindow.xaml.cs
@@ -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
+{
+
+ ///
+ /// Interaction logic for MainWindow.xaml
+ ///
+ public partial class MainWindow : Window
+ {
+ ObservableCollection list = new ObservableCollection();
+ 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 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, "");
+ cleanRegex = Regex.Replace(cleanRegex, patronNif, "");
+
+ 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
diff --git a/UtilitatPdf/PdfInfo.cs b/UtilitatPdf/PdfInfo.cs
new file mode 100644
index 0000000..c6d373c
--- /dev/null
+++ b/UtilitatPdf/PdfInfo.cs
@@ -0,0 +1,24 @@
+
+namespace UtilitatPdf
+{
+ ///
+ /// Class for ListView Filenames
+ ///
+ 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
+}
diff --git a/UtilitatPdf/PdfMergeFiles.cs b/UtilitatPdf/PdfMergeFiles.cs
new file mode 100644
index 0000000..80a50e2
--- /dev/null
+++ b/UtilitatPdf/PdfMergeFiles.cs
@@ -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;
+ }
+
+ }
+}
diff --git a/UtilitatPdf/Properties/PublishProfiles/FolderProfile.pubxml b/UtilitatPdf/Properties/PublishProfiles/FolderProfile.pubxml
new file mode 100644
index 0000000..69e61dc
--- /dev/null
+++ b/UtilitatPdf/Properties/PublishProfiles/FolderProfile.pubxml
@@ -0,0 +1,17 @@
+
+
+
+
+ Release
+ Any CPU
+ C:\Users\Vicente\git-repos\UtilitatPdf\bin
+ FileSystem
+ netcoreapp3.1
+ false
+ win-x64
+ True
+ False
+
+
\ No newline at end of file
diff --git a/UtilitatPdf/UtilitatPdf.csproj b/UtilitatPdf/UtilitatPdf.csproj
new file mode 100644
index 0000000..60e8129
--- /dev/null
+++ b/UtilitatPdf/UtilitatPdf.csproj
@@ -0,0 +1,33 @@
+
+
+
+ WinExe
+ netcoreapp3.1
+ true
+
+
+
+ embedded
+ true
+
+
+
+ embedded
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/UtilitatPdf/delete.png b/UtilitatPdf/delete.png
new file mode 100644
index 0000000..eee6faf
Binary files /dev/null and b/UtilitatPdf/delete.png differ
diff --git a/UtilitatPdf/pdf.ico b/UtilitatPdf/pdf.ico
new file mode 100644
index 0000000..ae2f6f3
Binary files /dev/null and b/UtilitatPdf/pdf.ico differ