mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 14:53:44 +08:00
Compare commits
2
Commits
44eb9e20b9
...
f2c71c5acf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f2c71c5acf | ||
|
|
b59d82a68a |
No files matched your search
@@ -876,7 +876,7 @@
|
|||||||
<section id="signaturePanel" class="signature-panel" hidden>
|
<section id="signaturePanel" class="signature-panel" hidden>
|
||||||
<div class="panel-row">
|
<div class="panel-row">
|
||||||
<div id="signaturePanelTitle" class="panel-title compact">签名</div>
|
<div id="signaturePanelTitle" class="panel-title compact">签名</div>
|
||||||
<span id="signatureSummary" class="count-pill">0</span>
|
<div class="panel-actions"><span id="signatureSummary" class="count-pill">0</span><button id="signatureClear" class="small-button" type="button" hidden>清空</button></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="signatureList" class="signature-list"></div>
|
<div id="signatureList" class="signature-list"></div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
+26
-2
@@ -638,6 +638,7 @@ const el = {
|
|||||||
structureStatus: document.querySelector("#structureStatus"),
|
structureStatus: document.querySelector("#structureStatus"),
|
||||||
structureSubmit: document.querySelector("#structureSubmit"),
|
structureSubmit: document.querySelector("#structureSubmit"),
|
||||||
signatureSummary: document.querySelector("#signatureSummary"),
|
signatureSummary: document.querySelector("#signatureSummary"),
|
||||||
|
signatureClear: document.querySelector("#signatureClear"),
|
||||||
signatureList: document.querySelector("#signatureList"),
|
signatureList: document.querySelector("#signatureList"),
|
||||||
annotationNote: document.querySelector("#annotationNote"),
|
annotationNote: document.querySelector("#annotationNote"),
|
||||||
annotationNoteTitle: document.querySelector("#annotationNoteTitle"),
|
annotationNoteTitle: document.querySelector("#annotationNoteTitle"),
|
||||||
@@ -1476,6 +1477,7 @@ el.objectStyleForm.addEventListener("submit", async event => {
|
|||||||
});
|
});
|
||||||
el.outlineCancel.addEventListener("click", () => el.outlinePanel.close());
|
el.outlineCancel.addEventListener("click", () => el.outlinePanel.close());
|
||||||
el.structureManage.addEventListener("click", openStructureDialog);
|
el.structureManage.addEventListener("click", openStructureDialog);
|
||||||
|
el.signatureClear.addEventListener("click", () => changeDocument("ofdgoChangeSignature", null, "clear", ""));
|
||||||
document.querySelector("#structureCancel").addEventListener("click", () => el.structureDialog.close());
|
document.querySelector("#structureCancel").addEventListener("click", () => el.structureDialog.close());
|
||||||
el.structureEntry.addEventListener("change", refreshStructureNodes);
|
el.structureEntry.addEventListener("change", refreshStructureNodes);
|
||||||
el.structureNodeSelect.addEventListener("change", refreshStructureFields);
|
el.structureNodeSelect.addEventListener("change", refreshStructureFields);
|
||||||
@@ -9190,6 +9192,17 @@ function renderSecurity() {
|
|||||||
el.encryptSaveButton.disabled = !state.doc || !state.ready || state.exporting || state.saving || document.body.hasAttribute("data-busy");
|
el.encryptSaveButton.disabled = !state.doc || !state.ready || state.exporting || state.saving || document.body.hasAttribute("data-busy");
|
||||||
el.verifyButton.disabled = el.encryptSaveButton.disabled;
|
el.verifyButton.disabled = el.encryptSaveButton.disabled;
|
||||||
el.signButton.disabled = el.encryptSaveButton.disabled;
|
el.signButton.disabled = el.encryptSaveButton.disabled;
|
||||||
|
el.signatureClear.hidden = !state.editing;
|
||||||
|
el.signatureClear.disabled = el.encryptSaveButton.disabled || !state.editing || !!state.doc?.detailsPending || !state.doc?.signatures?.length;
|
||||||
|
const scope = JSON.stringify([documentTab().id, documentContentKey(state)]);
|
||||||
|
if (!state.doc?.detailsPending || metaContents.get(el.signaturePanel) !== scope) {
|
||||||
|
renderMetaContent(el.signatureList, [scope, state.doc?.signatures, state.doc?.signatureError, state.editing], renderSignatures);
|
||||||
|
metaContents.set(el.signaturePanel, scope);
|
||||||
|
}
|
||||||
|
for (const button of el.signatureList.querySelectorAll(".signature-remove")) {
|
||||||
|
button.hidden = !state.editing;
|
||||||
|
button.disabled = el.signatureClear.disabled;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancelSigning() {
|
function cancelSigning() {
|
||||||
@@ -11540,7 +11553,6 @@ function renderMeta(keepDetails = false) {
|
|||||||
el.pageTotal.textContent = String(doc.pageCount || 0);
|
el.pageTotal.textContent = String(doc.pageCount || 0);
|
||||||
if (keepDetails && doc.detailsPending) return;
|
if (keepDetails && doc.detailsPending) return;
|
||||||
el.metaSignatures.textContent = doc.detailsPending ? "正在检查签名" : doc.detailsError ? "读取失败" : String(doc.signatureCount || 0);
|
el.metaSignatures.textContent = doc.detailsPending ? "正在检查签名" : doc.detailsError ? "读取失败" : String(doc.signatureCount || 0);
|
||||||
renderMetaContent(el.signatureList, [doc.signatures, doc.signatureError], renderSignatures);
|
|
||||||
updateStructureControls();
|
updateStructureControls();
|
||||||
renderMetaContent(el.docFontList, doc.fonts || [], renderDocumentFonts);
|
renderMetaContent(el.docFontList, doc.fonts || [], renderDocumentFonts);
|
||||||
refreshEditorFonts();
|
refreshEditorFonts();
|
||||||
@@ -11811,6 +11823,18 @@ function renderSignatures() {
|
|||||||
badges.className = "signature-badges";
|
badges.className = "signature-badges";
|
||||||
badges.append(fontBadge(signature.trustedValid ? "可信" : signature.status === "valid" ? "完整" : signature.status === "invalid" ? "异常" : "未验", signature.status));
|
badges.append(fontBadge(signature.trustedValid ? "可信" : signature.status === "valid" ? "完整" : signature.status === "invalid" ? "异常" : "未验", signature.status));
|
||||||
|
|
||||||
|
if (state.editing) {
|
||||||
|
const tab = documentTab(), key = documentContentKey(state);
|
||||||
|
const remove = document.createElement("button");
|
||||||
|
remove.className = "small-button signature-remove";
|
||||||
|
remove.type = "button";
|
||||||
|
remove.textContent = "移除";
|
||||||
|
remove.disabled = el.signatureClear.disabled;
|
||||||
|
remove.addEventListener("click", () => {
|
||||||
|
if (isForegroundDocument(tab) && documentContentKey(state) === key) changeDocument("ofdgoChangeSignature", null, "remove", signature.id);
|
||||||
|
});
|
||||||
|
badges.append(remove);
|
||||||
|
}
|
||||||
head.append(badges, name);
|
head.append(badges, name);
|
||||||
row.append(head);
|
row.append(head);
|
||||||
appendInfoLine(row, "签署人", signature.signer);
|
appendInfoLine(row, "签署人", signature.signer);
|
||||||
@@ -11913,7 +11937,7 @@ function signatureSummary(signatures) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function signatureNameNode(signature) {
|
function signatureNameNode(signature) {
|
||||||
const stamps = signature.docIndex ? [] : signature.stamps || [];
|
const stamps = (signature.docIndex || 0) === (state.doc?.documentIndex || 0) ? signature.stamps || [] : [];
|
||||||
const name = document.createElement("div");
|
const name = document.createElement("div");
|
||||||
name.className = "signature-name";
|
name.className = "signature-name";
|
||||||
if (!stamps.length) {
|
if (!stamps.length) {
|
||||||
|
|||||||
@@ -6746,6 +6746,25 @@ func (e *businessEngine) changeAttachment(args []platformValue) (any, error) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// changeSignature 移除当前文档签名,使用库层依赖检查和撤销历史
|
||||||
|
// 入参: args 操作及签名标识
|
||||||
|
// 返回: any 编辑状态, error 移除错误
|
||||||
|
func (e *businessEngine) changeSignature(args []platformValue) (any, error) {
|
||||||
|
if len(args) != 2 {
|
||||||
|
return nil, fmt.Errorf("签名参数无效")
|
||||||
|
}
|
||||||
|
return e.changeAtomicObjects(func() error {
|
||||||
|
switch args[0].String() {
|
||||||
|
case "remove":
|
||||||
|
return e.currentEditor.RemoveSignatureContext(e.operationContext(), args[1].String())
|
||||||
|
case "clear":
|
||||||
|
return e.currentEditor.ClearSignaturesContext(e.operationContext())
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("签名操作无效")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// changeFontBinding 调用库层字体资源操作,统一更新预览与撤销状态
|
// changeFontBinding 调用库层字体资源操作,统一更新预览与撤销状态
|
||||||
// 入参: args 字体标识、保存方式及可选字体数据
|
// 入参: args 字体标识、保存方式及可选字体数据
|
||||||
// 返回: any 编辑状态, error 字体处理错误
|
// 返回: any 编辑状态, error 字体处理错误
|
||||||
@@ -7980,6 +7999,7 @@ func (e *businessEngine) businessCommands() map[string]func([]platformValue) (an
|
|||||||
"ofdgoEditDocument": e.editDocument,
|
"ofdgoEditDocument": e.editDocument,
|
||||||
"ofdgoUpdateInfo": e.updateInfo,
|
"ofdgoUpdateInfo": e.updateInfo,
|
||||||
"ofdgoChangeAttachment": e.changeAttachment,
|
"ofdgoChangeAttachment": e.changeAttachment,
|
||||||
|
"ofdgoChangeSignature": e.changeSignature,
|
||||||
"ofdgoChangePage": e.changePage,
|
"ofdgoChangePage": e.changePage,
|
||||||
"ofdgoBatchPages": e.batchPages,
|
"ofdgoBatchPages": e.batchPages,
|
||||||
"ofdgoChangeOutline": e.changeOutline,
|
"ofdgoChangeOutline": e.changeOutline,
|
||||||
@@ -8068,6 +8088,8 @@ func (e *businessEngine) operationContext() context.Context {
|
|||||||
func failureResult(err error) apiResult {
|
func failureResult(err error) apiResult {
|
||||||
result := apiResult{Error: err.Error()}
|
result := apiResult{Error: err.Error()}
|
||||||
switch {
|
switch {
|
||||||
|
case errors.Is(err, ofdgo.ErrSignatureDependency):
|
||||||
|
result.Code, result.Error = "signatureDependency", "存在签名或版本依赖,无法移除"
|
||||||
case errors.Is(err, ofdgo.ErrIncompleteDocument):
|
case errors.Is(err, ofdgo.ErrIncompleteDocument):
|
||||||
result.Code, result.Error = "documentPending", "文档尚未准备完成"
|
result.Code, result.Error = "documentPending", "文档尚未准备完成"
|
||||||
case errors.Is(err, ofdgo.ErrPrintDenied):
|
case errors.Is(err, ofdgo.ErrPrintDenied):
|
||||||
|
|||||||
@@ -21,8 +21,10 @@ import (
|
|||||||
"crypto"
|
"crypto"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"maps"
|
||||||
"path"
|
"path"
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -40,6 +42,261 @@ const (
|
|||||||
// SignatureWriteMode 签署方式
|
// SignatureWriteMode 签署方式
|
||||||
type SignatureWriteMode uint8
|
type SignatureWriteMode uint8
|
||||||
|
|
||||||
|
// ErrSignatureDependency 表示移除操作会改变保留签名或其他版本使用的入口和保护文件
|
||||||
|
var ErrSignatureDependency = errors.New("signature dependency conflict")
|
||||||
|
|
||||||
|
// RemoveSignature 移除当前文档版本的指定签名及外观,支持撤销重做
|
||||||
|
// 仅清理无其他引用的签名文件,依赖冲突时不修改文档
|
||||||
|
// 入参: id 签名标识
|
||||||
|
// 返回: error 标识、依赖或读取错误
|
||||||
|
func (e *Editor) RemoveSignature(id string) error {
|
||||||
|
return e.RemoveSignatureContext(context.Background(), id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveSignatureContext 移除指定签名,取消或失败时不改变文档和历史
|
||||||
|
// 入参: ctx 取消上下文, id 签名标识
|
||||||
|
// 返回: error 标识、依赖、读取或取消错误
|
||||||
|
func (e *Editor) RemoveSignatureContext(ctx context.Context, id string) error {
|
||||||
|
if id == "" {
|
||||||
|
return fmt.Errorf("empty signature ID")
|
||||||
|
}
|
||||||
|
return e.removeSignatures(ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearSignatures 清空当前文档版本的签名及外观,保留其他文档和版本的引用
|
||||||
|
// 无签名时不产生历史记录,依赖冲突时不修改文档
|
||||||
|
// 返回: error 依赖或读取错误
|
||||||
|
func (e *Editor) ClearSignatures() error {
|
||||||
|
return e.ClearSignaturesContext(context.Background())
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearSignaturesContext 清空当前签名,取消或失败时不改变文档和历史
|
||||||
|
// 入参: ctx 取消上下文
|
||||||
|
// 返回: error 依赖、读取或取消错误
|
||||||
|
func (e *Editor) ClearSignaturesContext(ctx context.Context) error {
|
||||||
|
return e.removeSignatures(ctx, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// removeSignatures 在独立快照中移除签名入口,校验保留依赖后提交历史
|
||||||
|
// 入参: ctx 取消上下文, id 签名标识,空值清空
|
||||||
|
// 返回: error 标识、依赖、结构或取消错误
|
||||||
|
func (e *Editor) removeSignatures(ctx context.Context, id string) error {
|
||||||
|
if err := ctx.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
reader, err := e.readerContext(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
doc, err := reader.DocContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if doc.Signatures == "" {
|
||||||
|
if id != "" {
|
||||||
|
return fmt.Errorf("signature not found: %s", id)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
name := reader.ResPath(doc.Signatures)
|
||||||
|
data, err := reader.readFileViewContext(ctx, name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
root, err := parseEditorXMLContext(ctx, data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
removed := make(map[string]bool)
|
||||||
|
candidates := make(map[string]bool)
|
||||||
|
var patches []editorXMLPatch
|
||||||
|
remaining := 0
|
||||||
|
for _, node := range root.children {
|
||||||
|
if !node.matchesOFD("Signature") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if id != "" && node.attr("ID") != id {
|
||||||
|
remaining++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
location := signatureRefPath(name, node.attr("BaseLoc"))
|
||||||
|
files, _, err := reader.signatureRemovalFiles(ctx, location)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
maps.Copy(candidates, files)
|
||||||
|
removed[node.attr("ID")] = true
|
||||||
|
patches = append(patches, editorXMLPatch{start: node.start, end: node.end})
|
||||||
|
}
|
||||||
|
if id != "" && !removed[id] {
|
||||||
|
return fmt.Errorf("signature not found: %s", id)
|
||||||
|
}
|
||||||
|
protected, dependencies, err := reader.signatureRemovalProtected(ctx, name, removed)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
parts := make(map[string][]byte)
|
||||||
|
if reader.versionInfo != nil {
|
||||||
|
if remaining != 0 {
|
||||||
|
return fmt.Errorf("%w: version shares signature list %s", ErrSignatureDependency, name)
|
||||||
|
}
|
||||||
|
candidates[name] = true
|
||||||
|
used, err := reader.versionFileDependencies(ctx, reader.documentRoot, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
removedFiles := maps.Clone(candidates)
|
||||||
|
for file := range used {
|
||||||
|
delete(removedFiles, file)
|
||||||
|
}
|
||||||
|
shared, err := reader.versionSharedFiles(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := reader.versionManifest(ctx, parts, nil, used, shared, removedFiles); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if dependencies[name] {
|
||||||
|
return fmt.Errorf("%w: retained signature protects %s", ErrSignatureDependency, name)
|
||||||
|
}
|
||||||
|
for file := range candidates {
|
||||||
|
if dependencies[file] {
|
||||||
|
return fmt.Errorf("%w: retained signature protects %s", ErrSignatureDependency, file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
versions, err := reader.DocumentVersionsContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, version := range versions {
|
||||||
|
for _, file := range version.Files {
|
||||||
|
if file.Location == name {
|
||||||
|
return fmt.Errorf("%w: version %s uses %s", ErrSignatureDependency, version.ID, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entry, err := reader.readFileViewContext(ctx, "OFD.xml")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ofd, err := parseEditorXMLContext(ctx, entry)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
node := ofd.childAt("DocBody", reader.documentIndex).child("Signatures")
|
||||||
|
if remaining == 0 {
|
||||||
|
parts["OFD.xml"] = editorPatchXML(entry, []editorXMLPatch{{start: node.start, end: node.end}})
|
||||||
|
candidates[name] = true
|
||||||
|
} else {
|
||||||
|
target := name
|
||||||
|
shared := false
|
||||||
|
for index, body := range reader.OFD.DocBody {
|
||||||
|
shared = shared || index != reader.documentIndex && body.Signatures != "" && signatureRefPath("OFD.xml", body.Signatures) == name
|
||||||
|
}
|
||||||
|
if shared {
|
||||||
|
target = packageAvailableName(reader, parts, name)
|
||||||
|
parts["OFD.xml"] = editorPatchXML(entry, []editorXMLPatch{editorXMLContent(entry, node, editorFontXMLText("/"+target))})
|
||||||
|
}
|
||||||
|
parts[target] = editorPatchXML(data, patches)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for file, updated := range parts {
|
||||||
|
if !protected[file] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
same, err := packageDataEqual(ctx, reader, file, updated)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !same {
|
||||||
|
return fmt.Errorf("%w: protected file %s", ErrSignatureDependency, file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for file, data := range reader.files {
|
||||||
|
if _, changed := parts[file]; !changed {
|
||||||
|
parts[file] = data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reader.files = parts
|
||||||
|
for file := range protected {
|
||||||
|
delete(candidates, file)
|
||||||
|
}
|
||||||
|
if err := reader.retireVersionFiles(ctx, candidates); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return e.commitResourceSnapshot(ctx, reader)
|
||||||
|
}
|
||||||
|
|
||||||
|
// signatureRemovalFiles 区分签名自有文件和摘要保护内容,正文不作为删除候选
|
||||||
|
// 入参: ctx 取消上下文, name 签名描述路径
|
||||||
|
// 返回: map[string]bool 自有文件, map[string]bool 保护文件, error 读取或解析错误
|
||||||
|
func (r *Reader) signatureRemovalFiles(ctx context.Context, name string) (map[string]bool, map[string]bool, error) {
|
||||||
|
data, err := r.readFileViewContext(ctx, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
var signature SignatureFile
|
||||||
|
if err := xml.NewDecoder(imageInput{ReadCloser: io.NopCloser(bytes.NewReader(data)), ctx: ctx}).Decode(&signature); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
owned := map[string]bool{name: true}
|
||||||
|
for _, location := range []string{signature.SignedValue, signature.SignedInfo.Seal.BaseLoc} {
|
||||||
|
if location != "" {
|
||||||
|
owned[signatureRefPath(name, location)] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected := make(map[string]bool)
|
||||||
|
for _, reference := range signature.SignedInfo.References.Reference {
|
||||||
|
protected[signatureRefPath(name, reference.FileRef)] = true
|
||||||
|
}
|
||||||
|
return owned, protected, ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
// signatureRemovalProtected 汇总保留签名的原文及其他文档的签名入口,不要求证书或私钥
|
||||||
|
// 入参: ctx 取消上下文, selected 当前签名列表, removed 待移除标识
|
||||||
|
// 返回: map[string]bool 保留路径, map[string]bool 非共享的摘要保护路径, error 读取、结构或取消错误
|
||||||
|
func (r *Reader) signatureRemovalProtected(ctx context.Context, selected string, removed map[string]bool) (map[string]bool, map[string]bool, error) {
|
||||||
|
protected := make(map[string]bool)
|
||||||
|
dependencies := make(map[string]bool)
|
||||||
|
retained := make(map[string]bool)
|
||||||
|
for index, body := range r.OFD.DocBody {
|
||||||
|
if body.Signatures == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
name := signatureRefPath("OFD.xml", body.Signatures)
|
||||||
|
current := index == r.documentIndex && r.versionInfo == nil
|
||||||
|
if !current {
|
||||||
|
protected[name] = true
|
||||||
|
}
|
||||||
|
data, err := r.readFileViewContext(ctx, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
root, err := parseEditorXMLContext(ctx, data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
for _, node := range root.children {
|
||||||
|
if !node.matchesOFD("Signature") || current && name == selected && removed[node.attr("ID")] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
owned, refs, err := r.signatureRemovalFiles(ctx, signatureRefPath(name, node.attr("BaseLoc")))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
maps.Copy(protected, owned)
|
||||||
|
maps.Copy(retained, owned)
|
||||||
|
maps.Copy(protected, refs)
|
||||||
|
maps.Copy(dependencies, refs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for name := range retained {
|
||||||
|
delete(dependencies, name)
|
||||||
|
}
|
||||||
|
return protected, dependencies, ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
// SignatureWriteOptions 最终包签署选项,不修改Editor或调用方的原件
|
// SignatureWriteOptions 最终包签署选项,不修改Editor或调用方的原件
|
||||||
// SM2数字签名使用GB/T35275-2017消息结构;RSA/ECDSA使用裸签名,验签需WithSignatureCert
|
// SM2数字签名使用GB/T35275-2017消息结构;RSA/ECDSA使用裸签名,验签需WithSignatureCert
|
||||||
// Seal仅接受已有合法SES v4电子印章,使用SM2/SM3,不声明GM/T0031-2025兼容
|
// Seal仅接受已有合法SES v4电子印章,使用SM2/SM3,不声明GM/T0031-2025兼容
|
||||||
|
|||||||
Reference in new issue
Block a user