\n {t('Secret does not exist')}\n \n {t('It might be caused by any of these reasons.')}\n \n \n {t('Opened before')}\n \n {t(\n 'A secret can be restricted to a single download. It might be lost because the sender clicked this link before you viewed it.',\n )}\n \n {t(\n 'The secret might have been compromised and read by someone else. You should contact the sender and request a new secret.',\n )}\n\n {t('Broken link')}\n {t(\n 'The link must match perfectly in order for the decryption to work, it might be missing some magic digits.',\n )}\n {t('Expired')}\n {t(\n 'No secret last forever. All stored secrets will expires and self destruct automatically. Lifetime varies from one hour up to one week.',\n )}\n \n
\n );\n};\nexport default Error;\n","import { useState } from 'react';\nimport { Redirect } from 'react-router-dom';\nimport { Button } from '@flixbus/honeycomb-react';\nimport { Container, Grid, TextField } from '@material-ui/core';\nimport { useTranslation } from 'react-i18next';\n\ntype FormProps = {\n readonly uuid: string;\n readonly prefix: string;\n};\n\nconst Form = ({ uuid, prefix }: FormProps) => {\n const [password, setPassword] = useState('');\n const [redirect, setRedirect] = useState(false);\n const { t } = useTranslation();\n\n const doRedirect = (): void => {\n if (password) {\n setRedirect(true);\n }\n };\n\n if (redirect) {\n if (prefix === 'c' || prefix === 'd') {\n // Base64 encode the password to support special characters\n return ;\n }\n return ;\n }\n\n return (\n \n \n \n setPassword(e.target.value)}\n />\n \n \n \n \n \n \n );\n};\nexport default Form;\n","import { message, encrypt, decrypt, DecryptResult } from 'openpgp';\n\ntype Response = {\n // TODO: this shouldn't be any\n data: any;\n status: number;\n};\n\nexport const randomString = (): string => {\n let text = '';\n const possible =\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n for (let i = 0; i < 22; i++) {\n text += possible.charAt(randomInt(0, possible.length));\n }\n return text;\n};\n\nconst randomInt = (min: number, max: number): number => {\n const byteArray = new Uint8Array(1);\n window.crypto.getRandomValues(byteArray);\n\n const range = max - min;\n const maxRange = 256;\n if (byteArray[0] >= Math.floor(maxRange / range) * range) {\n return randomInt(min, max);\n }\n return min + (byteArray[0] % range);\n};\n\nexport const backendDomain = process.env.REACT_APP_BACKEND_URL\n ? `${process.env.REACT_APP_BACKEND_URL}`\n : '';\n\nexport const postSecret = async (body: any): Promise => {\n return post(backendDomain + '/secret', body);\n};\n\nexport const uploadFile = async (body: any): Promise => {\n return post(backendDomain + '/file', body);\n};\n\nconst post = async (url: string, body: any): Promise => {\n const request = await fetch(url, {\n body: JSON.stringify(body),\n method: 'POST',\n });\n return { data: await request.json(), status: request.status };\n};\n\nexport const decryptMessage = async (\n data: string,\n passwords: string,\n format: 'utf8' | 'binary',\n): Promise => {\n const r = await decrypt({\n message: await message.readArmored(data),\n passwords,\n format,\n });\n return r;\n};\n\nexport const encryptMessage = async (\n data: string,\n passwords: string,\n): Promise => {\n const r = await encrypt({\n message: message.fromText(data),\n passwords,\n });\n return r.data as string;\n};\n\nexport default randomString;\n","import { useTranslation } from 'react-i18next';\n\nconst Loading = () => {\n const { t } = useTranslation();\n return (\n
\n {t('Fetching from database and decrypting in browser, please hold...')}\n
\n \n {t('Downloading file and decrypting in browser, please hold...')}\n \n \n {t('Make sure to download the file since it is only available once')}\n \n
\n \n {t('Secret stored in database')}\n \n \n {t(\n 'Remember that the secret can only be downloaded once so do not open the link yourself.',\n )}\n \n {t(\n 'The cautious should send the decryption key in a separate communication channel.',\n )}\n \n {!isCustomPassword && (\n \n )}\n \n \n