Skip to content

Commit d59d2d1

Browse files
committed
fix(backup): failed to create directory for webdav
1 parent 6226eb7 commit d59d2d1

File tree

6 files changed

+55
-21
lines changed

6 files changed

+55
-21
lines changed

package.json

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@
3131
"@crowdin/crowdin-api-client": "^1.48.3",
3232
"@emotion/babel-plugin": "^11.13.5",
3333
"@emotion/css": "^11.13.5",
34-
"@rsdoctor/rspack-plugin": "^1.3.7",
35-
"@rspack/cli": "^1.6.0",
36-
"@rspack/core": "^1.6.0",
34+
"@rsdoctor/rspack-plugin": "^1.3.8",
35+
"@rspack/cli": "^1.6.1",
36+
"@rspack/core": "^1.6.1",
3737
"@swc/core": "^1.15.0",
3838
"@swc/jest": "^0.2.39",
3939
"@types/chrome": "0.1.27",
@@ -54,7 +54,7 @@
5454
"postcss": "^8.5.6",
5555
"postcss-loader": "^8.2.0",
5656
"postcss-rtlcss": "^5.7.1",
57-
"puppeteer": "^24.28.0",
57+
"puppeteer": "^24.29.0",
5858
"ts-loader": "^9.5.4",
5959
"ts-node": "^10.9.2",
6060
"tsconfig-paths": "^4.2.0",
@@ -64,12 +64,11 @@
6464
"@element-plus/icons-vue": "^2.3.2",
6565
"echarts": "^6.0.0",
6666
"element-plus": "2.11.7",
67-
"js-base64": "^3.7.8",
6867
"punycode": "^2.3.1",
69-
"vue": "^3.5.22",
68+
"vue": "^3.5.23",
7069
"vue-router": "^4.6.3"
7170
},
7271
"engines": {
7372
"node": ">=20"
7473
}
75-
}
74+
}

src/api/web-dav.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Testing with server implemented by https://github.com/svtslv/webdav-cli
55
*/
6-
import { encode } from 'js-base64'
6+
import { encode } from '@util/base64'
77
import { fetchDelete, fetchGet } from './http'
88

99
// Only support password for now
@@ -49,12 +49,23 @@ export async function judgeDirExist(context: WebDAVContext, dirPath: string): Pr
4949
}
5050
}
5151

52-
export async function makeDir(context: WebDAVContext, dirPath: string) {
52+
export async function makeDirs(context: WebDAVContext, dirPath: string) {
53+
const normalizedPath = dirPath.startsWith('/') ? dirPath.slice(1) : dirPath
54+
const pathSegments = normalizedPath.split('/').filter(segment => segment.length > 0)
55+
5356
const { auth, endpoint } = context || {}
54-
const url = `${endpoint}/${dirPath}`
55-
const headers = authHeaders(auth)
56-
const response = await fetch(url, { method: 'MKCOL', headers })
57-
handleWriteResponse(response)
57+
58+
for (let i = 0; i < pathSegments.length; i++) {
59+
const currentPath = pathSegments.slice(0, i + 1).join('/')
60+
61+
const exists = await judgeDirExist(context, currentPath)
62+
if (!exists) {
63+
const url = `${endpoint}/${currentPath}`
64+
const headers = authHeaders(auth)
65+
const response = await fetch(url, { method: 'MKCOL', headers })
66+
handleWriteResponse(response)
67+
}
68+
}
5869
}
5970

6071
export async function deleteDir(context: WebDAVContext, dirPath: string) {

src/pages/app/Layout/menu/Nav.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,10 @@ const _default = defineComponent<{}>(() => {
8787
<div class={menuWrapperCls} v-show={showMenu.value}>
8888
<ElMenu>
8989
{NAV_MENUS.map(item => (
90-
<ElMenuItem onClick={() => handleItemClick(item)}>
90+
<ElMenuItem
91+
index={item.index ?? item.route ?? item.href}
92+
onClick={() => handleItemClick(item)}
93+
>
9194
<ElIcon>
9295
{h(item.icon)}
9396
</ElIcon>

src/pages/app/Layout/menu/Side.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const useStyle = () => {
5858

5959
const renderItem = (item: MenuItem, router: Router, curr: Ref<string | undefined>) => (
6060
<ElMenuItem
61-
index={item.index ?? item.route}
61+
index={item.index ?? item.route ?? item.href}
6262
onClick={() => handleClick(item, router, curr)}
6363
v-slots={{
6464
default: () => <ElIcon size={18}>{h(item.icon)}</ElIcon>,

src/service/backup/web-dav/coordinator.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {
2-
deleteDir, judgeDirExist, makeDir, readFile, writeFile,
2+
deleteDir, judgeDirExist, makeDirs, readFile, writeFile,
33
type WebDAVAuth, type WebDAVContext,
44
} from "@api/web-dav"
55
import DateIterator from "@util/date-iterator"
@@ -84,10 +84,7 @@ export default class WebDAVCoordinator implements timer.backup.Coordinator<never
8484

8585
private async checkClientDirExist(davContext: WebDAVContext, dirPath: string, cid: string) {
8686
const clientDirPath = `${dirPath}${cid}`
87-
const clientExist = await judgeDirExist(davContext, clientDirPath)
88-
if (!clientExist) {
89-
await makeDir(davContext, clientDirPath)
90-
}
87+
await makeDirs(davContext, clientDirPath)
9188
return clientDirPath
9289
}
9390

@@ -111,9 +108,10 @@ export default class WebDAVCoordinator implements timer.backup.Coordinator<never
111108
const davContext: WebDAVContext = { endpoint, auth: davAuth }
112109
const webDavPath = processDir(dirPath)
113110
try {
111+
await makeDirs(davContext, webDavPath)
114112
const exist = await judgeDirExist(davContext, webDavPath)
115113
if (!exist) {
116-
return "Directory not found"
114+
return "Failed to create directory"
117115
}
118116
} catch (e) {
119117
return (e as Error)?.message ?? e?.toString?.() ?? 'Unknown error'

src/util/base64.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const BASE64_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
2+
3+
export function encode(str: string): string {
4+
const bytes = new TextEncoder().encode(str)
5+
let result = ''
6+
7+
for (let i = 0; i < bytes.length; i += 3) {
8+
const byte1 = bytes[i]
9+
const byte2 = bytes[i + 1] || 0
10+
const byte3 = bytes[i + 2] || 0
11+
12+
const char1 = byte1 >> 2
13+
const char2 = ((byte1 & 0x03) << 4) | (byte2 >> 4)
14+
const char3 = ((byte2 & 0x0F) << 2) | (byte3 >> 6)
15+
const char4 = byte3 & 0x3F
16+
17+
result += BASE64_CHARS[char1] + BASE64_CHARS[char2] +
18+
(i + 1 < bytes.length ? BASE64_CHARS[char3] : '=') +
19+
(i + 2 < bytes.length ? BASE64_CHARS[char4] : '=')
20+
}
21+
22+
return result
23+
}

0 commit comments

Comments
 (0)