I had a requirement that involved adding a
digital signature to word documents
uploaded on a document library when the document is approved. This article
discusses step by step how to add digital signatures to word documents.
I solve this problem by using the following
approach.
Step 1
Catch the update events (by writing ItemUpdated event handlers) (for more
info about event handlers implementation see the previous post).
Step 2
Make a copy of your file that is approved in the document library to a
temporary folder on the server.
Step 3
Add the digital signature to your own copied file on the server.
Step 4
Write the file again to your document library then remove the temporary
copy on the server.
Step 5
If the file is not signed the approval status of the document will be
converted into rejected.
I have used the following code to implement
this entire process.
The Strings Class is a class that contains all strings used in my code.
Listing 1 shows the Strings class and its members.
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Web;
namespace
DGEventReciever
{
public class Strings
{
// The
general keys .
#region
public const string
TemporaryFolderKey = @"C:\TempFolder";
public const string
ApprovalColumnKey = "Approval Status";
#endregion
//Other Strings.
#region
public const string
InDraftStatus = "0";
public const string
DateFormat = "yyyyyMMddhhmmss";
public const string IDColumn
= "ID";
public const string
NameColumn = "Name";
public const string
DocxExtension = ".docx";
public const string
DocExtension = ".doc";
#endregion
}
}
The Main Class that handles the events is
listed in Listing 2. I have used OfficeInterop COM library. Before you use this
code, you must add reference to Microsoft.Office.Interop.Word.Dll and other
required assemblies.
using System.Web;
using
Microsoft.SharePoint;
using
System.IO;
using
Microsoft.Office.Core;
namespace
DGEventReciever
{
public class DGEventHandler:SPItemEventReceiver
{
//All the
Public Used Variables.
#region
public
string TemporaryFolder = string.Empty;
public
string ApprovalColumnName = string.Empty;
#endregion
public override void
ItemUpdated(SPItemEventProperties properties)
{
EventHandlerConstructor();
if
(properties.ListItem[ApprovalColumnName].ToString() == Strings.InDraftStatus)
{
DownloadItem(properties);
}
}
private
void EventHandlerConstructor()
{
TemporaryFolder =
Strings.TemporaryFolderKey;
ApprovalColumnName = Strings.ApprovalColumnKey;
}
private
void DownloadItem(SPItemEventProperties
properties)
{
SPFile File =
properties.ListItem.File;
string
FileTempName = DateTime.Now.ToString(Strings.DateFormat) +
properties.ListItem[Strings.IDColumn].ToString()
+
properties.ListItem[Strings.NameColumn].ToString();
if
(File.Name.ToLower().EndsWith(Strings.DocxExtension) ||
File.Name.ToLower().EndsWith(Strings.DocExtension))
{
byte[]
Filebytes = File.OpenBinary(SPOpenBinaryOptions.None);
DirectoryInfo TempDirectory = new DirectoryInfo(TemporaryFolder);
if
(!TempDirectory.Exists)
{
TempDirectory.Create();
}
FileStream TempFileOnDisk = new FileStream(TemporaryFolder + FileTempName,
FileMode.CreateNew);
BinaryWriter bWriter = new BinaryWriter(TempFileOnDisk);
foreach
(byte b in
Filebytes)
{
bWriter.Write(b);
}
bWriter.Flush();
bWriter.Close();
TempFileOnDisk.Close();
bool
SignatureAdded = AddDigitalSignature(FileTempName, properties);
if
(SignatureAdded)
{
properties.ListItem.ParentList.ParentWeb.AllowUnsafeUpdates = true;
WriteFileAgain(properties,
FileTempName);
properties.ListItem.ParentList.ParentWeb.AllowUnsafeUpdates = false;
}
}
}
private
bool AddDigitalSignature(string FileTempName, SPItemEventProperties
properties)
{
object
TempFilePath = TemporaryFolder + FileTempName;
object
Visible = false;
object
readonlyfile = false;
try
{
object
missing = System.Reflection.Missing.Value;
Microsoft.Office.Interop.Word.ApplicationClass
wordapp = new
Microsoft.Office.Interop.Word.ApplicationClass();
Microsoft.Office.Interop.Word.Document wordDocument =
wordapp.Documents.Open(ref
TempFilePath, ref missing,
ref
readonlyfile, ref missing, ref missing,
ref
missing, ref missing, ref
missing,
ref
missing, ref missing, ref
missing,
ref
Visible, ref missing, ref
missing,
ref
missing, ref missing);
SignatureSet signatureSet =
wordDocument.Signatures;
Signature objSignature =
signatureSet.Add();
if
(objSignature == null)
{
DocumentNotSigned(properties);
return
false;
}
else
{
signatureSet.Commit();
object
saveChanges = true;
wordDocument.Close(ref saveChanges, ref
missing, ref missing);
wordapp.Quit(ref missing, ref
missing, ref missing);
return
true;
}
}
catch
{
return
false;
}
}
private
void WriteFileAgain(SPItemEventProperties
properties, string TemporaryFile)
{
SPFile currentFile =
properties.ListItem.File;
string
TempFilePath = TemporaryFolder+ TemporaryFile;
FileStream st = new FileStream(TempFilePath, FileMode.Open);
properties.ListItem.ParentList.ParentWeb.AllowUnsafeUpdates = true;
currentFile.CheckOut();
currentFile.SaveBinary(st);
this.DisableEventFiring();
currentFile.CheckIn(string.Empty);
currentFile.Publish(string.Empty);
currentFile.Approve(string.Empty);
st.Close();
properties.ListItem.ParentList.ParentWeb.AllowUnsafeUpdates = false;
this.EnableEventFiring();
FileInfo deletedfile = new FileInfo(TemporaryFolder + TemporaryFile);
deletedfile.Delete();
}
private
void DocumentNotSigned(SPItemEventProperties
properties)
{
properties.ListItem.ParentList.ParentWeb.AllowUnsafeUpdates
= true;
SPFile currentFile =
properties.ListItem.File;
if
(currentFile.CheckOutStatus == SPFile.SPCheckOutStatus.None)
{
currentFile.CheckOut();
}
this.DisableEventFiring();
currentFile.CheckIn(string.Empty);
currentFile.Publish(string.Empty);
currentFile.Deny(string.Empty);
properties.ListItem.ParentList.ParentWeb.AllowUnsafeUpdates = false;
this.EnableEventFiring();
}
}
}