Skip to content

Commit ba7d3f7

Browse files
author
wcr
committed
Merge branch 'dev' into dev-1.2.x
# Conflicts: # backend/all/all.go # backend/baidu_netdisk/baidu_netdisk_object.go
2 parents 1c8872f + 43a6313 commit ba7d3f7

31 files changed

+3089
-77
lines changed

.run/local lsf.run.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<component name="ProjectRunConfigurationManager">
2+
<configuration default="false" name="local lsf" type="GoApplicationRunConfiguration" factoryName="Go Application" folderName="local">
3+
<module name="rclone" />
4+
<working_directory value="$PROJECT_DIR$" />
5+
<go_parameters value="-tags &quot;cmount&quot;" />
6+
<parameters value="lsf baidudbchunk:备份/台式机/13600kf/G/ -l --log-level DEBUG" />
7+
<kind value="PACKAGE" />
8+
<package value="github.com/rclone/rclone" />
9+
<directory value="$PROJECT_DIR$" />
10+
<filePath value="$PROJECT_DIR$/rclone.go" />
11+
<output_directory value="$PROJECT_DIR$/build" />
12+
<method v="2" />
13+
</configuration>
14+
</component>

.run/mount baidu chunk.run.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<module name="rclone" />
44
<working_directory value="$PROJECT_DIR$" />
55
<go_parameters value="-tags &quot;cmount&quot;" />
6-
<parameters value="mount baiduchunk:\ S: --cache-dir D:\OneDrive --vfs-cache-mode full --vfs-cache-max-age 2h --vfs-read-chunk-streams 15 --vfs-read-chunk-size 30408704B --log-file Q:\rclone.log --log-level INFO" />
6+
<parameters value="mount baiduchunk:\ S: --cache-dir D:\OneDrive --vfs-cache-mode full --vfs-cache-max-age 2h --vfs-read-chunk-streams 15 --vfs-read-chunk-size 30408704B --log-level INFO" />
77
<kind value="PACKAGE" />
88
<package value="github.com/rclone/rclone" />
99
<directory value="$PROJECT_DIR$" />

.run/onedrive copy 2.run.xml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<component name="ProjectRunConfigurationManager">
2+
<configuration default="false" name="onedrive copy 2" type="GoApplicationRunConfiguration" factoryName="Go Application">
3+
<module name="rclone" />
4+
<working_directory value="$PROJECT_DIR$" />
5+
<parameters value="copy --verbose --transfers 4 --checkers 8 --contimeout 60s --timeout 300s --retries 3 --low-level-retries 10 --stats 1s --stats-file-name-length 0 --fast-list &quot;OneDrive_local:\1\test.txt&quot; D:\aria2down -vv" />
6+
<envs>
7+
<env name="HTTP_PROXY" value="http://127.0.0.1:8888" />
8+
<env name="http_proxy" value="http://127.0.0.1:8888" />
9+
<env name="HTTPS_PROXY" value="http://127.0.0.1:8888" />
10+
<env name="https_proxy" value="http://127.0.0.1:8888" />
11+
</envs>
12+
<kind value="PACKAGE" />
13+
<package value="github.com/morecup/rclone" />
14+
<directory value="$PROJECT_DIR$" />
15+
<filePath value="$PROJECT_DIR$/rclone.go" />
16+
<output_directory value="$PROJECT_DIR$/build" />
17+
<method v="2" />
18+
</configuration>
19+
</component>

backend/all/all.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
_ "github.com/morecup/rclone/backend/b2"
1010
_ "github.com/morecup/rclone/backend/baidu_netdisk"
1111
_ "github.com/morecup/rclone/backend/baidu_photo"
12+
_ "github.com/morecup/rclone/backend/baidu_youth"
1213
_ "github.com/morecup/rclone/backend/better_chunk"
1314
_ "github.com/morecup/rclone/backend/box"
1415
_ "github.com/morecup/rclone/backend/cache"

backend/baidu_netdisk/api/util.go

Lines changed: 97 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package api
22

33
import (
4+
"crypto/md5"
5+
"encoding/hex"
46
"fmt"
7+
"io"
58
"strconv"
69
"strings"
710
)
@@ -27,26 +30,107 @@ func BoolToStr(b bool) string {
2730
}
2831
return "0"
2932
}
30-
func EncryptMd5(e string) string {
31-
if len(e) != 32 {
32-
return e
33+
34+
// EncryptMd5 百度网盘的MD5加密,会对标准的md5做一些特殊的处理
35+
func EncryptMd5(t string) string {
36+
// 检查长度是否为32
37+
if len(t) != 32 {
38+
return t
39+
}
40+
41+
// 检查所有字符是否在0-9或a-f之间
42+
for _, ch := range t {
43+
if !((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f')) {
44+
return t
45+
}
46+
}
47+
48+
// 重新排列字符串的片段
49+
r := t[8:16] + t[0:8] + t[24:32] + t[16:24]
50+
n := strings.Builder{}
51+
52+
// 对每个字符进行转换
53+
for e := 0; e < len(r); e++ {
54+
// 将十六进制字符转换为数字
55+
v, _ := strconv.ParseInt(string(r[e]), 16, 64)
56+
// 执行异或操作
57+
zj := int(v) ^ (15 & e)
58+
// 转换回十六进制字符串(小写)
59+
n.WriteString(strconv.FormatInt(int64(zj), 16))
60+
}
61+
62+
result := n.String()
63+
// 转换第9位字符(索引9)
64+
if num, err := strconv.ParseInt(string(result[9]), 16, 64); err == nil {
65+
replacement := string(rune(103 + num)) // 103 = 'g'的ASCII码
66+
// 替换字符串的第9个字符
67+
return result[:9] + replacement + result[10:]
68+
}
69+
70+
return result
71+
}
72+
func DecryptMd5(encrypted string) string {
73+
// 1. 检查输入是否为有效的加密格式
74+
if len(encrypted) != 32 {
75+
return encrypted
76+
}
77+
78+
// 检查特殊字符位置(索引9)是否在g-v范围内
79+
if encrypted[9] < 'g' || encrypted[9] > 'v' {
80+
return encrypted
3381
}
3482

35-
for _, ch := range e {
36-
if !(ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'f') {
37-
return e
83+
// 检查其他位置是否都是十六进制字符
84+
for i, ch := range encrypted {
85+
if i == 9 {
86+
continue
87+
}
88+
if !((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f')) {
89+
return encrypted
3890
}
3991
}
4092

41-
var i = e[8:16] + e[0:8] + e[24:32] + e[16:24]
93+
// 2. 恢复原始n字符串
94+
// 取出索引9的特殊字符,计算原始十六进制值
95+
originalDigit := int(encrypted[9] - 'g') // 减去'g'的偏移量
96+
n := encrypted[:9] + fmt.Sprintf("%x", originalDigit) + encrypted[10:]
97+
98+
// 3. 重建r字符串
99+
r := strings.Builder{}
100+
for e := 0; e < len(n); e++ {
101+
// 将十六进制字符转换为数字
102+
v, _ := strconv.ParseInt(string(n[e]), 16, 64)
103+
// 反转异或操作
104+
original := int(v) ^ (15 & e)
105+
r.WriteString(fmt.Sprintf("%x", original))
106+
}
107+
rStr := r.String()
42108

43-
r := ""
44-
for o := 0; o < len(i); o++ {
45-
digit, _ := strconv.ParseInt(string(i[o]), 16, 0)
46-
r += strconv.FormatInt(digit^(int64(o))&15, 16)
109+
// 4. 重新排列字符串片段恢复原始数据
110+
if len(rStr) != 32 {
111+
return encrypted
47112
}
48113

49-
s := string('g' + int64(strings.Index("0123456789abcdef", string(r[9]))))
114+
// 反转排列操作
115+
return rStr[8:16] + // 对应原始t[0:8]
116+
rStr[0:8] + // 对应原始t[8:16]
117+
rStr[24:32] + // 对应原始t[16:24]
118+
rStr[16:24] // 对应原始t[24:32]
119+
}
120+
func Md5(in io.ReadCloser, limitSize int) (string, error) {
121+
// 确保在函数结束时关闭 io.ReadCloser
122+
defer in.Close()
123+
124+
// 创建一个新的 MD5 哈希对象
125+
hash := md5.New()
126+
127+
buffer := make([]byte, limitSize)
128+
129+
bytesRead, err := io.ReadFull(in, buffer)
130+
if err != nil {
131+
return "", err
132+
}
133+
hash.Write(buffer[:min(bytesRead, limitSize)])
50134

51-
return r[0:9] + s + r[10:]
135+
return hex.EncodeToString(hash.Sum(nil)), nil
52136
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package api
2+
3+
import "testing"
4+
5+
func TestEncryptMd5(t *testing.T) {
6+
type args struct {
7+
e string
8+
}
9+
tests := []struct {
10+
name string
11+
args args
12+
want string
13+
}{
14+
{
15+
name: "标准32位十六进制字符串",
16+
args: args{e: "0535ba4186c95852f6778ed91a2d19c4"},
17+
want: "87ea1d358s9e77ae1b0e5ca37fdc4336", // 这是示例值,需要根据实际算法计算正确值
18+
},
19+
}
20+
for _, tt := range tests {
21+
t.Run(tt.name, func(t *testing.T) {
22+
if got := EncryptMd5(tt.args.e); got != tt.want {
23+
t.Errorf("EncryptMd5() = %v, want %v", got, tt.want)
24+
}
25+
})
26+
}
27+
}
28+
29+
func TestDecryptMd5(t *testing.T) {
30+
type args struct {
31+
encrypted string
32+
}
33+
tests := []struct {
34+
name string
35+
args args
36+
want string
37+
}{
38+
{
39+
name: "标准32位十六进制字符串",
40+
args: args{encrypted: "87ea1d358s9e77ae1b0e5ca37fdc4336"},
41+
want: "0535ba4186c95852f6778ed91a2d19c4", // 这是示例值,需要根据实际算法计算正确值
42+
},
43+
}
44+
for _, tt := range tests {
45+
t.Run(tt.name, func(t *testing.T) {
46+
if got := DecryptMd5(tt.args.encrypted); got != tt.want {
47+
t.Errorf("decryptMd5() = %v, want %v", got, tt.want)
48+
}
49+
})
50+
}
51+
}

backend/baidu_netdisk/baidu_netdisk.go

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
309309
CaseInsensitive: false,
310310
ReadMimeType: true,
311311
CanHaveEmptyDirectories: true,
312-
ServerSideAcrossConfigs: opt.ServerSideAcrossConfigs,
312+
ServerSideAcrossConfigs: true,
313313
}).Fill(ctx, f)
314314
f.srv.Client.SetErrorHandler(errorHandler)
315315

@@ -637,15 +637,16 @@ func (f *Fs) itemToDirOrObject(ctx context.Context, dir string, info *api.Item)
637637
entry = NewDir(f, dir+info.ServerFilename, time.Unix(info.LocalMtime, 0)).SetID(strconv.Itoa(int(info.FsID))).SetItems(-1).SetSize(-1)
638638
} else if info.IsDir == 0 {
639639
entry = &Object{
640-
fs: f,
641-
remote: dir + info.ServerFilename,
642-
hasMetaData: true,
643-
isOneNoteFile: false,
644-
size: info.Size,
645-
modTime: time.Unix(info.LocalMtime, 0),
646-
id: strconv.Itoa(int(info.FsID)),
647-
hash: "md5",
648-
mimeType: "json",
640+
fs: f,
641+
remote: dir + info.ServerFilename,
642+
hasMetaData: true,
643+
isOneNoteFile: false,
644+
size: info.Size,
645+
modTime: time.Unix(info.LocalMtime, 0),
646+
id: strconv.Itoa(int(info.FsID)),
647+
hash: "md5",
648+
mimeType: "json",
649+
baiduNetDiskMd5: info.Md5,
649650
}
650651
}
651652
return entry, nil
@@ -657,15 +658,16 @@ func (f *Fs) NewObjectFromBaseItem(item *api.BaseItem) (*Object, error) {
657658
return nil, err
658659
}
659660
object := &Object{
660-
fs: f,
661-
remote: relativePath,
662-
hasMetaData: true,
663-
isOneNoteFile: false,
664-
size: item.Size,
665-
modTime: time.Unix(item.Mtime, 0),
666-
id: strconv.FormatInt(item.FsId, 10),
667-
hash: item.Md5,
668-
mimeType: "json",
661+
fs: f,
662+
remote: relativePath,
663+
hasMetaData: true,
664+
isOneNoteFile: false,
665+
size: item.Size,
666+
modTime: time.Unix(item.Mtime, 0),
667+
id: strconv.FormatInt(item.FsId, 10),
668+
hash: item.Md5,
669+
mimeType: "json",
670+
baiduNetDiskMd5: item.Md5,
669671
}
670672
return object, nil
671673
}

backend/baidu_netdisk/baidu_netdisk_object.go

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package baidu_netdisk
33
import (
44
"context"
55
"errors"
6+
"github.com/morecup/rclone/backend/baidu_netdisk/api"
67
"github.com/morecup/rclone/fs"
78
"github.com/morecup/rclone/fs/hash"
89
"io"
@@ -15,15 +16,16 @@ import (
1516
//
1617
// Will definitely have info but maybe not meta
1718
type Object struct {
18-
fs *Fs // what this object is part of
19-
remote string // The remote path absolute path
20-
hasMetaData bool // whether info below has been set
21-
isOneNoteFile bool // Whether the object is a OneNote file
22-
size int64 // size of the object
23-
modTime time.Time // modification time of the object
24-
id string // ID of the object
25-
hash string // Hash of the content, usually QuickXorHash but set as hash_type
26-
mimeType string // Content-Type of object from server (may not be as uploaded)
19+
fs *Fs // what this object is part of
20+
remote string // The remote path absolute path
21+
hasMetaData bool // whether info below has been set
22+
isOneNoteFile bool // Whether the object is a OneNote file
23+
size int64 // size of the object
24+
modTime time.Time // modification time of the object
25+
id string // ID of the object
26+
hash string // Hash of the content, usually QuickXorHash but set as hash_type
27+
mimeType string // Content-Type of object from server (may not be as uploaded)
28+
baiduNetDiskMd5 string //md5值(百度网盘特有值)
2729
}
2830

2931
// ------------------------------------------------------------
@@ -114,6 +116,26 @@ func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (in io.Read
114116
return o.fs.DownFileSerial(ctx, o.remote, o.size, options)
115117
}
116118

119+
func (o *Object) ContentMd5(ctx context.Context) string {
120+
return api.DecryptMd5(o.baiduNetDiskMd5)
121+
}
122+
123+
func (o *Object) SliceMd5(ctx context.Context) (string, error) {
124+
if o.size <= sliceSize {
125+
return o.ContentMd5(ctx), nil
126+
}
127+
rangeOpt := fs.RangeOption{End: sliceSize - 1}
128+
in, err := o.OpenOld(ctx, &rangeOpt)
129+
if err != nil {
130+
return "", err
131+
}
132+
md5, err := api.Md5(in, sliceSize)
133+
if err != nil {
134+
return "", err
135+
}
136+
return md5, nil
137+
}
138+
117139
// Update the object with the contents of the io.Reader, modTime and size
118140
//
119141
// The new object may have been created if an error is returned

backend/baidu_photo/baidu_photo.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ func NewFs(ctx context.Context, name, root string, m configmap.Mapper) (fs.Fs, e
241241
CaseInsensitive: false,
242242
ReadMimeType: true,
243243
CanHaveEmptyDirectories: true,
244-
ServerSideAcrossConfigs: opt.ServerSideAcrossConfigs,
244+
ServerSideAcrossConfigs: true,
245245
}).Fill(ctx, f)
246246
f.srv.Client.SetErrorHandler(errorHandler)
247247

0 commit comments

Comments
 (0)