浏览代码

add: 获取签名信息

wzl 11 月之前
父节点
当前提交
70cbed37ec

+ 10 - 4
packages/core/src/index.js

@@ -1072,9 +1072,7 @@ class ComPDFKitViewer {
       }
     }
 
-    const signatures = await this.messageHandler.sendWithPromise('GetSignatures', {
-      doc: this.doc,
-    })
+    await this.getSignatures()
 
     this.pdfViewer.pagesPtr = this.pagesPtr
 
@@ -3591,9 +3589,17 @@ class ComPDFKitViewer {
     }
   }
 
-  deleteSignature (signature) {
+  deleteSignature(signature) {
     this.eventBus.dispatch('deleteSignature', signature)
   }
+
+  async getSignatures() {
+    const signatureList = await this.messageHandler.sendWithPromise('GetSignatures', {
+      doc: this.doc
+    })
+    this.eventBus.dispatch('getSignatures', signatureList)
+    return signatureList
+  }
 }
 
 class PDFWorker {

+ 111 - 5
packages/core/src/worker/compdfkit_worker.js

@@ -34,6 +34,10 @@ let TextRectArray = []
 ImageAreaInfo = {}
 SignerArray = []
 CertArray = []
+AccessInfoArray = []
+PolicyArray = []
+CRLPointArray = []
+OCSPUrlArray = []
 
 import MessageHandler from "../message_handler"
 import { convertFileToBuffer, convertBase64ToBytes } from '../fileHandler';
@@ -1455,6 +1459,12 @@ class CPDFWorker {
         rect.top
       )
     })
+
+    messageHandler.on('RemoveSignature', (data) => {
+      const { doc, signPrt } = data
+
+      return Module._RemoveSignature(doc, signPrt)
+    })
   }
 }
 
@@ -2386,7 +2396,6 @@ async function getSignatures({
 }) {
   const signatureList = []
   const count = Module._GetSignatureCount(doc)
-  console.log(count)
 
   for (let i = 0; i < count; i++) {
     // 获取签名指针
@@ -2416,9 +2425,60 @@ async function getSignatures({
 
           const certPtr = Module._GetSignCert(signerPtr)
 
-          console.log('certPtr', certPtr)
           let result = false
+          
           if (certPtr) {
+            signer.version = Module._GetSignVersion(certPtr)
+            Module._GetSignAlgOid(certPtr)
+            signer.signAlgOid = U8StringData
+            signer.signAlgOidType = getSignatureAlgorithmType(signer.signAlgOid)
+            signer.subject = []
+            for (let i = 0; i < 7; i++) {
+              Module._GetSignSubject(certPtr, i)
+              signer.subject.push(U8StringData)
+            }
+            signer.issuer = []
+            for (let i = 0; i < 7; i++) {
+              Module._GetSignIssuer(certPtr, i)
+              signer.issuer.push(U8StringData)
+            }
+            Module._GetSignSerialNumber(certPtr)
+            signer.serialNumber = U8StringData
+            Module._GetSignValidDate(certPtr, 0)
+            signer.validDateStart = U8StringData
+            Module._GetSignValidDate(certPtr, 1)
+            signer.validDateEnd = U8StringData
+
+            AccessInfoArray = []
+            Module._GetAuthorityInfoAccess(certPtr)
+            signer.sccessInfo = AccessInfoArray
+            Module._GetSubjectKeyIdentifier(certPtr)
+            signer.subjectKeyIdentifier = U8StringData
+            signer.keyUsage = Module._GetKeyUsage(certPtr)
+            PolicyArray = []
+            Module._GetCertificatePolicies(certPtr)
+            signer.certificatePolicies = PolicyArray
+            Module._GetAuthorityKeyIdentifier(certPtr)
+            signer.authorityKeyIdentifier = U8StringData
+            CRLPointArray = []
+            Module._GetCRLDistributionPoints(certPtr)
+            signer.CRLDistributionPoints = CRLPointArray
+
+            Module._GetBasicConstraints(certPtr)
+            signer.basicConstraints = U8StringData
+            Module._GetPublicKey(certPtr)
+            signer.publicKey = U8StringData
+            Module._GetX509Data(certPtr)
+            signer.X509Data = U8StringData
+            Module._GetSHA1Digest(certPtr)
+            signer.SHA1Digest = U8StringData
+            Module._GetMD5Digest(certPtr)
+            signer.MD5Digest = U8StringData
+
+            OCSPUrlArray = []
+            Module._GetOCSPUrl(certPtr)
+            signer.ocspURL = OCSPUrlArray
+
             // TODO: 验证证书
             CertArray = []
             Module._ExportToFilePath(certPtr, 1)
@@ -2466,14 +2526,32 @@ async function getSignatures({
         }
       }
 
+      // 获取签名信息
+      Rect = {}
+      Module._GetSignatureRect(doc, signaturePtr)
+      signature.rect = {
+        left: roundToDecimalPlaces(Rect.Left),
+        top: roundToDecimalPlaces(Rect.Top),
+        right: roundToDecimalPlaces(Rect.Right),
+        bottom: roundToDecimalPlaces(Rect.Bottom)
+      }
+      Module._GetSignatureFieldName(signaturePtr)
+      signature.fieldName = U8StringData
       Module._GetSignatureName(signaturePtr)
-      const data = U8StringData
+      signature.name = U8StringData
+      Module._GetSignatureTime(signaturePtr)
+      const rawDate = U8StringData
+      signature.date = parseAdobePDFTimestamp(rawDate)
+      Module._GetSignatureReason(signaturePtr)
+      signature.reason = U8StringData
+      Module._GetSignatureLocation(signaturePtr)
+      signature.location = U8StringData
+      signature.pageIndex = Module._GetSignaturePageIndex(signaturePtr)
 
-      console.log('data', data)
       signatureList.push(signature)
-      console.log('signatureList', signatureList)
     }
   }
+  return signatureList
 }
 
 async function copyDocument(doc, password) {
@@ -3009,3 +3087,31 @@ function extractImage(data) {
   _free(imageptr)
   return imageArray
 }
+
+function getSignatureAlgorithmType(signAlgOid) {
+  switch (signAlgOid) {
+    case "1.2.840.113549.1.1.1":
+      return 'RSA_RSA';
+
+    case "1.2.840.113549.1.1.2":
+      return 'MD2RSA';
+
+    case "1.2.840.113549.1.1.3":
+      return 'MD4RSA';
+
+    case "1.2.840.113549.1.1.4":
+      return 'MD5RSA';
+
+    case "1.2.840.113549.1.1.5":
+      return 'SHA1RSA';
+
+    case "1.2.840.113549.1.1.11":
+      return 'SHA256RSA';
+
+    case "1.2.156.10197.1.501":
+      return 'SM3SM2';
+
+    default:
+      return 'RSA_RSA';
+  }
+}

+ 1 - 0
packages/webview/src/components/AnnotationContainer/AnnotationContent.vue

@@ -47,6 +47,7 @@
   const markup = ['highlight', 'underline', 'squiggly', 'strikeout']
 
   const setAnnotationList = ({ annotations }) => {
+    console.log(annotations)
     useDocument.initAnnotations(annotations)
     const instance = getCurrentInstance();
     instance?.proxy?.$forceUpdate();

+ 69 - 27
packages/webview/src/components/Dialogs/CertificationViewerDialog.vue

@@ -8,8 +8,13 @@
 
       <div class="container">
         <div class="left">
-          <p :class="{ 'highlighted': isHighlighted === 0 }" @focus="isHighlighted = 0" @blur="isHighlighted = -1" tabindex="-1">ComPDFKit 1</p>
-          <p :class="{ 'highlighted': isHighlighted === 1 }" @focus="isHighlighted = 1" @blur="isHighlighted = -1" tabindex="-1">ComPDFKit 2</p>
+          <p v-for="(signer, index) in signature.signerList" :key="index"
+            :class="{ 'highlighted': selectedSignerIndex === index }"
+            @focus="selectedSignerIndex = index"
+            @blur="selectedSignerIndex = 0"
+            tabindex="-1">
+            {{ signer.issuer[3] }}
+          </p>
         </div>
 
         <div class="right">
@@ -27,32 +32,32 @@
               </div>
               <div class="content">
                 <div v-show="activePanel === 1" class="abstracts">
-                  <p>{{ $t('signatures.certificateViewerDialog.issuedTo') }} <span>ComPDFKit&lt;12341234@qq.com&gt;</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.issuer') }} <span>ComPDFKit</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.validFrom') }} <span>2021/01/27 13:41:56 +08`00`</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.validTo') }} <span>Digital Signatures, Encrypted Documents, Key Agreements</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.issuedTo') }} <span>{{ selectedSigner.issuer[3] }}&lt;{{ selectedSigner.issuer[6] }}&gt;</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.issuer') }} <span>{{ selectedSigner.issuer[3] }}</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.validFrom') }} <span>{{ formatDate(selectedSigner.validDateStart) }}</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.validTo') }} <span>{{ formatDate(selectedSigner.validDateEnd) }}</span></p>
                   <p>{{ $t('signatures.certificateViewerDialog.intendedUsage') }} <span>Digital Signature, Non-Repudiation</span></p>
                 </div>
 
                 <div v-show="activePanel === 2" class="details">
-                  <p>{{ $t('signatures.certificateViewerDialog.version') }} <span>1.9.0</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.algorithm') }} <span>SHA - 256 with RSA encryption (1.2.840.113549.1.11)</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.subject') }} <span>C=CN,O=ComPDFKit</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.issuer') }} <span>ComPDFKit</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.serialNumber') }} <span>3223484506630560670</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.validFrom') }} <span>2021/01/27 13:41:56 +08`00`</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.validTo') }} <span>2021/01/27 13:41:56 +08`00`</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.certificatePolicy') }} <span>Windows Certificate Policy</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.crlDistributionPoints') }} <span>/</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.issuerInfoAccess') }} <span>223384759660</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.issuerKeyIdentifier') }} <span>223384759660</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.subjectKeyIdentifier') }} <span>/</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.basicConstraints') }} <span>View Detailed Information</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.keyUsage') }} <span>/</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.publicKey') }} <span>256 bytes: D3 10 27 F7 23</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.X509') }} <span>Unspecified value</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.SHA1Digest') }} <span>/</span></p>
-                  <p>{{ $t('signatures.certificateViewerDialog.MD5Digest') }} <span>50:28:38:22:09:34:63</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.version') }} <span>{{ selectedSigner.version }}</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.algorithm') }} <span>{{ selectedSigner.signAlgOidType }} ({{ selectedSigner.signAlgOid }})</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.subject') }} <span>C={{ selectedSigner.subject[0] }},ST={{ selectedSigner.subject[1] }},L={{ selectedSigner.subject[2] }},O={{ selectedSigner.subject[3] }},OU={{ selectedSigner.subject[4] }},CN={{ selectedSigner.subject[5] }},emailAddress={{ selectedSigner.subject[6] }}</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.issuer') }} <span>C={{ selectedSigner.issuer[0] }},ST={{ selectedSigner.issuer[1] }},L={{ selectedSigner.issuer[2] }},O={{ selectedSigner.issuer[3] }},OU={{ selectedSigner.issuer[4] }},CN={{ selectedSigner.issuer[5] }},emailAddress={{ selectedSigner.issuer[6] }}</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.serialNumber') }} <span>{{ selectedSigner.serialNumber }}</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.validFrom') }} <span>{{ formatDate(selectedSigner.validDateStart) }}</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.validTo') }} <span>{{ formatDate(selectedSigner.validDateEnd) }}</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.certificatePolicy') }} <span>{{ selectedSigner.certificatePolicies[0] }}</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.crlDistributionPoints') }} <span>{{ selectedSigner.CRLDistributionPoints }}</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.issuerInfoAccess') }} <span v-for="(info, index) in selectedSigner.sccessInfo" :key="index">{{ info.Key }}={{ info.AccessInfo }}{{ index === selectedSigner.sccessInfo.length - 1 ? '' : ',' }}</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.issuerKeyIdentifier') }} <span>{{ selectedSigner.authorityKeyIdentifier }}</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.subjectKeyIdentifier') }} <span>{{ selectedSigner.subjectKeyIdentifier }}</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.basicConstraints') }} <span>{{ selectedSigner.basicConstraints }}</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.keyUsage') }} <span>{{ selectedSigner.keyUsage }}</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.publicKey') }} <span>{{ selectedSigner.publicKey }}</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.X509') }} <span>{{ selectedSigner.X509Data }}</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.SHA1Digest') }} <span>{{ selectedSigner.SHA1Digest }}</span></p>
+                  <p>{{ $t('signatures.certificateViewerDialog.MD5Digest') }} <span>{{ selectedSigner.MD5Digest }}</span></p>
                 </div>
 
                 <div v-show="activePanel === 3" class="trust">
@@ -79,19 +84,50 @@
 <script setup>
 import { computed, ref } from 'vue'
 import { useViewerStore } from '@/stores/modules/viewer'
+import { useDocumentStore } from '@/stores/modules/document'
 
 const dialogName = 'certificateViewerDialog'
 
 const useViewer = useViewerStore()
+const useDocument = useDocumentStore()
 
 const show = computed(() => useViewer.isElementOpen(dialogName))
+const signature = computed(() => useDocument.getSelectedSignature)
+const selectedSigner = computed(() => signature.value.signerList[selectedSignerIndex.value])
 
 const activePanel = ref(1)
-const isHighlighted = ref(-1)
+const selectedSignerIndex = ref(0)
 
 const close = () => {
   useViewer.closeElement(dialogName)
 }
+
+const formatDate = (dateStr) => {
+    // const isoString = dateStr.replace(/Z$/, '')
+
+    // const utcDate = new Date(isoString)
+    // const localDate = new Date(utcDate.getTime() + (utcDate.getTimezoneOffset() * 60000))
+
+    // const year = localDate.getFullYear()
+    // const month = String(localDate.getMonth() + 1).padStart(2, '0')
+    // const day = String(localDate.getDate()).padStart(2, '0')
+    // const hours = String(localDate.getHours()).padStart(2, '0')
+    // const minutes = String(localDate.getMinutes()).padStart(2, '0')
+    // const seconds = String(localDate.getSeconds()).padStart(2, '0')
+
+    // const timeZoneOffset = '+0800'
+    // return `${year}/${month}/${day} ${hours}:${minutes}:${seconds} ${timeZoneOffset}`
+
+    let year = dateStr.slice(0, 4)
+    let month = dateStr.slice(4, 6)
+    let day = dateStr.slice(6, 8)
+    let hours = dateStr.slice(8, 10)
+    let minutes = dateStr.slice(10, 12)
+    let seconds = dateStr.slice(12, 14)
+    
+    return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`
+
+}
 </script>
 
 <style lang="scss">
@@ -224,8 +260,14 @@ const close = () => {
               color: var(--c-side-annotation-text);
             }
 
-            .details p {
-              color: var(--c-black-text);
+            .details {
+              overflow-y: auto;
+              max-height: 564px;
+
+              p {
+                color: var(--c-black-text);
+                word-break: break-all;
+              }
             }
 
             .trust p {

+ 21 - 2
packages/webview/src/components/Dialogs/SignatureDetailsDialog.vue

@@ -11,8 +11,8 @@
         <SignatureInvalid v-else-if="signature?.state === 'invalid'" />
         <SignatureUnknown v-else />
         <div>
-          <p class="title">{{ $t('signatures.detailsDialog.signBy') }} "ComPDFKit &lt;12341234@qq.com&gt;".</p>
-          <p class="desc">{{ $t('signatures.detailsDialog.signingTime') }} 2023-8-11 05:00:53 PM/AM (EST)</p>
+          <p class="title">{{ $t('signatures.detailsDialog.signBy') }} "{{ signature.signerList[0].issuer[3] }} &lt;{{ signature.signerList[0].issuer[6] }}&gt;".</p>
+          <p class="desc">{{ $t('signatures.detailsDialog.signingTime') }} {{ formatDate(signature.date) }}</p>
         </div>
       </div>
 
@@ -64,6 +64,25 @@ const openDialog = () => {
   close()
   useViewer.openElement('certificateViewerDialog')
 }
+
+const formatDate = (date) => {
+  return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()} ${formatAMPM(date.getHours())}:${addZero(date.getMinutes())}:${addZero(date.getSeconds())} ${getESTorEDT(date)}`
+}
+const formatAMPM = (hours) => {
+  return hours >= 12 ? 'PM' : 'AM'
+}
+const addZero = (num) => {
+  return num < 10 ? '0' + num : num
+}
+const getESTorEDT = (date) => {
+  let jan = new Date(date.getFullYear(), 0, 1)
+  let jul = new Date(date.getFullYear(), 6, 1)
+  if (date.getTimezoneOffset() < Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset())) {
+    return 'EST'
+  } else {
+    return 'EDT'
+  }
+}
 </script>
 
 <style lang="scss">

+ 12 - 2
packages/webview/src/components/SignatureContainer/SignatureContainer.vue

@@ -7,7 +7,7 @@
           <SignatureValid v-if="signature.state === 'valid'" />
           <SignatureInvalid v-else-if="signature.state === 'invalid'" />
           <SignatureUnknown v-else />
-          <span :title="signature.name">{{ signature.type }}</span>
+          <span :title="signature.name">{{ signature.name }}</span>
           <n-popover
             placement="bottom-start"
             trigger="click"
@@ -40,7 +40,7 @@
 </template>
 
 <script setup>
-import { computed, ref } from 'vue'
+import { computed, ref, getCurrentInstance } from 'vue'
 import core from '@/core'
 import { useViewerStore } from '@/stores/modules/viewer'
 import { useDocumentStore } from '@/stores/modules/document'
@@ -54,7 +54,16 @@ const selectedSignature = computed(() => useDocument.getSelectedSignature)
 
 const showPopover = ref(false)
 
+const setSignaturesList = (signatures) => {
+  console.log(signatures)
+  useDocument.initSignatures(signatures)
+  const instance = getCurrentInstance()
+  instance?.proxy?.$forceUpdate()
+}
+core.addEvent('getSignatures', setSignaturesList)
+
 const goToPage = (page) => {
+  if (page < 0) return
   core.pageNumberChanged({
     value: (page * 1 + 1).toString()
   })
@@ -73,6 +82,7 @@ const openDialog = (name) => {
 const selectSign = (data) => {
   showPopover.value = true
   useDocument.setSelectedSignature(data)
+  console.log(data)
 }
 </script>
 

+ 4 - 5
packages/webview/src/stores/modules/document.js

@@ -191,7 +191,6 @@ export const useDocumentStore = defineStore({
         annotationsCount: 0
       }
       const annotations = this.annotations
-      this.signatures = []
 
       for (const page in annotations) {
         const pageAnnotations = annotations[page]
@@ -230,10 +229,6 @@ export const useDocumentStore = defineStore({
               annotationsContainers.annotationsCount++
               annotationsContainers.annotations[page].annotations.push(pageAnnotations[i])
             }
-
-            if (pageAnnotations[i].type === 'signatureFields') {
-              this.signatures.push(pageAnnotations[i])
-            }
           }
         }
       }
@@ -442,6 +437,10 @@ export const useDocumentStore = defineStore({
     },
     setSelectedSignature (data) {
       this.selectedSignature = data
+    },
+    initSignatures (signatures) {
+      this.signatures = null
+      this.signatures = signatures
     }
   }
 })