From 4fee3dfd8ea6e9317af8800696405f52679260a3 Mon Sep 17 00:00:00 2001 From: xiaoqidun Date: Mon, 26 Oct 2026 22:12:22 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E7=BC=96=E8=BE=91=E8=83=BD=E5=8A=9B):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A4=9A=E7=89=88=E6=9C=AC=E5=AD=97=E4=BD=93?= =?UTF-8?q?=E8=A3=81=E5=89=AA=E4=B8=8E=E8=B5=84=E6=BA=90=E6=B8=85=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ofdgo_editor_font_binding.go | 16 +++++++++++-- ofdgo_editor_reference.go | 44 +++++++++++++++++++++++++++++++++--- ofdgo_editor_rich_text.go | 42 +++++++++++++++++++++------------- 3 files changed, 81 insertions(+), 21 deletions(-) diff --git a/ofdgo_editor_font_binding.go b/ofdgo_editor_font_binding.go index 3abac63..886e61b 100644 --- a/ofdgo_editor_font_binding.go +++ b/ofdgo_editor_font_binding.go @@ -963,7 +963,7 @@ func pruneUnreferencedFiles(ctx context.Context, reader *Reader, candidates ...s if root == "" { root = node.Name.Local } - if classifyOFDNamespace(node.Name.Space) == ofdXMLUnknown || slices.Contains([]string{"CustomTags", "Extensions", "ExtendData", "Data"}, node.Name.Local) { + if classifyOFDNamespace(node.Name.Space) == ofdXMLUnknown || root == "CustomTags" || slices.Contains([]string{"Extensions", "ExtendData", "Data"}, node.Name.Local) { uncertain = true return fmt.Errorf("unknown file dependencies in %s", name) } @@ -990,7 +990,19 @@ func pruneUnreferencedFiles(ctx context.Context, reader *Reader, candidates ...s versions[name] = append(versions[name], versionEditLink{node: node, target: target}) } } - if err := reader.scanDocumentFileReferences(ctx, name, true, add, record, inspect); err != nil { + err := reader.scanDocumentFileReferences(ctx, name, true, add, record, inspect) + if uncertain && (root == "CustomTags" || root == "RichText") { + data, readErr := reader.readFileViewContext(ctx, name) + if readErr != nil { + return readErr + } + refs := &editorResourceRefs{ids: make(map[string]bool), files: make(map[string]bool), fonts: make(map[string]*editorFontUsage)} + if _, safe := refs.scanContext(ctx, bytes.NewReader(data), name); safe { + uncertain = false + err = reader.scanDocumentFileReferences(ctx, name, true, add, record, nil) + } + } + if err != nil { var syntax *xml.SyntaxError if uncertain || errors.As(err, &syntax) { return ctx.Err() diff --git a/ofdgo_editor_reference.go b/ofdgo_editor_reference.go index fc70402..2444d0e 100644 --- a/ofdgo_editor_reference.go +++ b/ofdgo_editor_reference.go @@ -53,6 +53,7 @@ type editorReferenceScan struct { stack []string fonts []*editorFontUsage text strings.Builder + richText strings.Builder resource bool capture bool safe bool @@ -140,14 +141,39 @@ func (s *editorReferenceScan) accept(token xml.Token) bool { } switch token := token.(type) { case xml.StartElement: - if classifyOFDNamespace(token.Name.Space) == ofdXMLUnknown { + rich := token.Name.Space == richTextNamespace + known := classifyOFDNamespace(token.Name.Space) != ofdXMLUnknown + if rich { + known = len(s.stack) == 0 && token.Name.Local == "RichText" || len(s.stack) == 1 && s.stack[0] == "RichText" && token.Name.Local == "ObjectRef" + } else if len(s.stack) > 0 && s.stack[0] == "RichText" { + known = false + } + if len(s.stack) > 0 && s.stack[0] == "CustomTags" { + known = known && (len(s.stack) == 1 && token.Name.Local == "CustomTag" || len(s.stack) == 2 && s.stack[1] == "CustomTag" && (token.Name.Local == "FileLoc" || token.Name.Local == "SchemaLoc")) + } + if !known { s.safe = false return false } - if token.Name.Local == "CustomTags" || token.Name.Local == "Extensions" || token.Name.Local == "ExtendData" || token.Name.Local == "Data" { + if token.Name.Local == "Extensions" || token.Name.Local == "ExtendData" || token.Name.Local == "Data" { s.safe = false return false } + if token.Name.Local == "CustomTag" { + var kind, namespace string + for _, attr := range token.Attr { + if attr.Name.Space == "" && attr.Name.Local == "TypeID" { + kind = attr.Value + } + if attr.Name.Space == "" && attr.Name.Local == "NameSpace" { + namespace = attr.Value + } + } + if kind != richTextTagType || namespace != richTextNamespace { + s.safe = false + return false + } + } if len(s.stack) == 0 { if s.seen { s.safe = false @@ -184,7 +210,8 @@ func (s *editorReferenceScan) accept(token xml.Token) bool { if attr.Name.Space == "xmlns" || attr.Name.Local == "xmlns" || attr.Name.Local == "xmlns:ofd" || attr.Name.Space == XMLNamespace { continue } - if attr.Name.Space != "" { + custom := len(s.stack) == 0 && token.Name.Local == "CustomTags" || len(s.stack) > 0 && s.stack[0] == "CustomTags" + if attr.Name.Space != "" || rich && (token.Name.Local != "ObjectRef" || attr.Name.Local != "PageRef") || custom && (token.Name.Local != "CustomTag" || attr.Name.Local != "TypeID" && attr.Name.Local != "NameSpace") { s.safe = false return false } @@ -225,6 +252,9 @@ func (s *editorReferenceScan) accept(token xml.Token) bool { s.capture = true } case xml.CharData: + if len(s.stack) == 1 && s.stack[0] == "RichText" { + s.richText.Write(token) + } if len(s.stack) == 0 && len(bytes.Trim(token, " \t\r\n")) != 0 { s.safe = false return false @@ -233,6 +263,14 @@ func (s *editorReferenceScan) accept(token xml.Token) bool { s.text.Write(token) } case xml.EndElement: + if len(s.stack) == 3 && s.stack[0] == "CustomTags" && token.Name.Local == "SchemaLoc" && strings.TrimSpace(s.text.String()) != "" { + s.safe = false + return false + } + if len(s.stack) == 1 && s.stack[0] == "RichText" && !richTextMetadataFontSafe(s.richText.String()) { + s.safe = false + return false + } if len(s.stack) == 0 || s.stack[len(s.stack)-1] != token.Name.Local { s.safe = false return false diff --git a/ofdgo_editor_rich_text.go b/ofdgo_editor_rich_text.go index b7c4976..6ec4932 100644 --- a/ofdgo_editor_rich_text.go +++ b/ofdgo_editor_rich_text.go @@ -909,22 +909,7 @@ func richTextTagsFontSafe(ctx context.Context, reader *Reader, index int) (bool, if root.Name != "RichText" || root.Namespace != richTextNamespace || len(root.Attributes) != 0 { return false, nil } - var meta richTextMetadata - decoder := json.NewDecoder(bytes.NewBufferString(root.Text)) - decoder.DisallowUnknownFields() - if err := decoder.Decode(&meta); err != nil { - return false, nil - } - if decoder.Decode(new(any)) != io.EOF || meta.Version != 1 { - return false, nil - } - for i := range meta.Value.Runs { - if meta.Value.Runs[i].Format.Font != "" { - return false, nil - } - meta.Value.Runs[i].Format.Font = "1" - } - if err := meta.Value.Validate(); err != nil { + if !richTextMetadataFontSafe(root.Text) { return false, nil } for _, child := range root.Children { @@ -935,3 +920,28 @@ func richTextTagsFontSafe(ctx context.Context, reader *Reader, index int) (bool, } return true, ctx.Err() } + +// richTextMetadataFontSafe 核对本库富文本元数据不包含字体资源编号或未知字段 +// 入参: value 元数据JSON +// 返回: bool 是否可由标准图元完整统计字体引用 +func richTextMetadataFontSafe(value string) bool { + var meta richTextMetadata + decoder := json.NewDecoder(bytes.NewBufferString(value)) + decoder.DisallowUnknownFields() + if err := decoder.Decode(&meta); err != nil { + return false + } + if decoder.Decode(new(any)) != io.EOF || meta.Version != 1 { + return false + } + for i := range meta.Value.Runs { + if meta.Value.Runs[i].Format.Font != "" { + return false + } + meta.Value.Runs[i].Format.Font = "1" + } + if err := meta.Value.Validate(); err != nil { + return false + } + return true +}