mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-29 08:46:55 +08:00
1 parent
4d0a909de5
commit
b85d7457c1
13 files changed
+98
-42
No files matched your search
@@ -48,6 +48,12 @@ select {
|
|||||||
font: inherit;
|
font: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
select,
|
||||||
|
option {
|
||||||
|
text-align: left;
|
||||||
|
text-align-last: left;
|
||||||
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
border: 1px solid var(--line-strong);
|
border: 1px solid var(--line-strong);
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
@@ -135,7 +141,6 @@ a:focus-visible {
|
|||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #1f2428;
|
color: #1f2428;
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-paragraph > .editor-field,
|
.editor-paragraph > .editor-field,
|
||||||
@@ -650,7 +655,8 @@ button:not(:disabled):hover {
|
|||||||
inset: 0;
|
inset: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: flex-start;
|
||||||
|
padding-left: 4px;
|
||||||
padding-right: 12px;
|
padding-right: 12px;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
@@ -789,7 +795,6 @@ button:not(:disabled):hover {
|
|||||||
height: var(--control-height);
|
height: var(--control-height);
|
||||||
padding: 0 6px;
|
padding: 0 6px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
text-align: center;
|
|
||||||
font: inherit;
|
font: inherit;
|
||||||
border: 1px solid var(--line);
|
border: 1px solid var(--line);
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
@@ -802,6 +807,7 @@ button:not(:disabled):hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.convert-table input {
|
.convert-table input {
|
||||||
|
text-align: center;
|
||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2912,7 +2912,7 @@ function releasePageResources() {
|
|||||||
const images = new Set(), fonts = new Set();
|
const images = new Set(), fonts = new Set();
|
||||||
for (const page of state.pageCache.values()) {
|
for (const page of state.pageCache.values()) {
|
||||||
for (const name of page.imageNames) images.add(name);
|
for (const name of page.imageNames) images.add(name);
|
||||||
for (const font of page.fonts) fonts.add(font.name);
|
for (const font of page.fonts || []) fonts.add(font.name);
|
||||||
}
|
}
|
||||||
for (const [name, image] of state.svgImages) {
|
for (const [name, image] of state.svgImages) {
|
||||||
if (!images.has(name)) {
|
if (!images.has(name)) {
|
||||||
@@ -5495,6 +5495,7 @@ function trimPageCache() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!state.pageInFlight.size) releasePageResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadSVGFonts(fonts, openSeq) {
|
async function loadSVGFonts(fonts, openSeq) {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ require (
|
|||||||
github.com/tdewolff/canvas v0.0.0-20260923214215-09804640d00c
|
github.com/tdewolff/canvas v0.0.0-20260923214215-09804640d00c
|
||||||
github.com/tdewolff/font v0.0.0-20260913163313-54f98bb59ee6
|
github.com/tdewolff/font v0.0.0-20260913163313-54f98bb59ee6
|
||||||
github.com/xiaoqidun/jbig2 v1.1.1
|
github.com/xiaoqidun/jbig2 v1.1.1
|
||||||
github.com/xiaoqidun/pdfgo v0.0.0-20260928145637-87d467fc8ef1
|
github.com/xiaoqidun/pdfgo v0.0.0-20260928160629-4a36d082a27e
|
||||||
golang.org/x/crypto v0.57.0
|
golang.org/x/crypto v0.57.0
|
||||||
golang.org/x/image v0.46.0
|
golang.org/x/image v0.46.0
|
||||||
golang.org/x/text v0.42.0
|
golang.org/x/text v0.42.0
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ github.com/tdewolff/test v1.0.12 h1:7F21DqIajswxuche0geHdrUZRCWE4oko4b7bcmkkrxk=
|
|||||||
github.com/tdewolff/test v1.0.12/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
|
github.com/tdewolff/test v1.0.12/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
|
||||||
github.com/xiaoqidun/jbig2 v1.1.1 h1:SjliS9ZO0e9HX5oYUfBuXrfFsXhWricrSz+XY4zORDI=
|
github.com/xiaoqidun/jbig2 v1.1.1 h1:SjliS9ZO0e9HX5oYUfBuXrfFsXhWricrSz+XY4zORDI=
|
||||||
github.com/xiaoqidun/jbig2 v1.1.1/go.mod h1:8QonVWtENmh2kc6l+leqeGl7psb79DWlHDkCpdChjfQ=
|
github.com/xiaoqidun/jbig2 v1.1.1/go.mod h1:8QonVWtENmh2kc6l+leqeGl7psb79DWlHDkCpdChjfQ=
|
||||||
github.com/xiaoqidun/pdfgo v0.0.0-20260928145637-87d467fc8ef1 h1:meZvn/eb/AAbr6qfsP41UZZsW/g1v67a2CUYGzoJpS0=
|
github.com/xiaoqidun/pdfgo v0.0.0-20260928160629-4a36d082a27e h1:yc6JbpAQG36mxW6R+mNoAib9tbqTUAQxRcXjGLy6GRA=
|
||||||
github.com/xiaoqidun/pdfgo v0.0.0-20260928145637-87d467fc8ef1/go.mod h1:4Pf0JO0BEf1uzRY+uZjlMjN/OPn3PYa0YMi6cqPPTLQ=
|
github.com/xiaoqidun/pdfgo v0.0.0-20260928160629-4a36d082a27e/go.mod h1:4Pf0JO0BEf1uzRY+uZjlMjN/OPn3PYa0YMi6cqPPTLQ=
|
||||||
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||||
github.com/yuin/goldmark v1.8.5 h1:r6N5afV5qj/5S4UTch8agZHJ8UxNCMwX7WjkkJam2NA=
|
github.com/yuin/goldmark v1.8.5 h1:r6N5afV5qj/5S4UTch8agZHJ8UxNCMwX7WjkkJam2NA=
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ func NewRenderer(reader *Reader, opts ...RendererOption) *Renderer {
|
|||||||
DrawParams: reader.drawParamCache,
|
DrawParams: reader.drawParamCache,
|
||||||
CompositeGraphicUnits: reader.compositeGraphicUnitCache,
|
CompositeGraphicUnits: reader.compositeGraphicUnitCache,
|
||||||
templatePageCache: make(map[string]*PageContent),
|
templatePageCache: make(map[string]*PageContent),
|
||||||
imageCache: make(map[string]image.Image),
|
imageCache: renderCache[string, image.Image]{limit: imageCacheLimit},
|
||||||
backends: defaultRenderBackends(),
|
backends: defaultRenderBackends(),
|
||||||
backendStates: make(map[any]any),
|
backendStates: make(map[any]any),
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-5
@@ -25,6 +25,9 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// imageCacheLimit 限制图片缓存的编码数据及预计解码内存
|
||||||
|
const imageCacheLimit = 64 << 20
|
||||||
|
|
||||||
// EncodedImage 保留PNG或JPEG原始编码,首次读取像素时解码
|
// EncodedImage 保留PNG或JPEG原始编码,首次读取像素时解码
|
||||||
// Bytes返回只读数据,Image返回共享只读像素,解码错误由Image返回
|
// Bytes返回只读数据,Image返回共享只读像素,解码错误由Image返回
|
||||||
type EncodedImage struct {
|
type EncodedImage struct {
|
||||||
@@ -110,21 +113,37 @@ func newEncodedImage(data []byte) (*EncodedImage, error) {
|
|||||||
// 返回: image.Image 图片对象, error 读取错误
|
// 返回: image.Image 图片对象, error 读取错误
|
||||||
func (r *Renderer) cachedImageResource(resPath string) (image.Image, error) {
|
func (r *Renderer) cachedImageResource(resPath string) (image.Image, error) {
|
||||||
resPath = cleanPackagePath(r.Reader.ResPath(resPath))
|
resPath = cleanPackagePath(r.Reader.ResPath(resPath))
|
||||||
img, ok := r.imageCache[resPath]
|
img, ok := r.imageCache.get(resPath)
|
||||||
if !ok {
|
if !ok {
|
||||||
var err error
|
var err error
|
||||||
img, err = r.readImageResource(resPath)
|
img, err = r.readImageResource(resPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if r.imageCache == nil {
|
r.imageCache.put(resPath, img, imageResourceCost(img, r.imageCache.limit))
|
||||||
r.imageCache = make(map[string]image.Image)
|
|
||||||
}
|
|
||||||
r.imageCache[resPath] = img
|
|
||||||
}
|
}
|
||||||
return img, nil
|
return img, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// imageResourceCost 预留十六位像素展开空间,超预算图片不进入缓存
|
||||||
|
// 入参: img 图片资源, limit 缓存预算
|
||||||
|
// 返回: int 估算字节数或超预算标记
|
||||||
|
func imageResourceCost(img image.Image, limit int) int {
|
||||||
|
cost := 256
|
||||||
|
w, h := img.Bounds().Dx(), img.Bounds().Dy()
|
||||||
|
if limit < cost || w <= 0 || h <= 0 || w > (limit-cost)/8/h {
|
||||||
|
return limit + 1
|
||||||
|
}
|
||||||
|
cost += w * h * 8
|
||||||
|
if encoded, ok := img.(*EncodedImage); ok {
|
||||||
|
if len(encoded.data) > limit-cost {
|
||||||
|
return limit + 1
|
||||||
|
}
|
||||||
|
cost += len(encoded.data)
|
||||||
|
}
|
||||||
|
return cost
|
||||||
|
}
|
||||||
|
|
||||||
// decodeImageResource 读取或复用图片资源,按输出需要解码像素
|
// decodeImageResource 读取或复用图片资源,按输出需要解码像素
|
||||||
// 入参: resPath 图片资源路径
|
// 入参: resPath 图片资源路径
|
||||||
// 返回: image.Image 图片对象, error 读取或解码错误
|
// 返回: image.Image 图片对象, error 读取或解码错误
|
||||||
|
|||||||
+20
-7
@@ -15,6 +15,7 @@
|
|||||||
package ofdgo
|
package ofdgo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"cmp"
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -25,7 +26,7 @@ import (
|
|||||||
// 入参: value 页码表达式,如1-6,7,8-10, count 文档总页数
|
// 入参: value 页码表达式,如1-6,7,8-10, count 文档总页数
|
||||||
// 返回: []int 页面索引, error 错误信息
|
// 返回: []int 页面索引, error 错误信息
|
||||||
func ParsePageRange(value string, count int) ([]int, error) {
|
func ParsePageRange(value string, count int) ([]int, error) {
|
||||||
selected := make(map[int]bool)
|
var intervals [][2]int
|
||||||
for _, part := range strings.Split(strings.ReplaceAll(value, ",", ","), ",") {
|
for _, part := range strings.Split(strings.ReplaceAll(value, ",", ","), ",") {
|
||||||
first, last, interval := strings.Cut(strings.TrimSpace(part), "-")
|
first, last, interval := strings.Cut(strings.TrimSpace(part), "-")
|
||||||
start, err := strconv.Atoi(strings.TrimSpace(first))
|
start, err := strconv.Atoi(strings.TrimSpace(first))
|
||||||
@@ -42,15 +43,27 @@ func ParsePageRange(value string, count int) ([]int, error) {
|
|||||||
if start < 1 || end < start || end > count {
|
if start < 1 || end < start || end > count {
|
||||||
return nil, fmt.Errorf("page range %q outside 1-%d", part, count)
|
return nil, fmt.Errorf("page range %q outside 1-%d", part, count)
|
||||||
}
|
}
|
||||||
for index := start - 1; index < end; index++ {
|
intervals = append(intervals, [2]int{start - 1, end})
|
||||||
selected[index] = true
|
}
|
||||||
|
slices.SortFunc(intervals, func(a, b [2]int) int { return cmp.Compare(a[0], b[0]) })
|
||||||
|
merged := intervals[:0]
|
||||||
|
for _, interval := range intervals {
|
||||||
|
if len(merged) != 0 && interval[0] <= merged[len(merged)-1][1] {
|
||||||
|
merged[len(merged)-1][1] = max(merged[len(merged)-1][1], interval[1])
|
||||||
|
} else {
|
||||||
|
merged = append(merged, interval)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
indices := make([]int, 0, len(selected))
|
length := 0
|
||||||
for index := range selected {
|
for _, interval := range merged {
|
||||||
indices = append(indices, index)
|
length += interval[1] - interval[0]
|
||||||
|
}
|
||||||
|
indices := make([]int, 0, length)
|
||||||
|
for _, interval := range merged {
|
||||||
|
for index := interval[0]; index < interval[1]; index++ {
|
||||||
|
indices = append(indices, index)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
slices.Sort(indices)
|
|
||||||
return indices, nil
|
return indices, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -55,11 +55,13 @@ type Reader struct {
|
|||||||
encryption *encryptionState
|
encryption *encryptionState
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close 关闭阅读器
|
// Close 关闭阅读器持有的文件,重复调用不再关闭底层文件
|
||||||
// 返回: error 错误信息
|
// 返回: error 错误信息
|
||||||
func (r *Reader) Close() error {
|
func (r *Reader) Close() error {
|
||||||
if r.Closer != nil {
|
if r.Closer != nil {
|
||||||
return r.Closer.Close()
|
closer := r.Closer
|
||||||
|
r.Closer = nil
|
||||||
|
return closer.Close()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -34,7 +34,7 @@ type Renderer struct {
|
|||||||
DrawParams map[string]*DrawParam
|
DrawParams map[string]*DrawParam
|
||||||
CompositeGraphicUnits map[string]*CompositeGraphicUnit
|
CompositeGraphicUnits map[string]*CompositeGraphicUnit
|
||||||
templatePageCache map[string]*PageContent
|
templatePageCache map[string]*PageContent
|
||||||
imageCache map[string]image.Image
|
imageCache renderCache[string, image.Image]
|
||||||
fontDirs []string
|
fontDirs []string
|
||||||
fontFS []fs.FS
|
fontFS []fs.FS
|
||||||
decodeImages bool
|
decodeImages bool
|
||||||
@@ -57,7 +57,7 @@ type RendererOption func(*Renderer)
|
|||||||
// ClearCache 释放派生字体、图片、模板与后端缓存,不改变文档和渲染配置
|
// ClearCache 释放派生字体、图片、模板与后端缓存,不改变文档和渲染配置
|
||||||
func (r *Renderer) ClearCache() {
|
func (r *Renderer) ClearCache() {
|
||||||
r.backendStates = make(map[any]any)
|
r.backendStates = make(map[any]any)
|
||||||
r.imageCache = make(map[string]image.Image)
|
r.imageCache = renderCache[string, image.Image]{limit: imageCacheLimit}
|
||||||
r.templatePageCache = make(map[string]*PageContent)
|
r.templatePageCache = make(map[string]*PageContent)
|
||||||
r.resetFontCache()
|
r.resetFontCache()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,14 +74,7 @@ func textGlyphPath(face *canvas.FontFace, glyph textGlyph, outlines *sfntOutline
|
|||||||
width = face.MmPerEm * float64(face.Font.GlyphAdvance(glyphID))
|
width = face.MmPerEm * float64(face.Font.GlyphAdvance(glyphID))
|
||||||
}
|
}
|
||||||
if face.FauxBold != 0 {
|
if face.FauxBold != 0 {
|
||||||
d := face.FauxBold * face.Size
|
p = p.Offset(face.FauxBold*face.Size, canvas.Tolerance)
|
||||||
if face.Font.IsTrueType {
|
|
||||||
d = -d
|
|
||||||
}
|
|
||||||
origFastStroke := canvas.FastStroke
|
|
||||||
canvas.FastStroke = true
|
|
||||||
p = p.Offset(d, canvas.Tolerance)
|
|
||||||
canvas.FastStroke = origFastStroke
|
|
||||||
}
|
}
|
||||||
if face.FauxItalic != 0 {
|
if face.FauxItalic != 0 {
|
||||||
p = p.Transform(canvas.Identity.Shear(face.FauxItalic, 0))
|
p = p.Transform(canvas.Identity.Shear(face.FauxItalic, 0))
|
||||||
@@ -105,7 +98,7 @@ func (r *Renderer) cachedTextGlyphPath(face *canvas.FontFace, glyph textGlyph) (
|
|||||||
direction: face.Direction,
|
direction: face.Direction,
|
||||||
glyph: glyph,
|
glyph: glyph,
|
||||||
}
|
}
|
||||||
if cached, ok := r.canvasState().textGlyphPathCache[key]; ok {
|
if cached, ok := r.canvasState().textGlyphPathCache.get(key); ok {
|
||||||
return cached.path, cached.width
|
return cached.path, cached.width
|
||||||
}
|
}
|
||||||
outlines := r.canvasState().fontOutlines[face.Font]
|
outlines := r.canvasState().fontOutlines[face.Font]
|
||||||
@@ -118,7 +111,7 @@ func (r *Renderer) cachedTextGlyphPath(face *canvas.FontFace, glyph textGlyph) (
|
|||||||
r.renderError = err
|
r.renderError = err
|
||||||
return &canvas.Path{}, 0
|
return &canvas.Path{}, 0
|
||||||
}
|
}
|
||||||
r.canvasState().textGlyphPathCache[key] = textGlyphPathCacheValue{path: path, width: width}
|
r.canvasState().textGlyphPathCache.put(key, textGlyphPathCacheValue{path: path, width: width}, 256+len(path.Data())*8+len(glyph.Text)+len(face.Language))
|
||||||
return path, width
|
return path, width
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ func (r *Renderer) canvasEncodedImage(img image.Image) image.Image {
|
|||||||
return img
|
return img
|
||||||
}
|
}
|
||||||
state := r.canvasState()
|
state := r.canvasState()
|
||||||
if encoded, ok := state.images[source]; ok {
|
if encoded, ok := state.images.get(source); ok {
|
||||||
return encoded
|
return encoded
|
||||||
}
|
}
|
||||||
var encoded *canvasimage.Image
|
var encoded *canvasimage.Image
|
||||||
@@ -148,7 +148,7 @@ func (r *Renderer) canvasEncodedImage(img image.Image) image.Image {
|
|||||||
encoded, _ = canvasimage.NewPNGImage(bytes.NewReader(source.Bytes()))
|
encoded, _ = canvasimage.NewPNGImage(bytes.NewReader(source.Bytes()))
|
||||||
}
|
}
|
||||||
encoded.Bytes = source.Bytes()
|
encoded.Bytes = source.Bytes()
|
||||||
state.images[source] = encoded
|
state.images.put(source, encoded, 2*imageResourceCost(source, state.images.limit/2))
|
||||||
return encoded
|
return encoded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ import (
|
|||||||
|
|
||||||
// canvasBackendState 保存Canvas字体、字形和编码图片适配缓存
|
// canvasBackendState 保存Canvas字体、字形和编码图片适配缓存
|
||||||
type canvasBackendState struct {
|
type canvasBackendState struct {
|
||||||
images map[*EncodedImage]image.Image
|
images renderCache[*EncodedImage, image.Image]
|
||||||
fontMap map[string]*canvas.FontFamily
|
fontMap map[string]*canvas.FontFamily
|
||||||
svgFontCache map[*canvas.Font]SVGFont
|
svgFontCache map[*canvas.Font]SVGFont
|
||||||
textGlyphPathCache map[textGlyphPathCacheKey]textGlyphPathCacheValue
|
textGlyphPathCache renderCache[textGlyphPathCacheKey, textGlyphPathCacheValue]
|
||||||
fontOutlines map[*canvas.Font]*sfntOutliner
|
fontOutlines map[*canvas.Font]*sfntOutliner
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ func (r *Renderer) canvasState() *canvasBackendState {
|
|||||||
return state.(*canvasBackendState)
|
return state.(*canvasBackendState)
|
||||||
}
|
}
|
||||||
state := &canvasBackendState{
|
state := &canvasBackendState{
|
||||||
images: make(map[*EncodedImage]image.Image),
|
images: renderCache[*EncodedImage, image.Image]{limit: imageCacheLimit},
|
||||||
}
|
}
|
||||||
state.resetFonts()
|
state.resetFonts()
|
||||||
r.backendStates[key] = state
|
r.backendStates[key] = state
|
||||||
@@ -48,6 +48,6 @@ func (r *Renderer) canvasState() *canvasBackendState {
|
|||||||
func (s *canvasBackendState) resetFonts() {
|
func (s *canvasBackendState) resetFonts() {
|
||||||
s.fontMap = make(map[string]*canvas.FontFamily)
|
s.fontMap = make(map[string]*canvas.FontFamily)
|
||||||
s.svgFontCache = make(map[*canvas.Font]SVGFont)
|
s.svgFontCache = make(map[*canvas.Font]SVGFont)
|
||||||
s.textGlyphPathCache = make(map[textGlyphPathCacheKey]textGlyphPathCacheValue)
|
s.textGlyphPathCache = renderCache[textGlyphPathCacheKey, textGlyphPathCacheValue]{limit: 16 << 20}
|
||||||
s.fontOutlines = make(map[*canvas.Font]*sfntOutliner)
|
s.fontOutlines = make(map[*canvas.Font]*sfntOutliner)
|
||||||
}
|
}
|
||||||
+24
-2
@@ -29,6 +29,7 @@ import (
|
|||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"path"
|
"path"
|
||||||
@@ -36,6 +37,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/emmansun/gmsm/sm2"
|
"github.com/emmansun/gmsm/sm2"
|
||||||
|
"github.com/emmansun/gmsm/sm3"
|
||||||
"github.com/emmansun/gmsm/smx509"
|
"github.com/emmansun/gmsm/smx509"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -489,16 +491,36 @@ func (r *Reader) verifySignatureReference(sigPath, method string, ref SignatureR
|
|||||||
result.Error = err.Error()
|
result.Error = err.Error()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
data, err := r.readFile(refPath)
|
var digest hash.Hash
|
||||||
|
switch {
|
||||||
|
case strings.TrimSpace(method) == "":
|
||||||
|
digest = md5.New()
|
||||||
|
case isSM3DigestMethod(method):
|
||||||
|
digest = sm3.New()
|
||||||
|
default:
|
||||||
|
algorithm, ok := signatureDigestHash(method)
|
||||||
|
if !ok {
|
||||||
|
result.Error = fmt.Sprintf("unsupported digest method: %s", method)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
digest = algorithm.New()
|
||||||
|
}
|
||||||
|
input, err := r.openFile(refPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
result.Error = err.Error()
|
result.Error = err.Error()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
actual, err := signatureDigest(method, data)
|
_, err = io.Copy(digest, input)
|
||||||
|
closeErr := input.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
result.Error = err.Error()
|
result.Error = err.Error()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
if closeErr != nil {
|
||||||
|
result.Error = closeErr.Error()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
actual := digest.Sum(nil)
|
||||||
result.CheckValue = checkValue
|
result.CheckValue = checkValue
|
||||||
result.Actual = actual
|
result.Actual = actual
|
||||||
result.Checked = true
|
result.Checked = true
|
||||||
|
|||||||
Reference in new issue
Block a user