feat: override domain header
This commit is contained in:
parent
e80627a3c3
commit
83718d7b31
10 changed files with 224 additions and 101 deletions
5
src/components/icons/GlobeIcon.tsx
Normal file
5
src/components/icons/GlobeIcon.tsx
Normal file
|
@ -0,0 +1,5 @@
|
|||
import { Globe } from 'react-feather';
|
||||
|
||||
export default function GlobeIcon({ ...props }) {
|
||||
return <Globe size={15} {...props} />;
|
||||
}
|
|
@ -38,6 +38,7 @@ import InfoIcon from './InfoIcon';
|
|||
import FolderIcon from './FolderIcon';
|
||||
import FolderMinusIcon from './FolderMinusIcon';
|
||||
import FolderPlusIcon from './FolderPlusIcon';
|
||||
import GlobeIcon from './GlobeIcon';
|
||||
|
||||
export {
|
||||
ActivityIcon,
|
||||
|
@ -80,4 +81,5 @@ export {
|
|||
FolderIcon,
|
||||
FolderMinusIcon,
|
||||
FolderPlusIcon,
|
||||
GlobeIcon,
|
||||
};
|
||||
|
|
|
@ -61,6 +61,12 @@ export default function Flameshot({ user, open, setOpen }) {
|
|||
delete extraHeaders['Original-Name'];
|
||||
}
|
||||
|
||||
if (values.overrideDomain && values.overrideDomain.trim() !== '') {
|
||||
extraHeaders['Override-Domain'] = values.overrideDomain;
|
||||
} else {
|
||||
delete extraHeaders['Override-Domain'];
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(extraHeaders)) {
|
||||
curl.push('-H');
|
||||
curl.push(`"${key}: ${value}"`);
|
||||
|
|
|
@ -10,13 +10,16 @@ import {
|
|||
Stack,
|
||||
Switch,
|
||||
Text,
|
||||
TextInput,
|
||||
Title,
|
||||
} from '@mantine/core';
|
||||
import { useForm } from '@mantine/form';
|
||||
import { DownloadIcon } from 'components/icons';
|
||||
import { DownloadIcon, GlobeIcon } from 'components/icons';
|
||||
import Link from 'components/Link';
|
||||
import MutedText from 'components/MutedText';
|
||||
import { useState } from 'react';
|
||||
import { useReducer, useState } from 'react';
|
||||
|
||||
const DEFAULT_OD_DESC = 'Override the default domain(s). Type in a URL, e.g https://example.com';
|
||||
|
||||
export function GeneratorModal({ opened, onClose, title, onSubmit, ...other }) {
|
||||
const form = useForm({
|
||||
|
@ -30,6 +33,7 @@ export function GeneratorModal({ opened, onClose, title, onSubmit, ...other }) {
|
|||
wlCompositorNotSupported: false,
|
||||
noJSON: false,
|
||||
originalName: false,
|
||||
overrideDomain: null,
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -40,6 +44,42 @@ export function GeneratorModal({ opened, onClose, title, onSubmit, ...other }) {
|
|||
form.setFieldValue('type', value);
|
||||
};
|
||||
|
||||
const [odState, setODState] = useReducer((state, newState) => ({ ...state, ...newState }), {
|
||||
description: DEFAULT_OD_DESC,
|
||||
error: '',
|
||||
domain: '',
|
||||
});
|
||||
|
||||
const handleOD = (e) => {
|
||||
setODState({ error: '' });
|
||||
|
||||
if (e.currentTarget.value === '') {
|
||||
setODState({ description: DEFAULT_OD_DESC, error: '', domain: null });
|
||||
form.setFieldValue('overrideDomain', null);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const url = new URL(e.currentTarget.value);
|
||||
setODState({
|
||||
description: (
|
||||
<>
|
||||
{DEFAULT_OD_DESC}
|
||||
<br />
|
||||
<br />
|
||||
Using domain "<b>{url.hostname}</b>"
|
||||
</>
|
||||
),
|
||||
error: '',
|
||||
domain: url.hostname,
|
||||
});
|
||||
form.setFieldValue('overrideDomain', url.hostname);
|
||||
} catch (e) {
|
||||
setODState({ error: 'Invalid URL', domain: '' });
|
||||
form.setFieldValue('overrideDomain', null);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal opened={opened} onClose={onClose} title={<Title order={3}>{title}</Title>} size='lg'>
|
||||
{other.desc && (
|
||||
|
@ -85,6 +125,14 @@ export function GeneratorModal({ opened, onClose, title, onSubmit, ...other }) {
|
|||
{...form.getInputProps('imageCompression')}
|
||||
/>
|
||||
|
||||
<TextInput
|
||||
label='Override Domain'
|
||||
onChange={handleOD}
|
||||
icon={<GlobeIcon />}
|
||||
description={odState.description}
|
||||
error={odState.error}
|
||||
/>
|
||||
|
||||
<Stack my='md'>
|
||||
<Switch
|
||||
label='Zero Width Space'
|
||||
|
|
|
@ -79,6 +79,12 @@ export default function ShareX({ user, open, setOpen }) {
|
|||
delete config.Headers['Original-Name'];
|
||||
}
|
||||
|
||||
if (values.overrideDomain && values.overrideDomain.trim() !== '') {
|
||||
config.Headers['Override-Domain'] = values.overrideDomain;
|
||||
} else {
|
||||
delete config.Headers['Override-Domain'];
|
||||
}
|
||||
|
||||
const pseudoElement = document.createElement('a');
|
||||
pseudoElement.setAttribute(
|
||||
'href',
|
||||
|
|
|
@ -276,6 +276,7 @@ export default function File({ chunks: chunks_config }) {
|
|||
options.zeroWidth && req.setRequestHeader('Zws', 'true');
|
||||
options.format !== 'default' && req.setRequestHeader('Format', options.format);
|
||||
options.originalName && req.setRequestHeader('Original-Name', 'true');
|
||||
options.overrideDomain && req.setRequestHeader('Override-Domain', options.overrideDomain);
|
||||
|
||||
req.send(body);
|
||||
}
|
||||
|
@ -283,7 +284,7 @@ export default function File({ chunks: chunks_config }) {
|
|||
|
||||
return (
|
||||
<>
|
||||
<OptionsModal />
|
||||
{OptionsModal}
|
||||
<Title mb='md'>Upload Files</Title>
|
||||
|
||||
<Dropzone loading={loading} onDrop={(f) => setFiles([...files, ...f])}>
|
||||
|
|
|
@ -71,13 +71,14 @@ export default function Text() {
|
|||
options.zeroWidth && req.setRequestHeader('Zws', 'true');
|
||||
options.format !== 'default' && req.setRequestHeader('Format', options.format);
|
||||
options.originalName && req.setRequestHeader('Original-Name', 'true');
|
||||
options.overrideDomain && req.setRequestHeader('Override-Domain', options.overrideDomain);
|
||||
|
||||
req.send(body);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<OptionsModal />
|
||||
{OptionsModal}
|
||||
<Title mb='md'>Upload Text</Title>
|
||||
|
||||
<Tabs defaultValue='text' variant='pills'>
|
||||
|
|
|
@ -7,52 +7,72 @@ import {
|
|||
Select,
|
||||
Stack,
|
||||
Switch,
|
||||
TextInput,
|
||||
Title,
|
||||
} from '@mantine/core';
|
||||
import { ClockIcon, ImageIcon, KeyIcon, TypeIcon, UserIcon } from 'components/icons';
|
||||
import { ClockIcon, ImageIcon, KeyIcon, TypeIcon, UserIcon, GlobeIcon } from 'components/icons';
|
||||
import React, { Dispatch, SetStateAction, useReducer, useState } from 'react';
|
||||
|
||||
export default function useUploadOptions(): [
|
||||
{
|
||||
expires: string;
|
||||
password: string;
|
||||
maxViews: number;
|
||||
compression: string;
|
||||
zeroWidth: boolean;
|
||||
embedded: boolean;
|
||||
format: string;
|
||||
originalName: boolean;
|
||||
},
|
||||
Dispatch<SetStateAction<boolean>>,
|
||||
React.FC
|
||||
] {
|
||||
const [state, setState] = useReducer((state, newState) => ({ ...state, ...newState }), {
|
||||
expires: 'never',
|
||||
password: '',
|
||||
maxViews: 0,
|
||||
compression: 'none',
|
||||
zeroWidth: false,
|
||||
embedded: false,
|
||||
format: 'default',
|
||||
originalName: false,
|
||||
export type UploadOptionsState = {
|
||||
expires: string;
|
||||
password: string;
|
||||
maxViews: number;
|
||||
compression: string;
|
||||
zeroWidth: boolean;
|
||||
embedded: boolean;
|
||||
format: string;
|
||||
originalName: boolean;
|
||||
overrideDomain: string;
|
||||
};
|
||||
|
||||
const DEFAULT_OD_DESC = 'Override the default domain(s). Type in a URL, e.g https://example.com';
|
||||
|
||||
export function OptionsModal({
|
||||
opened,
|
||||
setOpened,
|
||||
state,
|
||||
setState,
|
||||
reset,
|
||||
}: {
|
||||
opened: boolean;
|
||||
setOpened: Dispatch<SetStateAction<boolean>>;
|
||||
state: UploadOptionsState;
|
||||
setState: Dispatch<SetStateAction<any>>;
|
||||
reset: () => void;
|
||||
}) {
|
||||
const [odState, setODState] = useReducer((state, newState) => ({ ...state, ...newState }), {
|
||||
description: DEFAULT_OD_DESC,
|
||||
error: '',
|
||||
});
|
||||
|
||||
const [opened, setOpened] = useState(false);
|
||||
const handleOD = (e) => {
|
||||
setODState({ error: '' });
|
||||
|
||||
const reset = () => {
|
||||
setState({
|
||||
expires: 'never',
|
||||
password: '',
|
||||
maxViews: 0,
|
||||
compression: 'none',
|
||||
zeroWidth: false,
|
||||
embedded: false,
|
||||
format: 'default',
|
||||
originalName: false,
|
||||
});
|
||||
if (e.currentTarget.value === '') {
|
||||
setODState({ description: DEFAULT_OD_DESC, error: '' });
|
||||
setState({ overrideDomain: '' });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const url = new URL(e.currentTarget.value);
|
||||
setODState({
|
||||
description: (
|
||||
<>
|
||||
{DEFAULT_OD_DESC}
|
||||
<br />
|
||||
<br />
|
||||
Using domain "<b>{url.hostname}</b>"
|
||||
</>
|
||||
),
|
||||
});
|
||||
setState({ overrideDomain: url.hostname });
|
||||
} catch (e) {
|
||||
setODState({ error: 'Invalid URL' });
|
||||
}
|
||||
};
|
||||
|
||||
const OptionsModal: React.FC = () => (
|
||||
return (
|
||||
<Modal title={<Title>Upload Options</Title>} size='lg' opened={opened} onClose={() => setOpened(false)}>
|
||||
<Stack>
|
||||
<NumberInput
|
||||
|
@ -134,6 +154,13 @@ export default function useUploadOptions(): [
|
|||
onChange={(e) => setState({ password: e.currentTarget.value })}
|
||||
icon={<KeyIcon />}
|
||||
/>
|
||||
<TextInput
|
||||
label='Override Domain'
|
||||
onChange={handleOD}
|
||||
icon={<GlobeIcon />}
|
||||
description={odState.description}
|
||||
error={odState.error}
|
||||
/>
|
||||
<Group>
|
||||
<Switch
|
||||
label='Zero Width'
|
||||
|
@ -165,6 +192,47 @@ export default function useUploadOptions(): [
|
|||
</Stack>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
return [state, setOpened, OptionsModal];
|
||||
}
|
||||
|
||||
export default function useUploadOptions(): [UploadOptionsState, Dispatch<SetStateAction<boolean>>, any] {
|
||||
const [state, setState] = useReducer((state, newState) => ({ ...state, ...newState }), {
|
||||
expires: 'never',
|
||||
password: '',
|
||||
maxViews: 0,
|
||||
compression: 'none',
|
||||
zeroWidth: false,
|
||||
embedded: false,
|
||||
format: 'default',
|
||||
originalName: false,
|
||||
overrideDomain: '',
|
||||
} as UploadOptionsState);
|
||||
|
||||
const [opened, setOpened] = useState(false);
|
||||
|
||||
const reset = () => {
|
||||
setState({
|
||||
expires: 'never',
|
||||
password: '',
|
||||
maxViews: 0,
|
||||
compression: 'none',
|
||||
zeroWidth: false,
|
||||
embedded: false,
|
||||
format: 'default',
|
||||
originalName: false,
|
||||
overrideDomain: '',
|
||||
});
|
||||
};
|
||||
|
||||
return [
|
||||
state,
|
||||
setOpened,
|
||||
<OptionsModal
|
||||
state={state}
|
||||
setState={setState}
|
||||
reset={reset}
|
||||
opened={opened}
|
||||
setOpened={setOpened}
|
||||
key={1}
|
||||
/>,
|
||||
];
|
||||
}
|
||||
|
|
|
@ -56,27 +56,31 @@ async function handler(req: NextApiReq, res: NextApiRes) {
|
|||
|
||||
logger.info(`User ${user.username} (${user.id}) shortenned a url ${url.destination} (${url.id})`);
|
||||
|
||||
if (config.discord?.shorten) {
|
||||
await sendShorten(
|
||||
user,
|
||||
url,
|
||||
`${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}${
|
||||
zconfig.urls.route === '/' ? '/' : `${zconfig.urls.route}/`
|
||||
}${req.body.vanity ? req.body.vanity : invis ? invis.invis : url.id}`
|
||||
);
|
||||
let domain;
|
||||
if (req.headers['override-domain']) {
|
||||
domain = `${zconfig.core.return_https ? 'https' : 'http'}://${req.headers['override-domain']}`;
|
||||
} else if (user.domains.length) {
|
||||
const randomDomain = user.domains[Math.floor(Math.random() * user.domains.length)];
|
||||
domain = `${zconfig.core.return_https ? 'https' : 'http'}://${randomDomain}`;
|
||||
} else {
|
||||
domain = `${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}`;
|
||||
}
|
||||
|
||||
const fullUrl = `${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}${
|
||||
zconfig.urls.route === '/' ? '/' : zconfig.urls.route
|
||||
}/${req.body.vanity ? req.body.vanity : invis ? invis.invis : url.id}`;
|
||||
const responseUrl = `${domain}${zconfig.uploader.route === '/' ? '/' : zconfig.uploader.route}${
|
||||
req.body.vanity ? req.body.vanity : invis ? invis.invis : url.id
|
||||
}`;
|
||||
|
||||
if (config.discord?.shorten) {
|
||||
await sendShorten(user, url, responseUrl);
|
||||
}
|
||||
|
||||
if (req.headers['no-json']) {
|
||||
res.setHeader('Content-Type', 'text/plain');
|
||||
return res.end(fullUrl);
|
||||
return res.end(responseUrl);
|
||||
}
|
||||
|
||||
return res.json({
|
||||
url: fullUrl,
|
||||
url: responseUrl,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -171,32 +171,24 @@ async function handler(req: NextApiReq, res: NextApiRes) {
|
|||
await datasource.save(file.name, Buffer.from(chunks));
|
||||
|
||||
logger.info(`User ${user.username} (${user.id}) uploaded ${file.name} (${file.id}) (chunked)`);
|
||||
if (user.domains.length) {
|
||||
const domain = user.domains[Math.floor(Math.random() * user.domains.length)];
|
||||
response.files.push(
|
||||
`${domain}${zconfig.uploader.route === '/' ? '/' : zconfig.uploader.route}/${
|
||||
invis ? invis.invis : file.name
|
||||
}`
|
||||
);
|
||||
let domain;
|
||||
if (req.headers['override-domain']) {
|
||||
domain = `${zconfig.core.return_https ? 'https' : 'http'}://${req.headers['override-domain']}`;
|
||||
} else if (user.domains.length) {
|
||||
const randomDomain = user.domains[Math.floor(Math.random() * user.domains.length)];
|
||||
domain = `${zconfig.core.return_https ? 'https' : 'http'}://${randomDomain}`;
|
||||
} else {
|
||||
response.files.push(
|
||||
`${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}${
|
||||
zconfig.uploader.route === '/' ? '/' : zconfig.uploader.route
|
||||
}/${invis ? invis.invis : file.name}`
|
||||
);
|
||||
domain = `${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}`;
|
||||
}
|
||||
|
||||
const responseUrl = `${domain}${zconfig.uploader.route === '/' ? '/' : zconfig.uploader.route}${
|
||||
invis ? invis.invis : file.name
|
||||
}`;
|
||||
|
||||
response.files.push(responseUrl);
|
||||
|
||||
if (zconfig.discord?.upload) {
|
||||
await sendUpload(
|
||||
user,
|
||||
file,
|
||||
`${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}/r/${
|
||||
invis ? invis.invis : file.name
|
||||
}`,
|
||||
`${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}${
|
||||
zconfig.uploader.route === '/' ? '/' : zconfig.uploader.route
|
||||
}/${invis ? invis.invis : file.name}`
|
||||
);
|
||||
await sendUpload(user, file, `${domain}/r/${invis ? invis.invis : file.name}`, responseUrl);
|
||||
}
|
||||
|
||||
if (zconfig.exif.enabled && zconfig.exif.remove_gps && mimetype.startsWith('image/')) {
|
||||
|
@ -318,34 +310,24 @@ async function handler(req: NextApiReq, res: NextApiRes) {
|
|||
}
|
||||
|
||||
logger.info(`User ${user.username} (${user.id}) uploaded ${fileUpload.name} (${fileUpload.id})`);
|
||||
if (user.domains.length) {
|
||||
const domain = user.domains[Math.floor(Math.random() * user.domains.length)];
|
||||
response.files.push(
|
||||
`${domain}${zconfig.uploader.route === '/' ? '' : zconfig.uploader.route}/${
|
||||
invis ? invis.invis : fileUpload.name
|
||||
}`
|
||||
);
|
||||
let domain;
|
||||
if (req.headers['override-domain']) {
|
||||
domain = `${zconfig.core.return_https ? 'https' : 'http'}://${req.headers['override-domain']}`;
|
||||
} else if (user.domains.length) {
|
||||
const randomDomain = user.domains[Math.floor(Math.random() * user.domains.length)];
|
||||
domain = `${zconfig.core.return_https ? 'https' : 'http'}://${randomDomain}`;
|
||||
} else {
|
||||
response.files.push(
|
||||
`${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}${
|
||||
zconfig.uploader.route === '/' ? '' : zconfig.uploader.route
|
||||
}/${invis ? invis.invis : fileUpload.name}`
|
||||
);
|
||||
domain = `${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}`;
|
||||
}
|
||||
|
||||
logger.debug(`sent response: ${JSON.stringify(response)}`);
|
||||
const responseUrl = `${domain}${zconfig.uploader.route === '/' ? '/' : zconfig.uploader.route}${
|
||||
invis ? invis.invis : fileUpload.name
|
||||
}`;
|
||||
|
||||
response.files.push(responseUrl);
|
||||
|
||||
if (zconfig.discord?.upload) {
|
||||
await sendUpload(
|
||||
user,
|
||||
fileUpload,
|
||||
`${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}/r/${
|
||||
invis ? invis.invis : fileUpload.name
|
||||
}`,
|
||||
`${zconfig.core.return_https ? 'https' : 'http'}://${req.headers.host}${
|
||||
zconfig.uploader.route === '/' ? '' : zconfig.uploader.route
|
||||
}/${invis ? invis.invis : fileUpload.name}`
|
||||
);
|
||||
await sendUpload(user, fileUpload, `${domain}/r/${invis ? invis.invis : fileUpload.name}`, responseUrl);
|
||||
}
|
||||
|
||||
if (zconfig.exif.enabled && zconfig.exif.remove_gps && fileUpload.mimetype.startsWith('image/')) {
|
||||
|
|
Loading…
Reference in a new issue