fix encoding url in archive

This commit is contained in:
2023-10-20 18:25:33 +02:00
parent 600475f603
commit 6688bc3977
8 changed files with 70 additions and 55 deletions

View File

@@ -14,6 +14,7 @@
"@fontsource/roboto": "^5.0.6",
"@mui/icons-material": "^5.11.16",
"@mui/material": "^5.13.5",
"fp-ts": "^2.16.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-helmet": "^6.1.0",

View File

@@ -1,13 +1,24 @@
export async function ffetch<T>(
url: string,
onSuccess: (res: T) => void,
onError: (err: string) => void,
opt?: RequestInit,
) {
import { tryCatch } from 'fp-ts/TaskEither'
import { flow } from 'fp-ts/lib/function'
export const ffetch = <T>(url: string, opt?: RequestInit) => flow(
tryCatch(
() => fetcher<T>(url, opt),
(e) => `error while fetching: ${e}`
)
)
const fetcher = async <T>(url: string, opt?: RequestInit) => {
const res = await fetch(url, opt)
if (!res.ok) {
onError(await res.text())
return
if (opt && !opt.headers) {
opt.headers = {
'Content-Type': 'application/json',
}
}
onSuccess(await res.json() as T)
if (!res.ok) {
throw await res.text()
}
return res.json() as T
}

View File

@@ -1,3 +1,4 @@
import { pipe } from 'fp-ts/lib/function'
import type { RPCResponse } from "./types"
/**
@@ -10,15 +11,6 @@ export function validateIP(ipAddr: string): boolean {
return ipRegex.test(ipAddr)
}
/**
* Validate a domain via regex.
* The validation pass if the domain respects the following formats:
* - localhost
* - domain.tld
* - dir.domain.tld
* @param domainName
* @returns domain validity test
*/
export function validateDomain(url: string): boolean {
const urlRegex = /(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()!@:%_\+.~#?&\/\/=]*)/
const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/
@@ -28,17 +20,6 @@ export function validateDomain(url: string): boolean {
return urlRegex.test(url) || name === 'localhost' && slugRegex.test(slug)
}
/**
* Validate a domain via regex.
* Exapmples
* - http://example.com
* - https://example.com
* - http://www.example.com
* - https://www.example.com
* - http://10.0.0.1/[something]/[something-else]
* @param url
* @returns url validity test
*/
export function isValidURL(url: string): boolean {
let urlRegex = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()!@:%_\+.~#?&\/\/=]*)/
return urlRegex.test(url)
@@ -93,4 +74,11 @@ export function mapProcessStatus(status: number) {
}
export const prefersDarkMode = () =>
window.matchMedia('(prefers-color-scheme: dark)').matches
window.matchMedia('(prefers-color-scheme: dark)').matches
export const base64URLEncode = (s: string) => pipe(
s,
s => String.fromCodePoint(...new TextEncoder().encode(s)),
btoa,
encodeURIComponent
)

View File

@@ -26,22 +26,26 @@ import FolderIcon from '@mui/icons-material/Folder'
import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile'
import VideoFileIcon from '@mui/icons-material/VideoFile'
import { matchW } from 'fp-ts/lib/TaskEither'
import { pipe } from 'fp-ts/lib/function'
import { useEffect, useMemo, useState, useTransition } from 'react'
import { useNavigate } from 'react-router-dom'
import { useRecoilValue } from 'recoil'
import { BehaviorSubject, Subject, combineLatestWith, map, share } from 'rxjs'
import { serverURL } from '../atoms/settings'
import { useObservable } from '../hooks/observable'
import { useToast } from '../hooks/toast'
import { useI18n } from '../hooks/useI18n'
import { ffetch } from '../lib/httpClient'
import { DeleteRequest, DirectoryEntry } from '../types'
import { roundMiB } from '../utils'
import { base64URLEncode, roundMiB } from '../utils'
export default function Downloaded() {
const serverAddr = useRecoilValue(serverURL)
const navigate = useNavigate()
const { i18n } = useI18n()
const { pushMessage } = useToast()
const [openDialog, setOpenDialog] = useState(false)
@@ -50,20 +54,24 @@ export default function Downloaded() {
const [isPending, startTransition] = useTransition()
const fetcher = () => ffetch<DirectoryEntry[]>(
`${serverAddr}/archive/downloaded`,
(d) => files$.next(d),
() => navigate('/login'),
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
const fetcher = () => pipe(
ffetch<DirectoryEntry[]>(
`${serverAddr}/archive/downloaded`,
{
method: 'POST',
body: JSON.stringify({
subdir: '',
})
}
),
matchW(
(e) => {
pushMessage(e)
navigate('/login')
},
body: JSON.stringify({
subdir: '',
})
}
)
(d) => files$.next(d),
)
)()
const fetcherSubfolder = (sub: string) => {
const folders = sub.startsWith('/')
@@ -137,9 +145,7 @@ export default function Downloaded() {
}, [serverAddr])
const onFileClick = (path: string) => startTransition(() => {
const encoded = btoa(
String.fromCodePoint(...new TextEncoder().encode(path))
)
const encoded = base64URLEncode(path)
window.open(`${serverAddr}/archive/d/${encoded}`)
})