Skip to content

Commit 3e65a2d

Browse files
committed
Pass one at unfucking the stupid file encoding issues
1 parent 24417ac commit 3e65a2d

File tree

10 files changed

+33
-19
lines changed

10 files changed

+33
-19
lines changed

app/Http/Controllers/Api/Client/Servers/FileController.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public function directory(ListFilesRequest $request, Server $server): array
7272
{
7373
$contents = $this->fileRepository
7474
->setServer($server)
75-
->getDirectory($this->encode($request->get('directory') ?? '/'));
75+
->getDirectory(rawurldecode($request->get('directory') ?? '/'));
7676

7777
return $this->fractal->collection($contents)
7878
->transformWith($this->getTransformer(FileObjectTransformer::class))
@@ -93,7 +93,7 @@ public function contents(GetFileContentsRequest $request, Server $server): Respo
9393
{
9494
return new Response(
9595
$this->fileRepository->setServer($server)->getContent(
96-
$this->encode($request->get('file')), config('pterodactyl.files.max_edit_size')
96+
rawurldecode($request->get('file')), config('pterodactyl.files.max_edit_size')
9797
),
9898
Response::HTTP_OK,
9999
['Content-Type' => 'text/plain']

app/Transformers/Daemon/FileObjectTransformer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class FileObjectTransformer extends BaseDaemonTransformer
2323
public function transform(array $item)
2424
{
2525
return [
26-
'name' => Arr::get($item, 'name'),
26+
'name' => rawurlencode(Arr::get($item, 'name')),
2727
'mode' => Arr::get($item, 'mode'),
2828
'mode_bits' => Arr::get($item, 'mode_bits'),
2929
'size' => Arr::get($item, 'size'),

resources/scripts/api/server/files/getFileContents.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import http from '@/api/http';
33
export default (server: string, file: string): Promise<string> => {
44
return new Promise((resolve, reject) => {
55
http.get(`/api/client/servers/${server}/files/contents`, {
6-
params: { file: encodeURI(decodeURI(file)) },
6+
params: { file },
77
transformResponse: res => res,
88
responseType: 'text',
99
})

resources/scripts/api/server/files/loadDirectory.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ export interface FileObject {
1818

1919
export default async (uuid: string, directory?: string): Promise<FileObject[]> => {
2020
const { data } = await http.get(`/api/client/servers/${uuid}/files/list`, {
21-
params: { directory: encodeURI(directory ?? '/') },
21+
// At this point the directory is still encoded so we need to decode it since axios
22+
// will automatically re-encode this value before sending it along in the request.
23+
params: { directory: decodeURI(directory ?? '/') },
2224
});
2325

2426
return (data.data || []).map(rawDataToFileObject);

resources/scripts/api/server/files/saveFileContents.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import http from '@/api/http';
22

33
export default async (uuid: string, file: string, content: string): Promise<void> => {
44
await http.post(`/api/client/servers/${uuid}/files/write`, content, {
5-
params: { file: encodeURI(decodeURI(file)) },
5+
params: { file },
66
headers: {
77
'Content-Type': 'text/plain',
88
},

resources/scripts/components/server/files/FileEditContainer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export default () => {
6161
setLoading(true);
6262
clearFlashes('files:view');
6363
fetchFileContent()
64-
.then(content => saveFileContents(uuid, name || hash.replace(/^#/, ''), content))
64+
.then(content => saveFileContents(uuid, name || decodeURI(hash.replace(/^#/, '')), content))
6565
.then(() => {
6666
if (name) {
6767
history.push(`/server/${id}/files/edit#/${name}`);

resources/scripts/components/server/files/FileManagerBreadcrumbs.tsx

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useEffect, useState } from 'react';
22
import { ServerContext } from '@/state/server';
3-
import { NavLink } from 'react-router-dom';
3+
import { NavLink, useLocation } from 'react-router-dom';
44
import { cleanDirectoryPath } from '@/helpers';
55
import tw from 'twin.macro';
66

@@ -14,14 +14,28 @@ export default ({ renderLeft, withinFileEditor, isNewFile }: Props) => {
1414
const [ file, setFile ] = useState<string | null>(null);
1515
const id = ServerContext.useStoreState(state => state.server.data!.id);
1616
const directory = ServerContext.useStoreState(state => state.files.directory);
17+
const { hash } = useLocation();
1718

1819
useEffect(() => {
19-
const parts = cleanDirectoryPath(window.location.hash).split('/');
20+
let pathHash = cleanDirectoryPath(hash);
21+
try {
22+
pathHash = decodeURI(pathHash);
23+
} catch (e) {
24+
console.warn('Error decoding URL parts in hash:', e);
25+
}
2026

2127
if (withinFileEditor && !isNewFile) {
22-
setFile(parts.pop() || null);
28+
let name = pathHash.split('/').pop() || null;
29+
if (name) {
30+
try {
31+
name = decodeURIComponent(name);
32+
} catch (e) {
33+
console.warn('Error decoding filename:', e);
34+
}
35+
}
36+
setFile(name);
2337
}
24-
}, [ withinFileEditor, isNewFile ]);
38+
}, [ withinFileEditor, isNewFile, hash ]);
2539

2640
const breadcrumbs = (): { name: string; path?: string }[] => directory.split('/')
2741
.filter(directory => !!directory)
@@ -51,16 +65,16 @@ export default ({ renderLeft, withinFileEditor, isNewFile }: Props) => {
5165
to={`/server/${id}/files#${crumb.path}`}
5266
css={tw`px-1 text-neutral-200 no-underline hover:text-neutral-100`}
5367
>
54-
{crumb.name}
68+
{decodeURIComponent(crumb.name)}
5569
</NavLink>/
5670
</React.Fragment>
5771
:
58-
<span key={index} css={tw`px-1 text-neutral-300`}>{crumb.name}</span>
72+
<span key={index} css={tw`px-1 text-neutral-300`}>{decodeURIComponent(crumb.name)}</span>
5973
))
6074
}
6175
{file &&
6276
<React.Fragment>
63-
<span css={tw`px-1 text-neutral-300`}>{decodeURI(file)}</span>
77+
<span css={tw`px-1 text-neutral-300`}>{file}</span>
6478
</React.Fragment>
6579
}
6680
</div>

resources/scripts/components/server/files/FileManagerContainer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export default () => {
3939
useEffect(() => {
4040
clearFlashes('files');
4141
setSelectedFiles([]);
42-
setDirectory(hash.length > 0 ? decodeURI(hash) : '/');
42+
setDirectory(hash.length > 0 ? hash : '/');
4343
}, [ hash ]);
4444

4545
useEffect(() => {

resources/scripts/components/server/files/FileObjectRow.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const Clickable: React.FC<{ file: FileObject }> = memo(({ file, children }) => {
2424
const history = useHistory();
2525
const match = useRouteMatch();
2626

27-
const destination = cleanDirectoryPath(`${directory}/${file.name}`).split('/').map(v => encodeURI(v)).join('/');
27+
const destination = cleanDirectoryPath(`${directory}/${file.name}`).split('/').join('/');
2828

2929
const onRowClick = (e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
3030
// Don't rely on the onClick to work with the generated URL. Because of the way this
@@ -72,7 +72,7 @@ const FileObjectRow = ({ file }: { file: FileObject }) => (
7272
}
7373
</div>
7474
<div css={tw`flex-1 truncate`}>
75-
{file.name}
75+
{decodeURIComponent(file.name)}
7676
</div>
7777
{file.isFile &&
7878
<div css={tw`w-1/6 text-right mr-4 hidden sm:block`}>

resources/scripts/plugins/useFileManagerSwr.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ export default () => {
77
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
88
const directory = ServerContext.useStoreState(state => state.files.directory);
99

10-
console.log('firing');
11-
1210
return useSWR<FileObject[]>(
1311
`${uuid}:files:${directory}`,
1412
() => loadDirectory(uuid, cleanDirectoryPath(directory)),

0 commit comments

Comments
 (0)