4 Replies Latest reply on Oct 17, 2016 5:23 AM by jorgep37884552

    Lock document after signing

    jorgep37884552

      Hi everyone,

       

      I found a javascript code here to signing in batch but it doesnt lock the file after signed and I need it.

       

      Any idea?

       

      Thanks in advance!

       

      ps: sorry for my english

        • 1. Re: Lock document after signing
          George_Johnson MVP & Adobe Community Professional

          What script are you using?

          • 2. Re: Lock document after signing
            jorgep37884552 Level 1

            I'm using this script to lock every Field

             

             

            for (var i = 0; i < this.numFields; i++) {

            var fname = this.getNthFieldName(i);

            this.getField(fname).readonly = true;

            }

             

            But I dont know if the result is the same that checkbox "lock after sign". Do you know?

             

            • 3. Re: Lock document after signing
              George_Johnson MVP & Adobe Community Professional

              No, it's not the same at all. The script simply sets the fields to read-only.

               

              You can configure a digital signature field so that it locks the document when signed. That's what I'd recommend you do. If you need help with this, you'll need to provide more information on how you're signing the document in a batch operation.

              • 4. Re: Lock document after signing
                jorgep37884552 Level 1

                This is the code I'm using to signing in batch (I found here too)

                 

                //Assinatura em lote - Batch signing - PDFs script for Adobe Acrobat Pro (tested w/10.1.14 release)

                ////////////////////////////////////-> 100 chars long lines <-/////////////////////////////////////

                //Acrobat batch sequence (JavaScript) to add a visible signature to all documents.

                //This script is called for each file on batch processing, in "action wizard".

                //A visible signature field is added above the last ocurrence of signer's complete name,

                //or at end of the document, if the name was not found.

                //Also, a visible annotation is added on the remaining pages, as a footer.

                //For use with A1 or A3 certificates, smartcard or token. Prompt for PIN once only.

                //By SSUP/CSUP/SETIN/TST (tst.jus.br) 2015-June

                //Uncomment "console" lines to see debug results

                 

                //Constants (all named like cXxxYyy):

                //Dimensions, expressed in points (1/72 inch):

                var cSignHeight = 18; //height of signature field

                var cSignMinWidth = 200; //Minimum width of signature above the signer's name

                var cFooterHeight = 12; //height of signature/annotations on footers

                var cSgnFootWidth = 380; //width of signature on footer

                var cMm2Pt = 72/25.4; //multiplier to convert mm to points

                var cRepSize = [297*cMm2Pt, 210*cMm2Pt] //report in a landscape A4-size PDF

                var cRepMargin = 10*cMm2Pt; //with 10mm borders

                //Colors and text appearance:

                var cSgnFilColr = color.transparent; //fill color of signatures. Sign. bar=["RGB",0.63,0.76,0.84]

                var cSignColor = ["RGB", 0.25, 0.45, 0.55]; //text and outline color of signatures

                var cFootNotColr = ["RGB", 0.0, 0.2, 0.3]; //text and outline color of footer annotations

                var cFootNotOpct = 0.7; //opacity of footer annotations

                var cFooterTextSize = 9; //footer text size

                //Date formats:

                var cDateFmtSec = "dd/mm/yyyy HH:MM:ss"; //date format with seconds

                var cDateFmtMin = "dd/mm/yyyy HH:MM"; //date format without seconds

                //This is the "appearance" of visible signature (in appearances.acrodata file), you must

                //create an appearance with this name, in Edit -> Preferences -> Security -> Appearances.

                //The recommended setting is "No graphic", and only "Reason" displayed.

                var cSignAppce = "BatchSigning";

                //File and field names:

                var cReportFile = "/C/temp/BatchSigningResult_%s.pdf"; //report file name (template) "/C/temp/"??

                var cAnnotName = "BatchSignAnnotation_p"; //names of footer annotations

                //Maximum milliseconds elapsed (from last document) to consider which is in the same batch run:

                var cTimeOutMs = 1000;

                //Error messages:

                var cAbortMessage = "Batch signing aborted.";

                var cLoginFailMsg = "Login failure!";

                var cSignFailMsg = "Signing failure for document ";

                var cNameNotFoundMsg = "Signer's name was not found, signing on footer";

                var cAddAnnotLinkErrMsg = "(Error adding Link/Annotation on page %d: %s)";

                //Texts which will appear on signatures and footer annotations:

                var cSignReason = "Digital signature of %CN% at %DATE%, as in law ....."; //sign reason

                var cTestSigRsn = "Digital signature of %CN% only for testing"; //only for testing

                var cFooterAnnot = "Document certified by digital signature, as in law .....";

                var cRepMsgOkFirst = "OK, first signature.";

                var cRepMsgOkAlrSgn = "OK, but already had been signed by other person(s).";

                var cRepMsgSkipped = "Already signed by the same person, nothing to do.";

                //Instructions in case of fail of test sign:

                var cTSignFailMsg = "Failure on test signing!\nVerify the default digital identity for signing "

                                  + "on \"Tools\"->\"Sign and Certify\"->\"More Sign and Certify\"->"

                                  + "\"Security Settings\", if the correct digital ID is set by default "

                                  + "(with the pen icon at left side of name).\nIf not, "

                                  + "select the correct ID with mouse and set as default, in "

                                  + "\"Usage Options\"->\"Use for Signing\".\nAlso verify if the smart card "

                                  + "is correctly inserted, and if all required drivers and softwares are installed."

                                  + "\nIf all appears OK, make a single signature to test and check.";

                //Report summary header (printf syntax):

                var cRepSummary = "Batch signing at %s\nCN=\"%s\" (%s)\n"

                                + "------------------------------------------------\n"

                                + "Results, and quantity of documents:\n"

                                + "%d - " + cRepMsgOkFirst + " - Signed over last ocurrence of signer's name.\n"

                                + "%d - " + cRepMsgOkFirst + " - " + cNameNotFoundMsg + ".\n"

                                + "%d - " + cRepMsgOkAlrSgn + " - Signed over last ocurrence of signer's name.\n"

                                + "%d - " + cRepMsgOkAlrSgn + " - " + cNameNotFoundMsg + ".\n"

                                + "%d - " + cRepMsgSkipped + "\n"

                                + "%d - With errors, or incomplete processing.\n"

                                + "------------------------------------------------\n"

                 

                //trim function, does not exist on Acrobat 10

                if (!String.prototype.trim) {

                  (function() {

                    String.prototype.trim = function() {

                      return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,''); }; }

                  )(); }

                 

                //console "add-on" function, to print all properties of a object literal:

                console.printObjProps = function(paHeader, paProps) {

                  this.println(paHeader);

                  for (var vProperty in paProps) this.println(vProperty+": "+paProps[vProperty]); };

                 

                //function to prepare names to search for, cleaning confusing characters

                function normalizeName(paText) {

                  if ((paText==null)||(typeof paText!="string")) return ""; //replace raises error if not a string

                  paText = paText.replace(/[ÀÁÂÃÄÅàáâãäåª]/g,"A"); //clean AEIOU, N, Y, Ç

                  paText = paText.replace(/[ÈÉÊË&èéêë]/g,"E");

                  paText = paText.replace(/[ÌÍÎÏìíîï]/g,"I");

                  paText = paText.replace(/[ÒÓÔÕÖòóôõöº]/g,"O");

                  paText = paText.replace(/[ÙÚÛÜùúûü]/g,"U");

                  paText = paText.replace(/[Ññ]/g,"N");

                  paText = paText.replace(/[Ýý]/g,"Y");

                  paText = paText.replace(/[Çç]/g,"C");

                  paText = paText.replace(/[-_\.\t\n\r\v\f]/g," "); //separators to spaces

                  paText = paText.replace(/[\s\uFEFF\xA0]{2,6}/g," "); //remove multiple spaces, up to 6

                  paText = paText.trim();

                  paText = paText.replace(/[^A-Z\s]/gi,""); //only letters and spaces are allowed

                  return paText.toUpperCase(); }

                 

                //function to get position of signature/annotation on footer, upper-left X Y and lower-right X Y

                function getPositionOnFooter(paPage) {

                var vBBox = this.getPageBox("BBox", paPage); //perimeter of actual visible content

                //console.println("BBox of page "+paPage+": "+vBBox);

                //look through all Fields and find the fields in this page outside BBox:

                var vNumFields = this.numFields;

                for (var vIField=0; vIField<vNumFields; vIField++) {

                  var vFieldName = this.getNthFieldName(vIField);

                  for (var vIWidget=0; ; vIWidget++) {

                    var vFieldWidget = this.getField(vFieldName+"."+vIWidget);

                    //console.println("Field "+vIField+"("+vFieldName+")."+vIWidget+" null?"+(vFieldWidget==null));

                    if (vFieldWidget == null) break;

                    try {

                      if ((vFieldWidget.hidden)||(vFieldWidget.display==display.hidden)) continue;

                      if (vFieldWidget.page!=paPage) continue;

                      vRect = vFieldWidget.rect; //expand the BBox

                      if (vRect[0]<vBBox[0]) vBBox[0] = vRect[0];

                      if (vRect[1]>vBBox[1]) vBBox[1] = vRect[1];

                      if (vRect[2]>vBBox[2]) vBBox[2] = vRect[2];

                      if (vRect[3]<vBBox[3]) vBBox[3] = vRect[3]; }

                    catch (e) {} } }

                //look all annotations to find annotations outside BBox:

                var vAnnots = this.getAnnots(paPage);

                if (vAnnots == null) vNumAnnots = 0;

                else vNumAnnots = vAnnots.length;

                for (var vIAnnot=0; vIAnnot<vNumAnnots; vIAnnot++) {

                  var vAnnot = vAnnots[vIAnnot];

                  if (vAnnot.hidden) continue;

                  vRect = convertULLRtoLLUR(vAnnot.rect); //expand the BBox

                  //console.println(vAnnot.name+" on p."+vAnnot.page+" rect="+vAnnot.rect);

                  if (vRect[0]<vBBox[0]) vBBox[0] = vRect[0];

                  if (vRect[1]>vBBox[1]) vBBox[1] = vRect[1];

                  if (vRect[2]>vBBox[2]) vBBox[2] = vRect[2];

                  if (vRect[3]<vBBox[3]) vBBox[3] = vRect[3]; }

                //console.println("expanded BBox of page "+paPage+": "+vBBox);

                var vPosition = [vBBox[0], vBBox[3], vBBox[0]+cSgnFootWidth, vBBox[3]-cFooterHeight]; //below BBox

                //console.println("BBox-derived Footer: "+vPosition);

                vPosition = ensureIsOnPage(paPage, vPosition, cSgnFootWidth, cFooterHeight);

                //console.println("Corrected footer: "+vPosition);

                return vPosition; }

                 

                //function to check and correct for positions outside ArtBox limits:

                function ensureIsOnPage(paPage, paPosition, paWidth, paHeight) {

                var vArtBox = this.getPageBox("Art", paPage); //limit to put visible content

                //console.println("ArtBox of page "+paPage+": "+vArtBox);

                //now check and correct for positions outside ArtBox limits:

                if (paPosition[0] < vArtBox[0]) { //left

                  paPosition[0] = vArtBox[0];

                  paPosition[2] = paPosition[0]+paWidth; }

                if (paPosition[2] > vArtBox[2]) { //rigth

                  paPosition[2] = vArtBox[2];

                  paPosition[0] = paPosition[2]-paWidth;

                  if (paPosition[0] < vArtBox[0]) paPosition[0] = vArtBox[0]; }

                if (paPosition[1] > vArtBox[1]) { //top

                  paPosition[1] = vArtBox[1];

                  paPosition[3] = paPosition[1]-paHeight; }

                if (paPosition[3] < vArtBox[3]) { //bottom

                  paPosition[3] = vArtBox[3];

                  paPosition[1] = paPosition[3]+paHeight;

                  if (paPosition[1] > vArtBox[1]) paPosition[1] = vArtBox[1]; }

                return paPosition; }

                 

                //function to Convert quads in default user space to rotated User space used by Links and fields.

                function defaultToUserSpace(paPage, paCoords) {

                  var vMatrix2D = (new Matrix2D).fromRotated(this, paPage);

                  var vMatrInv = vMatrix2D.invert(vMatrix2D);

                  return vMatrInv.transform(paCoords); }

                 

                //convert a rectangle on format (upper-left X Y and lower-right X Y) used by boxes and fields

                //to (lower-left X Y and upper-right X Y), used by annotations

                function convertULLRtoLLUR(paRect) {

                return [paRect[0], paRect[3], paRect[2], paRect[1]]; }

                 

                //look at persistent data (global object), to check if this run is a continue of a batch:

                function isContinuing() {

                if ((typeof global.gLastDate != "number") ||

                    (typeof global.gIniDate != "object") ||

                    (typeof global.gCntDocs != "number") ||

                    (typeof global.gReport != "object") ||

                    (typeof global.gRepDocs != "object") ||

                    (typeof global.gRepSumm != "object") ||

                    (typeof global.gRepSign != "object") ||

                    (typeof global.gResult != "object")) return false;

                return (Math.abs(Date.now()-global.gLastDate) < cTimeOutMs); }

                 

                //function to manage report: continues a batch processing, or starts a new report

                function manageReport(paContinuing) {

                //console.println("\nBEGIN "+this.documentFileName+" - Continuing="+paContinuing);

                if (paContinuing) {

                  this.vRepLine += "\n";

                  global.gCntDocs++; }

                else {

                  global.gIniDate = new Date();

                  global.gResult = {nFirstFound:0, nFstNotFound:0, nNotFstFound:0, nNotFstNotFnd:0,

                                     nSkipped:0, nIncomplete:0};

                  global.gReport = app.newDoc(cRepSize[0], cRepSize[1]); //blank report

                  global.gReport.layout = "SinglePage";

                  global.gReport.zoomType = zoomtype.fitP;

                  global.gReport.saveAs(util.printf(cReportFile, util.printd("yyyymmdd_HHMMss", global.gIniDate)));

                  var vBox = global.gReport.getPageBox("Crop"); //get crop box and add margins

                  vBox = [vBox[0]+cRepMargin, vBox[1]-cRepMargin, vBox[2]-cRepMargin, vBox[3]+cRepMargin];

                  var vHeight = vBox[1]-vBox[3];

                  var vWidth = vBox[2]-vBox[0];

                  var vSep = cRepMargin/8; //separation between fields = 1/8 of margin

                  //add docs report text field and adjust some attributes:

                  global.gRepDocs = global.gReport.addField("docs", "text", 0,

                                           [vBox[0], vBox[1]-vHeight*0.5, vBox[2], vBox[3]]);

                  global.gRepDocs.borderStyle = border.s;

                  global.gRepDocs.lineWidth = 1;

                  global.gRepDocs.doNotSpellCheck = true;

                  global.gRepDocs.multiline = true; // Multiline

                  global.gRepDocs.readonly = true;

                  global.gRepDocs.strokeColor = color.black;

                  global.gRepDocs.textSize = 9;

                  //add summary report text field and adjust some attributes:

                  global.gRepSumm = global.gReport.addField("summ", "text", 0,

                                           [vBox[0], vBox[1], vBox[0]+vWidth*0.8, vBox[1]-vHeight*0.5+vSep]);

                  global.gRepSumm.borderStyle = border.s;

                  global.gRepSumm.lineWidth = 1;

                  global.gRepSumm.doNotSpellCheck = true;

                  global.gRepSumm.multiline = true; // Multiline

                  global.gRepSumm.readonly = true;

                  global.gRepSumm.strokeColor = color.black;

                  global.gRepSumm.textSize = 11;

                  //add test signature field but don't sign it:

                  global.gRepSign = global.gReport.addField("sign", "signature", 0,

                                           [vBox[0]+vWidth*0.8+vSep, vBox[1], vBox[2], vBox[1]-vHeight*0.1]);

                  global.gRepSign.strokeColor = cSignColor;

                  global.gRepSign.textColor = cSignColor;

                  global.gRepSign.fillColor = cSgnFilColr;

                  global.gRepSign.borderStyle = border.s;

                  global.gCntDocs = 1; }

                //initial line information about document being processed:

                this.vRepLine += global.gCntDocs+" - "+this.documentFileName+" ("+this.numPages+"p)"; }

                 

                //function to start security handler, login, and get info about the signer

                function getSignerInfo() {

                var vHandler = security.getHandler(security.PPKLiteHandler, true);

                vHandler.login({bUI:true});

                if (!vHandler.isLoggedIn) throw cLoginFailMsg+"\n"+cAbortMessage;

                var vCert = vHandler.digitalIDs.oEndUserSignCert;

                //get the complete normalized name of certificate owner (the signer)

                var vSigner = normalizeName(vCert.subjectCN);

                var vNames = vSigner.split(" ");

                var vSignReason = cSignReason.replace("%CN%", vCert.subjectCN);

                vSignReason = vSignReason.replace("%DATE%", util.printd(cDateFmtMin, new Date()));

                //console.printObjProps("Reason:"+vSignReason);

                return {handler:vHandler, cert:vCert, reason: vSignReason,

                        nName:vSigner, names:vNames, numNames:vNames.length}; }

                 

                //function to increment counters and update report summary, saving it:

                function updateReportSummary(paIncrements) {

                if (paIncrements.nFirstFound!=null) global.gResult.nFirstFound += paIncrements.nFirstFound;

                if (paIncrements.nFstNotFound!=null) global.gResult.nFstNotFound += paIncrements.nFstNotFound;

                if (paIncrements.nNotFstFound!=null) global.gResult.nNotFstFound += paIncrements.nNotFstFound;

                if (paIncrements.nNotFstNotFnd!=null) global.gResult.nNotFstNotFnd += paIncrements.nNotFstNotFnd;

                if (paIncrements.nSkipped!=null) global.gResult.nSkipped += paIncrements.nSkipped;

                if (paIncrements.nIncomplete!=null) global.gResult.nIncomplete += paIncrements.nIncomplete;

                global.gRepSumm.value = util.printf(cRepSummary, util.printd(cDateFmtSec, global.gIniDate),

                                                    this.vSigInfo.cert.subjectCN, this.vSigInfo.nName,

                                                    global.gResult.nFirstFound, global.gResult.nFstNotFound,

                                                    global.gResult.nNotFstFound, global.gResult.nNotFstNotFnd,

                                                    global.gResult.nSkipped, global.gResult.nIncomplete);

                global.gReport.saveAs(global.gReport.path); }

                 

                //function to sign the report document, to test if all is ready to sign the batch docs

                function doTestSigning() {

                global.gRepSumm.value = cTSignFailMsg; //if signature fails, the content will be this fail msg

                var vSignReason = cTestSigRsn.replace("%CN%", this.vSigInfo.cert.subjectCN);

                if (!global.gRepSign.signatureSign(this.vSigInfo.handler,

                                                   {reason:vSignReason, appearance:cSignAppce}))

                  throw cSignFailMsg; }

                 

                //function to look through all Fields and find the signature fields

                function getExistingSignatures() {

                var vNumFields = this.numFields;

                var vSignatures = [];

                for (var vIField=0; vIField<vNumFields; vIField++) {

                  var vFieldName = this.getNthFieldName(vIField);

                  var vField = this.getField(vFieldName);

                  if (vField == null) continue;

                  if (vField.type != "signature") continue;

                  var vSignInfo = vField.signatureInfo();

                  if (vSignInfo == null) continue;

                  //console.println("Field "+vFieldName+" rect:"+vField.rect+" signer's name:"+vSignInfo.name);

                  //check if already signed by this same signer, and throw a specific error:

                  if (normalizeName(vSignInfo.name) == normalizeName(this.vSigInfo.nName)) {

                    updateReportSummary({nSkipped:1, nIncomplete:-1});

                    event.rc = true; //don't abort the batch, only skip this document!

                    throw util.printf(cRepMsgSkipped, this.vSigInfo.nName) } ;

                  vSignatures.push(vFieldName); }

                return vSignatures; }

                 

                //function to search for last ocurrence of signer's complete name within the document

                function getSignaturePosition() {

                var vFound = false;

                //console.println("Searching document, "+this.numPages+" page(s):");

                lSearch: for (var vIPage=this.numPages-1; vIPage>=0; vIPage--) {

                  //for each page:

                  var vArrayWords = [];

                  var vArrPositions = [];

                  var vNamesFound = 0;

                  var vNumWords = this.getPageNumWords(vIPage);

                  //console.println("Page "+vIPage+": "+vNumWords+" word(s)");

                  //populate arrays with valid words and their respective positions on page (Nth)

                  for (var vIWord=0; vIWord<vNumWords; vIWord++) {

                    vTWord = normalizeName(this.getPageNthWord(vIPage, vIWord));

                    if (vTWord.length > 0) {

                      vArrayWords.push(vTWord);

                      vArrPositions.push(vIWord); } }

                  var vNumWords = vArrayWords.length; //number of valid words on page

                  //search the array of valid words (from end to begin) for signer's names in sequence

                  for (vIWord=vNumWords-1; vIWord>=0; vIWord--) {

                    if (vArrayWords[vIWord] == this.vSigInfo.names[this.vSigInfo.numNames-1-vNamesFound]) {

                      vNamesFound++;

                      if (vNamesFound == this.vSigInfo.numNames) {

                        vFound = true;

                        break lSearch; } }

                    else vNamesFound = 0; } }

                //calculate position of signature field above the signer's name

                if (vFound) {

                  var vLeft = -1;

                  var vRight = -1;

                  var vTop = -1;

                  for (var vIName=0; vIName<this.vSigInfo.numNames; vIName++) {

                    var vPosName = vArrPositions[vIWord+vIName];

                    var vQuads = this.getPageNthWordQuads(vIPage, vPosName)[0]; //coords of each name (words)

                    //console.println(this.vSigInfo.names[vIName]+": p."+vIPage+"("+vPosName+") \""

                    //               +this.getPageNthWord(vIPage, vPosName)+"\"");

                    for (var vIPoint=0; vIPoint<=((vQuads.length-1)/2); vIPoint++) { //get the opposite corners

                      var vQuadX = vQuads[vIPoint*2];

                      var vQuadY = vQuads[vIPoint*2+1];

                      if (vQuadX<vLeft || vLeft<0) vLeft = vQuadX;

                      if (vQuadX>vRight || vRight<0) vRight = vQuadX;

                      if (vTop<vQuadY || vTop<0) vTop = vQuadY; } }

                  if ((vRight-vLeft)<cSignMinWidth) {

                    var vDif = (cSignMinWidth-(vRight-vLeft))/2;

                    vRight += vDif;

                    vLeft -= vDif; };

                  //coordinates for signature, upper-left X Y and lower-right X Y

                  vSignCoords = [vLeft, vTop+cSignHeight, vRight, vTop];

                  vSignCoords = ensureIsOnPage(vIPage, vSignCoords, cSignMinWidth, cSignHeight); }

                else {

                  //console.println("Signer's complete name was not found!");

                  this.vRepLine += " - "+cNameNotFoundMsg;

                  //set default position for signature field on the footer of last page:

                  vIPage=this.numPages-1;

                  vSignCoords = getPositionOnFooter(vIPage); }

                return {found:vFound, page:vIPage, rect:vSignCoords}; }

                 

                //function to add the annotations on footer of each page:

                function addAnnotations() {

                for (var vIPag2=this.numPages-1; vIPag2>=0; vIPag2--) {

                  if (vIPag2 == this.vSigPos.page) continue; //don't create footer annotation on signature's page.

                  var vAnnot = this.getAnnot(vIPag2, cAnnotName+vIPag2); // get previous annotation if exists

                  if (vAnnot != null) {

                    //console.printObjProps("Annot. "+cAnnotName+vIPag2+" already exists:", vAnnot.getProps());

                    continue; } //already exists, skip page

                  var vSignCoords = getPositionOnFooter(vIPag2); //create new annotation:

                  //console.println("New annotation: p."+vIPag2+" coords: "+vSignCoords);

                  try { //addAnnot may fail if security options prohibits new annotations

                    vAnnot = this.addAnnot({page:vIPag2, type:"FreeText", rect:convertULLRtoLLUR(vSignCoords),

                                            opacity:cFootNotOpct, print:true, strokeColor:cFootNotColr,

                                            name:cAnnotName+vIPag2, fillColor:cSgnFilColr, width:1, style:"S",

                                            richDefaults:{alignment:1, textSize:cFooterTextSize,

                                                           textFont:font.Helv, textColor:cFootNotColr}});

                    //text content must be set AFTER set richDefaults, to take effect!

                    vAnnot.setProps({contents: cFooterAnnot, readOnly: true});

                    //add links to signature panel over the footer annotations:

                    if (this.signatureFieldNames.length == 0) { //only if document isn't already signed

                      var vLink = this.addLink(vIPag2, defaultToUserSpace(vIPag2, vSignCoords));

                      vLink.borderColor = cFootNotColr;

                      vLink.borderWidth = 0;

                      vLink.setAction("app.execMenuItem(\"ShowHideSignatures\");"); } }

                  catch (e) {

                    this.vRepLine += " "+util.printf(cAddAnnotLinkErrMsg, vIPag2, vError); } } }

                 

                //function to search for a field name which does not already exists and add a new signature:

                function addSignature() {

                vIField = 0;

                do {

                  vIField++;

                  vFieldName = "Signature"+vIField;

                  var vField = this.getField(vFieldName); }

                while (vField != null);

                //console.println("Coordinates of new signature field \""+vFieldName+"\": "+this.vSigPos.rect);

                vField = this.addField(vFieldName, "signature", this.vSigPos.page,

                                       defaultToUserSpace(this.vSigPos.page, this.vSigPos.rect));

                vField.strokeColor = cSignColor;

                vField.textColor = cSignColor;

                vField.fillColor = cSgnFilColr;

                vField.borderStyle = border.s;

                //sign the signature field and save (overwrite) the document, this is done by SignatureSign:

                if (!vField.signatureSign(this.vSigInfo.handler,

                                          {reason:this.vSigInfo.reason, appearance:cSignAppce}))

                  throw cSignFailMsg+" "+this.documentFileName;

                //report the results:

                var vFound = Number(this.vSigPos.found);

                var vNotFnd = Number(!this.vSigPos.found);

                if (this.signatureFieldNames.length == 0) {

                  updateReportSummary({nFirstFound:vFound, nFstNotFound:vNotFnd, nIncomplete:-1});

                  this.vRepLine += " - "+cRepMsgOkFirst; }

                else {

                  updateReportSummary({nNotFstFound:vFound, nNotFstNotFnd:vNotFnd, nIncomplete:-1});

                  this.vRepLine += " - "+cRepMsgOkAlrSgn; } }

                 

                //----------- BEGIN OF PROCESSING -----------

                //console.show();

                event.rc = false; //if an error ocurs, the script won't run for next docs

                //almost all processing is within this try...catch statement:

                try {

                  this.vRepLine = ""; //report line

                  var vContinuing = isContinuing(); //check time elapsed since last run

                  //start or continue the report:

                  manageReport(vContinuing);

                  //get security and signer info, and do the test signing:

                  this.vSigInfo = getSignerInfo();

                  if (!vContinuing) doTestSigning();

                  updateReportSummary({nIncomplete:1}); //document being processed is incomplete

                  //search document for correct signature position:

                  this.syncAnnotScan(); //read all annotations

                  this.signatureFieldNames = getExistingSignatures();

                  this.vSigPos = getSignaturePosition();

                  //add annotations and signature to document:

                  addAnnotations();

                  addSignature();

                  event.rc = true; //no error happened, enable run for next docs

                  } //end of main try...catch

                catch (vError) { //get error message and put it on report:

                  if (event.rc) this.vRepLine += " - "+vError; //not an aborting error: only displays for this doc

                  else { //display error and abort batch processing

                    var vLineNumber = "";

                    if (typeof vError.lineNumber == "number") vLineNumber = " ("+vError.lineNumber+")";

                    this.vRepLine += "\n"+vError+vLineNumber+"\n"+cAbortMessage;

                    app.alert(vError+vLineNumber+" - "+cAbortMessage); } }

                 

                //append this.vRepLine at end of report (and summary if aborting!):

                try {

                  global.gRepDocs.value += this.vRepLine;

                  if (!event.rc) global.gRepSumm.value = this.vRepLine+"\n--------------\n"+global.gRepSumm.value;

                  global.gReport.saveAs(global.gReport.path);

                  global.gLastDate = Date.now(); } //save last datetime for processing control

                catch (vError) {

                  if (event.rc) event.rc = false; //don't continue batch if was unable to append a report line

                  else app.alert(this.vRepLine+" - "+vError.message+" - "+cAbortMessage); };

                //end of script