init: 自 zomaintain/backend/rdplib 平移独立成库; module path 从上游 github.com/nakagami/grdp 改为 git.zeroonesoft.cn/golib/rdplib
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
package cliprdr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Windows "HTML Format" 剪贴板编解码(MS-Doc: HTML Clipboard Format)。
|
||||
//
|
||||
// 字节流 = 固定文本头 + HTML 文档。头共 5 行、每行 \r\n 结尾:
|
||||
//
|
||||
// Version:0.9\r\n (13 字节)
|
||||
// StartHTML:0000000105\r\n (22 字节)
|
||||
// EndHTML:0000000256\r\n (20 字节)
|
||||
// StartFragment:0000000139\r\n (26 字节)
|
||||
// EndFragment:0000000222\r\n (24 字节)
|
||||
//
|
||||
// 偏移为 10 位零填充的十进制**字节**偏移(UTF-8)。固定头总长 105 字节。
|
||||
|
||||
const cfHTMLHeaderLen = 13 + 22 + 20 + 26 + 24 // 105
|
||||
|
||||
const cfHTMLWrapPrefix = "<html><body><!--StartFragment-->"
|
||||
const cfHTMLWrapSuffix = "<!--EndFragment--></body></html>"
|
||||
|
||||
// EncodeCFHTML 把 HTML 片段(fragment)包装成 "HTML Format" 剪贴板字节流。
|
||||
func EncodeCFHTML(fragment string) []byte {
|
||||
startHTML := cfHTMLHeaderLen
|
||||
startFragment := startHTML + len(cfHTMLWrapPrefix)
|
||||
endFragment := startFragment + len(fragment)
|
||||
endHTML := endFragment + len(cfHTMLWrapSuffix)
|
||||
|
||||
head := fmt.Sprintf("Version:0.9\r\nStartHTML:%010d\r\nEndHTML:%010d\r\nStartFragment:%010d\r\nEndFragment:%010d\r\n",
|
||||
startHTML, endHTML, startFragment, endFragment)
|
||||
doc := cfHTMLWrapPrefix + fragment + cfHTMLWrapSuffix
|
||||
return []byte(head + doc)
|
||||
}
|
||||
|
||||
// DecodeCFHTML 从 "HTML Format" 剪贴板字节流中提取 StartFragment 到
|
||||
// EndFragment 之间的 HTML 内容。头部解析失败时回退为整段字符串。
|
||||
func DecodeCFHTML(data []byte) string {
|
||||
s := string(data)
|
||||
lines := strings.Split(s, "\r\n")
|
||||
var startFragment, endFragment int = -1, -1
|
||||
// 头最多 5 行;解析到两个 Fragment 偏移即可停止。
|
||||
for i, ln := range lines {
|
||||
if i >= 5 {
|
||||
break
|
||||
}
|
||||
if v, ok := parseOffsetLine(ln, "StartFragment:"); ok {
|
||||
startFragment = v
|
||||
} else if v, ok := parseOffsetLine(ln, "EndFragment:"); ok {
|
||||
endFragment = v
|
||||
}
|
||||
if startFragment >= 0 && endFragment > startFragment && endFragment <= len(data) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if startFragment < 0 || endFragment <= startFragment || endFragment > len(data) {
|
||||
// 回退:无有效偏移时原样返回(去除首行头部不可行,尽力而为)
|
||||
return s
|
||||
}
|
||||
return s[startFragment:endFragment]
|
||||
}
|
||||
|
||||
func parseOffsetLine(line, key string) (int, bool) {
|
||||
if !strings.HasPrefix(line, key) {
|
||||
return 0, false
|
||||
}
|
||||
v := 0
|
||||
for _, c := range line[len(key):] {
|
||||
if c < '0' || c > '9' {
|
||||
return 0, false
|
||||
}
|
||||
v = v*10 + int(c-'0')
|
||||
}
|
||||
return v, true
|
||||
}
|
||||
Reference in New Issue
Block a user